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