static int citty_ioctl_tiocgicount(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct citty_port *citty = tty->driver_data; F_ENTER(); if (cmd == TIOCGICOUNT) { struct async_icount cnow = citty->icount; struct serial_icounter_struct icount; icount.cts = cnow.cts; icount.dsr = cnow.dsr; icount.rng = cnow.rng; icount.dcd = cnow.dcd; icount.rx = cnow.rx; icount.tx = cnow.tx; icount.frame = cnow.frame; icount.overrun = cnow.overrun; icount.parity = cnow.parity; icount.brk = cnow.brk; icount.buf_overrun = cnow.buf_overrun; if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) return -EFAULT; return 0; } F_LEAVE(); return -ENOIOCTLCMD; }
static void citty_close(struct tty_struct *tty, struct file *file) { struct citty_port *citty = NULL; int index = tty->index; F_ENTER(); down(&sem_lock_tty[index]); citty = citty_table[index]; /* Modified by Rovin Yu: release citty and related resource */ if (citty) { if (!citty->port->count) { /* port was never opened */ goto exit; } --citty->port->count; PDEBUG("citty_close: index is %d, count is %d\n", index, citty->port->count); if (citty->port->count <= 0) { citty_table[index] = NULL; kfree(citty); } } exit: up(&sem_lock_tty[index]); F_LEAVE(); }
/* the real citty_ioctl function. * The above is done to get the small functions*/ static int citty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct file *file = NULL; F_ENTER(); switch (cmd) { case TIOCGSERIAL: return citty_ioctl_tiocgserial(tty, file, cmd, arg); case TIOCMIWAIT: return citty_ioctl_tiocmiwait(tty, file, cmd, arg); case TIOCGICOUNT: return citty_ioctl_tiocgicount(tty, file, cmd, arg); case TCSETS: return citty_ioctl_tcsets(tty, file, cmd, arg); case TCGETS: /* 0x5401 ioctls.h */ return citty_ioctl_tcgets(tty, file, cmd, arg); case TCSETSF: /* 0x5404 */ case TCSETAF: /* 0x5408 */ return 0; /* has to return zero for qtopia to work */ default: PDEBUG("citty_ioctl cmd: %d.\n", cmd); return -ENOIOCTLCMD; /* for PPPD to work? */ break; } F_LEAVE(); }
int cctdev_open(struct inode *inode, struct file *filp) { struct cctdev_dev *dev; /* device information */ F_ENTER(); dev = container_of(inode->i_cdev, struct cctdev_dev, cdev); filp->private_data = dev; /* for other methods */ /* now trim to 0 the length of the device if open was write-only */ /* if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) { if (down_interruptible(&dev->sem)) return -ERESTARTSYS; up(&dev->sem); } */ /* used to keep track of how many readers */ down(&dev->sem); if (filp->f_mode & FMODE_READ) dev->nreaders++; if (filp->f_mode & FMODE_WRITE) dev->nwriters++; up(&dev->sem); F_LEAVE(); return nonseekable_open(inode, filp); /* success */ }
static int citty_write_room(struct tty_struct *tty) { struct citty_port *citty = NULL; int index = tty->index; int room = -EINVAL; F_ENTER(); down(&sem_lock_tty[index]); citty = citty_table[index]; if (!citty) { up(&sem_lock_tty[index]); return -ENODEV; } if (!citty->port->count) { PDEBUG("citty_write_room: no port is open."); /* port was not opened */ goto exit; } /* calculate how much room is left in the device */ /* CHECKPOINT */ /* room = CITTY_BUF_SIZE * spacefree( &txCittyBuf ); */ room = CITTY_BUF_SIZE * spacefree(&txCittyBuf[tty->index]); exit: up(&sem_lock_tty[index]); F_LEAVE(); return room; }
void cci_init_buffer(struct buf_struct *buffer) { int i; F_ENTER(); for (i = 0; i < NUM_CITTY_BUF; i++) { buffer->pBuf[i] = kmalloc(CITTY_BUF_SIZE, GFP_KERNEL); if (!buffer->pBuf[i]) printk(KERN_ERR "Failed to allocate memory.\n"); buffer->iBufIn = 0; buffer->iBufOut = 0; } sema_init(&(buffer->gSem), 1); /* init the queue */ init_waitqueue_head(&(buffer->gInq)); init_waitqueue_head(&(buffer->gOutq)); F_LEAVE(); }
static void do_close(struct cidatatty_port *cidatatty) { unsigned long flags; F_ENTER(); down(&cidatatty->sem_lock_tty); spin_lock_irqsave(&cidatatty->port_lock, flags); if (!cidatatty->port.count) { /* port was never opened */ goto exit; } --cidatatty->port.count; if (cidatatty->port.count <= 0) { /* The port is being closed by the last user. */ /* Do any hardware specific stuff here */ if (cidatatty->port.tty->index == PSDTTYINDEX) unregisterRxCallBack(PDP_PPP); else if (cidatatty->port.tty->index == CSDTTYINDEX) unregisterRxCallBack(CSD_RAW); else if (cidatatty->port.tty->index == IMSTTYINDEX) unregisterRxCallBack(IMS_RAW); } exit: spin_unlock_irqrestore(&cidatatty->port_lock, flags); up(&cidatatty->sem_lock_tty); PDEBUG("Leaving do_close: "); }
static void __exit citty_exit(void) { struct citty_serial *citty; int i; F_ENTER(); for (i = 0; i < CITTY_TTY_MINORS; ++i) tty_unregister_device(citty_tty_driver, i); tty_unregister_driver(citty_tty_driver); put_tty_driver(citty_tty_driver); /* free the memory */ for (i = 0; i < CITTY_TTY_MINORS; ++i) { down(&sem[i]); citty = citty_table[i]; if (citty) { kfree(citty); citty_table[i] = NULL; //cci_free_buffer(&txCittyBuf[i]); } up(&sem[i]); cci_free_buffer(&txCittyBuf[i]); //Modified by Rovin to move here } /* clean up for the cctdev stuff */ cctdev_cleanup_module(); F_LEAVE(); }
static void __exit cidatatty_exit(void) { struct cidatatty_port *cidatatty; int i; F_ENTER(); /* unregister device */ for (i = 0; i < CIDATATTY_TTY_MINORS; ++i) { cidatatty = cidatatty_table[i].data_port; if (cidatatty) { /* close the port */ while (cidatatty->port.count) do_close(cidatatty); cidatatty_table[i].data_port = NULL; tty_port_destroy(&cidatatty->port); kfree(cidatatty); } tty_unregister_device(cidatatty_tty_driver, i); } /* unregister driver */ tty_unregister_driver(cidatatty_tty_driver); cctdatadev_cleanup_module(); F_LEAVE(); }
static int citty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) #endif { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) struct file *file = NULL; #endif F_ENTER(); switch (cmd) { case TIOCGSERIAL: return citty_ioctl_tiocgserial(tty, file, cmd, arg); case TIOCMIWAIT: return citty_ioctl_tiocmiwait(tty, file, cmd, arg); case TIOCGICOUNT: return citty_ioctl_tiocgicount(tty, file, cmd, arg); case TCSETS: return citty_ioctl_tcsets(tty, file, cmd, arg); case TCGETS: //0x5401 ioctls.h return citty_ioctl_tcgets(tty, file, cmd, arg); case TCSETSF: //0x5404 case TCSETAF: //0x5408 return 0; //has to return zero for qtopia to work default: PDEBUG("citty_ioctl cmd: %d.\n", cmd); return -ENOIOCTLCMD; // for PPPD to work? break; } F_LEAVE(); }
static void __exit citty_exit(void) { struct citty_port *citty = NULL; int i; F_ENTER(); /* unregister devices */ for (i = 0; i < CITTY_TTY_MINORS; ++i) { down(&sem_lock_tty[i]); citty = citty_table[i]; if (citty) { citty_table[i] = NULL; kfree(citty); } up(&sem_lock_tty[i]); tty_port_destroy(&citty_port_table[i]); tty_unregister_device(citty_tty_driver, i); cci_free_buffer(&txCittyBuf[i]); } /* unregister driver */ tty_unregister_driver(citty_tty_driver); put_tty_driver(citty_tty_driver); /* clean up for the cctdev stuff */ cctdev_cleanup_module(); F_LEAVE(); }
unsigned int cctdev_poll(struct file *filp, poll_table *wait) { struct cctdev_dev *dev = filp->private_data; int minor_num; unsigned int mask = 0; F_ENTER(); minor_num = MINOR(dev->cdev.dev); down(&txCittyBuf[minor_num].gSem); poll_wait(filp, &txCittyBuf[minor_num].gInq, wait); if (txCittyBuf[minor_num].iBufOut != txCittyBuf[minor_num].iBufIn) mask |= POLLIN | POLLRDNORM; mask |= POLLOUT | POLLWRNORM; up(&txCittyBuf[minor_num].gSem); F_LEAVE(); return mask; }
static int __init citty_init(void) { int retval; int i; F_ENTER(); /* allocate the tty driver */ citty_tty_driver = alloc_tty_driver(CITTY_TTY_MINORS); if (!citty_tty_driver) return -ENOMEM; /* initialize the tty driver */ citty_tty_driver->owner = THIS_MODULE; citty_tty_driver->driver_name = "citty_tty"; citty_tty_driver->name = "citty"; citty_tty_driver->major = CITTY_TTY_MAJOR; citty_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; citty_tty_driver->subtype = SERIAL_TYPE_NORMAL; citty_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; citty_tty_driver->init_termios = tty_std_termios; /* B115200 | CS8 | CREAD | HUPCL | CLOCAL; */ citty_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; citty_tty_driver->init_termios.c_iflag = IGNBRK | IGNCR | IGNPAR; citty_tty_driver->init_termios.c_oflag = 0; citty_tty_driver->init_termios.c_lflag = 0; tty_set_operations(citty_tty_driver, &serial_ops); /* register the tty driver */ retval = tty_register_driver(citty_tty_driver); if (retval) { printk(KERN_ERR "failed to register citty tty driver"); put_tty_driver(citty_tty_driver); citty_tty_driver = NULL; return retval; } /* register tty devices */ for (i = 0; i < CITTY_TTY_MINORS; ++i) { /* Init buffer */ cci_init_buffer(&txCittyBuf[i]); sema_init(&sem_lock_tty[i], 1); tty_port_init(&citty_port_table[i]); tty_port_register_device(&citty_port_table[i], citty_tty_driver, i, NULL); } printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n"); cctdev_init_module(); F_LEAVE(); return retval; }
/******************************************************************* * FUNCTION: cctdev_write * * DESCRIPTION: Once data come, push it to the tty port * * * RETURNS: utlFAILED or utlSUCCESS * *******************************************************************/ ssize_t cctdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct cctdev_dev *dev = filp->private_data; int minor_num; int c; char *tbuf = NULL; /* send the data to the tty layer for users to read. * This doesn't * actually push the data through unless tty->low_latency is set */ struct citty_port *citty = NULL; struct tty_struct *tty = NULL; F_ENTER(); /* Extract Minor Number */ minor_num = MINOR(dev->cdev.dev); PDEBUG("cctdev_write: minor_num:%d\n", minor_num); mutex_lock(&mutex_lock_tty[minor_num]); /* * get the serial object associated with this tty pointer * always give the data to the first open Dev. */ citty = citty_table[minor_num]; PDEBUG("cctdev_write: citty: 0x%x, minor_num:%d\n", (unsigned long)citty, minor_num); if (!citty) { PDEBUG("Warning: citty is NULL.\n"); mutex_unlock(&mutex_lock_tty[minor_num]); return -ENODEV; } tty = citty->port->tty; if (!tty) { mutex_unlock(&mutex_lock_tty[minor_num]); return -ENODEV; } tbuf = memdup_user(buf, count); if (IS_ERR(tbuf)) { pr_warn("%s: memdup_user returned error[%ld]\n", __func__, PTR_ERR(tbuf)); mutex_unlock(&mutex_lock_tty[minor_num]); return PTR_ERR(tbuf); } c = tty->ldisc->ops->receive_buf2(tty, tbuf, NULL, count); kfree(tbuf); mutex_unlock(&mutex_lock_tty[minor_num]); return c; }
static void cidatatty_close(struct tty_struct *tty, struct file *file) { struct cidatatty_port *cidatatty = tty->driver_data; F_ENTER(); if (cidatatty) do_close(cidatatty); F_LEAVE(); }
static int citty_open(struct tty_struct *tty, struct file *file) { struct citty_serial *citty; int index; F_ENTER(); schedule(); /* initialize the pointer in case something fails */ tty->driver_data = NULL; /* get the serial object associated with this tty pointer */ index = tty->index; if (!cctdev_ready || (cctdev_devices[index].nreaders == 0 && cctdev_devices[index].nwriters == 0)) return -EAGAIN; down(&sem[index]); citty = citty_table[index]; if (citty == NULL) { /* first time accessing this device, let's create it */ citty = kmalloc(sizeof(*citty), GFP_KERNEL); if (!citty) { up(&sem[index]); return -ENOMEM; } citty->open_count = 0; citty_table[index] = citty; } /* save our structure within the tty structure */ tty->driver_data = citty; /* vcy */ tty->flags = TTY_NO_WRITE_SPLIT | tty->flags; citty->tty = tty; ++citty->open_count; if (citty->open_count == 1) { /* this is the first time this port is opened */ /* do any hardware initialization needed here */ } up(&sem[index]); F_LEAVE(); return 0; }
int data_rx_csd(char *packet, int len, unsigned char cid) { struct tty_struct *tty = NULL; struct cidatatty_port *cidatatty; int ret; F_ENTER(); if (!cidatatty_table[CSDTTYINDEX].data_port || cidatatty_table[CSDTTYINDEX].data_port->cid != cid || cidatatty_table[CSDTTYINDEX].data_port->devinuse != 1) { printk(KERN_ERR "data_rx_csd: not found tty device. cid = %d\n", cid); return 0; } else { tty = cidatatty_table[CSDTTYINDEX].data_port->port.tty; } if (!tty) { printk(KERN_ERR "data_rx_csd: tty device is null. cid = %d\n", cid); return 0; } cidatatty = tty->driver_data; /* drop packets if nobody uses cidatatty */ if (cidatatty == NULL) { printk(KERN_ERR "data_rx_csd: drop packets if nobody uses cidatatty. cid = %d\n", cid); return 0; } down(&cidatatty->sem_lock_tty); if (cidatatty->port.count == 0) { up(&cidatatty->sem_lock_tty); printk(KERN_ERR "data_rx_csd: cidatatty device is closed\n"); return 0; } ret = tty_insert_flip_string(&cidatatty->port, packet, len); tty_flip_buffer_push(&cidatatty->port); up(&cidatatty->sem_lock_tty); if (ret < len) printk(KERN_ERR "data_rx_csd: give up because receive_room left\n"); return ret; }
static int citty_write(struct tty_struct *tty, const unsigned char *buffer, int count) { struct citty_port *citty = NULL; int index = tty->index; int retval = -EINVAL; F_ENTER(); /* for some reason, this function is called with count == 0 */ if (count <= 0) { printk(KERN_ERR "Error: count is %d.\n", count); return 0; } down(&sem_lock_tty[index]); citty = citty_table[index]; if (!citty) { up(&sem_lock_tty[index]); PDEBUG("Warning: citty_write: citty is NULL\n"); return -ENODEV; } if (!citty->port->count) { printk(KERN_ERR "Error: citty_write: port was not open\n"); /* port was not opened */ goto exit; } #ifdef DEBUG_BUF_CONTENT /* int i; */ printk(KERN_DEBUG "CITTY Tx Buffer datalen is %d\n data:", count); for (i = 0; i < count; i++) printk(KERN_DEBUG "%02x(%c)", buffer[i]&0xff, buffer[i]&0xff); /* printk(KERN_DEBUG " %02x", buffer[i]&0xff ); */ printk(KERN_DEBUG "\n"); #endif /* * packet is ready for transmission: * write the packet to TxCitty buffer */ retval = write_citty_buffer(&txCittyBuf[tty->index], buffer, count, COPY_FROM_CITTY); exit: up(&sem_lock_tty[index]); F_LEAVE(); return retval; }
static int citty_open(struct tty_struct *tty, struct file *file) { struct citty_port *citty = NULL; int index = tty->index; F_ENTER(); schedule(); /* initialize the pointer in case something fails */ tty->driver_data = NULL; /* get the serial object associated with this tty pointer */ if (!cctdev_ready || (cctdev_devices[index].nreaders == 0 && cctdev_devices[index].nwriters == 0)) return -EAGAIN; mutex_lock(&mutex_lock_tty[index]); citty = citty_table[index]; if (!citty) { citty = kmalloc(sizeof(*citty), GFP_KERNEL); if (!citty) { mutex_unlock(&mutex_lock_tty[index]); return -ENOMEM; } /* save tty_port structure within the our structure */ citty_table[index] = citty; citty->port = &citty_port_table[index]; citty->port->count = 0; } /* do the real open operation */ /* save our structure within the tty structure */ tty->driver_data = citty; /* vcy */ tty->flags = TTY_NO_WRITE_SPLIT | tty->flags; /* save tty_struct within the tty_port structure */ citty->port->tty = tty; ++citty->port->count; if (citty->port->count == 1) { /* this is the first time this port is opened */ /* do any hardware initialization needed here */ } mutex_unlock(&mutex_lock_tty[index]); F_LEAVE(); return 0; }
static int citty_ioctl_tcgets(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { F_ENTER(); if (copy_to_user((void *)arg, tty->termios, sizeof(struct termios))) { printk("Failed to copy to user for tcgets.\n"); return -EFAULT; } F_LEAVE(); return 0; }
/******************************************************************* * FUNCTION: cctdev_write * * DESCRIPTION: Once data come, push it to the tty port * * * RETURNS: utlFAILED or utlSUCCESS * *******************************************************************/ ssize_t cctdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct cctdev_dev *dev = filp->private_data; int minor_num; int c; /* send the data to the tty layer for users to read. * This doesn't * actually push the data through unless tty->low_latency is set */ struct citty_port *citty = NULL; struct tty_struct *tty = NULL; F_ENTER(); /* Extract Minor Number */ minor_num = MINOR(dev->cdev.dev); PDEBUG("cctdev_write: minor_num:%d\n", minor_num); down(&sem_lock_tty[minor_num]); /* * get the serial object associated with this tty pointer * always give the data to the first open Dev. */ citty = citty_table[minor_num]; PDEBUG("cctdev_write: citty: 0x%x, minor_num:%d\n", (unsigned long)citty, minor_num); if (!citty) { PDEBUG("Warning: citty is NULL.\n"); up(&sem_lock_tty[minor_num]); return 0; } tty = citty->port->tty; if (!tty) { up(&sem_lock_tty[minor_num]); return 0; } c = tty->receive_room; if (c > count) c = count; tty->ldisc->ops->receive_buf(tty, buf, NULL, c); up(&sem_lock_tty[minor_num]); return c; }
/* * Set up the char_dev structure for this device. */ static void cctdev_setup_cdev(struct cctdev_dev *dev, int index) { int err, devno = MKDEV(cctdev_major, cctdev_minor + index); F_ENTER(); cdev_init(&dev->cdev, &cctdev_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &cctdev_fops; err = cdev_add(&dev->cdev, devno, 1); /* Fail gracefully if need be */ if (err) printk(KERN_NOTICE "Error %d adding cctdev%d", err, index); F_LEAVE(); }
static int citty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) #endif { struct citty_serial *citty = tty->driver_data; unsigned int mcr = citty->mcr; F_ENTER(); if (set & TIOCM_RTS) mcr |= MCR_RTS; if (set & TIOCM_DTR) mcr |= MCR_RTS; if (set & TIOCM_LOOP) mcr |= MCR_RTS; if (set & TIOCM_CTS) mcr |= MCR_RTS; if (set & TIOCM_RI) mcr |= MCR_RTS; if (set & TIOCM_DSR) mcr |= MCR_RTS; if (set & TIOCM_CAR) mcr |= MCR_RTS; if (clear & TIOCM_RTS) mcr &= ~MCR_RTS; if (clear & TIOCM_DTR) mcr &= ~MCR_RTS; if (clear & TIOCM_LOOP) mcr &= ~MCR_RTS; if (clear & TIOCM_CTS) mcr &= ~MCR_RTS; if (clear & TIOCM_CAR) mcr &= ~MCR_RTS; if (clear & TIOCM_RI) mcr &= ~MCR_RTS; if (clear & TIOCM_DSR) mcr &= ~MCR_RTS; /* set the new MCR value in the device */ citty->mcr = mcr; F_LEAVE(); return 0; }
static int citty_ioctl_tiocmiwait(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct citty_serial *citty = tty->driver_data; F_ENTER(); if (cmd == TIOCMIWAIT) { DECLARE_WAITQUEUE(wait, current); struct async_icount cnow; struct async_icount cprev; cprev = citty->icount; while (1) { add_wait_queue(&citty->wait, &wait); set_current_state(TASK_INTERRUPTIBLE); schedule(); remove_wait_queue(&citty->wait, &wait); /* see if a signal woke us up */ if (signal_pending(current)) return -ERESTARTSYS; cnow = citty->icount; if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { return 0; } cprev = cnow; } } F_LEAVE(); return -ENOIOCTLCMD; }
int cctdatadev_open(struct inode *inode, struct file *filp) { struct cctdatadev_dev *dev; F_ENTER(); #if 1 dev = container_of(inode->i_cdev, struct cctdatadev_dev, cdev); filp->private_data = dev; /* for other methods */ /* used to keep track of how many readers */ if (filp->f_mode & FMODE_READ) dev->nreaders++; if (filp->f_mode & FMODE_WRITE) dev->nwriters++; #endif F_LEAVE(); return nonseekable_open(inode, filp); /* success */ }
/******************************************************************* * FUNCTION: cctdev_read * * DESCRIPTION: To pass the data from TxBuffer to CI * * RETURNS: utlFAILED or utlSUCCESS * *******************************************************************/ ssize_t cctdev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct cctdev_dev *dev = filp->private_data; ssize_t retval = 0; int minor_num; F_ENTER(); /* Extract Minor Number*/ minor_num = MINOR(dev->cdev.dev); PDEBUG("txCittyBuf[%d].iBufOut: %d, iBufIn: %d\n", minor_num, txCittyBuf[minor_num].iBufOut, txCittyBuf[minor_num].iBufIn); retval = read_citty_buffer( buf, &txCittyBuf[minor_num], COPY_TO_USER); F_LEAVE(); return retval; }
static int citty_tiocmget(struct tty_struct *tty) { struct citty_port *citty = tty->driver_data; unsigned int result = 0; unsigned int msr = citty->msr; unsigned int mcr = citty->mcr; F_ENTER(); result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */ ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */ ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */ ((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */ ((msr & MSR_CD) ? TIOCM_CAR : 0) | /* CD is set */ ((msr & MSR_RI) ? TIOCM_RI : 0) | /* RI is set */ ((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */ F_LEAVE(); return result; }
static int citty_tiocmget(struct tty_struct *tty, struct file *file) #endif { struct citty_serial *citty = tty->driver_data; unsigned int result = 0; unsigned int msr = citty->msr; unsigned int mcr = citty->mcr; F_ENTER(); result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */ ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */ ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */ ((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */ ((msr & MSR_CD) ? TIOCM_CAR : 0) | /* Carrier detect is set*/ ((msr & MSR_RI) ? TIOCM_RI : 0) | /* Ring Indicator is set */ ((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */ F_LEAVE(); return result; }
int cctdev_open(struct inode *inode, struct file *filp) { struct cctdev_dev *dev; /* device information */ F_ENTER(); dev = container_of(inode->i_cdev, struct cctdev_dev, cdev); filp->private_data = dev; /* for other methods */ /* used to keep track of how many readers */ mutex_lock(&dev->lock); if (filp->f_mode & FMODE_READ) dev->nreaders++; if (filp->f_mode & FMODE_WRITE) dev->nwriters++; mutex_unlock(&dev->lock); F_LEAVE(); return nonseekable_open(inode, filp); /* success */ }
static int cidatatty_ioctl_tiocgserial(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct cidatatty_port *cidatatty = tty->driver_data; F_ENTER(); if (cmd == TIOCGSERIAL) { struct serial_struct tmp; if (!arg) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); tmp.type = cidatatty->serial.type; tmp.line = cidatatty->serial.line; tmp.port = cidatatty->serial.port; tmp.irq = cidatatty->serial.irq; tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; tmp.xmit_fifo_size = cidatatty->serial.xmit_fifo_size; tmp.baud_base = cidatatty->serial.baud_base; tmp.close_delay = 5 * HZ; tmp.closing_wait = 30 * HZ; tmp.custom_divisor = cidatatty->serial.custom_divisor; tmp.hub6 = cidatatty->serial.hub6; tmp.io_type = cidatatty->serial.io_type; if (copy_to_user ((void __user *)arg, &tmp, sizeof(struct serial_struct))) return -EFAULT; return 0; } F_LEAVE(); return -ENOIOCTLCMD; }