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