4 * Copyright (c) 2003-2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 #include "qemu/osdep.h"
25 #include "qemu-common.h"
26 #include "qapi/error.h"
29 static void win_chr_readfile(Chardev
*chr
)
31 WinChardev
*s
= WIN_CHARDEV(chr
);
34 uint8_t buf
[CHR_READ_BUF_LEN
];
37 ZeroMemory(&s
->orecv
, sizeof(s
->orecv
));
38 s
->orecv
.hEvent
= s
->hrecv
;
39 ret
= ReadFile(s
->hcom
, buf
, s
->len
, &size
, &s
->orecv
);
42 if (err
== ERROR_IO_PENDING
) {
43 ret
= GetOverlappedResult(s
->hcom
, &s
->orecv
, &size
, TRUE
);
48 qemu_chr_be_write(chr
, buf
, size
);
52 static void win_chr_read(Chardev
*chr
)
54 WinChardev
*s
= WIN_CHARDEV(chr
);
56 if (s
->len
> s
->max_size
) {
63 win_chr_readfile(chr
);
66 static int win_chr_read_poll(Chardev
*chr
)
68 WinChardev
*s
= WIN_CHARDEV(chr
);
70 s
->max_size
= qemu_chr_be_can_write(chr
);
74 static int win_chr_poll(void *opaque
)
76 Chardev
*chr
= CHARDEV(opaque
);
77 WinChardev
*s
= WIN_CHARDEV(opaque
);
81 ClearCommError(s
->hcom
, &comerr
, &status
);
82 if (status
.cbInQue
> 0) {
83 s
->len
= status
.cbInQue
;
84 win_chr_read_poll(chr
);
91 int win_chr_init(Chardev
*chr
, const char *filename
, Error
**errp
)
93 WinChardev
*s
= WIN_CHARDEV(chr
);
95 COMMTIMEOUTS cto
= { 0, 0, 0, 0, 0};
100 s
->hsend
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
102 error_setg(errp
, "Failed CreateEvent");
105 s
->hrecv
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
107 error_setg(errp
, "Failed CreateEvent");
111 s
->hcom
= CreateFile(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
112 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
113 if (s
->hcom
== INVALID_HANDLE_VALUE
) {
114 error_setg(errp
, "Failed CreateFile (%lu)", GetLastError());
119 if (!SetupComm(s
->hcom
, NRECVBUF
, NSENDBUF
)) {
120 error_setg(errp
, "Failed SetupComm");
124 ZeroMemory(&comcfg
, sizeof(COMMCONFIG
));
125 size
= sizeof(COMMCONFIG
);
126 GetDefaultCommConfig(filename
, &comcfg
, &size
);
127 comcfg
.dcb
.DCBlength
= sizeof(DCB
);
128 CommConfigDialog(filename
, NULL
, &comcfg
);
130 if (!SetCommState(s
->hcom
, &comcfg
.dcb
)) {
131 error_setg(errp
, "Failed SetCommState");
135 if (!SetCommMask(s
->hcom
, EV_ERR
)) {
136 error_setg(errp
, "Failed SetCommMask");
140 cto
.ReadIntervalTimeout
= MAXDWORD
;
141 if (!SetCommTimeouts(s
->hcom
, &cto
)) {
142 error_setg(errp
, "Failed SetCommTimeouts");
146 if (!ClearCommError(s
->hcom
, &err
, &comstat
)) {
147 error_setg(errp
, "Failed ClearCommError");
150 qemu_add_polling_cb(win_chr_poll
, chr
);
157 int win_chr_pipe_poll(void *opaque
)
159 Chardev
*chr
= CHARDEV(opaque
);
160 WinChardev
*s
= WIN_CHARDEV(opaque
);
163 PeekNamedPipe(s
->hcom
, NULL
, 0, NULL
, &size
, NULL
);
166 win_chr_read_poll(chr
);
173 /* Called with chr_write_lock held. */
174 static int win_chr_write(Chardev
*chr
, const uint8_t *buf
, int len1
)
176 WinChardev
*s
= WIN_CHARDEV(chr
);
177 DWORD len
, ret
, size
, err
;
180 ZeroMemory(&s
->osend
, sizeof(s
->osend
));
181 s
->osend
.hEvent
= s
->hsend
;
184 ret
= WriteFile(s
->hcom
, buf
, len
, &size
, &s
->osend
);
186 ret
= WriteFile(s
->hcom
, buf
, len
, &size
, NULL
);
189 err
= GetLastError();
190 if (err
== ERROR_IO_PENDING
) {
191 ret
= GetOverlappedResult(s
->hcom
, &s
->osend
, &size
, TRUE
);
209 static void char_win_finalize(Object
*obj
)
211 Chardev
*chr
= CHARDEV(obj
);
212 WinChardev
*s
= WIN_CHARDEV(chr
);
219 CloseHandle(s
->hsend
);
222 CloseHandle(s
->hrecv
);
225 CloseHandle(s
->hcom
);
228 qemu_del_polling_cb(win_chr_pipe_poll
, chr
);
230 qemu_del_polling_cb(win_chr_poll
, chr
);
233 qemu_chr_be_event(chr
, CHR_EVENT_CLOSED
);
236 void qemu_chr_open_win_file(Chardev
*chr
, HANDLE fd_out
)
238 WinChardev
*s
= WIN_CHARDEV(chr
);
244 static void char_win_class_init(ObjectClass
*oc
, void *data
)
246 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
248 cc
->chr_write
= win_chr_write
;
251 static const TypeInfo char_win_type_info
= {
252 .name
= TYPE_CHARDEV_WIN
,
253 .parent
= TYPE_CHARDEV
,
254 .instance_size
= sizeof(WinChardev
),
255 .instance_finalize
= char_win_finalize
,
256 .class_init
= char_win_class_init
,
260 static void register_types(void)
262 type_register_static(&char_win_type_info
);
265 type_init(register_types
);