/* Serial interface for local (hardwired) serial ports on Windows systems
- Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
This file is part of GDB.
HANDLE except_event;
};
+/* CancelIo is not available for Windows 95 OS, so we need to use
+ LoadLibrary/GetProcAddress to avoid a startup failure. */
+#define CancelIo dyn_CancelIo
+static BOOL WINAPI (*CancelIo) (HANDLE);
+
/* Open up a real live device for serial I/O. */
static int
return -1;
}
- scb->fd = _open_osfhandle ((long) h, O_RDWR);
+ scb->fd = _open_osfhandle ((intptr_t) h, O_RDWR);
if (scb->fd < 0)
{
errno = ENOENT;
scb->current_timeout = 0;
if (SetCommState (h, &state) == 0)
- warning (_("SetCommState failed\n"));
+ warning (_("SetCommState failed"));
}
static int
{
struct ser_windows_state *state;
- /* Stop any pending selects. */
- CancelIo ((HANDLE) _get_osfhandle (scb->fd));
+ /* Stop any pending selects. On Windows 95 OS, CancelIo function does
+ not exist. In that case, it can be replaced by a call to CloseHandle,
+ but this is not necessary here as we do close the Windows handle
+ by calling close (scb->fd) below. */
+ if (CancelIo)
+ CancelIo ((HANDLE) _get_osfhandle (scb->fd));
state = scb->state;
CloseHandle (state->ov.hEvent);
CloseHandle (state->except_event);
the started state. */
HANDLE start_select;
/* Signaled by the main program to tell the select thread to enter
- the stopped state. */
+ the stopped state. */
HANDLE stop_select;
/* Signaled by the main program to tell the select thread to
exit. */
wait_events[0] = state->stop_select;
wait_events[1] = h;
- event_index = WaitForMultipleObjects (2, wait_events, FALSE, INFINITE);
+ event_index = WaitForMultipleObjects (2, wait_events,
+ FALSE, INFINITE);
if (event_index == WAIT_OBJECT_0
|| WaitForSingleObject (state->stop_select, 0) == WAIT_OBJECT_0)
SetEvent(state->have_stopped);
}
+ return 0;
}
static int
SetEvent (state->have_stopped);
}
+ return 0;
}
static DWORD WINAPI
{
select_thread_wait (state);
- if (SetFilePointer (h, 0, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+ if (SetFilePointer (h, 0, NULL, FILE_CURRENT)
+ == INVALID_SET_FILE_POINTER)
SetEvent (state->except_event);
else
SetEvent (state->read_event);
SetEvent (state->have_stopped);
}
+ return 0;
}
static void
if (isatty (scb->fd))
{
struct ser_console_ttystate *state;
+
state = (struct ser_console_ttystate *) xmalloc (sizeof *state);
state->is_a_tty = 1;
return state;
if (ps->input)
fclose (ps->input);
if (ps->pex)
- pex_free (ps->pex);
- /* pex_free closes ps->output. */
+ {
+ pex_free (ps->pex);
+ /* pex_free closes ps->output. */
+ }
+ else if (ps->output)
+ fclose (ps->output);
xfree (ps);
back_to = make_cleanup_freeargv (argv);
if (! argv[0] || argv[0][0] == '\0')
- error ("missing child command");
+ error (_("missing child command"));
ps = make_pipe_state ();
make_cleanup (cleanup_pipe_state, ps);
all the same information here, plus err_msg provided by
pex_run, so we just raise the error here. */
if (err)
- error ("error starting child process '%s': %s: %s",
+ error (_("error starting child process '%s': %s: %s"),
name, err_msg, safe_strerror (err));
else
- error ("error starting child process '%s': %s",
+ error (_("error starting child process '%s': %s"),
name, err_msg);
}
}
return -1;
}
+static int
+pipe_windows_fdopen (struct serial *scb, int fd)
+{
+ struct pipe_state *ps;
+
+ ps = make_pipe_state ();
+
+ ps->input = fdopen (fd, "r+");
+ if (! ps->input)
+ goto fail;
+
+ ps->output = fdopen (fd, "r+");
+ if (! ps->output)
+ goto fail;
+
+ scb->fd = fd;
+ scb->state = (void *) ps;
+
+ return 0;
+
+ fail:
+ free_pipe_state (ps);
+ return -1;
+}
static void
pipe_windows_close (struct serial *scb)
HANDLE h = (HANDLE) _get_osfhandle (fd);
DWORD numBytes;
BOOL r = PeekNamedPipe (h, NULL, 0, NULL, &numBytes, NULL);
+
if (r == FALSE)
numBytes = 0;
return numBytes;
}
+int
+gdb_pipe (int pdes[2])
+{
+ if (_pipe (pdes, 512, _O_BINARY | _O_NOINHERIT) == -1)
+ return -1;
+ return 0;
+}
+
struct net_windows_state
{
struct ser_console_state base;
WSADATA wsa_data;
struct serial_ops *ops;
- /* First register the serial port driver. */
+ HMODULE hm = NULL;
+
+ /* First find out if kernel32 exports CancelIo function. */
+ hm = LoadLibrary ("kernel32.dll");
+ if (hm)
+ {
+ CancelIo = (void *) GetProcAddress (hm, "CancelIo");
+ FreeLibrary (hm);
+ }
+ else
+ CancelIo = NULL;
+ /* Now register the serial port driver. */
ops = XMALLOC (struct serial_ops);
memset (ops, 0, sizeof (struct serial_ops));
ops->name = "hardwire";
/* These are only used for stdin; we do not need them for serial
ports, so supply the standard dummies. */
ops->get_tty_state = ser_base_get_tty_state;
+ ops->copy_tty_state = ser_base_copy_tty_state;
ops->set_tty_state = ser_base_set_tty_state;
ops->print_tty_state = ser_base_print_tty_state;
ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
ops->close = ser_console_close;
ops->get_tty_state = ser_console_get_tty_state;
+ ops->copy_tty_state = ser_base_copy_tty_state;
ops->set_tty_state = ser_base_set_tty_state;
ops->print_tty_state = ser_base_print_tty_state;
ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
ops->next = 0;
ops->open = pipe_windows_open;
ops->close = pipe_windows_close;
+ ops->fdopen = pipe_windows_fdopen;
ops->readchar = ser_base_readchar;
ops->write = ser_base_write;
ops->flush_output = ser_base_flush_output;
ops->send_break = ser_base_send_break;
ops->go_raw = ser_base_raw;
ops->get_tty_state = ser_base_get_tty_state;
+ ops->copy_tty_state = ser_base_copy_tty_state;
ops->set_tty_state = ser_base_set_tty_state;
ops->print_tty_state = ser_base_print_tty_state;
ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
ops->send_break = ser_tcp_send_break;
ops->go_raw = ser_base_raw;
ops->get_tty_state = ser_base_get_tty_state;
+ ops->copy_tty_state = ser_base_copy_tty_state;
ops->set_tty_state = ser_base_set_tty_state;
ops->print_tty_state = ser_base_print_tty_state;
ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;