diff options
author | Marcel Holtmann <marcel@holtmann.org> | 2014-07-12 19:49:13 +0200 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-07-12 19:49:13 +0200 |
commit | 5182dc7c3df8897aaff42515b1ef9964b984757d (patch) | |
tree | 1e58b753560561baced2ebeeeb81659b128f3112 /emulator/serial.c | |
parent | a18440c23b23704dba92c49fd60cae9032015233 (diff) | |
download | bluez-5182dc7c3df8897aaff42515b1ef9964b984757d.tar.gz |
emulator: Reopen PTY master when slave closes it
Diffstat (limited to 'emulator/serial.c')
-rw-r--r-- | emulator/serial.c | 66 |
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); } |