From 1c8cd096b57a876c4fb0afc5113aac05d75d924e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 13 Apr 2023 19:38:42 +0200 Subject: [PATCH] Integrate the new packet I/O in the backends Replace the custom packet handling code in the iconhd and ostc3 backends with the new layered packet I/O, and also integrate it into the idive and extreme backends. --- src/divesystem_idive.c | 37 +++++++++-- src/hw_ostc3.c | 83 ++++++++++++------------- src/mares_iconhd.c | 136 +++++++++++++---------------------------- src/mclean_extreme.c | 40 +++++++++--- 4 files changed, 150 insertions(+), 146 deletions(-) diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index 4a0bca3..9841a6f 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -29,6 +29,7 @@ #include "platform.h" #include "checksum.h" #include "array.h" +#include "packet.h" #define ISINSTANCE(device) dc_device_isinstance((device), &divesystem_idive_device_vtable) @@ -102,6 +103,7 @@ typedef struct divesystem_idive_device_t { static dc_status_t divesystem_idive_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); static dc_status_t divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); static dc_status_t divesystem_idive_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime); +static dc_status_t divesystem_idive_device_close (dc_device_t *abstract); static const dc_device_vtable_t divesystem_idive_device_vtable = { sizeof(divesystem_idive_device_t), @@ -112,7 +114,7 @@ static const dc_device_vtable_t divesystem_idive_device_vtable = { NULL, /* dump */ divesystem_idive_device_foreach, /* foreach */ divesystem_idive_device_timesync, /* timesync */ - NULL /* close */ + divesystem_idive_device_close /* close */ }; static const divesystem_idive_commands_t idive = { @@ -152,6 +154,7 @@ divesystem_idive_device_open (dc_device_t **out, dc_context_t *context, dc_iostr { dc_status_t status = DC_STATUS_SUCCESS; divesystem_idive_device_t *device = NULL; + dc_transport_t transport = dc_iostream_get_transport (iostream); if (out == NULL) return DC_STATUS_INVALIDARGS; @@ -164,22 +167,32 @@ divesystem_idive_device_open (dc_device_t **out, dc_context_t *context, dc_iostr } // Set the default values. - device->iostream = iostream; memset (device->fingerprint, 0, sizeof (device->fingerprint)); device->model = model; + // Create the packet stream. + if (transport == DC_TRANSPORT_BLE) { + status = dc_packet_open (&device->iostream, context, iostream, 244, 244); + if (status != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to create the packet stream."); + goto error_free; + } + } else { + device->iostream = iostream; + } + // Set the serial communication protocol (115200 8N1). status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to set the terminal attributes."); - goto error_free; + goto error_free_iostream; } // Set the timeout for receiving data (1000ms). status = dc_iostream_set_timeout (device->iostream, 1000); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to set the timeout."); - goto error_free; + goto error_free_iostream; } // Make sure everything is in a sane state. @@ -190,11 +203,27 @@ divesystem_idive_device_open (dc_device_t **out, dc_context_t *context, dc_iostr return DC_STATUS_SUCCESS; +error_free_iostream: + if (transport == DC_TRANSPORT_BLE) { + dc_iostream_close (device->iostream); + } error_free: dc_device_deallocate ((dc_device_t *) device); return status; } +static dc_status_t +divesystem_idive_device_close (dc_device_t *abstract) +{ + divesystem_idive_device_t *device = (divesystem_idive_device_t *) abstract; + + // Close the packet stream. + if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) { + return dc_iostream_close (device->iostream); + } + + return DC_STATUS_SUCCESS; +} static dc_status_t divesystem_idive_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 629e482..2016158 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -30,6 +30,7 @@ #include "array.h" #include "aes.h" #include "platform.h" +#include "packet.h" #define ISINSTANCE(device) dc_device_isinstance((device), &hw_ostc3_device_vtable) @@ -119,9 +120,6 @@ typedef struct hw_ostc3_device_t { unsigned int firmware; unsigned char fingerprint[5]; hw_ostc3_state_t state; - unsigned char cache[244]; - unsigned int available; - unsigned int offset; } hw_ostc3_device_t; typedef struct hw_ostc3_logbook_t { @@ -207,41 +205,20 @@ static dc_status_t hw_ostc3_read (hw_ostc3_device_t *device, dc_event_progress_t *progress, unsigned char data[], size_t size) { dc_status_t rc = DC_STATUS_SUCCESS; - dc_transport_t transport = dc_iostream_get_transport(device->iostream); size_t nbytes = 0; while (nbytes < size) { - if (transport == DC_TRANSPORT_BLE) { - if (device->available == 0) { - // Read a packet into the cache. - size_t len = 0; - rc = dc_iostream_read (device->iostream, device->cache, sizeof(device->cache), &len); - if (rc != DC_STATUS_SUCCESS) - return rc; - - device->available = len; - device->offset = 0; - } - } - // Set the minimum packet size. - size_t length = (transport == DC_TRANSPORT_BLE) ? device->available : 1024; + size_t length = 1024; // Limit the packet size to the total size. if (nbytes + length > size) length = size - nbytes; - if (transport == DC_TRANSPORT_BLE) { - // Copy the data from the cached packet. - memcpy (data + nbytes, device->cache + device->offset, length); - device->available -= length; - device->offset += length; - } else { - // Read the packet. - rc = dc_iostream_read (device->iostream, data + nbytes, length, NULL); - if (rc != DC_STATUS_SUCCESS) - return rc; - } + // Read the packet. + rc = dc_iostream_read (device->iostream, data + nbytes, length, NULL); + if (rc != DC_STATUS_SUCCESS) + return rc; // Update and emit a progress event. if (progress) { @@ -259,12 +236,11 @@ static dc_status_t hw_ostc3_write (hw_ostc3_device_t *device, dc_event_progress_t *progress, const unsigned char data[], size_t size) { dc_status_t rc = DC_STATUS_SUCCESS; - dc_transport_t transport = dc_iostream_get_transport(device->iostream); size_t nbytes = 0; while (nbytes < size) { // Set the maximum packet size. - size_t length = (transport == DC_TRANSPORT_BLE) ? sizeof(device->cache) : 64; + size_t length = 1024; // Limit the packet size to the total size. if (nbytes + length > size) @@ -313,7 +289,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, // Send the command. unsigned char command[1] = {cmd}; - status = hw_ostc3_write (device, NULL, command, sizeof (command)); + status = dc_iostream_write (device->iostream, command, sizeof (command), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to send the command."); return status; @@ -321,7 +297,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, // Read the echo. unsigned char echo[1] = {0}; - status = hw_ostc3_read (device, NULL, echo, sizeof (echo)); + status = dc_iostream_read (device->iostream, echo, sizeof (echo), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to receive the echo."); return status; @@ -407,14 +383,14 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, } } - if (delay && device->available == 0) { + if (delay) { dc_iostream_poll (device->iostream, delay); } if (cmd != EXIT) { // Read the ready byte. unsigned char answer[1] = {0}; - status = hw_ostc3_read (device, NULL, answer, sizeof (answer)); + status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to receive the ready byte."); return status; @@ -439,6 +415,7 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *i { dc_status_t status = DC_STATUS_SUCCESS; hw_ostc3_device_t *device = NULL; + dc_transport_t transport = dc_iostream_get_transport (iostream); if (out == NULL) return DC_STATUS_INVALIDARGS; @@ -451,29 +428,36 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *i } // Set the default values. - device->iostream = iostream; device->hardware = INVALID; device->feature = 0; device->model = 0; device->serial = 0; device->firmware = 0; memset (device->fingerprint, 0, sizeof (device->fingerprint)); - memset (device->cache, 0, sizeof (device->cache)); - device->available = 0; - device->offset = 0; + + // Create the packet stream. + if (transport == DC_TRANSPORT_BLE) { + status = dc_packet_open (&device->iostream, context, iostream, 244, 244); + if (status != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to create the packet stream."); + goto error_free; + } + } else { + device->iostream = iostream; + } // Set the serial communication protocol (115200 8N1). status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to set the terminal attributes."); - goto error_free; + goto error_free_iostream; } // Set the timeout for receiving data (3000ms). status = dc_iostream_set_timeout (device->iostream, 3000); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to set the timeout."); - goto error_free; + goto error_free_iostream; } // Make sure everything is in a sane state. @@ -486,6 +470,10 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *i return DC_STATUS_SUCCESS; +error_free_iostream: + if (transport == DC_TRANSPORT_BLE) { + dc_iostream_close (device->iostream); + } error_free: dc_device_deallocate ((dc_device_t *) device); return status; @@ -548,14 +536,14 @@ hw_ostc3_device_init_service (hw_ostc3_device_t *device) unsigned char answer[5] = {0}; // Send the command and service key. - status = hw_ostc3_write (device, NULL, command, sizeof (command)); + status = dc_iostream_write (device->iostream, command, sizeof (command), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to send the command."); return status; } // Read the response. - status = hw_ostc3_read (device, NULL, answer, sizeof (answer)); + status = dc_iostream_read (device->iostream, answer, sizeof (answer), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to receive the answer."); return status; @@ -656,6 +644,15 @@ hw_ostc3_device_close (dc_device_t *abstract) } } + // Close the packet stream. + if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) { + rc = dc_iostream_close (device->iostream); + if (rc != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to close the packet stream."); + dc_status_set_error(&status, rc); + } + } + return status; } diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index 55b684f..2f5bd28 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -29,6 +29,7 @@ #include "array.h" #include "rbstream.h" #include "platform.h" +#include "packet.h" #define ISINSTANCE(device) dc_device_isinstance((device), &mares_iconhd_device_vtable) @@ -93,15 +94,13 @@ typedef struct mares_iconhd_device_t { unsigned char version[140]; unsigned int model; unsigned int packetsize; - unsigned char cache[20]; - unsigned int available; - unsigned int offset; } mares_iconhd_device_t; static dc_status_t mares_iconhd_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); static dc_status_t mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size); static dc_status_t mares_iconhd_device_dump (dc_device_t *abstract, dc_buffer_t *buffer); static dc_status_t mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); +static dc_status_t mares_iconhd_device_close (dc_device_t *abstract); static const dc_device_vtable_t mares_iconhd_device_vtable = { sizeof(mares_iconhd_device_t), @@ -112,7 +111,7 @@ static const dc_device_vtable_t mares_iconhd_device_vtable = { mares_iconhd_device_dump, /* dump */ mares_iconhd_device_foreach, /* foreach */ NULL, /* timesync */ - NULL /* close */ + mares_iconhd_device_close /* close */ }; static const mares_iconhd_layout_t mares_iconhd_layout = { @@ -177,78 +176,6 @@ mares_iconhd_get_model (mares_iconhd_device_t *device) return model; } -static dc_status_t -mares_iconhd_read (mares_iconhd_device_t *device, unsigned char data[], size_t size) -{ - dc_status_t rc = DC_STATUS_SUCCESS; - dc_transport_t transport = dc_iostream_get_transport(device->iostream); - - size_t nbytes = 0; - while (nbytes < size) { - if (transport == DC_TRANSPORT_BLE) { - if (device->available == 0) { - // Read a packet into the cache. - size_t len = 0; - rc = dc_iostream_read (device->iostream, device->cache, sizeof(device->cache), &len); - if (rc != DC_STATUS_SUCCESS) - return rc; - - device->available = len; - device->offset = 0; - } - } - - // Set the minimum packet size. - size_t length = (transport == DC_TRANSPORT_BLE) ? device->available : size - nbytes; - - // Limit the packet size to the total size. - if (nbytes + length > size) - length = size - nbytes; - - if (transport == DC_TRANSPORT_BLE) { - // Copy the data from the cached packet. - memcpy (data + nbytes, device->cache + device->offset, length); - device->available -= length; - device->offset += length; - } else { - // Read the packet. - rc = dc_iostream_read (device->iostream, data + nbytes, length, &length); - if (rc != DC_STATUS_SUCCESS) - return rc; - } - - nbytes += length; - } - - return rc; -} - -static dc_status_t -mares_iconhd_write (mares_iconhd_device_t *device, const unsigned char data[], size_t size) -{ - dc_status_t rc = DC_STATUS_SUCCESS; - dc_transport_t transport = dc_iostream_get_transport(device->iostream); - - size_t nbytes = 0; - while (nbytes < size) { - // Set the maximum packet size. - size_t length = (transport == DC_TRANSPORT_BLE) ? sizeof(device->cache) : size - nbytes; - - // Limit the packet size to the total size. - if (nbytes + length > size) - length = size - nbytes; - - // Write the packet. - rc = dc_iostream_write (device->iostream, data + nbytes, length, &length); - if (rc != DC_STATUS_SUCCESS) - return rc; - - nbytes += length; - } - - return rc; -} - static dc_status_t mares_iconhd_packet (mares_iconhd_device_t *device, const unsigned char command[], unsigned int csize, @@ -263,7 +190,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device, return DC_STATUS_CANCELLED; // Send the command header to the dive computer. - status = mares_iconhd_write (device, command, 2); + status = dc_iostream_write (device->iostream, command, 2, NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to send the command."); return status; @@ -271,7 +198,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device, // Receive the header byte. unsigned char header[1] = {0}; - status = mares_iconhd_read (device, header, sizeof (header)); + status = dc_iostream_read (device->iostream, header, sizeof (header), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to receive the answer."); return status; @@ -285,7 +212,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device, // Send the command payload to the dive computer. if (csize > 2) { - status = mares_iconhd_write (device, command + 2, csize - 2); + status = dc_iostream_write (device->iostream, command + 2, csize - 2, NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to send the command."); return status; @@ -293,7 +220,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device, } // Read the packet. - status = mares_iconhd_read (device, answer, asize); + status = dc_iostream_read (device->iostream, answer, asize, NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to receive the answer."); return status; @@ -301,7 +228,7 @@ mares_iconhd_packet (mares_iconhd_device_t *device, // Receive the trailer byte. unsigned char trailer[1] = {0}; - status = mares_iconhd_read (device, trailer, sizeof (trailer)); + status = dc_iostream_read (device->iostream, trailer, sizeof (trailer), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to receive the answer."); return status; @@ -334,8 +261,6 @@ mares_iconhd_transfer (mares_iconhd_device_t *device, const unsigned char comman // Discard any garbage bytes. dc_iostream_sleep (device->iostream, 100); dc_iostream_purge (device->iostream, DC_DIRECTION_INPUT); - device->available = 0; - device->offset = 0; } return DC_STATUS_SUCCESS; @@ -459,6 +384,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_ { dc_status_t status = DC_STATUS_SUCCESS; mares_iconhd_device_t *device = NULL; + dc_transport_t transport = dc_iostream_get_transport (iostream); if (out == NULL) return DC_STATUS_INVALIDARGS; @@ -471,43 +397,50 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_ } // Set the default values. - device->iostream = iostream; device->layout = NULL; memset (device->fingerprint, 0, sizeof (device->fingerprint)); device->fingerprint_size = sizeof (device->fingerprint); memset (device->version, 0, sizeof (device->version)); device->model = 0; device->packetsize = 0; - memset (device->cache, 0, sizeof (device->cache)); - device->available = 0; - device->offset = 0; + + // Create the packet stream. + if (transport == DC_TRANSPORT_BLE) { + status = dc_packet_open (&device->iostream, context, iostream, 20, 20); + if (status != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to create the packet stream."); + goto error_free; + } + } else { + device->iostream = iostream; + } // Set the serial communication protocol (115200 8E1). status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_EVEN, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to set the terminal attributes."); - goto error_free; + goto error_free_iostream; } // Set the timeout for receiving data (3000 ms). status = dc_iostream_set_timeout (device->iostream, 3000); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to set the timeout."); - goto error_free; + goto error_free_iostream; } // Clear the DTR line. status = dc_iostream_set_dtr (device->iostream, 0); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to clear the DTR line."); - goto error_free; + goto error_free_iostream; } // Clear the RTS line. status = dc_iostream_set_rts (device->iostream, 0); if (status != DC_STATUS_SUCCESS) { ERROR (context, "Failed to clear the RTS line."); - goto error_free; + goto error_free_iostream; } // Make sure everything is in a sane state. @@ -518,7 +451,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_ status = mares_iconhd_transfer (device, command, sizeof (command), device->version, sizeof (device->version)); if (status != DC_STATUS_SUCCESS) { - goto error_free; + goto error_free_iostream; } // Autodetect the model using the version packet. @@ -586,12 +519,31 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_ return DC_STATUS_SUCCESS; + +error_free_iostream: + if (transport == DC_TRANSPORT_BLE) { + dc_iostream_close (device->iostream); + } error_free: dc_device_deallocate ((dc_device_t *) device); return status; } +static dc_status_t +mares_iconhd_device_close (dc_device_t *abstract) +{ + mares_iconhd_device_t *device = (mares_iconhd_device_t *) abstract; + + // Close the packet stream. + if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) { + return dc_iostream_close (device->iostream); + } + + return DC_STATUS_SUCCESS; +} + + static dc_status_t mares_iconhd_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size) { diff --git a/src/mclean_extreme.c b/src/mclean_extreme.c index 98038ff..2ef1a87 100644 --- a/src/mclean_extreme.c +++ b/src/mclean_extreme.c @@ -26,6 +26,7 @@ #include "context-private.h" #include "device-private.h" #include "array.h" +#include "packet.h" #define ISINSTANCE(device) dc_device_isinstance((device), &mclean_extreme_device_vtable) @@ -391,6 +392,7 @@ mclean_extreme_device_open(dc_device_t **out, dc_context_t *context, dc_iostream { dc_status_t status = DC_STATUS_SUCCESS; mclean_extreme_device_t *device = NULL; + dc_transport_t transport = dc_iostream_get_transport (iostream); if (out == NULL) return DC_STATUS_INVALIDARGS; @@ -403,21 +405,31 @@ mclean_extreme_device_open(dc_device_t **out, dc_context_t *context, dc_iostream } // Set the default values. - device->iostream = iostream; memset(device->fingerprint, 0, sizeof(device->fingerprint)); + // Create the packet stream. + if (transport == DC_TRANSPORT_BLE) { + status = dc_packet_open (&device->iostream, context, iostream, 244, 244); + if (status != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to create the packet stream."); + goto error_free; + } + } else { + device->iostream = iostream; + } + // Set the serial communication protocol (115200 8N1). status = dc_iostream_configure(device->iostream, 115200, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE); if (status != DC_STATUS_SUCCESS) { ERROR(context, "Failed to set the terminal attributes."); - goto error_free; + goto error_free_iostream; } // Set the timeout for receiving data (1000ms). status = dc_iostream_set_timeout(device->iostream, 1000); if (status != DC_STATUS_SUCCESS) { ERROR(context, "Failed to set the timeout."); - goto error_free; + goto error_free_iostream; } // Make sure everything is in a sane state. @@ -428,6 +440,10 @@ mclean_extreme_device_open(dc_device_t **out, dc_context_t *context, dc_iostream return DC_STATUS_SUCCESS; +error_free_iostream: + if (transport == DC_TRANSPORT_BLE) { + dc_iostream_close (device->iostream); + } error_free: dc_device_deallocate((dc_device_t *)device); return status; @@ -438,14 +454,24 @@ mclean_extreme_device_close(dc_device_t *abstract) { dc_status_t status = DC_STATUS_SUCCESS; mclean_extreme_device_t *device = (mclean_extreme_device_t *)abstract; + dc_status_t rc = DC_STATUS_SUCCESS; - status = mclean_extreme_send(device, CMD_CLOSE, NULL, 0); - if (status != DC_STATUS_SUCCESS) { + rc = mclean_extreme_send(device, CMD_CLOSE, NULL, 0); + if (rc != DC_STATUS_SUCCESS) { ERROR(abstract->context, "Failed to send the exit command."); - return status; + dc_status_set_error(&status, rc); } - return DC_STATUS_SUCCESS; + // Close the packet stream. + if (dc_iostream_get_transport (device->iostream) == DC_TRANSPORT_BLE) { + rc = dc_iostream_close (device->iostream); + if (rc != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to close the packet stream."); + dc_status_set_error(&status, rc); + } + } + + return status; } static dc_status_t