summaryrefslogtreecommitdiff
path: root/emulator/serial.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-07-12 19:49:13 +0200
committerMarcel Holtmann <marcel@holtmann.org>2014-07-12 19:49:13 +0200
commit5182dc7c3df8897aaff42515b1ef9964b984757d (patch)
tree1e58b753560561baced2ebeeeb81659b128f3112 /emulator/serial.c
parenta18440c23b23704dba92c49fd60cae9032015233 (diff)
downloadbluez-5182dc7c3df8897aaff42515b1ef9964b984757d.tar.gz
emulator: Reopen PTY master when slave closes it
Diffstat (limited to 'emulator/serial.c')
-rw-r--r--emulator/serial.c66
1 files changed, 39 insertions, 27 deletions
diff --git a/emulator/serial.c b/emulator/serial.c
index d87a700fd..27a0cba6f 100644
--- a/emulator/serial.c
+++ b/emulator/serial.c
@@ -57,15 +57,17 @@ struct serial {
uint16_t pkt_offset;
};
+static void open_pty(struct serial *serial);
+
static void serial_destroy(void *user_data)
{
struct serial *serial = user_data;
btdev_destroy(serial->btdev);
+ serial->btdev = NULL;
close(serial->fd);
-
- free(serial);
+ serial->fd = -1;
}
static void serial_write_callback(const void *data, uint16_t len,
@@ -89,6 +91,7 @@ static void serial_read_callback(int fd, uint32_t events, void *user_data)
if (events & (EPOLLERR | EPOLLHUP)) {
mainloop_remove_fd(serial->fd);
+ open_pty(serial);
return;
}
@@ -152,38 +155,28 @@ again:
}
}
-struct serial *serial_open(enum serial_type type)
+static void open_pty(struct serial *serial)
{
- struct serial *serial;
- enum btdev_type uninitialized_var(dev_type);
-
- serial = malloc(sizeof(*serial));
- if (!serial)
- return NULL;
-
- memset(serial, 0, sizeof(*serial));
- serial->type = type;
- serial->id = 0x42;
+ enum btdev_type uninitialized_var(type);
serial->fd = getpt();
if (serial->fd < 0) {
perror("Failed to get master pseudo terminal");
- free(serial);
- return NULL;
+ return;
}
if (grantpt(serial->fd) < 0) {
perror("Failed to grant slave pseudo terminal");
close(serial->fd);
- free(serial);
- return NULL;
+ serial->fd = -1;
+ return;
}
if (unlockpt(serial->fd) < 0) {
perror("Failed to unlock slave pseudo terminal");
close(serial->fd);
- free(serial);
- return NULL;
+ serial->fd = -1;
+ return;
}
ptsname_r(serial->fd, serial->path, sizeof(serial->path));
@@ -192,24 +185,24 @@ struct serial *serial_open(enum serial_type type)
switch (serial->type) {
case SERIAL_TYPE_BREDRLE:
- dev_type = BTDEV_TYPE_BREDRLE;
+ type = BTDEV_TYPE_BREDRLE;
break;
case SERIAL_TYPE_BREDR:
- dev_type = BTDEV_TYPE_BREDR;
+ type = BTDEV_TYPE_BREDR;
break;
case SERIAL_TYPE_LE:
- dev_type = BTDEV_TYPE_LE;
+ type = BTDEV_TYPE_LE;
break;
case SERIAL_TYPE_AMP:
- dev_type = BTDEV_TYPE_AMP;
+ type = BTDEV_TYPE_AMP;
break;
}
serial->btdev = btdev_create(type, serial->id);
if (!serial->btdev) {
close(serial->fd);
- free(serial);
- return NULL;
+ serial->fd = -1;
+ return;
}
btdev_set_send_handler(serial->btdev, serial_write_callback, serial);
@@ -217,10 +210,27 @@ struct serial *serial_open(enum serial_type type)
if (mainloop_add_fd(serial->fd, EPOLLIN, serial_read_callback,
serial, serial_destroy) < 0) {
btdev_destroy(serial->btdev);
+ serial->btdev = NULL;
close(serial->fd);
- free(serial);
- return NULL;
+ serial->fd = -1;
+ return;
}
+}
+
+struct serial *serial_open(enum serial_type type)
+{
+ struct serial *serial;
+ enum btdev_type uninitialized_var(dev_type);
+
+ serial = malloc(sizeof(*serial));
+ if (!serial)
+ return NULL;
+
+ memset(serial, 0, sizeof(*serial));
+ serial->type = type;
+ serial->id = 0x42;
+
+ open_pty(serial);
return serial;
}
@@ -231,4 +241,6 @@ void serial_close(struct serial *serial)
return;
mainloop_remove_fd(serial->fd);
+
+ free(serial);
}