Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
0003 
0004 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/errno.h>
0008 #include <linux/tty.h>
0009 #include <linux/tty_driver.h>
0010 #include <linux/tty_flip.h>
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 #include <linux/usb/cdc.h>
0014 #include <linux/serial.h>
0015 #include "gdm_tty.h"
0016 
0017 #define GDM_TTY_MAJOR 0
0018 #define GDM_TTY_MINOR 32
0019 
0020 #define WRITE_SIZE 2048
0021 
0022 #define MUX_TX_MAX_SIZE 2048
0023 
0024 #define GDM_TTY_READY(gdm) (gdm && gdm->tty_dev && gdm->port.count)
0025 
0026 static struct tty_driver *gdm_driver[TTY_MAX_COUNT];
0027 static struct gdm *gdm_table[TTY_MAX_COUNT][GDM_TTY_MINOR];
0028 static DEFINE_MUTEX(gdm_table_lock);
0029 
0030 static const char *DRIVER_STRING[TTY_MAX_COUNT] = {"GCTATC", "GCTDM"};
0031 static char *DEVICE_STRING[TTY_MAX_COUNT] = {"GCT-ATC", "GCT-DM"};
0032 
0033 static void gdm_port_destruct(struct tty_port *port)
0034 {
0035     struct gdm *gdm = container_of(port, struct gdm, port);
0036 
0037     mutex_lock(&gdm_table_lock);
0038     gdm_table[gdm->index][gdm->minor] = NULL;
0039     mutex_unlock(&gdm_table_lock);
0040 
0041     kfree(gdm);
0042 }
0043 
0044 static const struct tty_port_operations gdm_port_ops = {
0045     .destruct = gdm_port_destruct,
0046 };
0047 
0048 static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
0049 {
0050     struct gdm *gdm = NULL;
0051     int ret;
0052 
0053     ret = match_string(DRIVER_STRING, TTY_MAX_COUNT,
0054                tty->driver->driver_name);
0055     if (ret < 0)
0056         return -ENODEV;
0057 
0058     mutex_lock(&gdm_table_lock);
0059     gdm = gdm_table[ret][tty->index];
0060     if (!gdm) {
0061         mutex_unlock(&gdm_table_lock);
0062         return -ENODEV;
0063     }
0064 
0065     tty_port_get(&gdm->port);
0066 
0067     ret = tty_standard_install(driver, tty);
0068     if (ret) {
0069         tty_port_put(&gdm->port);
0070         mutex_unlock(&gdm_table_lock);
0071         return ret;
0072     }
0073 
0074     tty->driver_data = gdm;
0075     mutex_unlock(&gdm_table_lock);
0076 
0077     return 0;
0078 }
0079 
0080 static int gdm_tty_open(struct tty_struct *tty, struct file *filp)
0081 {
0082     struct gdm *gdm = tty->driver_data;
0083 
0084     return tty_port_open(&gdm->port, tty, filp);
0085 }
0086 
0087 static void gdm_tty_cleanup(struct tty_struct *tty)
0088 {
0089     struct gdm *gdm = tty->driver_data;
0090 
0091     tty_port_put(&gdm->port);
0092 }
0093 
0094 static void gdm_tty_hangup(struct tty_struct *tty)
0095 {
0096     struct gdm *gdm = tty->driver_data;
0097 
0098     tty_port_hangup(&gdm->port);
0099 }
0100 
0101 static void gdm_tty_close(struct tty_struct *tty, struct file *filp)
0102 {
0103     struct gdm *gdm = tty->driver_data;
0104 
0105     tty_port_close(&gdm->port, tty, filp);
0106 }
0107 
0108 static int gdm_tty_recv_complete(void *data,
0109                  int len,
0110                  int index,
0111                  struct tty_dev *tty_dev,
0112                  int complete)
0113 {
0114     struct gdm *gdm = tty_dev->gdm[index];
0115 
0116     if (!GDM_TTY_READY(gdm)) {
0117         if (complete == RECV_PACKET_PROCESS_COMPLETE)
0118             gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
0119                         gdm_tty_recv_complete);
0120         return TO_HOST_PORT_CLOSE;
0121     }
0122 
0123     if (data && len) {
0124         if (tty_buffer_request_room(&gdm->port, len) == len) {
0125             tty_insert_flip_string(&gdm->port, data, len);
0126             tty_flip_buffer_push(&gdm->port);
0127         } else {
0128             return TO_HOST_BUFFER_REQUEST_FAIL;
0129         }
0130     }
0131 
0132     if (complete == RECV_PACKET_PROCESS_COMPLETE)
0133         gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
0134                     gdm_tty_recv_complete);
0135 
0136     return 0;
0137 }
0138 
0139 static void gdm_tty_send_complete(void *arg)
0140 {
0141     struct gdm *gdm = arg;
0142 
0143     if (!GDM_TTY_READY(gdm))
0144         return;
0145 
0146     tty_port_tty_wakeup(&gdm->port);
0147 }
0148 
0149 static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf,
0150              int len)
0151 {
0152     struct gdm *gdm = tty->driver_data;
0153     int remain = len;
0154     int sent_len = 0;
0155     int sending_len = 0;
0156 
0157     if (!GDM_TTY_READY(gdm))
0158         return -ENODEV;
0159 
0160     if (!len)
0161         return 0;
0162 
0163     while (1) {
0164         sending_len = min(MUX_TX_MAX_SIZE, remain);
0165         gdm->tty_dev->send_func(gdm->tty_dev->priv_dev,
0166                     (void *)(buf + sent_len),
0167                     sending_len,
0168                     gdm->index,
0169                     gdm_tty_send_complete,
0170                     gdm);
0171         sent_len += sending_len;
0172         remain -= sending_len;
0173         if (remain <= 0)
0174             break;
0175     }
0176 
0177     return len;
0178 }
0179 
0180 static unsigned int gdm_tty_write_room(struct tty_struct *tty)
0181 {
0182     struct gdm *gdm = tty->driver_data;
0183 
0184     if (!GDM_TTY_READY(gdm))
0185         return 0;
0186 
0187     return WRITE_SIZE;
0188 }
0189 
0190 int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device)
0191 {
0192     struct gdm *gdm;
0193     int i;
0194     int j;
0195 
0196     for (i = 0; i < TTY_MAX_COUNT; i++) {
0197         gdm = kmalloc(sizeof(*gdm), GFP_KERNEL);
0198         if (!gdm)
0199             return -ENOMEM;
0200 
0201         mutex_lock(&gdm_table_lock);
0202         for (j = 0; j < GDM_TTY_MINOR; j++) {
0203             if (!gdm_table[i][j])
0204                 break;
0205         }
0206 
0207         if (j == GDM_TTY_MINOR) {
0208             kfree(gdm);
0209             mutex_unlock(&gdm_table_lock);
0210             return -EINVAL;
0211         }
0212 
0213         gdm_table[i][j] = gdm;
0214         mutex_unlock(&gdm_table_lock);
0215 
0216         tty_dev->gdm[i] = gdm;
0217         tty_port_init(&gdm->port);
0218 
0219         gdm->port.ops = &gdm_port_ops;
0220         gdm->index = i;
0221         gdm->minor = j;
0222         gdm->tty_dev = tty_dev;
0223 
0224         tty_port_register_device(&gdm->port, gdm_driver[i],
0225                      gdm->minor, device);
0226     }
0227 
0228     for (i = 0; i < MAX_ISSUE_NUM; i++)
0229         gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
0230                     gdm_tty_recv_complete);
0231 
0232     return 0;
0233 }
0234 
0235 void unregister_lte_tty_device(struct tty_dev *tty_dev)
0236 {
0237     struct gdm *gdm;
0238     struct tty_struct *tty;
0239     int i;
0240 
0241     for (i = 0; i < TTY_MAX_COUNT; i++) {
0242         gdm = tty_dev->gdm[i];
0243         if (!gdm)
0244             continue;
0245 
0246         mutex_lock(&gdm_table_lock);
0247         gdm_table[gdm->index][gdm->minor] = NULL;
0248         mutex_unlock(&gdm_table_lock);
0249 
0250         tty = tty_port_tty_get(&gdm->port);
0251         if (tty) {
0252             tty_vhangup(tty);
0253             tty_kref_put(tty);
0254         }
0255 
0256         tty_unregister_device(gdm_driver[i], gdm->minor);
0257         tty_port_put(&gdm->port);
0258     }
0259 }
0260 
0261 static const struct tty_operations gdm_tty_ops = {
0262     .install =  gdm_tty_install,
0263     .open =     gdm_tty_open,
0264     .close =    gdm_tty_close,
0265     .cleanup =  gdm_tty_cleanup,
0266     .hangup =   gdm_tty_hangup,
0267     .write =    gdm_tty_write,
0268     .write_room =   gdm_tty_write_room,
0269 };
0270 
0271 int register_lte_tty_driver(void)
0272 {
0273     struct tty_driver *tty_driver;
0274     int i;
0275     int ret;
0276 
0277     for (i = 0; i < TTY_MAX_COUNT; i++) {
0278         tty_driver = tty_alloc_driver(GDM_TTY_MINOR,
0279                 TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
0280         if (IS_ERR(tty_driver))
0281             return PTR_ERR(tty_driver);
0282 
0283         tty_driver->owner = THIS_MODULE;
0284         tty_driver->driver_name = DRIVER_STRING[i];
0285         tty_driver->name = DEVICE_STRING[i];
0286         tty_driver->major = GDM_TTY_MAJOR;
0287         tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
0288         tty_driver->subtype = SERIAL_TYPE_NORMAL;
0289         tty_driver->init_termios = tty_std_termios;
0290         tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
0291         tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
0292         tty_set_operations(tty_driver, &gdm_tty_ops);
0293 
0294         ret = tty_register_driver(tty_driver);
0295         if (ret) {
0296             tty_driver_kref_put(tty_driver);
0297             return ret;
0298         }
0299 
0300         gdm_driver[i] = tty_driver;
0301     }
0302 
0303     return ret;
0304 }
0305 
0306 void unregister_lte_tty_driver(void)
0307 {
0308     struct tty_driver *tty_driver;
0309     int i;
0310 
0311     for (i = 0; i < TTY_MAX_COUNT; i++) {
0312         tty_driver = gdm_driver[i];
0313         if (tty_driver) {
0314             tty_unregister_driver(tty_driver);
0315             tty_driver_kref_put(tty_driver);
0316         }
0317     }
0318 }
0319