tty/module.c
changeset 2589 2b9c78543663
parent 2411 01370d59233d
child 2659 8e6fad4f9a74
equal deleted inserted replaced
2415:af21f0bdc7c9 2589:2b9c78543663
    63 char *ec_master_version_str = EC_MASTER_VERSION; /**< Version string. */
    63 char *ec_master_version_str = EC_MASTER_VERSION; /**< Version string. */
    64 unsigned int debug_level = 0;
    64 unsigned int debug_level = 0;
    65 
    65 
    66 static struct tty_driver *tty_driver = NULL;
    66 static struct tty_driver *tty_driver = NULL;
    67 ec_tty_t *ttys[EC_TTY_MAX_DEVICES];
    67 ec_tty_t *ttys[EC_TTY_MAX_DEVICES];
    68 struct ec_mutex_t tty_sem;
    68 struct semaphore tty_sem;
    69 
    69 
    70 void ec_tty_wakeup(unsigned long);
    70 void ec_tty_wakeup(unsigned long);
    71 
    71 
    72 /*****************************************************************************/
    72 /*****************************************************************************/
    73 
    73 
   109     unsigned int rx_write_idx;
   109     unsigned int rx_write_idx;
   110 
   110 
   111     struct timer_list timer;
   111     struct timer_list timer;
   112     struct tty_struct *tty;
   112     struct tty_struct *tty;
   113     unsigned int open_count;
   113     unsigned int open_count;
   114     struct ec_mutex_t sem;
   114     struct semaphore sem;
   115 
   115 
   116     ec_tty_operations_t ops;
   116     ec_tty_operations_t ops;
   117     void *cb_data;
   117     void *cb_data;
   118 };
   118 };
   119 
   119 
   129 {
   129 {
   130     int i, ret = 0;
   130     int i, ret = 0;
   131 
   131 
   132     printk(KERN_INFO PFX "TTY driver %s\n", EC_MASTER_VERSION);
   132     printk(KERN_INFO PFX "TTY driver %s\n", EC_MASTER_VERSION);
   133 
   133 
   134     ec_mutex_init(&tty_sem);
   134     sema_init(&tty_sem, 1);
   135 
   135 
   136     for (i = 0; i < EC_TTY_MAX_DEVICES; i++) {
   136     for (i = 0; i < EC_TTY_MAX_DEVICES; i++) {
   137         ttys[i] = NULL;
   137         ttys[i] = NULL;
   138     }
   138     }
   139 
   139 
   190         const ec_tty_operations_t *ops, void *cb_data)
   190         const ec_tty_operations_t *ops, void *cb_data)
   191 {
   191 {
   192     int ret;
   192     int ret;
   193     tcflag_t cflag;
   193     tcflag_t cflag;
   194     struct tty_struct *tty;
   194     struct tty_struct *tty;
       
   195     struct ktermios *termios;
   195 
   196 
   196     t->minor = minor;
   197     t->minor = minor;
   197     t->tx_read_idx = 0;
   198     t->tx_read_idx = 0;
   198     t->tx_write_idx = 0;
   199     t->tx_write_idx = 0;
   199     t->wakeup = 0;
   200     t->wakeup = 0;
   200     t->rx_read_idx = 0;
   201     t->rx_read_idx = 0;
   201     t->rx_write_idx = 0;
   202     t->rx_write_idx = 0;
   202     init_timer(&t->timer);
   203     init_timer(&t->timer);
   203     t->tty = NULL;
   204     t->tty = NULL;
   204     t->open_count = 0;
   205     t->open_count = 0;
   205     ec_mutex_init(&t->sem);
   206     sema_init(&t->sem, 1);
   206     t->ops = *ops;
   207     t->ops = *ops;
   207     t->cb_data = cb_data;
   208     t->cb_data = cb_data;
   208 
   209 
   209     t->dev = tty_register_device(tty_driver, t->minor, NULL);
   210     t->dev = tty_register_device(tty_driver, t->minor, NULL);
   210     if (IS_ERR(t->dev)) {
   211     if (IS_ERR(t->dev)) {
   213     }
   214     }
   214 
   215 
   215     // Tell the device-specific implementation about the initial cflags
   216     // Tell the device-specific implementation about the initial cflags
   216     tty = tty_driver->ttys[minor];
   217     tty = tty_driver->ttys[minor];
   217 
   218 
   218     if (tty && tty->termios) { // already opened before
   219     termios =
   219         cflag = tty->termios->c_cflag;
   220 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
       
   221         &tty->termios
       
   222 #else
       
   223         tty->termios
       
   224 #endif
       
   225         ;
       
   226 
       
   227     if (tty && termios) { // already opened before
       
   228         cflag = termios->c_cflag;
   220     } else {
   229     } else {
   221         cflag = tty_driver->init_termios.c_cflag;
   230         cflag = tty_driver->init_termios.c_cflag;
   222     }
   231     }
   223     ret = t->ops.cflag_changed(t->cb_data, cflag);
   232     ret = t->ops.cflag_changed(t->cb_data, cflag);
   224     if (ret) {
   233     if (ret) {
   389     if (!t->tty) {
   398     if (!t->tty) {
   390         t->tty = tty;
   399         t->tty = tty;
   391         tty->driver_data = t;
   400         tty->driver_data = t;
   392     }
   401     }
   393 
   402 
   394     ec_mutex_lock(&t->sem);
   403     down(&t->sem);
   395     t->open_count++;
   404     t->open_count++;
   396     ec_mutex_unlock(&t->sem);
   405     up(&t->sem);
   397     return 0;
   406     return 0;
   398 }
   407 }
   399 
   408 
   400 /*****************************************************************************/
   409 /*****************************************************************************/
   401 
   410 
   407     printk(KERN_INFO PFX "%s(tty=%p, file=%p): Closing line %i.\n",
   416     printk(KERN_INFO PFX "%s(tty=%p, file=%p): Closing line %i.\n",
   408             __func__, tty, file, tty->index);
   417             __func__, tty, file, tty->index);
   409 #endif
   418 #endif
   410 
   419 
   411     if (t) {
   420     if (t) {
   412         ec_mutex_lock(&t->sem);
   421         down(&t->sem);
   413         if (--t->open_count == 0) {
   422         if (--t->open_count == 0) {
   414             t->tty = NULL;
   423             t->tty = NULL;
   415         }
   424         }
   416         ec_mutex_unlock(&t->sem);
   425         up(&t->sem);
   417     }
   426     }
   418 }
   427 }
   419 
   428 
   420 /*****************************************************************************/
   429 /*****************************************************************************/
   421 
   430 
   480 
   489 
   481 static int ec_tty_write_room(struct tty_struct *tty)
   490 static int ec_tty_write_room(struct tty_struct *tty)
   482 {
   491 {
   483     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   492     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   484     int ret = ec_tty_tx_space(t);
   493     int ret = ec_tty_tx_space(t);
   485     
   494 
   486 #if EC_TTY_DEBUG >= 2
   495 #if EC_TTY_DEBUG >= 2
   487     printk(KERN_INFO PFX "%s() = %i.\n", __func__, ret);
   496     printk(KERN_INFO PFX "%s() = %i.\n", __func__, ret);
   488 #endif
   497 #endif
   489 
   498 
   490     return ret;
   499     return ret;
   494 
   503 
   495 static int ec_tty_chars_in_buffer(struct tty_struct *tty)
   504 static int ec_tty_chars_in_buffer(struct tty_struct *tty)
   496 {
   505 {
   497     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   506     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   498     int ret;
   507     int ret;
   499     
   508 
   500 #if EC_TTY_DEBUG >= 2
   509 #if EC_TTY_DEBUG >= 2
   501     printk(KERN_INFO PFX "%s().\n", __func__);
   510     printk(KERN_INFO PFX "%s().\n", __func__);
   502 #endif
   511 #endif
   503 
   512 
   504     ret = ec_tty_tx_size(t);
   513     ret = ec_tty_tx_size(t);
   505 
   514 
   506 #if EC_TTY_DEBUG >= 2
   515 #if EC_TTY_DEBUG >= 2
   507     printk(KERN_INFO PFX "%s() = %i.\n", __func__, ret);
   516     printk(KERN_INFO PFX "%s() = %i.\n", __func__, ret);
   508 #endif
   517 #endif
   509     
   518 
   510     return ret;
   519     return ret;
   511 }
   520 }
   512 
   521 
   513 /*****************************************************************************/
   522 /*****************************************************************************/
   514 
   523 
   521     // FIXME empty ring buffer
   530     // FIXME empty ring buffer
   522 }
   531 }
   523 
   532 
   524 /*****************************************************************************/
   533 /*****************************************************************************/
   525 
   534 
   526 static int ec_tty_ioctl(struct tty_struct *tty, struct file *file,
   535 static int ec_tty_ioctl(struct tty_struct *tty,
       
   536 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
       
   537         struct file *file,
       
   538 #endif
   527         unsigned int cmd, unsigned long arg)
   539         unsigned int cmd, unsigned long arg)
   528 {
   540 {
   529     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   541     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   530     int ret = -ENOTTY;
   542     int ret = -ENOTTY;
   531     
   543 
   532 #if EC_TTY_DEBUG >= 2
   544 #if EC_TTY_DEBUG >= 2
   533     printk(KERN_INFO PFX "%s(tty=%p, file=%p, cmd=%08x, arg=%08lx).\n",
   545     printk(KERN_INFO PFX "%s(tty=%p, "
   534             __func__, tty, file, cmd, arg);
   546 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
       
   547             "file=%p, "
       
   548 #endif
       
   549             "cmd=%08x, arg=%08lx).\n",
       
   550             __func__, tty,
       
   551 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
       
   552             file,
       
   553 #endif
       
   554             cmd, arg);
   535     printk(KERN_INFO PFX "decoded: type=%02x nr=%u\n",
   555     printk(KERN_INFO PFX "decoded: type=%02x nr=%u\n",
   536             _IOC_TYPE(cmd), _IOC_NR(cmd));
   556             _IOC_TYPE(cmd), _IOC_NR(cmd));
   537 #endif
   557 #endif
   538 
   558 
   539     switch (cmd) {
   559     switch (cmd) {
   562 static void ec_tty_set_termios(struct tty_struct *tty,
   582 static void ec_tty_set_termios(struct tty_struct *tty,
   563         struct ktermios *old_termios)
   583         struct ktermios *old_termios)
   564 {
   584 {
   565     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   585     ec_tty_t *t = (ec_tty_t *) tty->driver_data;
   566     int ret;
   586     int ret;
       
   587     struct ktermios *termios;
   567 
   588 
   568 #if EC_TTY_DEBUG >= 2
   589 #if EC_TTY_DEBUG >= 2
   569     printk(KERN_INFO PFX "%s().\n", __func__);
   590     printk(KERN_INFO PFX "%s().\n", __func__);
   570 #endif
   591 #endif
   571 
   592 
   572     if (tty->termios->c_cflag == old_termios->c_cflag)
   593     termios =
       
   594 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
       
   595         &tty->termios
       
   596 #else
       
   597         tty->termios
       
   598 #endif
       
   599         ;
       
   600 
       
   601     if (termios->c_cflag == old_termios->c_cflag)
   573         return;
   602         return;
   574 
   603 
   575 #if EC_TTY_DEBUG >= 2
   604 #if EC_TTY_DEBUG >= 2
   576     printk(KERN_INFO "cflag changed from %x to %x.\n",
   605     printk(KERN_INFO "cflag changed from %x to %x.\n",
   577             old_termios->c_cflag, tty->termios->c_cflag);
   606             old_termios->c_cflag, termios->c_cflag);
   578 #endif
   607 #endif
   579 
   608 
   580     ret = t->ops.cflag_changed(t->cb_data, tty->termios->c_cflag);
   609     ret = t->ops.cflag_changed(t->cb_data, termios->c_cflag);
   581     if (ret) {
   610     if (ret) {
   582         printk(KERN_ERR PFX "ERROR: cflag 0x%x not accepted.\n",
   611         printk(KERN_ERR PFX "ERROR: cflag 0x%x not accepted.\n",
   583                 tty->termios->c_cflag);
   612                 termios->c_cflag);
   584         tty->termios->c_cflag = old_termios->c_cflag;
   613         termios->c_cflag = old_termios->c_cflag;
   585     }
   614     }
   586 }
   615 }
   587 
   616 
   588 /*****************************************************************************/
   617 /*****************************************************************************/
   589 
   618 
   674 ec_tty_t *ectty_create(const ec_tty_operations_t *ops, void *cb_data)
   703 ec_tty_t *ectty_create(const ec_tty_operations_t *ops, void *cb_data)
   675 {
   704 {
   676     ec_tty_t *tty;
   705     ec_tty_t *tty;
   677     int minor, ret;
   706     int minor, ret;
   678 
   707 
   679     if (ec_mutex_lock_interruptible(&tty_sem)) {
   708     if (down_interruptible(&tty_sem)) {
   680         return ERR_PTR(-EINTR);
   709         return ERR_PTR(-EINTR);
   681     }
   710     }
   682 
   711 
   683     for (minor = 0; minor < EC_TTY_MAX_DEVICES; minor++) {
   712     for (minor = 0; minor < EC_TTY_MAX_DEVICES; minor++) {
   684         if (!ttys[minor]) {
   713         if (!ttys[minor]) {
   685             printk(KERN_INFO PFX "Creating TTY interface %i.\n", minor);
   714             printk(KERN_INFO PFX "Creating TTY interface %i.\n", minor);
   686 
   715 
   687             tty = kmalloc(sizeof(ec_tty_t), GFP_KERNEL);
   716             tty = kmalloc(sizeof(ec_tty_t), GFP_KERNEL);
   688             if (!tty) {
   717             if (!tty) {
   689                 ec_mutex_unlock(&tty_sem);
   718                 up(&tty_sem);
   690                 printk(KERN_ERR PFX "Failed to allocate memory.\n");
   719                 printk(KERN_ERR PFX "Failed to allocate memory.\n");
   691                 return ERR_PTR(-ENOMEM);
   720                 return ERR_PTR(-ENOMEM);
   692             }
   721             }
   693 
   722 
   694             ret = ec_tty_init(tty, minor, ops, cb_data);
   723             ret = ec_tty_init(tty, minor, ops, cb_data);
   695             if (ret) {
   724             if (ret) {
   696                 ec_mutex_unlock(&tty_sem);
   725                 up(&tty_sem);
   697                 kfree(tty);
   726                 kfree(tty);
   698                 return ERR_PTR(ret);
   727                 return ERR_PTR(ret);
   699             }
   728             }
   700 
   729 
   701             ttys[minor] = tty;
   730             ttys[minor] = tty;
   702             ec_mutex_unlock(&tty_sem);
   731             up(&tty_sem);
   703             return tty;
   732             return tty;
   704         }
   733         }
   705     }
   734     }
   706 
   735 
   707     ec_mutex_unlock(&tty_sem);
   736     up(&tty_sem);
   708     printk(KERN_ERR PFX "No free interfaces avaliable.\n");
   737     printk(KERN_ERR PFX "No free interfaces avaliable.\n");
   709     return ERR_PTR(-EBUSY);
   738     return ERR_PTR(-EBUSY);
   710 }
   739 }
   711 
   740 
   712 /*****************************************************************************/
   741 /*****************************************************************************/