⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interface.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * interface to user space for the gigaset driver * * Copyright (c) 2004 by Hansjoerg Lipp <hjlipp@web.de> * * ===================================================================== *    This program is free software; you can redistribute it and/or *    modify it under the terms of the GNU General Public License as *    published by the Free Software Foundation; either version 2 of *    the License, or (at your option) any later version. * ===================================================================== */#include "gigaset.h"#include <linux/gigaset_dev.h>#include <linux/tty.h>#include <linux/tty_flip.h>/*** our ioctls ***/static int if_lock(struct cardstate *cs, int *arg){	int cmd = *arg;	gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);	if (cmd > 1)		return -EINVAL;	if (cmd < 0) {		*arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove?		return 0;	}	if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED	    && cs->connected) {		cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);		cs->ops->baud_rate(cs, B115200);		cs->ops->set_line_ctrl(cs, CS8);		cs->control_state = TIOCM_DTR|TIOCM_RTS;	}	cs->waiting = 1;	if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK,			       NULL, cmd, NULL)) {		cs->waiting = 0;		return -ENOMEM;	}	gig_dbg(DEBUG_CMD, "scheduling IF_LOCK");	gigaset_schedule_event(cs);	wait_event(cs->waitqueue, !cs->waiting);	if (cs->cmd_result >= 0) {		*arg = cs->cmd_result;		return 0;	}	return cs->cmd_result;}static int if_version(struct cardstate *cs, unsigned arg[4]){	static const unsigned version[4] = GIG_VERSION;	static const unsigned compat[4] = GIG_COMPAT;	unsigned cmd = arg[0];	gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);	switch (cmd) {	case GIGVER_DRIVER:		memcpy(arg, version, sizeof version);		return 0;	case GIGVER_COMPAT:		memcpy(arg, compat, sizeof compat);		return 0;	case GIGVER_FWBASE:		cs->waiting = 1;		if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER,				       NULL, 0, arg)) {			cs->waiting = 0;			return -ENOMEM;		}		gig_dbg(DEBUG_CMD, "scheduling IF_VER");		gigaset_schedule_event(cs);		wait_event(cs->waitqueue, !cs->waiting);		if (cs->cmd_result >= 0)			return 0;		return cs->cmd_result;	default:		return -EINVAL;	}}static int if_config(struct cardstate *cs, int *arg){	gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg);	if (*arg != 1)		return -EINVAL;	if (atomic_read(&cs->mstate) != MS_LOCKED)		return -EBUSY;	if (!cs->connected) {		err("not connected!");		return -ENODEV;	}	*arg = 0;	return gigaset_enterconfigmode(cs);}/*** the terminal driver ***//* stolen from usbserial and some other tty drivers */static int  if_open(struct tty_struct *tty, struct file *filp);static void if_close(struct tty_struct *tty, struct file *filp);static int  if_ioctl(struct tty_struct *tty, struct file *file,		     unsigned int cmd, unsigned long arg);static int  if_write_room(struct tty_struct *tty);static int  if_chars_in_buffer(struct tty_struct *tty);static void if_throttle(struct tty_struct *tty);static void if_unthrottle(struct tty_struct *tty);static void if_set_termios(struct tty_struct *tty, struct termios *old);static int  if_tiocmget(struct tty_struct *tty, struct file *file);static int  if_tiocmset(struct tty_struct *tty, struct file *file,			unsigned int set, unsigned int clear);static int  if_write(struct tty_struct *tty,		     const unsigned char *buf, int count);static struct tty_operations if_ops = {	.open =			if_open,	.close =		if_close,	.ioctl =		if_ioctl,	.write =		if_write,	.write_room =		if_write_room,	.chars_in_buffer =	if_chars_in_buffer,	.set_termios =		if_set_termios,	.throttle =		if_throttle,	.unthrottle =		if_unthrottle,#if 0	.break_ctl =		serial_break,#endif	.tiocmget =		if_tiocmget,	.tiocmset =		if_tiocmset,};static int if_open(struct tty_struct *tty, struct file *filp){	struct cardstate *cs;	unsigned long flags;	gig_dbg(DEBUG_IF, "%d+%d: %s()",		tty->driver->minor_start, tty->index, __func__);	tty->driver_data = NULL;	cs = gigaset_get_cs_by_tty(tty);	if (!cs)		return -ENODEV;	if (mutex_lock_interruptible(&cs->mutex))		return -ERESTARTSYS; // FIXME -EINTR?	tty->driver_data = cs;	++cs->open_count;	if (cs->open_count == 1) {		spin_lock_irqsave(&cs->lock, flags);		cs->tty = tty;		spin_unlock_irqrestore(&cs->lock, flags);		tty->low_latency = 1; //FIXME test	}	mutex_unlock(&cs->mutex);	return 0;}static void if_close(struct tty_struct *tty, struct file *filp){	struct cardstate *cs;	unsigned long flags;	cs = (struct cardstate *) tty->driver_data;	if (!cs) {		err("cs==NULL in %s", __func__);		return;	}	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);	mutex_lock(&cs->mutex);	if (!cs->open_count)		warn("%s: device not opened", __func__);	else {		if (!--cs->open_count) {			spin_lock_irqsave(&cs->lock, flags);			cs->tty = NULL;			spin_unlock_irqrestore(&cs->lock, flags);		}	}	mutex_unlock(&cs->mutex);}static int if_ioctl(struct tty_struct *tty, struct file *file,		    unsigned int cmd, unsigned long arg){	struct cardstate *cs;	int retval = -ENODEV;	int int_arg;	unsigned char buf[6];	unsigned version[4];	cs = (struct cardstate *) tty->driver_data;	if (!cs) {		err("cs==NULL in %s", __func__);		return -ENODEV;	}	gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd);	if (mutex_lock_interruptible(&cs->mutex))		return -ERESTARTSYS; // FIXME -EINTR?	if (!cs->open_count)		warn("%s: device not opened", __func__);	else {		retval = 0;		switch (cmd) {		case GIGASET_REDIR:			retval = get_user(int_arg, (int __user *) arg);			if (retval >= 0)				retval = if_lock(cs, &int_arg);			if (retval >= 0)				retval = put_user(int_arg, (int __user *) arg);			break;		case GIGASET_CONFIG:			retval = get_user(int_arg, (int __user *) arg);			if (retval >= 0)				retval = if_config(cs, &int_arg);			if (retval >= 0)				retval = put_user(int_arg, (int __user *) arg);			break;		case GIGASET_BRKCHARS:			//FIXME test if MS_LOCKED			if (!cs->connected) {				gig_dbg(DEBUG_ANY,				    "can't communicate with unplugged device");				retval = -ENODEV;				break;			}			retval = copy_from_user(&buf,					(const unsigned char __user *) arg, 6)				? -EFAULT : 0;			if (retval >= 0) {				gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS",						6, (const unsigned char *) arg);				retval = cs->ops->brkchars(cs, buf);			}			break;		case GIGASET_VERSION:			retval = copy_from_user(version,					(unsigned __user *) arg, sizeof version)				? -EFAULT : 0;			if (retval >= 0)				retval = if_version(cs, version);			if (retval >= 0)				retval = copy_to_user((unsigned __user *) arg,						      version, sizeof version)					? -EFAULT : 0;			break;		default:			gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x",				__func__, cmd);			retval = -ENOIOCTLCMD;		}	}	mutex_unlock(&cs->mutex);	return retval;}static int if_tiocmget(struct tty_struct *tty, struct file *file){	struct cardstate *cs;	int retval;	cs = (struct cardstate *) tty->driver_data;	if (!cs) {		err("cs==NULL in %s", __func__);		return -ENODEV;	}	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);	if (mutex_lock_interruptible(&cs->mutex))		return -ERESTARTSYS; // FIXME -EINTR?	// FIXME read from device?	retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);	mutex_unlock(&cs->mutex);	return retval;}static int if_tiocmset(struct tty_struct *tty, struct file *file,		       unsigned int set, unsigned int clear){	struct cardstate *cs;	int retval;	unsigned mc;	cs = (struct cardstate *) tty->driver_data;	if (!cs) {		err("cs==NULL in %s", __func__);		return -ENODEV;	}	gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)",		cs->minor_index, __func__, set, clear);	if (mutex_lock_interruptible(&cs->mutex))		return -ERESTARTSYS; // FIXME -EINTR?	if (!cs->connected) {		gig_dbg(DEBUG_ANY, "can't communicate with unplugged device");		retval = -ENODEV;	} else {		mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR);		retval = cs->ops->set_modem_ctrl(cs, cs->control_state, mc);		cs->control_state = mc;	}	mutex_unlock(&cs->mutex);	return retval;}static int if_write(struct tty_struct *tty, const unsigned char *buf, int count){	struct cardstate *cs;	int retval = -ENODEV;	cs = (struct cardstate *) tty->driver_data;	if (!cs) {		err("cs==NULL in %s", __func__);		return -ENODEV;	}	gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);	if (mutex_lock_interruptible(&cs->mutex))		return -ERESTARTSYS; // FIXME -EINTR?

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -