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 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 == NULL) { 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 return tty_port_open(&gdm->port, tty, filp); 115 } 116 117 static void gdm_tty_cleanup(struct tty_struct *tty) 118 { 119 struct gdm *gdm = tty->driver_data; 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 tty_port_hangup(&gdm->port); 127 } 128 129 static void gdm_tty_close(struct tty_struct *tty, struct file *filp) 130 { 131 struct gdm *gdm = tty->driver_data; 132 tty_port_close(&gdm->port, tty, filp); 133 } 134 135 static int gdm_tty_recv_complete(void *data, 136 int len, 137 int index, 138 struct tty_dev *tty_dev, 139 int complete) 140 { 141 struct gdm *gdm = tty_dev->gdm[index]; 142 if (!GDM_TTY_READY(gdm)) { 143 if (complete == RECV_PACKET_PROCESS_COMPLETE) 144 gdm_tty_recv(gdm, gdm_tty_recv_complete); 145 return TO_HOST_PORT_CLOSE; 146 } 147 148 if (data && len) { 149 if (tty_buffer_request_room(&gdm->port, len) == len) { 150 tty_insert_flip_string(&gdm->port, data, len); 151 tty_flip_buffer_push(&gdm->port); 152 } else { 153 return TO_HOST_BUFFER_REQUEST_FAIL; 154 } 155 } 156 157 if (complete == RECV_PACKET_PROCESS_COMPLETE) 158 gdm_tty_recv(gdm, gdm_tty_recv_complete); 159 160 return 0; 161 } 162 163 static void gdm_tty_send_complete(void *arg) 164 { 165 struct gdm *gdm = (struct 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 = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE : 189 remain; 190 gdm_tty_send(gdm, 191 (void *)(buf+sent_len), 192 sending_len, 193 gdm->index, 194 gdm_tty_send_complete, 195 gdm 196 ); 197 sent_len += sending_len; 198 remain -= sending_len; 199 if (remain <= 0) 200 break; 201 } 202 203 return len; 204 } 205 206 static int gdm_tty_write_room(struct tty_struct *tty) 207 { 208 struct gdm *gdm = tty->driver_data; 209 210 if (!GDM_TTY_READY(gdm)) 211 return -ENODEV; 212 213 return WRITE_SIZE; 214 } 215 216 int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device) 217 { 218 struct gdm *gdm; 219 int i; 220 int j; 221 222 for (i = 0; i < TTY_MAX_COUNT; i++) { 223 224 gdm = kmalloc(sizeof(struct 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