📄 io_edgeport.c
字号:
struct tty_struct *tty = edge_port->port->tty; if (!tty) return -ENOIOCTLCMD; result = tty->read_cnt; dbg("%s(%d) = %d", __FUNCTION__, edge_port->port->number, result); if (copy_to_user(value, &result, sizeof(int))) return -EFAULT; //return 0; return -ENOIOCTLCMD;}static int edge_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear){ struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int mcr; dbg("%s - port %d", __FUNCTION__, port->number); mcr = edge_port->shadowMCR; if (set & TIOCM_RTS) mcr |= MCR_RTS; if (set & TIOCM_DTR) mcr |= MCR_DTR; if (set & TIOCM_LOOP) mcr |= MCR_LOOPBACK; if (clear & TIOCM_RTS) mcr &= ~MCR_RTS; if (clear & TIOCM_DTR) mcr &= ~MCR_DTR; if (clear & TIOCM_LOOP) mcr &= ~MCR_LOOPBACK; edge_port->shadowMCR = mcr; send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); return 0;}static int edge_tiocmget(struct usb_serial_port *port, struct file *file){ struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int result = 0; unsigned int msr; unsigned int mcr; dbg("%s - port %d", __FUNCTION__, port->number); msr = edge_port->shadowMSR; mcr = edge_port->shadowMCR; result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ | ((mcr & MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ | ((msr & EDGEPORT_MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ | ((msr & EDGEPORT_MSR_CD) ? TIOCM_CAR: 0) /* 0x040 */ | ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ dbg("%s -- %x", __FUNCTION__, result); return result;}static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *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){ 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); struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial); int status; if ((!edge_serial->is_epic) || ((edge_serial->is_epic) && (edge_serial->epic_descriptor.Supports.IOSPChase))) { /* 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 ((!edge_serial->is_epic) || ((edge_serial->is_epic) && (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) { 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 =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -