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/module.h"
27 #include "qapi/error.h"
28 #include "chardev/char-win.h"
30 static void win_chr_read(Chardev
*chr
, DWORD len
)
32 WinChardev
*s
= WIN_CHARDEV(chr
);
33 int max_size
= qemu_chr_be_can_write(chr
);
35 uint8_t buf
[CHR_READ_BUF_LEN
];
45 ZeroMemory(&s
->orecv
, sizeof(s
->orecv
));
46 s
->orecv
.hEvent
= s
->hrecv
;
47 ret
= ReadFile(s
->file
, buf
, len
, &size
, &s
->orecv
);
50 if (err
== ERROR_IO_PENDING
) {
51 ret
= GetOverlappedResult(s
->file
, &s
->orecv
, &size
, TRUE
);
56 qemu_chr_be_write(chr
, buf
, size
);
60 static int win_chr_serial_poll(void *opaque
)
62 Chardev
*chr
= CHARDEV(opaque
);
63 WinChardev
*s
= WIN_CHARDEV(opaque
);
67 ClearCommError(s
->file
, &comerr
, &status
);
68 if (status
.cbInQue
> 0) {
69 win_chr_read(chr
, status
.cbInQue
);
75 int win_chr_serial_init(Chardev
*chr
, const char *filename
, Error
**errp
)
77 WinChardev
*s
= WIN_CHARDEV(chr
);
79 COMMTIMEOUTS cto
= { 0, 0, 0, 0, 0};
84 s
->hsend
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
86 error_setg(errp
, "Failed CreateEvent");
89 s
->hrecv
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
91 error_setg(errp
, "Failed CreateEvent");
95 s
->file
= CreateFile(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
96 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
97 if (s
->file
== INVALID_HANDLE_VALUE
) {
98 error_setg(errp
, "Failed CreateFile (%lu)", GetLastError());
103 if (!SetupComm(s
->file
, NRECVBUF
, NSENDBUF
)) {
104 error_setg(errp
, "Failed SetupComm");
108 ZeroMemory(&comcfg
, sizeof(COMMCONFIG
));
109 size
= sizeof(COMMCONFIG
);
110 GetDefaultCommConfig(filename
, &comcfg
, &size
);
111 comcfg
.dcb
.DCBlength
= sizeof(DCB
);
112 CommConfigDialog(filename
, NULL
, &comcfg
);
114 if (!SetCommState(s
->file
, &comcfg
.dcb
)) {
115 error_setg(errp
, "Failed SetCommState");
119 if (!SetCommMask(s
->file
, EV_ERR
)) {
120 error_setg(errp
, "Failed SetCommMask");
124 cto
.ReadIntervalTimeout
= MAXDWORD
;
125 if (!SetCommTimeouts(s
->file
, &cto
)) {
126 error_setg(errp
, "Failed SetCommTimeouts");
130 if (!ClearCommError(s
->file
, &err
, &comstat
)) {
131 error_setg(errp
, "Failed ClearCommError");
134 qemu_add_polling_cb(win_chr_serial_poll
, chr
);
141 int win_chr_pipe_poll(void *opaque
)
143 Chardev
*chr
= CHARDEV(opaque
);
144 WinChardev
*s
= WIN_CHARDEV(opaque
);
147 PeekNamedPipe(s
->file
, NULL
, 0, NULL
, &size
, NULL
);
149 win_chr_read(chr
, size
);
155 /* Called with chr_write_lock held. */
156 static int win_chr_write(Chardev
*chr
, const uint8_t *buf
, int len1
)
158 WinChardev
*s
= WIN_CHARDEV(chr
);
159 DWORD len
, ret
, size
, err
;
162 ZeroMemory(&s
->osend
, sizeof(s
->osend
));
163 s
->osend
.hEvent
= s
->hsend
;
166 ret
= WriteFile(s
->file
, buf
, len
, &size
, &s
->osend
);
168 ret
= WriteFile(s
->file
, buf
, len
, &size
, NULL
);
171 err
= GetLastError();
172 if (err
== ERROR_IO_PENDING
) {
173 ret
= GetOverlappedResult(s
->file
, &s
->osend
, &size
, TRUE
);
191 static void char_win_finalize(Object
*obj
)
193 Chardev
*chr
= CHARDEV(obj
);
194 WinChardev
*s
= WIN_CHARDEV(chr
);
197 CloseHandle(s
->hsend
);
200 CloseHandle(s
->hrecv
);
202 if (!s
->keep_open
&& s
->file
) {
203 CloseHandle(s
->file
);
206 qemu_del_polling_cb(win_chr_pipe_poll
, chr
);
208 qemu_del_polling_cb(win_chr_serial_poll
, chr
);
211 qemu_chr_be_event(chr
, CHR_EVENT_CLOSED
);
214 void win_chr_set_file(Chardev
*chr
, HANDLE file
, bool keep_open
)
216 WinChardev
*s
= WIN_CHARDEV(chr
);
218 s
->keep_open
= keep_open
;
222 static void char_win_class_init(ObjectClass
*oc
, void *data
)
224 ChardevClass
*cc
= CHARDEV_CLASS(oc
);
226 cc
->chr_write
= win_chr_write
;
229 static const TypeInfo char_win_type_info
= {
230 .name
= TYPE_CHARDEV_WIN
,
231 .parent
= TYPE_CHARDEV
,
232 .instance_size
= sizeof(WinChardev
),
233 .instance_finalize
= char_win_finalize
,
234 .class_init
= char_win_class_init
,
238 static void register_types(void)
240 type_register_static(&char_win_type_info
);
243 type_init(register_types
);