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
25 #include "qemu/osdep.h"
26 #include "qemu/main-loop.h"
27 #include "qemu/module.h"
28 #include "qapi/error.h"
29 #include "chardev/char-win.h"
31 static void win_chr_read(Chardev
*chr
, DWORD len
)
33 WinChardev
*s
= WIN_CHARDEV(chr
);
34 int max_size
= qemu_chr_be_can_write(chr
);
36 uint8_t buf
[CHR_READ_BUF_LEN
];
46 ZeroMemory(&s
->orecv
, sizeof(s
->orecv
));
47 s
->orecv
.hEvent
= s
->hrecv
;
48 ret
= ReadFile(s
->file
, buf
, len
, &size
, &s
->orecv
);
51 if (err
== ERROR_IO_PENDING
) {
52 ret
= GetOverlappedResult(s
->file
, &s
->orecv
, &size
, TRUE
);
57 qemu_chr_be_write(chr
, buf
, size
);
61 static int win_chr_serial_poll(void *opaque
)
63 Chardev
*chr
= CHARDEV(opaque
);
64 WinChardev
*s
= WIN_CHARDEV(opaque
);
68 ClearCommError(s
->file
, &comerr
, &status
);
69 if (status
.cbInQue
> 0) {
70 win_chr_read(chr
, status
.cbInQue
);
76 int win_chr_serial_init(Chardev
*chr
, const char *filename
, Error
**errp
)
78 WinChardev
*s
= WIN_CHARDEV(chr
);
80 COMMTIMEOUTS cto
= { 0, 0, 0, 0, 0};
85 s
->hsend
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
87 error_setg(errp
, "Failed CreateEvent");
90 s
->hrecv
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
92 error_setg(errp
, "Failed CreateEvent");
96 s
->file
= CreateFile(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
97 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
98 if (s
->file
== INVALID_HANDLE_VALUE
) {
99 error_setg_win32(errp
, GetLastError(), "Failed CreateFile");
104 if (!SetupComm(s
->file
, NRECVBUF
, NSENDBUF
)) {
105 error_setg(errp
, "Failed SetupComm");
109 ZeroMemory(&comcfg
, sizeof(COMMCONFIG
));
110 size
= sizeof(COMMCONFIG
);
111 GetDefaultCommConfig(filename
, &comcfg
, &size
);
112 comcfg
.dcb
.DCBlength
= sizeof(DCB
);
113 CommConfigDialog(filename
, NULL
, &comcfg
);
115 if (!SetCommState(s
->file
, &comcfg
.dcb
)) {
116 error_setg(errp
, "Failed SetCommState");
120 if (!SetCommMask(s
->file
, EV_ERR
)) {
121 error_setg(errp
, "Failed SetCommMask");
125 cto
.ReadIntervalTimeout
= MAXDWORD
;
126 if (!SetCommTimeouts(s
->file
, &cto
)) {
127 error_setg(errp
, "Failed SetCommTimeouts");
131 if (!ClearCommError(s
->file
, &err
, &comstat
)) {
132 error_setg(errp
, "Failed ClearCommError");
135 qemu_add_polling_cb(win_chr_serial_poll
, chr
);
142 int win_chr_pipe_poll(void *opaque
)
144 Chardev
*chr
= CHARDEV(opaque
);
145 WinChardev
*s
= WIN_CHARDEV(opaque
);
148 PeekNamedPipe(s
->file
, NULL
, 0, NULL
, &size
, NULL
);
150 win_chr_read(chr
, size
);
156 /* Called with chr_write_lock held. */
157 static int win_chr_write(Chardev
*chr
, const uint8_t *buf
, int len1
)
159 WinChardev
*s
= WIN_CHARDEV(chr
);
160 DWORD len
, ret
, size
, err
;
163 ZeroMemory(&s
->osend
, sizeof(s
->osend
));
164 s
->osend
.hEvent
= s
->hsend
;
167 ret
= WriteFile(s
->file
, buf
, len
, &size
, &s
->osend
);
169 ret
= WriteFile(s
->file
, buf
, len
, &size
, NULL
);
172 err
= GetLastError();
173 if (err
== ERROR_IO_PENDING
) {
174 ret
= GetOverlappedResult(s
->file
, &s
->osend
, &size
, TRUE
);
192 static void char_win_finalize(Object
*obj
)
194 Chardev
*chr
= CHARDEV(obj
);
195 WinChardev
*s
= WIN_CHARDEV(chr
);
198 CloseHandle(s
->hsend
);
201 CloseHandle(s
->hrecv
);
203 if (!s
->keep_open
&& s
->file
) {
204 CloseHandle(s
->file
);
207 qemu_del_polling_cb(win_chr_pipe_poll
, chr
);
209 qemu_del_polling_cb(win_chr_serial_poll
, chr
);
212 qemu_chr_be_event(chr
, CHR_EVENT_CLOSED
);
215 void win_chr_set_file(Chardev
*chr
, HANDLE file
, bool keep_open
)
217 WinChardev
*s
= WIN_CHARDEV(chr
);
219 s
->keep_open
= keep_open
;
223 static void char_win_class_init(ObjectClass
*oc
, void *data
)
225 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
227 cc
->chr_write
= win_chr_write
;
230 static const TypeInfo char_win_type_info
= {
231 .name
= TYPE_CHARDEV_WIN
,
232 .parent
= TYPE_CHARDEV
,
233 .instance_size
= sizeof(WinChardev
),
234 .instance_finalize
= char_win_finalize
,
235 .class_init
= char_win_class_init
,
239 static void register_types(void)
241 type_register_static(&char_win_type_info
);
244 type_init(register_types
);