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

📄 io_edgeport.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	tty = port->tty;	/* if we are implementing XON/XOFF, send the start character */	if (I_IXOFF(tty)) {		unsigned char start_char = START_CHAR(tty);		status = edge_write (port, 0, &start_char, 1);		if (status <= 0) {			return;		}	}	/* if we are implementing RTS/CTS, toggle that line */	if (tty->termios->c_cflag & CRTSCTS) {		edge_port->shadowMCR |= MCR_RTS;		status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);		if (status != 0) {			return;		}	}	return;}/***************************************************************************** * SerialSetTermios *	this function is called by the tty driver when it wants to change the termios structure *****************************************************************************/static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios){	struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);	struct tty_struct *tty = port->tty;	unsigned int cflag = tty->termios->c_cflag;	dbg(__FUNCTION__" - clfag %08x %08x iflag %08x %08x", 	    tty->termios->c_cflag,	    old_termios->c_cflag,	    RELEVANT_IFLAG(tty->termios->c_iflag),	    RELEVANT_IFLAG(old_termios->c_iflag)	   );	/* check that they really want us to change something */	if (old_termios) {		if ((cflag == old_termios->c_cflag) &&		    (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {			dbg(__FUNCTION__" - nothing to change");			return;		}	}	dbg(__FUNCTION__" - port %d", port->number);	if (edge_port == NULL)		return;	if (!edge_port->open) {		dbg (__FUNCTION__" - port not opened");		return;	}	/* change the port settings to the new ones specified */	change_port_settings (edge_port, old_termios);	return;}/***************************************************************************** * get_lsr_info - get line status register info * * Purpose: Let user call ioctl() to get info when the UART physically * 	    is emptied.  On bus types like RS485, the transmitter must * 	    release the bus after transmitting. This must be done when * 	    the transmit shift register is empty, not be done when the * 	    transmit holding register is empty.  This functionality * 	    allows an RS485 driver to be written in user space.  *****************************************************************************/static int get_lsr_info(struct edgeport_port *edge_port, unsigned int *value){	unsigned int result = 0;	if (edge_port->maxTxCredits == edge_port->txCredits &&	    edge_port->txfifo.count == 0) {		dbg(__FUNCTION__" -- Empty");		result = TIOCSER_TEMT;	}	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}static int get_number_bytes_avail(struct edgeport_port *edge_port, unsigned int *value){	unsigned int result = 0;	struct tty_struct *tty = edge_port->port->tty;	result = tty->read_cnt;	dbg(__FUNCTION__"(%d) = %d",  edge_port->port->number, result);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	//return 0;	return -ENOIOCTLCMD;}static int set_modem_info(struct edgeport_port *edge_port, unsigned int cmd, unsigned int *value){	unsigned int mcr = edge_port->shadowMCR;	unsigned int arg;	if (copy_from_user(&arg, value, sizeof(int)))		return -EFAULT;	switch (cmd) {		case TIOCMBIS:			if (arg & TIOCM_RTS)				mcr |= MCR_RTS;			if (arg & TIOCM_DTR)				mcr |= MCR_RTS;			if (arg & TIOCM_LOOP)				mcr |= MCR_LOOPBACK;			break;		case TIOCMBIC:			if (arg & TIOCM_RTS)				mcr &= ~MCR_RTS;			if (arg & TIOCM_DTR)				mcr &= ~MCR_RTS;			if (arg & TIOCM_LOOP)				mcr &= ~MCR_LOOPBACK;			break;		case TIOCMSET:			/* turn off the RTS and DTR and LOOPBACK 			 * and then only turn on what was asked to */			mcr &=  ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);			mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);			mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);			mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);			break;	}	edge_port->shadowMCR = mcr;	send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR);	return 0;}static int get_modem_info(struct edgeport_port *edge_port, unsigned int *value){	unsigned int result = 0;	unsigned int msr = edge_port->shadowMSR;	unsigned int mcr = edge_port->shadowMCR;	result = ((mcr & MCR_DTR)	? TIOCM_DTR: 0)	  /* 0x002 */		  | ((mcr & MCR_RTS)	? TIOCM_RTS: 0)   /* 0x004 */		  | ((msr & MSR_CTS)	? TIOCM_CTS: 0)   /* 0x020 */		  | ((msr & MSR_CD)	? TIOCM_CAR: 0)   /* 0x040 */		  | ((msr & MSR_RI)	? TIOCM_RI:  0)   /* 0x080 */		  | ((msr & MSR_DSR)	? TIOCM_DSR: 0);  /* 0x100 */	dbg(__FUNCTION__" -- %x", result);	if (copy_to_user(value, &result, sizeof(int)))		return -EFAULT;	return 0;}static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct * retinfo){	struct serial_struct tmp;	if (!retinfo)		return -EFAULT;	memset(&tmp, 0, sizeof(tmp));	tmp.type		= PORT_16550A;	tmp.line		= edge_port->port->serial->minor;	tmp.port		= edge_port->port->number;	tmp.irq			= 0;	tmp.flags		= ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;	tmp.xmit_fifo_size	= edge_port->maxTxCredits;	tmp.baud_base		= 9600;	tmp.close_delay		= 5*HZ;	tmp.closing_wait	= 30*HZ;//	tmp.custom_divisor	= state->custom_divisor;//	tmp.hub6		= state->hub6;//	tmp.io_type		= state->io_type;	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))		return -EFAULT;	return 0;}/***************************************************************************** * SerialIoctl *	this function handles any ioctl calls to the driver *****************************************************************************/static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg){	struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);	struct async_icount cnow;	struct async_icount cprev;	struct serial_icounter_struct icount;	dbg(__FUNCTION__" - port %d, cmd = 0x%x", port->number, cmd);	switch (cmd) {		// return number of bytes available		case TIOCINQ:			dbg(__FUNCTION__" (%d) TIOCINQ",  port->number);			return get_number_bytes_avail(edge_port, (unsigned int *) arg);			break;		case TIOCSERGETLSR:			dbg(__FUNCTION__" (%d) TIOCSERGETLSR",  port->number);			return get_lsr_info(edge_port, (unsigned int *) arg);			return 0;		case TIOCMBIS:		case TIOCMBIC:		case TIOCMSET:			dbg(__FUNCTION__" (%d) TIOCMSET/TIOCMBIC/TIOCMSET",  port->number);			return set_modem_info(edge_port, cmd, (unsigned int *) arg);		case TIOCMGET:  			dbg(__FUNCTION__" (%d) TIOCMGET",  port->number);			return get_modem_info(edge_port, (unsigned int *) arg);		case TIOCGSERIAL:			dbg(__FUNCTION__" (%d) TIOCGSERIAL",  port->number);			return get_serial_info(edge_port, (struct serial_struct *) arg);		case TIOCSSERIAL:			dbg(__FUNCTION__" (%d) TIOCSSERIAL",  port->number);			break;		case TIOCMIWAIT:			dbg(__FUNCTION__" (%d) TIOCMIWAIT",  port->number);			cprev = edge_port->icount;			while (1) {				interruptible_sleep_on(&edge_port->delta_msr_wait);				/* see if a signal did it */				if (signal_pending(current))					return -ERESTARTSYS;				cnow = edge_port->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;			}			/* NOTREACHED */			break;		case TIOCGICOUNT:			cnow = edge_port->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;			dbg(__FUNCTION__" (%d) TIOCGICOUNT RX=%d, TX=%d",  port->number, icount.rx, icount.tx );			if (copy_to_user((void *)arg, &icount, sizeof(icount)))				return -EFAULT;			return 0;	}	return -ENOIOCTLCMD;}/***************************************************************************** * SerialBreak *	this function sends a break to the port *****************************************************************************/static void edge_break (struct usb_serial_port *port, int break_state){	struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);	int status;	/* flush and chase */	edge_port->chaseResponsePending = TRUE;	dbg(__FUNCTION__" - Sending IOSP_CMD_CHASE_PORT");	status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);	if (status == 0) {		// block until chase finished		block_until_chase_response(edge_port);	} else {		edge_port->chaseResponsePending = FALSE;	}	if (break_state == -1) {		dbg(__FUNCTION__" - Sending IOSP_CMD_SET_BREAK");		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);	} else {		dbg(__FUNCTION__" - Sending IOSP_CMD_CLEAR_BREAK");		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);	}	if (status) {		dbg(__FUNCTION__" - error sending break set/clear command.");	}	return;}/***************************************************************************** * process_rcvd_data *	this function handles the data received on the bulk in pipe. *****************************************************************************/static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char * buffer, __u16 bufferLength){	struct usb_serial_port *port;	struct edgeport_port *edge_port;	struct tty_struct *tty;	__u16 lastBufferLength;	__u16 rxLen;	int i;	dbg(__FUNCTION__);	lastBufferLength = bufferLength + 1;	while (bufferLength > 0) {		/* failsafe incase we get a message that we don't understand */		if (lastBufferLength == bufferLength) {			dbg(__FUNCTION__" - stuck in loop, exiting it.");			break;		}		lastBufferLength = bufferLength;		switch (edge_serial->rxState) {			case EXPECT_HDR1:				edge_serial->rxHeader1 = *buffer;				++buffer;				--bufferLength;				if (bufferLength == 0) {					edge_serial->rxState = EXPECT_HDR2;					break;				}				/* otherwise, drop on through */			case EXPECT_HDR2:				edge_serial->rxHeader2 = *buffer;				++buffer;				--bufferLength;				dbg(__FUNCTION__" - Hdr1=%02X Hdr2=%02X", edge_serial->rxHeader1, edge_serial->rxHeader2);				// Process depending on whether this header is				// data or status				if (IS_CMD_STAT_HDR(edge_serial->rxHeader1)) {					// Decode this status header and goto EXPECT_HDR1 (if we					// can process the status with only 2 bytes), or goto					// EXPECT_HDR3 to get the third byte.					edge_serial->rxPort       = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);					edge_serial->rxStatusCode = IOSP_GET_STATUS_CODE(edge_serial->rxHeader1);					if (!IOSP_STATUS_IS_2BYTE(edge_serial->rxStatusCode)) {						// This status needs additional bytes. Save what we have						// and then wait for more data.						edge_serial->rxStatusParam = edge_serial->rxHeader2;						edge_serial->rxState = EXPECT_HDR3;						break;					}					// We have all the header bytes, process the status now					process_rcvd_status (edge_serial, edge_serial->rxHeader2, 0);					edge_serial->rxState = EXPECT_HDR1;					break;				} else {					edge_serial->rxPort = IOSP_GET_HDR_PORT(edge_serial->rxHeader1);					edge_serial->rxBytesRemaining = IOSP_GET_HDR_DATA_LEN(edge_serial->rxHeader1, edge_serial->rxHeader2);					dbg(__FUNCTION__" - Data for Port %u Len 

⌨️ 快捷键说明

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