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 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 int i; 59 int j; 60 61 j = GDM_TTY_MINOR; 62 for (i = 0; i < TTY_MAX_COUNT; i++) { 63 if (!strcmp(tty->driver->driver_name, DRIVER_STRING[i])) { 64 j = tty->index; 65 break; 66 } 67 } 68 69 if (j == GDM_TTY_MINOR) 70 return -ENODEV; 71 72 mutex_lock(&gdm_table_lock); 73 gdm = gdm_table[i][j]; 74 if (!gdm) { 75 mutex_unlock(&gdm_table_lock); 76 return -ENODEV; 77 } 78 79 tty_port_get(&gdm->port); 80 81 ret = tty_standard_install(driver, tty); 82 if (ret) { 83 tty_port_put(&gdm->port); 84 mutex_unlock(&gdm_table_lock); 85 return ret; 86 } 87 88 tty->driver_data = gdm; 89 mutex_unlock(&gdm_table_lock); 90 91 return 0; 92 } 93 94 static int gdm_tty_open(struct tty_struct *tty, struct file *filp) 95 { 96 struct gdm *gdm = tty->driver_data; 97 98 return tty_port_open(&gdm->port, tty, filp); 99 } 100 101 static void gdm_tty_cleanup(struct tty_struct *tty) 102 { 103 struct gdm *gdm = tty->driver_data; 104 105 tty_port_put(&gdm->port); 106 } 107 108 static void gdm_tty_hangup(struct tty_struct *tty) 109 { 110 struct gdm *gdm = tty->driver_data; 111 112 tty_port_hangup(&gdm->port); 113 } 114 115 static void gdm_tty_close(struct tty_struct *tty, struct file *filp) 116 { 117 struct gdm *gdm = tty->driver_data; 118 119 tty_port_close(&gdm->port, tty, filp); 120 } 121 122 static int gdm_tty_recv_complete(void *data, 123 int len, 124 int index, 125 struct tty_dev *tty_dev, 126 int complete) 127 { 128 struct gdm *gdm = tty_dev->gdm[index]; 129 130 if (!GDM_TTY_READY(gdm)) { 131 if (complete == RECV_PACKET_PROCESS_COMPLETE) 132 gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev, 133 gdm_tty_recv_complete); 134 return TO_HOST_PORT_CLOSE; 135 } 136 137 if (data && len) { 138 if (tty_buffer_request_room(&gdm->port, len) == len) { 139 tty_insert_flip_string(&gdm->port, data, len); 140 tty_flip_buffer_push(&gdm->port); 141 } else { 142 return TO_HOST_BUFFER_REQUEST_FAIL; 143 } 144 } 145 146 if (complete == RECV_PACKET_PROCESS_COMPLETE) 147 gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev, 148 gdm_tty_recv_complete); 149 150 return 0; 151 } 152 153 static void gdm_tty_send_complete(void *arg) 154 { 155 struct gdm *gdm = arg; 156 157 if (!GDM_TTY_READY(gdm)) 158 return; 159 160 tty_port_tty_wakeup(&gdm->port); 161 } 162 163 static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, 164 int len) 165 { 166 struct gdm *gdm = tty->driver_data; 167 int remain = len; 168 int sent_len = 0; 169 int sending_len = 0; 170 171 if (!GDM_TTY_READY(gdm)) 172 return -ENODEV; 173 174 if (!len) 175 return 0; 176 177 while (1) { 178 sending_len = min(MUX_TX_MAX_SIZE, remain); 179 gdm->tty_dev->send_func(gdm->tty_dev->priv_dev, 180 (void *)(buf + sent_len), 181 sending_len, 182 gdm->index, 183 gdm_tty_send_complete, 184 gdm); 185 sent_len += sending_len; 186 remain -= sending_len; 187 if (remain <= 0) 188 break; 189 } 190 191 return len; 192 } 193 194 static int gdm_tty_write_room(struct tty_struct *tty) 195 { 196 struct gdm *gdm = tty->driver_data; 197 198 if (!GDM_TTY_READY(gdm)) 199 return -ENODEV; 200 201 return WRITE_SIZE; 202 } 203 204 int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device) 205 { 206 struct gdm *gdm; 207 int i; 208 int j; 209 210 for (i = 0; i < TTY_MAX_COUNT; i++) { 211 gdm = kmalloc(sizeof(*gdm), GFP_KERNEL); 212 if (!gdm) 213 return -ENOMEM; 214 215 mutex_lock(&gdm_table_lock); 216 for (j = 0; j < GDM_TTY_MINOR; j++) { 217 if (!gdm_table[i][j]) 218 break; 219 } 220 221 if (j == GDM_TTY_MINOR) { 222 kfree(gdm); 223 mutex_unlock(&gdm_table_lock); 224 return -EINVAL; 225 } 226 227 gdm_table[i][j] = gdm; 228 mutex_unlock(&gdm_table_lock); 229 230 tty_dev->gdm[i] = gdm; 231 tty_port_init(&gdm->port); 232 233 gdm->port.ops = &gdm_port_ops; 234 gdm->index = i; 235 gdm->minor = j; 236 gdm->tty_dev = tty_dev; 237 238 tty_port_register_device(&gdm->port, gdm_driver[i], 239 gdm->minor, device); 240 } 241 242 for (i = 0; i < MAX_ISSUE_NUM; i++) 243 gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev, 244 gdm_tty_recv_complete); 245 246 return 0; 247 } 248 249 void unregister_lte_tty_device(struct tty_dev *tty_dev) 250 { 251 struct gdm *gdm; 252 struct tty_struct *tty; 253 int i; 254 255 for (i = 0; i < TTY_MAX_COUNT; i++) { 256 gdm = tty_dev->gdm[i]; 257 if (!gdm) 258 continue; 259 260 mutex_lock(&gdm_table_lock); 261 gdm_table[gdm->index][gdm->minor] = NULL; 262 mutex_unlock(&gdm_table_lock); 263 264 tty = tty_port_tty_get(&gdm->port); 265 if (tty) { 266 tty_vhangup(tty); 267 tty_kref_put(tty); 268 } 269 270 tty_unregister_device(gdm_driver[i], gdm->minor); 271 tty_port_put(&gdm->port); 272 } 273 } 274 275 static const struct tty_operations gdm_tty_ops = { 276 .install = gdm_tty_install, 277 .open = gdm_tty_open, 278 .close = gdm_tty_close, 279 .cleanup = gdm_tty_cleanup, 280 .hangup = gdm_tty_hangup, 281 .write = gdm_tty_write, 282 .write_room = gdm_tty_write_room, 283 }; 284 285 int register_lte_tty_driver(void) 286 { 287 struct tty_driver *tty_driver; 288 int i; 289 int ret; 290 291 for (i = 0; i < TTY_MAX_COUNT; i++) { 292 tty_driver = alloc_tty_driver(GDM_TTY_MINOR); 293 if (!tty_driver) 294 return -ENOMEM; 295 296 tty_driver->owner = THIS_MODULE; 297 tty_driver->driver_name = DRIVER_STRING[i]; 298 tty_driver->name = DEVICE_STRING[i]; 299 tty_driver->major = GDM_TTY_MAJOR; 300 tty_driver->type = TTY_DRIVER_TYPE_SERIAL; 301 tty_driver->subtype = SERIAL_TYPE_NORMAL; 302 tty_driver->flags = TTY_DRIVER_REAL_RAW | 303 TTY_DRIVER_DYNAMIC_DEV; 304 tty_driver->init_termios = tty_std_termios; 305 tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL; 306 tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN; 307 tty_set_operations(tty_driver, &gdm_tty_ops); 308 309 ret = tty_register_driver(tty_driver); 310 if (ret) { 311 put_tty_driver(tty_driver); 312 return ret; 313 } 314 315 gdm_driver[i] = tty_driver; 316 } 317 318 return ret; 319 } 320 321 void unregister_lte_tty_driver(void) 322 { 323 struct tty_driver *tty_driver; 324 int i; 325 326 for (i = 0; i < TTY_MAX_COUNT; i++) { 327 tty_driver = gdm_driver[i]; 328 if (tty_driver) { 329 tty_unregister_driver(tty_driver); 330 put_tty_driver(tty_driver); 331 } 332 } 333 } 334 335