?? vl.c
字號:
return; } if (size > 0) { if (qemu_chr_can_read(chr) > 0) { qemu_chr_read(chr, buf, 1); } else if (term_fifo_size == 0) { term_fifo[term_fifo_size++] = buf[0]; } }}/* init terminal so that we can grab keys */static struct termios oldtty;static int old_fd0_flags;static void term_exit(void){ tcsetattr (0, TCSANOW, &oldtty); fcntl(0, F_SETFL, old_fd0_flags);}static void term_init(void){ struct termios tty; tcgetattr (0, &tty); oldtty = tty; old_fd0_flags = fcntl(0, F_GETFL); tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); tty.c_oflag |= OPOST; tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); /* if graphical mode, we allow Ctrl-C handling */ if (nographic) tty.c_lflag &= ~ISIG; tty.c_cflag &= ~(CSIZE|PARENB); tty.c_cflag |= CS8; tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; tcsetattr (0, TCSANOW, &tty); atexit(term_exit); fcntl(0, F_SETFL, O_NONBLOCK);}static CharDriverState *qemu_chr_open_stdio(void){ CharDriverState *chr; if (stdio_nb_clients >= STDIO_MAX_CLIENTS) return NULL; chr = qemu_chr_open_fd(0, 1); qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr); stdio_nb_clients++; term_init(); return chr;}#if defined(__linux__) || defined(__sun__)static CharDriverState *qemu_chr_open_pty(void){ struct termios tty; char slave_name[1024]; int master_fd, slave_fd;#if defined(__linux__) /* Not satisfying */ if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) { return NULL; }#endif /* Disabling local echo and line-buffered output */ tcgetattr (master_fd, &tty); tty.c_lflag &= ~(ECHO|ICANON|ISIG); tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; tcsetattr (master_fd, TCSAFLUSH, &tty); fprintf(stderr, "char device redirected to %s\n", slave_name); return qemu_chr_open_fd(master_fd, master_fd);}static void tty_serial_init(int fd, int speed, int parity, int data_bits, int stop_bits){ struct termios tty; speed_t spd;#if 0 printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", speed, parity, data_bits, stop_bits);#endif tcgetattr (fd, &tty); switch(speed) { case 50: spd = B50; break; case 75: spd = B75; break; case 300: spd = B300; break; case 600: spd = B600; break; case 1200: spd = B1200; break; case 2400: spd = B2400; break; case 4800: spd = B4800; break; case 9600: spd = B9600; break; case 19200: spd = B19200; break; case 38400: spd = B38400; break; case 57600: spd = B57600; break; default: case 115200: spd = B115200; break; } cfsetispeed(&tty, spd); cfsetospeed(&tty, spd); tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); tty.c_oflag |= OPOST; tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB); switch(data_bits) { default: case 8: tty.c_cflag |= CS8; break; case 7: tty.c_cflag |= CS7; break; case 6: tty.c_cflag |= CS6; break; case 5: tty.c_cflag |= CS5; break; } switch(parity) { default: case 'N': break; case 'E': tty.c_cflag |= PARENB; break; case 'O': tty.c_cflag |= PARENB | PARODD; break; } if (stop_bits == 2) tty.c_cflag |= CSTOPB; tcsetattr (fd, TCSANOW, &tty);}static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg){ FDCharDriver *s = chr->opaque; switch(cmd) { case CHR_IOCTL_SERIAL_SET_PARAMS: { QEMUSerialSetParams *ssp = arg; tty_serial_init(s->fd_in, ssp->speed, ssp->parity, ssp->data_bits, ssp->stop_bits); } break; case CHR_IOCTL_SERIAL_SET_BREAK: { int enable = *(int *)arg; if (enable) tcsendbreak(s->fd_in, 1); } break; default: return -ENOTSUP; } return 0;}static CharDriverState *qemu_chr_open_tty(const char *filename){ CharDriverState *chr; int fd; TFR(fd = open(filename, O_RDWR | O_NONBLOCK)); fcntl(fd, F_SETFL, O_NONBLOCK); tty_serial_init(fd, 115200, 'N', 8, 1); chr = qemu_chr_open_fd(fd, fd); if (!chr) { close(fd); return NULL; } chr->chr_ioctl = tty_serial_ioctl; qemu_chr_reset(chr); return chr;}#else /* ! __linux__ && ! __sun__ */static CharDriverState *qemu_chr_open_pty(void){ return NULL;}#endif /* __linux__ || __sun__ */#if defined(__linux__)typedef struct { int fd; int mode;} ParallelCharDriver;static int pp_hw_mode(ParallelCharDriver *s, uint16_t mode){ if (s->mode != mode) { int m = mode; if (ioctl(s->fd, PPSETMODE, &m) < 0) return 0; s->mode = mode; } return 1;}static int pp_ioctl(CharDriverState *chr, int cmd, void *arg){ ParallelCharDriver *drv = chr->opaque; int fd = drv->fd; uint8_t b; switch(cmd) { case CHR_IOCTL_PP_READ_DATA: if (ioctl(fd, PPRDATA, &b) < 0) return -ENOTSUP; *(uint8_t *)arg = b; break; case CHR_IOCTL_PP_WRITE_DATA: b = *(uint8_t *)arg; if (ioctl(fd, PPWDATA, &b) < 0) return -ENOTSUP; break; case CHR_IOCTL_PP_READ_CONTROL: if (ioctl(fd, PPRCONTROL, &b) < 0) return -ENOTSUP; /* Linux gives only the lowest bits, and no way to know data direction! For better compatibility set the fixed upper bits. */ *(uint8_t *)arg = b | 0xc0; break; case CHR_IOCTL_PP_WRITE_CONTROL: b = *(uint8_t *)arg; if (ioctl(fd, PPWCONTROL, &b) < 0) return -ENOTSUP; break; case CHR_IOCTL_PP_READ_STATUS: if (ioctl(fd, PPRSTATUS, &b) < 0) return -ENOTSUP; *(uint8_t *)arg = b; break; case CHR_IOCTL_PP_EPP_READ_ADDR: if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) { struct ParallelIOArg *parg = arg; int n = read(fd, parg->buffer, parg->count); if (n != parg->count) { return -EIO; } } break; case CHR_IOCTL_PP_EPP_READ: if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) { struct ParallelIOArg *parg = arg; int n = read(fd, parg->buffer, parg->count); if (n != parg->count) { return -EIO; } } break; case CHR_IOCTL_PP_EPP_WRITE_ADDR: if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) { struct ParallelIOArg *parg = arg; int n = write(fd, parg->buffer, parg->count); if (n != parg->count) { return -EIO; } } break; case CHR_IOCTL_PP_EPP_WRITE: if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) { struct ParallelIOArg *parg = arg; int n = write(fd, parg->buffer, parg->count); if (n != parg->count) { return -EIO; } } break; default: return -ENOTSUP; } return 0;}static void pp_close(CharDriverState *chr){ ParallelCharDriver *drv = chr->opaque; int fd = drv->fd; pp_hw_mode(drv, IEEE1284_MODE_COMPAT); ioctl(fd, PPRELEASE); close(fd); qemu_free(drv);}static CharDriverState *qemu_chr_open_pp(const char *filename){ CharDriverState *chr; ParallelCharDriver *drv; int fd; TFR(fd = open(filename, O_RDWR)); if (fd < 0) return NULL; if (ioctl(fd, PPCLAIM) < 0) { close(fd); return NULL; } drv = qemu_mallocz(sizeof(ParallelCharDriver)); if (!drv) { close(fd); return NULL; } drv->fd = fd; drv->mode = IEEE1284_MODE_COMPAT; chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) { qemu_free(drv); close(fd); return NULL; } chr->chr_write = null_chr_write; chr->chr_ioctl = pp_ioctl; chr->chr_close = pp_close; chr->opaque = drv; qemu_chr_reset(chr); return chr;}#endif /* __linux__ */#else /* _WIN32 */typedef struct { int max_size; HANDLE hcom, hrecv, hsend; OVERLAPPED orecv, osend; BOOL fpipe; DWORD len;} WinCharState;#define NSENDBUF 2048#define NRECVBUF 2048#define MAXCONNECT 1#define NTIMEOUT 5000static int win_chr_poll(void *opaque);static int win_chr_pipe_poll(void *opaque);static void win_chr_close(CharDriverState *chr){ WinCharState *s = chr->opaque; if (s->hsend) { CloseHandle(s->hsend); s->hsend = NULL; } if (s->hrecv) { CloseHandle(s->hrecv); s->hrecv = NULL; } if (s->hcom) { CloseHandle(s->hcom); s->hcom = NULL; } if (s->fpipe) qemu_del_polling_cb(win_chr_pipe_poll, chr); else qemu_del_polling_cb(win_chr_poll, chr);}static int win_chr_init(CharDriverState *chr, const char *filename){ WinCharState *s = chr->opaque; COMMCONFIG comcfg; COMMTIMEOUTS cto = { 0, 0, 0, 0, 0}; COMSTAT comstat; DWORD size; DWORD err; s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); if (!s->hsend) { fprintf(stderr, "Failed CreateEvent\n"); goto fail; } s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL); if (!s->hrecv) { fprintf(stderr, "Failed CreateEvent\n"); goto fail; } s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); if (s->hcom == INVALID_HANDLE_VALUE) { fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError()); s->hcom = NULL; goto fail; } if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) { fprintf(stderr, "Failed SetupComm\n"); goto fail; } ZeroMemory(&comcfg, sizeof(COMMCONFIG)); size = sizeof(COMMCONFIG); GetDefaultCommConfig(filename, &comcfg, &size); comcfg.dcb.DCBlength = sizeof(DCB); CommConfigDialog(filename, NULL, &comcfg); if (!SetCommState(s->hcom, &comcfg.dcb)) { fprintf(stderr, "Failed SetCommState\n"); goto fail; } if (!SetCommMask(s->hcom, EV_ERR)) { fprintf(stderr, "Failed SetCommMask\n"); goto fail; } cto.ReadIntervalTimeout = MAXDWORD; if (!SetCommTimeouts(s->hcom, &cto)) { fprintf(stderr, "Failed SetCommTimeouts\n"); goto fail; } if (!ClearCommError(s->hcom, &err, &comstat)) { fprintf(stderr, "Failed ClearCommError\n"); goto fail; } qemu_add_polling_cb(win_chr_poll, chr); return 0; fail: win_chr_close(chr); return -1;}static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1){ WinCharState *s = chr->opaque; DWORD len, ret, size, err; len = len1; ZeroMemory(&s->osend, sizeof(s->osend)); s->osend.hEvent = s->hsend; while (len > 0) { if (s->hsend) ret = WriteFile(s->hcom, buf, len, &size, &s->osend); else ret = WriteFile(s->hcom, buf, len, &size, NULL); if (!ret) { err = GetLastError(); if (err == ERROR_IO_PENDING) { ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE); if (ret) { buf += size; len -= size; } else { break; } } else { break; } } else { buf += size; len -= size; } } return len1 - len;}static int win_chr_read_poll(CharDriverState *chr){ WinCharState *s = chr->opaque; s->max_size = qemu_chr_can_read(chr); return s->max_size;}static void win_chr_readfile(CharDriverState *chr){ WinCharState *s = chr->opaque; int ret, err; uint8_t buf[1024]; DWORD size; ZeroMemory(&s->orecv, sizeof(s->orecv)); s->orecv.hEvent = s->hrecv; ret = ReadFile(s->hcom, buf, s->len, &size, &
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -