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"
27 #include "chardev/char-win.h"
29 static void win_chr_read(Chardev
*chr
, DWORD len
)
31 WinChardev
*s
= WIN_CHARDEV(chr
);
32 int max_size
= qemu_chr_be_can_write(chr
);
34 uint8_t buf
[CHR_READ_BUF_LEN
];
44 ZeroMemory(&s
->orecv
, sizeof(s
->orecv
));
45 s
->orecv
.hEvent
= s
->hrecv
;
46 ret
= ReadFile(s
->file
, buf
, len
, &size
, &s
->orecv
);
49 if (err
== ERROR_IO_PENDING
) {
50 ret
= GetOverlappedResult(s
->file
, &s
->orecv
, &size
, TRUE
);
55 qemu_chr_be_write(chr
, buf
, size
);
59 static int win_chr_serial_poll(void *opaque
)
61 Chardev
*chr
= CHARDEV(opaque
);
62 WinChardev
*s
= WIN_CHARDEV(opaque
);
66 ClearCommError(s
->file
, &comerr
, &status
);
67 if (status
.cbInQue
> 0) {
68 win_chr_read(chr
, status
.cbInQue
);
74 int win_chr_serial_init(Chardev
*chr
, const char *filename
, Error
**errp
)
76 WinChardev
*s
= WIN_CHARDEV(chr
);
78 COMMTIMEOUTS cto
= { 0, 0, 0, 0, 0};
83 s
->hsend
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
85 error_setg(errp
, "Failed CreateEvent");
88 s
->hrecv
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
90 error_setg(errp
, "Failed CreateEvent");
94 s
->file
= CreateFile(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
95 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
96 if (s
->file
== INVALID_HANDLE_VALUE
) {
97 error_setg(errp
, "Failed CreateFile (%lu)", GetLastError());
102 if (!SetupComm(s
->file
, NRECVBUF
, NSENDBUF
)) {
103 error_setg(errp
, "Failed SetupComm");
107 ZeroMemory(&comcfg
, sizeof(COMMCONFIG
));
108 size
= sizeof(COMMCONFIG
);
109 GetDefaultCommConfig(filename
, &comcfg
, &size
);
110 comcfg
.dcb
.DCBlength
= sizeof(DCB
);
111 CommConfigDialog(filename
, NULL
, &comcfg
);
113 if (!SetCommState(s
->file
, &comcfg
.dcb
)) {
114 error_setg(errp
, "Failed SetCommState");
118 if (!SetCommMask(s
->file
, EV_ERR
)) {
119 error_setg(errp
, "Failed SetCommMask");
123 cto
.ReadIntervalTimeout
= MAXDWORD
;
124 if (!SetCommTimeouts(s
->file
, &cto
)) {
125 error_setg(errp
, "Failed SetCommTimeouts");
129 if (!ClearCommError(s
->file
, &err
, &comstat
)) {
130 error_setg(errp
, "Failed ClearCommError");
133 qemu_add_polling_cb(win_chr_serial_poll
, chr
);
140 int win_chr_pipe_poll(void *opaque
)
142 Chardev
*chr
= CHARDEV(opaque
);
143 WinChardev
*s
= WIN_CHARDEV(opaque
);
146 PeekNamedPipe(s
->file
, NULL
, 0, NULL
, &size
, NULL
);
148 win_chr_read(chr
, size
);
154 /* Called with chr_write_lock held. */
155 static int win_chr_write(Chardev
*chr
, const uint8_t *buf
, int len1
)
157 WinChardev
*s
= WIN_CHARDEV(chr
);
158 DWORD len
, ret
, size
, err
;
161 ZeroMemory(&s
->osend
, sizeof(s
->osend
));
162 s
->osend
.hEvent
= s
->hsend
;
165 ret
= WriteFile(s
->file
, buf
, len
, &size
, &s
->osend
);
167 ret
= WriteFile(s
->file
, buf
, len
, &size
, NULL
);
170 err
= GetLastError();
171 if (err
== ERROR_IO_PENDING
) {
172 ret
= GetOverlappedResult(s
->file
, &s
->osend
, &size
, TRUE
);
190 static void char_win_finalize(Object
*obj
)
192 Chardev
*chr
= CHARDEV(obj
);
193 WinChardev
*s
= WIN_CHARDEV(chr
);
196 CloseHandle(s
->hsend
);
199 CloseHandle(s
->hrecv
);
201 if (!s
->keep_open
&& s
->file
) {
202 CloseHandle(s
->file
);
205 qemu_del_polling_cb(win_chr_pipe_poll
, chr
);
207 qemu_del_polling_cb(win_chr_serial_poll
, chr
);
210 qemu_chr_be_event(chr
, CHR_EVENT_CLOSED
);
213 void win_chr_set_file(Chardev
*chr
, HANDLE file
, bool keep_open
)
215 WinChardev
*s
= WIN_CHARDEV(chr
);
217 s
->keep_open
= keep_open
;
221 static void char_win_class_init(ObjectClass
*oc
, void *data
)
223 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
225 cc
->chr_write
= win_chr_write
;
228 static const TypeInfo char_win_type_info
= {
229 .name
= TYPE_CHARDEV_WIN
,
230 .parent
= TYPE_CHARDEV
,
231 .instance_size
= sizeof(WinChardev
),
232 .instance_finalize
= char_win_finalize
,
233 .class_init
= char_win_class_init
,
237 static void register_types(void)
239 type_register_static(&char_win_type_info
);
242 type_init(register_types
);