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