Revision f331110f vl.c
b/vl.c | ||
---|---|---|
1713 | 1713 |
|
1714 | 1714 |
#endif /* !defined(_WIN32) */ |
1715 | 1715 |
|
1716 |
#ifdef _WIN32 |
|
1717 |
typedef struct { |
|
1718 |
IOCanRWHandler *fd_can_read; |
|
1719 |
IOReadHandler *fd_read; |
|
1720 |
void *win_opaque; |
|
1721 |
int max_size; |
|
1722 |
HANDLE hcom, hrecv, hsend; |
|
1723 |
OVERLAPPED orecv, osend; |
|
1724 |
BOOL fpipe; |
|
1725 |
DWORD len; |
|
1726 |
} WinCharState; |
|
1727 |
|
|
1728 |
#define NSENDBUF 2048 |
|
1729 |
#define NRECVBUF 2048 |
|
1730 |
#define MAXCONNECT 1 |
|
1731 |
#define NTIMEOUT 5000 |
|
1732 |
|
|
1733 |
static int win_chr_poll(void *opaque); |
|
1734 |
static int win_chr_pipe_poll(void *opaque); |
|
1735 |
|
|
1736 |
static void win_chr_close2(WinCharState *s) |
|
1737 |
{ |
|
1738 |
if (s->hsend) { |
|
1739 |
CloseHandle(s->hsend); |
|
1740 |
s->hsend = NULL; |
|
1741 |
} |
|
1742 |
if (s->hrecv) { |
|
1743 |
CloseHandle(s->hrecv); |
|
1744 |
s->hrecv = NULL; |
|
1745 |
} |
|
1746 |
if (s->hcom) { |
|
1747 |
CloseHandle(s->hcom); |
|
1748 |
s->hcom = NULL; |
|
1749 |
} |
|
1750 |
if (s->fpipe) |
|
1751 |
qemu_del_polling_cb(win_chr_pipe_poll, s); |
|
1752 |
else |
|
1753 |
qemu_del_polling_cb(win_chr_poll, s); |
|
1754 |
} |
|
1755 |
|
|
1756 |
static void win_chr_close(CharDriverState *chr) |
|
1757 |
{ |
|
1758 |
WinCharState *s = chr->opaque; |
|
1759 |
win_chr_close2(s); |
|
1760 |
} |
|
1761 |
|
|
1762 |
static int win_chr_init(WinCharState *s, const char *filename) |
|
1763 |
{ |
|
1764 |
COMMCONFIG comcfg; |
|
1765 |
COMMTIMEOUTS cto = { 0, 0, 0, 0, 0}; |
|
1766 |
COMSTAT comstat; |
|
1767 |
DWORD size; |
|
1768 |
DWORD err; |
|
1769 |
|
|
1770 |
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); |
|
1771 |
if (!s->hsend) { |
|
1772 |
fprintf(stderr, "Failed CreateEvent\n"); |
|
1773 |
goto fail; |
|
1774 |
} |
|
1775 |
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL); |
|
1776 |
if (!s->hrecv) { |
|
1777 |
fprintf(stderr, "Failed CreateEvent\n"); |
|
1778 |
goto fail; |
|
1779 |
} |
|
1780 |
|
|
1781 |
s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, |
|
1782 |
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); |
|
1783 |
if (s->hcom == INVALID_HANDLE_VALUE) { |
|
1784 |
fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError()); |
|
1785 |
s->hcom = NULL; |
|
1786 |
goto fail; |
|
1787 |
} |
|
1788 |
|
|
1789 |
if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) { |
|
1790 |
fprintf(stderr, "Failed SetupComm\n"); |
|
1791 |
goto fail; |
|
1792 |
} |
|
1793 |
|
|
1794 |
ZeroMemory(&comcfg, sizeof(COMMCONFIG)); |
|
1795 |
size = sizeof(COMMCONFIG); |
|
1796 |
GetDefaultCommConfig(filename, &comcfg, &size); |
|
1797 |
comcfg.dcb.DCBlength = sizeof(DCB); |
|
1798 |
CommConfigDialog(filename, NULL, &comcfg); |
|
1799 |
|
|
1800 |
if (!SetCommState(s->hcom, &comcfg.dcb)) { |
|
1801 |
fprintf(stderr, "Failed SetCommState\n"); |
|
1802 |
goto fail; |
|
1803 |
} |
|
1804 |
|
|
1805 |
if (!SetCommMask(s->hcom, EV_ERR)) { |
|
1806 |
fprintf(stderr, "Failed SetCommMask\n"); |
|
1807 |
goto fail; |
|
1808 |
} |
|
1809 |
|
|
1810 |
cto.ReadIntervalTimeout = MAXDWORD; |
|
1811 |
if (!SetCommTimeouts(s->hcom, &cto)) { |
|
1812 |
fprintf(stderr, "Failed SetCommTimeouts\n"); |
|
1813 |
goto fail; |
|
1814 |
} |
|
1815 |
|
|
1816 |
if (!ClearCommError(s->hcom, &err, &comstat)) { |
|
1817 |
fprintf(stderr, "Failed ClearCommError\n"); |
|
1818 |
goto fail; |
|
1819 |
} |
|
1820 |
qemu_add_polling_cb(win_chr_poll, s); |
|
1821 |
return 0; |
|
1822 |
|
|
1823 |
fail: |
|
1824 |
win_chr_close2(s); |
|
1825 |
return -1; |
|
1826 |
} |
|
1827 |
|
|
1828 |
static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1) |
|
1829 |
{ |
|
1830 |
WinCharState *s = chr->opaque; |
|
1831 |
DWORD len, ret, size, err; |
|
1832 |
|
|
1833 |
len = len1; |
|
1834 |
ZeroMemory(&s->osend, sizeof(s->osend)); |
|
1835 |
s->osend.hEvent = s->hsend; |
|
1836 |
while (len > 0) { |
|
1837 |
if (s->hsend) |
|
1838 |
ret = WriteFile(s->hcom, buf, len, &size, &s->osend); |
|
1839 |
else |
|
1840 |
ret = WriteFile(s->hcom, buf, len, &size, NULL); |
|
1841 |
if (!ret) { |
|
1842 |
err = GetLastError(); |
|
1843 |
if (err == ERROR_IO_PENDING) { |
|
1844 |
ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE); |
|
1845 |
if (ret) { |
|
1846 |
buf += size; |
|
1847 |
len -= size; |
|
1848 |
} else { |
|
1849 |
break; |
|
1850 |
} |
|
1851 |
} else { |
|
1852 |
break; |
|
1853 |
} |
|
1854 |
} else { |
|
1855 |
buf += size; |
|
1856 |
len -= size; |
|
1857 |
} |
|
1858 |
} |
|
1859 |
return len1 - len; |
|
1860 |
} |
|
1861 |
|
|
1862 |
static int win_chr_read_poll(WinCharState *s) |
|
1863 |
{ |
|
1864 |
s->max_size = s->fd_can_read(s->win_opaque); |
|
1865 |
return s->max_size; |
|
1866 |
} |
|
1867 |
|
|
1868 |
static void win_chr_readfile(WinCharState *s) |
|
1869 |
{ |
|
1870 |
int ret, err; |
|
1871 |
uint8_t buf[1024]; |
|
1872 |
DWORD size; |
|
1873 |
|
|
1874 |
ZeroMemory(&s->orecv, sizeof(s->orecv)); |
|
1875 |
s->orecv.hEvent = s->hrecv; |
|
1876 |
ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv); |
|
1877 |
if (!ret) { |
|
1878 |
err = GetLastError(); |
|
1879 |
if (err == ERROR_IO_PENDING) { |
|
1880 |
ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE); |
|
1881 |
} |
|
1882 |
} |
|
1883 |
|
|
1884 |
if (size > 0) { |
|
1885 |
s->fd_read(s->win_opaque, buf, size); |
|
1886 |
} |
|
1887 |
} |
|
1888 |
|
|
1889 |
static void win_chr_read(WinCharState *s) |
|
1890 |
{ |
|
1891 |
if (s->len > s->max_size) |
|
1892 |
s->len = s->max_size; |
|
1893 |
if (s->len == 0) |
|
1894 |
return; |
|
1895 |
|
|
1896 |
win_chr_readfile(s); |
|
1897 |
} |
|
1898 |
|
|
1899 |
static int win_chr_poll(void *opaque) |
|
1900 |
{ |
|
1901 |
WinCharState *s = opaque; |
|
1902 |
COMSTAT status; |
|
1903 |
DWORD comerr; |
|
1904 |
|
|
1905 |
ClearCommError(s->hcom, &comerr, &status); |
|
1906 |
if (status.cbInQue > 0) { |
|
1907 |
s->len = status.cbInQue; |
|
1908 |
win_chr_read_poll(s); |
|
1909 |
win_chr_read(s); |
|
1910 |
return 1; |
|
1911 |
} |
|
1912 |
return 0; |
|
1913 |
} |
|
1914 |
|
|
1915 |
static void win_chr_add_read_handler(CharDriverState *chr, |
|
1916 |
IOCanRWHandler *fd_can_read, |
|
1917 |
IOReadHandler *fd_read, void *opaque) |
|
1918 |
{ |
|
1919 |
WinCharState *s = chr->opaque; |
|
1920 |
|
|
1921 |
s->fd_can_read = fd_can_read; |
|
1922 |
s->fd_read = fd_read; |
|
1923 |
s->win_opaque = opaque; |
|
1924 |
} |
|
1925 |
|
|
1926 |
CharDriverState *qemu_chr_open_win(const char *filename) |
|
1927 |
{ |
|
1928 |
CharDriverState *chr; |
|
1929 |
WinCharState *s; |
|
1930 |
|
|
1931 |
chr = qemu_mallocz(sizeof(CharDriverState)); |
|
1932 |
if (!chr) |
|
1933 |
return NULL; |
|
1934 |
s = qemu_mallocz(sizeof(WinCharState)); |
|
1935 |
if (!s) { |
|
1936 |
free(chr); |
|
1937 |
return NULL; |
|
1938 |
} |
|
1939 |
chr->opaque = s; |
|
1940 |
chr->chr_write = win_chr_write; |
|
1941 |
chr->chr_add_read_handler = win_chr_add_read_handler; |
|
1942 |
chr->chr_close = win_chr_close; |
|
1943 |
|
|
1944 |
if (win_chr_init(s, filename) < 0) { |
|
1945 |
free(s); |
|
1946 |
free(chr); |
|
1947 |
return NULL; |
|
1948 |
} |
|
1949 |
return chr; |
|
1950 |
} |
|
1951 |
|
|
1952 |
static int win_chr_pipe_poll(void *opaque) |
|
1953 |
{ |
|
1954 |
WinCharState *s = opaque; |
|
1955 |
DWORD size; |
|
1956 |
|
|
1957 |
PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL); |
|
1958 |
if (size > 0) { |
|
1959 |
s->len = size; |
|
1960 |
win_chr_read_poll(s); |
|
1961 |
win_chr_read(s); |
|
1962 |
return 1; |
|
1963 |
} |
|
1964 |
return 0; |
|
1965 |
} |
|
1966 |
|
|
1967 |
static int win_chr_pipe_init(WinCharState *s, const char *filename) |
|
1968 |
{ |
|
1969 |
OVERLAPPED ov; |
|
1970 |
int ret; |
|
1971 |
DWORD size; |
|
1972 |
char openname[256]; |
|
1973 |
|
|
1974 |
s->fpipe = TRUE; |
|
1975 |
|
|
1976 |
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); |
|
1977 |
if (!s->hsend) { |
|
1978 |
fprintf(stderr, "Failed CreateEvent\n"); |
|
1979 |
goto fail; |
|
1980 |
} |
|
1981 |
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL); |
|
1982 |
if (!s->hrecv) { |
|
1983 |
fprintf(stderr, "Failed CreateEvent\n"); |
|
1984 |
goto fail; |
|
1985 |
} |
|
1986 |
|
|
1987 |
snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename); |
|
1988 |
s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, |
|
1989 |
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | |
|
1990 |
PIPE_WAIT, |
|
1991 |
MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL); |
|
1992 |
if (s->hcom == INVALID_HANDLE_VALUE) { |
|
1993 |
fprintf(stderr, "Failed CreateNamedPipe (%lu)\n", GetLastError()); |
|
1994 |
s->hcom = NULL; |
|
1995 |
goto fail; |
|
1996 |
} |
|
1997 |
|
|
1998 |
ZeroMemory(&ov, sizeof(ov)); |
|
1999 |
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
|
2000 |
ret = ConnectNamedPipe(s->hcom, &ov); |
|
2001 |
if (ret) { |
|
2002 |
fprintf(stderr, "Failed ConnectNamedPipe\n"); |
|
2003 |
goto fail; |
|
2004 |
} |
|
2005 |
|
|
2006 |
ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE); |
|
2007 |
if (!ret) { |
|
2008 |
fprintf(stderr, "Failed GetOverlappedResult\n"); |
|
2009 |
if (ov.hEvent) { |
|
2010 |
CloseHandle(ov.hEvent); |
|
2011 |
ov.hEvent = NULL; |
|
2012 |
} |
|
2013 |
goto fail; |
|
2014 |
} |
|
2015 |
|
|
2016 |
if (ov.hEvent) { |
|
2017 |
CloseHandle(ov.hEvent); |
|
2018 |
ov.hEvent = NULL; |
|
2019 |
} |
|
2020 |
qemu_add_polling_cb(win_chr_pipe_poll, s); |
|
2021 |
return 0; |
|
2022 |
|
|
2023 |
fail: |
|
2024 |
win_chr_close2(s); |
|
2025 |
return -1; |
|
2026 |
} |
|
2027 |
|
|
2028 |
|
|
2029 |
CharDriverState *qemu_chr_open_win_pipe(const char *filename) |
|
2030 |
{ |
|
2031 |
CharDriverState *chr; |
|
2032 |
WinCharState *s; |
|
2033 |
|
|
2034 |
chr = qemu_mallocz(sizeof(CharDriverState)); |
|
2035 |
if (!chr) |
|
2036 |
return NULL; |
|
2037 |
s = qemu_mallocz(sizeof(WinCharState)); |
|
2038 |
if (!s) { |
|
2039 |
free(chr); |
|
2040 |
return NULL; |
|
2041 |
} |
|
2042 |
chr->opaque = s; |
|
2043 |
chr->chr_write = win_chr_write; |
|
2044 |
chr->chr_add_read_handler = win_chr_add_read_handler; |
|
2045 |
chr->chr_close = win_chr_close; |
|
2046 |
|
|
2047 |
if (win_chr_pipe_init(s, filename) < 0) { |
|
2048 |
free(s); |
|
2049 |
free(chr); |
|
2050 |
return NULL; |
|
2051 |
} |
|
2052 |
return chr; |
|
2053 |
} |
|
2054 |
|
|
2055 |
CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) |
|
2056 |
{ |
|
2057 |
CharDriverState *chr; |
|
2058 |
WinCharState *s; |
|
2059 |
|
|
2060 |
chr = qemu_mallocz(sizeof(CharDriverState)); |
|
2061 |
if (!chr) |
|
2062 |
return NULL; |
|
2063 |
s = qemu_mallocz(sizeof(WinCharState)); |
|
2064 |
if (!s) { |
|
2065 |
free(chr); |
|
2066 |
return NULL; |
|
2067 |
} |
|
2068 |
s->hcom = fd_out; |
|
2069 |
chr->opaque = s; |
|
2070 |
chr->chr_write = win_chr_write; |
|
2071 |
chr->chr_add_read_handler = win_chr_add_read_handler; |
|
2072 |
return chr; |
|
2073 |
} |
|
2074 |
|
|
2075 |
CharDriverState *qemu_chr_open_win_file_out(const char *file_out) |
|
2076 |
{ |
|
2077 |
HANDLE fd_out; |
|
2078 |
|
|
2079 |
fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL, |
|
2080 |
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
|
2081 |
if (fd_out == INVALID_HANDLE_VALUE) |
|
2082 |
return NULL; |
|
2083 |
|
|
2084 |
return qemu_chr_open_win_file(fd_out); |
|
2085 |
} |
|
2086 |
#endif |
|
2087 |
|
|
1716 | 2088 |
CharDriverState *qemu_chr_open(const char *filename) |
1717 | 2089 |
{ |
1718 |
#ifndef _WIN32 |
|
1719 | 2090 |
const char *p; |
1720 |
#endif |
|
1721 | 2091 |
|
1722 | 2092 |
if (!strcmp(filename, "vc")) { |
1723 | 2093 |
return text_console_init(&display_state); |
... | ... | |
1743 | 2113 |
return qemu_chr_open_tty(filename); |
1744 | 2114 |
} else |
1745 | 2115 |
#endif |
2116 |
#ifdef _WIN32 |
|
2117 |
if (strstart(filename, "COM", NULL)) { |
|
2118 |
return qemu_chr_open_win(filename); |
|
2119 |
} else |
|
2120 |
if (strstart(filename, "pipe:", &p)) { |
|
2121 |
return qemu_chr_open_win_pipe(p); |
|
2122 |
} else |
|
2123 |
if (strstart(filename, "file:", &p)) { |
|
2124 |
return qemu_chr_open_win_file_out(p); |
|
2125 |
} |
|
2126 |
#endif |
|
1746 | 2127 |
{ |
1747 | 2128 |
return NULL; |
1748 | 2129 |
} |
1749 | 2130 |
} |
1750 | 2131 |
|
2132 |
void qemu_chr_close(CharDriverState *chr) |
|
2133 |
{ |
|
2134 |
if (chr->chr_close) |
|
2135 |
chr->chr_close(chr); |
|
2136 |
} |
|
2137 |
|
|
1751 | 2138 |
/***********************************************************/ |
1752 | 2139 |
/* network device redirectors */ |
1753 | 2140 |
|
... | ... | |
3090 | 3477 |
} |
3091 | 3478 |
|
3092 | 3479 |
/***********************************************************/ |
3480 |
/* Polling handling */ |
|
3481 |
|
|
3482 |
typedef struct PollingEntry { |
|
3483 |
PollingFunc *func; |
|
3484 |
void *opaque; |
|
3485 |
struct PollingEntry *next; |
|
3486 |
} PollingEntry; |
|
3487 |
|
|
3488 |
static PollingEntry *first_polling_entry; |
|
3489 |
|
|
3490 |
int qemu_add_polling_cb(PollingFunc *func, void *opaque) |
|
3491 |
{ |
|
3492 |
PollingEntry **ppe, *pe; |
|
3493 |
pe = qemu_mallocz(sizeof(PollingEntry)); |
|
3494 |
if (!pe) |
|
3495 |
return -1; |
|
3496 |
pe->func = func; |
|
3497 |
pe->opaque = opaque; |
|
3498 |
for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next); |
|
3499 |
*ppe = pe; |
|
3500 |
return 0; |
|
3501 |
} |
|
3502 |
|
|
3503 |
void qemu_del_polling_cb(PollingFunc *func, void *opaque) |
|
3504 |
{ |
|
3505 |
PollingEntry **ppe, *pe; |
|
3506 |
for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) { |
|
3507 |
pe = *ppe; |
|
3508 |
if (pe->func == func && pe->opaque == opaque) { |
|
3509 |
*ppe = pe->next; |
|
3510 |
qemu_free(pe); |
|
3511 |
break; |
|
3512 |
} |
|
3513 |
} |
|
3514 |
} |
|
3515 |
|
|
3516 |
/***********************************************************/ |
|
3093 | 3517 |
/* savevm/loadvm support */ |
3094 | 3518 |
|
3095 | 3519 |
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) |
... | ... | |
3955 | 4379 |
fd_set rfds, wfds; |
3956 | 4380 |
int ret, nfds; |
3957 | 4381 |
struct timeval tv; |
4382 |
PollingEntry *pe; |
|
4383 |
|
|
3958 | 4384 |
|
4385 |
/* XXX: need to suppress polling by better using win32 events */ |
|
4386 |
ret = 0; |
|
4387 |
for(pe = first_polling_entry; pe != NULL; pe = pe->next) { |
|
4388 |
ret |= pe->func(pe->opaque); |
|
4389 |
} |
|
3959 | 4390 |
#ifdef _WIN32 |
3960 |
/* XXX: see how to merge it with the select. The constraint is |
|
3961 |
that the select must be interrupted by the timer */ |
|
3962 |
if (timeout > 0) |
|
4391 |
if (ret == 0 && timeout > 0) { |
|
3963 | 4392 |
Sleep(timeout); |
4393 |
} |
|
3964 | 4394 |
#endif |
3965 | 4395 |
/* poll any events */ |
3966 | 4396 |
/* XXX: separate device handlers from system ones */ |
Also available in: Unified diff