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