/* * function_felica_uart */ static ssize_t felica_uart_write(struct file *filp, const char __user *data, size_t len, loff_t *ppos) { ssize_t result; struct file *tty; result = uart_write(filp, data, len, ppos); if (result > 0) { MFCUART_DRV_DBG_LOG("tty_wait_until_sent"); tty = (struct file *)filp->private_data; if (tty) { tty_wait_until_sent(file_tty(tty), 0); } } return result; }
struct file *ptmx_open(int index, unsigned int flags) { struct file *file; struct file **stack = NULL; int depth = 0; for (;;) { struct tty_struct *tty; file = filp_open("/dev/ptmx", flags|O_NONBLOCK|O_NOCTTY|O_RDWR, 0); if (IS_ERR(file)) break; tty = file_tty(file); if (tty->index == index) break; if (depth == PAGE_SIZE/sizeof(struct file *)) { fput(file); file = ERR_PTR(-EBUSY); break; } if (stack == NULL) { stack = (struct file **)__get_free_page(GFP_KERNEL); if (!stack) { fput(file); file = ERR_PTR(-ENOMEM); break; } } stack[depth] = file; depth++; } while (depth > 0) { depth--; fput(stack[depth]); } if (stack) free_page((unsigned long)stack); return file; }
struct file * rst_open_tty(cpt_object_t *mntobj, char *name, struct cpt_file_image *fi, struct cpt_inode_image *ii, unsigned flags, struct cpt_context *ctx) { int err; cpt_object_t *obj; struct file *master, *slave; struct tty_struct *stty; struct cpt_tty_image *pi; static char *a = "pqrstuvwxyzabcde"; static char *b = "0123456789abcdef"; char pairname[16]; unsigned master_flags, slave_flags; if (fi->cpt_priv == CPT_NULL) return ERR_PTR(-EINVAL); obj = lookup_cpt_obj_bypos(CPT_OBJ_TTY, fi->cpt_priv, ctx); if (obj && obj->o_parent) { dprintk_ctx("obtained pty as pair to existing\n"); master = obj->o_parent; stty = file_tty(master); if (stty->driver->subtype == PTY_TYPE_MASTER && (stty->driver->flags&TTY_DRIVER_DEVPTS_MEM)) { wprintk_ctx("cloning ptmx\n"); get_file(master); return master; } master = dentry_open(dget(master->f_dentry), mntget(master->f_vfsmnt), flags, current_cred()); if (!IS_ERR(master)) { stty = file_tty(master); if (stty->driver->subtype != PTY_TYPE_MASTER) fixup_tty_attrs(ii, master, ctx); } return master; } pi = cpt_get_buf(ctx); err = rst_get_object(CPT_OBJ_TTY, fi->cpt_priv, pi, ctx); if (err) { cpt_release_buf(ctx); return ERR_PTR(err); } if (MAJOR(ii->cpt_rdev) == TTY_MAJOR || ii->cpt_rdev == MKDEV(TTYAUX_MAJOR, 1)) { if (mntobj && (mntobj->o_flags & CPT_VFSMOUNT_DELAYFS)) return ERR_PTR(-ENOTSUPP); master = rst_open_file(mntobj, name, fi, flags|O_NONBLOCK|O_NOCTTY, ctx); if (IS_ERR(master)) { eprintk_ctx("rst_open_tty: %s %Ld %ld\n", name, (long long)fi->cpt_priv, PTR_ERR(master)); return master; } stty = file_tty(master); obj = cpt_object_add(CPT_OBJ_TTY, stty, ctx); obj->o_parent = master; cpt_obj_setpos(obj, fi->cpt_priv, ctx); obj = cpt_object_add(CPT_OBJ_FILE, master, ctx); cpt_obj_setpos(obj, CPT_NULL, ctx); get_file(master); /* Do not restore /dev/ttyX state */ cpt_release_buf(ctx); return master; } master_flags = slave_flags = 0; if (pi->cpt_drv_subtype == PTY_TYPE_MASTER) master_flags = flags; else slave_flags = flags; /* * Open pair master/slave. */ if (pi->cpt_drv_flags&TTY_DRIVER_DEVPTS_MEM) { master = ptmx_open(pi->cpt_index, master_flags); } else { sprintf(pairname, "/dev/pty%c%c", a[pi->cpt_index/16], b[pi->cpt_index%16]); master = filp_open(pairname, master_flags|O_NONBLOCK|O_NOCTTY|O_RDWR, 0); } if (IS_ERR(master)) { eprintk_ctx("filp_open master: %Ld %ld\n", (long long)fi->cpt_priv, PTR_ERR(master)); cpt_release_buf(ctx); return master; } stty = file_tty(master); clear_bit(TTY_PTY_LOCK, &stty->flags); if (pi->cpt_drv_flags&TTY_DRIVER_DEVPTS_MEM) sprintf(pairname, "/dev/pts/%d", stty->index); else sprintf(pairname, "/dev/tty%c%c", a[stty->index/16], b[stty->index%16]); slave = filp_open(pairname, slave_flags|O_NONBLOCK|O_NOCTTY|O_RDWR, 0); if (IS_ERR(slave)) { eprintk_ctx("filp_open slave %s: %ld\n", pairname, PTR_ERR(slave)); fput(master); cpt_release_buf(ctx); return slave; } if (pi->cpt_drv_subtype != PTY_TYPE_MASTER) fixup_tty_attrs(ii, slave, ctx); cpt_object_add(CPT_OBJ_TTY, file_tty(master), ctx); cpt_object_add(CPT_OBJ_TTY, file_tty(slave), ctx); cpt_object_add(CPT_OBJ_FILE, master, ctx); cpt_object_add(CPT_OBJ_FILE, slave, ctx); if (pi->cpt_drv_subtype == PTY_TYPE_MASTER) { loff_t pos; obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(master), ctx); obj->o_parent = master; cpt_obj_setpos(obj, fi->cpt_priv, ctx); pty_setup(stty, fi->cpt_priv, pi, ctx); obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(slave), ctx); obj->o_parent = slave; pos = find_pty_pair(stty->link, fi->cpt_priv, pi, ctx); cpt_obj_setpos(obj, pos, ctx); obj = lookup_cpt_object(CPT_OBJ_FILE, slave, ctx); cpt_obj_setpos(obj, CPT_NULL, ctx); get_file(master); cpt_release_buf(ctx); return master; } else { loff_t pos; obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(slave), ctx); obj->o_parent = slave; cpt_obj_setpos(obj, fi->cpt_priv, ctx); pty_setup(stty->link, fi->cpt_priv, pi, ctx); obj = lookup_cpt_object(CPT_OBJ_TTY, file_tty(master), ctx); obj->o_parent = master; pos = find_pty_pair(stty, fi->cpt_priv, pi, ctx); cpt_obj_setpos(obj, pos, ctx); obj = lookup_cpt_object(CPT_OBJ_FILE, master, ctx); cpt_obj_setpos(obj, CPT_NULL, ctx); get_file(slave); cpt_release_buf(ctx); return slave; } }