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

📄 io_edgeport.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
{	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){	DEFINE_WAIT(wait);	struct edgeport_port *edge_port = usb_get_serial_port_data(port);	struct async_icount cnow;	struct async_icount cprev;	struct serial_icounter_struct icount;	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);	switch (cmd) {		// return number of bytes available		case TIOCINQ:			dbg("%s (%d) TIOCINQ", __FUNCTION__,  port->number);			return get_number_bytes_avail(edge_port, (unsigned int __user *) arg);			break;		case TIOCSERGETLSR:			dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__,  port->number);			return get_lsr_info(edge_port, (unsigned int __user *) arg);			return 0;		case TIOCGSERIAL:			dbg("%s (%d) TIOCGSERIAL", __FUNCTION__,  port->number);			return get_serial_info(edge_port, (struct serial_struct __user *) arg);		case TIOCSSERIAL:			dbg("%s (%d) TIOCSSERIAL", __FUNCTION__,  port->number);			break;		case TIOCMIWAIT:			dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);			cprev = edge_port->icount;			while (1) {				prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);				schedule();				finish_wait(&edge_port->delta_msr_wait, &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;			memset(&icount, 0, sizeof(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("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,  port->number, icount.rx, icount.tx );			if (copy_to_user((void __user *)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 = usb_get_serial_port_data(port);	int status;	/* flush and chase */	edge_port->chaseResponsePending = TRUE;	dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);	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("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__);		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);	} else {		dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__);		status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);	}	if (status) {		dbg("%s - error sending break set/clear command.", __FUNCTION__);	}	return;}/***************************************************************************** * process_rcvd_data *	this function handles the data received on the bulk in pipe. *****************************************************************************/static void 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;	dbg("%s", __FUNCTION__);	lastBufferLength = bufferLength + 1;	while (bufferLength > 0) {		/* failsafe incase we get a message that we don't understand */		if (lastBufferLength == bufferLength) {			dbg("%s - stuck in loop, exiting it.", __FUNCTION__);			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("%s - Hdr1=%02X Hdr2=%02X", __FUNCTION__, 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("%s - Data for Port %u Len %u", __FUNCTION__, edge_serial->rxPort, edge_serial->rxBytesRemaining);					//ASSERT( DevExt->RxPort < DevExt->NumPorts );					//ASSERT( DevExt->RxBytesRemaining < IOSP_MAX_DATA_LENGTH );					if (bufferLength == 0 ) {						edge_serial->rxState = EXPECT_DATA;						break;					}					// Else, drop through				}			case EXPECT_DATA:	// Expect data				if (bufferLength < edge_serial->rxBytesRemaining) {					rxLen = bufferLength;					edge_serial->rxState = EXPECT_DATA;	// Expect data to start next buffer				} else {					// BufLen >= RxBytesRemaining					rxLen = edge_serial->rxBytesRemaining;					edge_serial->rxState = EXPECT_HDR1;	// Start another header next time				}				bufferLength -= rxLen;				edge_serial->rxBytesRemaining -= rxLen;				/* spit this data back into the tty driver if this port is open */				if (rxLen) {					port = edge_serial->serial->port[edge_serial->rxPort];					edge_port = usb_get_serial_port_data(port);					if (edge_port->open) {						tty = edge_port->port->tty;						if (tty) {							dbg("%s - Sending %d bytes to TTY for port %d", __FUNCTION__, rxLen, edge_serial->rxPort);							edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen);						}						edge_port->icount.rx += rxLen;					}					buffer += rxLen;				}				break;			case EXPECT_HDR3:			// Expect 3rd byte of status header				edge_serial->rxHeader3 = *buffer;				++buffer;				--bufferLength;				// We have all the header bytes, process the status now				process_rcvd_status (edge_serial, edge_serial->rxStatusParam, edge_serial->rxHeader3);				edge_serial->rxState = EXPECT_HDR1;				break;		}	}}/***************************************************************************** * process_rcvd_status *	this function handles the any status messages received on the bulk in pipe. *****************************************************************************/static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3){	struct usb_serial_port *port;	struct edgeport_port *edge_port;	__u8 code = edge_serial->rxStatusCode;	/* switch the port pointer to the one being currently talked about */	port = edge_serial->serial->port[edge_serial->rxPort];	edge_port = usb_get_serial_port_data(port);	if (edge_port == NULL) {		dev_err(&edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __FUNCTION__, edge_serial->rxPort);		return;	}	dbg("%s - port %d", __FUNCTION__, edge_serial->rxPort);	if (code == IOSP_EXT_STATUS) {		switch (byte2) {			case IOSP_EXT_STATUS_CHASE_RSP:				// we want to do EXT status regardless of port open/closed 				dbg("%s - Port %u EXT CHASE_RSP Data = %02x", __FUNCTION__, edge_serial->rxPort, byte3 );				// Currently, the only EXT_STATUS is Chase, so process here instead of one more call				// to one more subroutine. If/when more EXT_STATUS, there'll be more work to do.				// Also, we currently clear flag and close the port regardless of content of above's Byte3.				// We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,				// like wait longer in block_until_chase_response, but for now we don't. 				edge_port->chaseResponsePending = FALSE;				wake_up (&edge_port->wait_chase);				return;			case IOSP_EXT_STATUS_RX_CHECK_RSP:				dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", __FUNCTION__, edge_serial->rxPort, byte3 );				//Port->RxCheckRsp = TRUE;				return;		}	}	if (code == IOSP_STATUS_OPEN_RSP) {		edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3);		edge_port->maxTxCredits = edge_port->txCredits;		dbg("%s - Port %u Open Response Inital MSR = %02x TxBufferSize = %d", __FUNCTION__, edge_serial->rxPort, byte2, edge_port->txCredits);		handle_new_msr (edge_port, byte2);		/* send the current line settings to the port so we are in sync with any further termios calls */		if (edge_port->port->tty)			change_port_settings (edge_port, edge_port->port->tty->termios);		/* we have completed the open */		edge_port->openPending = FALSE;		edge_port->open = TRUE;		wake_up(&edge_port->wait_open);		return;	}	// If port is closed, silently discard all rcvd status. We can	// have cases where buffered status is received AFTER the close	// port command is sent to the Edgeport.	if ((!edge_port->open ) || (edge_port->closePending)) {		return;	}	switch (code) {		// Not currently sent by Edgeport		case IOSP_STATUS_LSR:			dbg("%s - Port %u LSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);			handle_new_lsr (edge_port, FALSE, byte2, 0);			break;		case IOSP_STATUS_LSR_DATA:			dbg("%s - Port %u LSR Status = %02x, Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);			// byte2 is LSR Register			// byte3 is broken data byte			handle_new_lsr (edge_port, TRUE, byte2, byte3);			break;			//			//	case IOSP_EXT_4_STATUS:			//		dbg("%s - Port %u LSR Status = %02x Data = %02x", __FUNCTION__, edge_serial->rxPort, byte2, byte3);			//		break;			//		case IOSP_STATUS_MSR:			dbg("%s - Port %u MSR Status = %02x", __FUNCTION__, edge_serial->rxPort, byte2);			// Process this new modem status and generate appropriate			// events, etc, based on the new status. This routine			// also saves the MSR in Port->ShadowMsr.			handle_new_msr(edge_port, byte2);			break;		default:			dbg("%s - Unrecognized IOSP status code %u\n", __FUNCTION__, code);			break;	}	return;}/***************************************************************************** * edge_tty_recv *	this function passes data on to the tty flip buffer *****************************************************************************/static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length){	int cnt;	do {		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {			tty_flip_buffer_push(tty);			if (tty->flip.count >= TTY_FLIPBUF_SIZE) {				dev_err(dev, "%s - dropping data, %d bytes lost\n",					__FUNCTION__, length);				return;			}

⌨️ 快捷键说明

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