📄 serial.c
字号:
g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1); strcpy(g_rdpdr_device[*id].local_path, pos2); printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name, g_rdpdr_device[*id].local_path); /* set device type */ g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL; g_rdpdr_device[*id].pdevice_data = (void *) pser_inf; count++; (*id)++; optarg = pos; } return count;}static NTSTATUSserial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition, uint32 flags_and_attributes, char *filename, NTHANDLE * handle){ NTHANDLE serial_fd; SERIAL_DEVICE *pser_inf; struct termios *ptermios; pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[device_id].pdevice_data; ptermios = pser_inf->ptermios; serial_fd = open(g_rdpdr_device[device_id].local_path, O_RDWR | O_NOCTTY | O_NONBLOCK); if (serial_fd == -1) { perror("open"); return STATUS_ACCESS_DENIED; } if (!get_termios(pser_inf, serial_fd)) { printf("INFO: SERIAL %s access denied\n", g_rdpdr_device[device_id].name); fflush(stdout); return STATUS_ACCESS_DENIED; } /* Store handle for later use */ g_rdpdr_device[device_id].handle = serial_fd; /* some sane information */ DEBUG_SERIAL(("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u, rts %u\n", g_rdpdr_device[device_id].name, g_rdpdr_device[device_id].local_path, pser_inf->baud_rate, pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length, pser_inf->dtr, pser_inf->rts)); pser_inf->ptermios->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); pser_inf->ptermios->c_oflag &= ~OPOST; pser_inf->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); pser_inf->ptermios->c_cflag &= ~(CSIZE | PARENB); pser_inf->ptermios->c_cflag |= CS8; tcsetattr(serial_fd, TCSANOW, pser_inf->ptermios); pser_inf->event_txempty = 0; pser_inf->event_cts = 0; pser_inf->event_dsr = 0; pser_inf->event_rlsd = 0; pser_inf->event_pending = 0; *handle = serial_fd; /* all read and writes should be non blocking */ if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1) perror("fcntl"); pser_inf->read_total_timeout_constant = 5; return STATUS_SUCCESS;}static NTSTATUSserial_close(NTHANDLE handle){ int i = get_device_index(handle); if (i >= 0) g_rdpdr_device[i].handle = 0; rdpdr_abort_io(handle, 0, STATUS_TIMEOUT); close(handle); return STATUS_SUCCESS;}static NTSTATUSserial_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result){ long timeout; SERIAL_DEVICE *pser_inf; struct termios *ptermios;#ifdef WITH_DEBUG_SERIAL int bytes_inqueue;#endif timeout = 90; pser_inf = get_serial_info(handle); ptermios = pser_inf->ptermios; /* Set timeouts kind of like the windows serial timeout parameters. Multiply timeout with requested read size */ if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant) { timeout = (pser_inf->read_total_timeout_multiplier * length + pser_inf->read_total_timeout_constant + 99) / 100; } else if (pser_inf->read_interval_timeout) { timeout = (pser_inf->read_interval_timeout * length + 99) / 100; } /* If a timeout is set, do a blocking read, which times out after some time. It will make rdesktop less responsive, but it will improve serial performance, by not reading one character at a time. */ if (timeout == 0) { ptermios->c_cc[VTIME] = 0; ptermios->c_cc[VMIN] = 0; } else { ptermios->c_cc[VTIME] = timeout; ptermios->c_cc[VMIN] = 1; } tcsetattr(handle, TCSANOW, ptermios);#if defined(WITH_DEBUG_SERIAL) && defined(TIOCINQ) ioctl(handle, TIOCINQ, &bytes_inqueue); DEBUG_SERIAL(("serial_read inqueue: %d expected %d\n", bytes_inqueue, length));#endif *result = read(handle, data, length);#ifdef WITH_DEBUG_SERIAL DEBUG_SERIAL(("serial_read Bytes %d\n", *result)); if (*result > 0) hexdump(data, *result);#endif return STATUS_SUCCESS;}static NTSTATUSserial_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result){ SERIAL_DEVICE *pser_inf; pser_inf = get_serial_info(handle); *result = write(handle, data, length); if (*result > 0) pser_inf->event_txempty = *result; DEBUG_SERIAL(("serial_write length %d, offset %d result %d\n", length, offset, *result)); return STATUS_SUCCESS;}static NTSTATUSserial_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out){ int flush_mask, purge_mask; uint32 result, modemstate; uint8 immediate; SERIAL_DEVICE *pser_inf; struct termios *ptermios; if ((request >> 16) != FILE_DEVICE_SERIAL_PORT) return STATUS_INVALID_PARAMETER; pser_inf = get_serial_info(handle); ptermios = pser_inf->ptermios; /* extract operation */ request >>= 2; request &= 0xfff; switch (request) { case SERIAL_SET_BAUD_RATE: in_uint32_le(in, pser_inf->baud_rate); set_termios(pser_inf, handle); DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BAUD_RATE %d\n", pser_inf->baud_rate)); break; case SERIAL_GET_BAUD_RATE: out_uint32_le(out, pser_inf->baud_rate); DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_BAUD_RATE %d\n", pser_inf->baud_rate)); break; case SERIAL_SET_QUEUE_SIZE: in_uint32_le(in, pser_inf->queue_in_size); in_uint32_le(in, pser_inf->queue_out_size); DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d\n", pser_inf->queue_in_size, pser_inf->queue_out_size)); break; case SERIAL_SET_LINE_CONTROL: in_uint8(in, pser_inf->stop_bits); in_uint8(in, pser_inf->parity); in_uint8(in, pser_inf->word_length); set_termios(pser_inf, handle); DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d\n", pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length)); break; case SERIAL_GET_LINE_CONTROL: DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_LINE_CONTROL\n")); out_uint8(out, pser_inf->stop_bits); out_uint8(out, pser_inf->parity); out_uint8(out, pser_inf->word_length); break; case SERIAL_IMMEDIATE_CHAR: DEBUG_SERIAL(("serial_ioctl -> SERIAL_IMMEDIATE_CHAR\n")); in_uint8(in, immediate); serial_write(handle, &immediate, 1, 0, &result); break; case SERIAL_CONFIG_SIZE: DEBUG_SERIAL(("serial_ioctl -> SERIAL_CONFIG_SIZE\n")); out_uint32_le(out, 0); break; case SERIAL_GET_CHARS: DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_CHARS\n")); out_uint8a(out, pser_inf->chars, 6); break; case SERIAL_SET_CHARS: DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_CHARS\n")); in_uint8a(in, pser_inf->chars, 6);#ifdef WITH_DEBUG_SERIAL hexdump(pser_inf->chars, 6);#endif set_termios(pser_inf, handle); break; case SERIAL_GET_HANDFLOW: DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_HANDFLOW\n")); get_termios(pser_inf, handle); out_uint32_le(out, pser_inf->control); out_uint32_le(out, pser_inf->xonoff); /* Xon/Xoff */ out_uint32_le(out, pser_inf->onlimit); out_uint32_le(out, pser_inf->offlimit); break; case SERIAL_SET_HANDFLOW: in_uint32_le(in, pser_inf->control); in_uint32_le(in, pser_inf->xonoff); in_uint32_le(in, pser_inf->onlimit); in_uint32_le(in, pser_inf->offlimit); DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_HANDFLOW %x %x %x %x\n", pser_inf->control, pser_inf->xonoff, pser_inf->onlimit, pser_inf->onlimit)); set_termios(pser_inf, handle); break; case SERIAL_SET_TIMEOUTS: in_uint32(in, pser_inf->read_interval_timeout); in_uint32(in, pser_inf->read_total_timeout_multiplier); in_uint32(in, pser_inf->read_total_timeout_constant); in_uint32(in, pser_inf->write_total_timeout_multiplier); in_uint32(in, pser_inf->write_total_timeout_constant); DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d\n", pser_inf->read_interval_timeout, pser_inf->read_total_timeout_multiplier, pser_inf->read_total_timeout_constant)); break; case SERIAL_GET_TIMEOUTS: DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d\n", pser_inf->read_interval_timeout, pser_inf->read_total_timeout_multiplier, pser_inf->read_total_timeout_constant)); out_uint32(out, pser_inf->read_interval_timeout); out_uint32(out, pser_inf->read_total_timeout_multiplier); out_uint32(out, pser_inf->read_total_timeout_constant); out_uint32(out, pser_inf->write_total_timeout_multiplier); out_uint32(out, pser_inf->write_total_timeout_constant); break; case SERIAL_GET_WAIT_MASK: DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_WAIT_MASK %X\n", pser_inf->wait_mask)); out_uint32(out, pser_inf->wait_mask); break; case SERIAL_SET_WAIT_MASK: in_uint32(in, pser_inf->wait_mask); DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_WAIT_MASK %X\n", pser_inf->wait_mask)); break; case SERIAL_SET_DTR: DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_DTR\n")); ioctl(handle, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(handle, TIOCMSET, &result); pser_inf->dtr = 1; break; case SERIAL_CLR_DTR: DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_DTR\n")); ioctl(handle, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(handle, TIOCMSET, &result); pser_inf->dtr = 0; break; case SERIAL_SET_RTS: DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_RTS\n")); ioctl(handle, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(handle, TIOCMSET, &result); pser_inf->rts = 1; break; case SERIAL_CLR_RTS: DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_RTS\n")); ioctl(handle, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(handle, TIOCMSET, &result); pser_inf->rts = 0; break; case SERIAL_GET_MODEMSTATUS: modemstate = 0;#ifdef TIOCMGET ioctl(handle, TIOCMGET, &result); if (result & TIOCM_CTS) modemstate |= SERIAL_MS_CTS; if (result & TIOCM_DSR) modemstate |= SERIAL_MS_DSR; if (result & TIOCM_RNG) modemstate |= SERIAL_MS_RNG; if (result & TIOCM_CAR) modemstate |= SERIAL_MS_CAR; if (result & TIOCM_DTR) modemstate |= SERIAL_MS_DTR; if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS;#endif DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X\n", modemstate)); out_uint32_le(out, modemstate); break; case SERIAL_GET_COMMSTATUS: out_uint32_le(out, 0); /* Errors */ out_uint32_le(out, 0); /* Hold reasons */ result = 0;#ifdef TIOCINQ ioctl(handle, TIOCINQ, &result);#endif out_uint32_le(out, result); /* Amount in in queue */ if (result) DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d\n", result)); result = 0;#ifdef TIOCOUTQ ioctl(handle, TIOCOUTQ, &result);#endif out_uint32_le(out, result); /* Amount in out queue */ if (result) DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d\n", result)); out_uint8(out, 0); /* EofReceived */ out_uint8(out, 0); /* WaitForImmediate */ break; case SERIAL_PURGE: in_uint32(in, purge_mask); DEBUG_SERIAL(("serial_ioctl -> SERIAL_PURGE purge_mask %X\n", purge_mask)); flush_mask = 0; if (purge_mask & SERIAL_PURGE_TXCLEAR) flush_mask |= TCOFLUSH; if (purge_mask & SERIAL_PURGE_RXCLEAR) flush_mask |= TCIFLUSH; if (flush_mask != 0) tcflush(handle, flush_mask); if (purge_mask & SERIAL_PURGE_TXABORT) rdpdr_abort_io(handle, 4, STATUS_CANCELLED); if (purge_mask & SERIAL_PURGE_RXABORT) rdpdr_abort_io(handle, 3, STATUS_CANCELLED); break; case SERIAL_WAIT_ON_MASK: DEBUG_SERIAL(("serial_ioctl -> SERIAL_WAIT_ON_MASK %X\n", pser_inf->wait_mask)); pser_inf->event_pending = 1; if (serial_get_event(handle, &result)) { DEBUG_SERIAL(("WAIT end event = %x\n", result)); out_uint32_le(out, result); break; } return STATUS_PENDING; break; case SERIAL_SET_BREAK_ON: DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n")); tcsendbreak(handle, 0); break; case SERIAL_RESET_DEVICE: DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n")); break; case SERIAL_SET_BREAK_OFF: DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_OFF\n")); break; case SERIAL_SET_XOFF: DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XOFF\n")); break; case SERIAL_SET_XON: DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XON\n")); tcflow(handle, TCION); break; default: unimpl("SERIAL IOCTL %d\n", request); return STATUS_INVALID_PARAMETER; } return STATUS_SUCCESS;}BOOLserial_get_event(NTHANDLE handle, uint32 * result){ int index; SERIAL_DEVICE *pser_inf; int bytes; BOOL ret = False; *result = 0; index = get_device_index(handle); if (index < 0) return False;#ifdef TIOCINQ pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data; ioctl(handle, TIOCINQ, &bytes); if (bytes > 0) { DEBUG_SERIAL(("serial_get_event Bytes %d\n", bytes)); if (bytes > pser_inf->event_rlsd) { pser_inf->event_rlsd = bytes; if (pser_inf->wait_mask & SERIAL_EV_RLSD) { DEBUG_SERIAL(("Event -> SERIAL_EV_RLSD \n")); *result |= SERIAL_EV_RLSD; ret = True; } } if ((bytes > 1) && (pser_inf->wait_mask & SERIAL_EV_RXFLAG)) { DEBUG_SERIAL(("Event -> SERIAL_EV_RXFLAG Bytes %d\n", bytes)); *result |= SERIAL_EV_RXFLAG; ret = True; } if ((pser_inf->wait_mask & SERIAL_EV_RXCHAR)) { DEBUG_SERIAL(("Event -> SERIAL_EV_RXCHAR Bytes %d\n", bytes)); *result |= SERIAL_EV_RXCHAR; ret = True; } } else { pser_inf->event_rlsd = 0; }#endif#ifdef TIOCOUTQ ioctl(handle, TIOCOUTQ, &bytes); if ((bytes == 0) && (pser_inf->event_txempty > 0) && (pser_inf->wait_mask & SERIAL_EV_TXEMPTY)) { DEBUG_SERIAL(("Event -> SERIAL_EV_TXEMPTY\n")); *result |= SERIAL_EV_TXEMPTY; ret = True; } pser_inf->event_txempty = bytes;#endif ioctl(handle, TIOCMGET, &bytes); if ((bytes & TIOCM_DSR) != pser_inf->event_dsr) { pser_inf->event_dsr = bytes & TIOCM_DSR; if (pser_inf->wait_mask & SERIAL_EV_DSR) { DEBUG_SERIAL(("event -> SERIAL_EV_DSR %s\n", (bytes & TIOCM_DSR) ? "ON" : "OFF")); *result |= SERIAL_EV_DSR; ret = True; } } if ((bytes & TIOCM_CTS) != pser_inf->event_cts) { pser_inf->event_cts = bytes & TIOCM_CTS; if (pser_inf->wait_mask & SERIAL_EV_CTS) { DEBUG_SERIAL((" EVENT-> SERIAL_EV_CTS %s\n", (bytes & TIOCM_CTS) ? "ON" : "OFF")); *result |= SERIAL_EV_CTS; ret = True; } } if (ret) pser_inf->event_pending = 0; return ret;}/* Read timeout for a given file descripter (device) when adding fd's to select() */BOOLserial_get_timeout(NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout){ int index; SERIAL_DEVICE *pser_inf; index = get_device_index(handle); if (index < 0) return True; if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL) { return False; } pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data; *timeout = pser_inf->read_total_timeout_multiplier * length + pser_inf->read_total_timeout_constant; *itv_timeout = pser_inf->read_interval_timeout; return True;}DEVICE_FNS serial_fns = { serial_create, serial_close, serial_read, serial_write, serial_device_control};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -