diff --git a/src/descriptor.c b/src/descriptor.c index 6a31c29..0d0ed66 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -284,11 +284,11 @@ static const dc_descriptor_t g_descriptors[] = { {"Shearwater", "Predator", DC_FAMILY_SHEARWATER_PREDATOR, 2, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_shearwater}, /* Shearwater Petrel */ {"Shearwater", "Petrel", DC_FAMILY_SHEARWATER_PETREL, 3, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_shearwater}, - {"Shearwater", "Petrel 2", DC_FAMILY_SHEARWATER_PETREL, 3, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_shearwater}, + {"Shearwater", "Petrel 2", DC_FAMILY_SHEARWATER_PETREL, 3, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_shearwater}, {"Shearwater", "Nerd", DC_FAMILY_SHEARWATER_PETREL, 4, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_shearwater}, - {"Shearwater", "Perdix", DC_FAMILY_SHEARWATER_PETREL, 5, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH, dc_filter_shearwater}, - {"Shearwater", "Perdix AI", DC_FAMILY_SHEARWATER_PETREL, 6, DC_TRANSPORT_NONE, dc_filter_shearwater}, - {"Shearwater", "Nerd 2", DC_FAMILY_SHEARWATER_PETREL, 7, DC_TRANSPORT_NONE, dc_filter_shearwater}, + {"Shearwater", "Perdix", DC_FAMILY_SHEARWATER_PETREL, 5, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_shearwater}, + {"Shearwater", "Perdix AI", DC_FAMILY_SHEARWATER_PETREL, 6, DC_TRANSPORT_BLE, dc_filter_shearwater}, + {"Shearwater", "Nerd 2", DC_FAMILY_SHEARWATER_PETREL, 7, DC_TRANSPORT_BLE, dc_filter_shearwater}, /* Dive Rite NiTek Q */ {"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0, DC_TRANSPORT_SERIAL, NULL}, /* Citizen Hyper Aqualand */ diff --git a/src/shearwater_common.c b/src/shearwater_common.c index 130ff62..a7f67f6 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -25,6 +25,7 @@ #include "shearwater_common.h" #include "context-private.h" +#include "platform.h" #include "array.h" #define SZ_PACKET 254 @@ -122,19 +123,33 @@ shearwater_common_decompress_xor (unsigned char *data, unsigned int size) return 0; } - static dc_status_t shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned char data[], unsigned int size) { dc_status_t status = DC_STATUS_SUCCESS; + dc_transport_t transport = dc_iostream_get_transport(device->iostream); unsigned char buffer[32]; unsigned int nbytes = 0; -#if 0 - // Send an initial END character to flush out any data that may have - // accumulated in the receiver due to line noise. - buffer[nbytes++] = END; -#endif + if (transport == DC_TRANSPORT_BLE) { + // Calculate the total number of bytes. + unsigned int count = 1; + for (unsigned int i = 0; i < size; ++i) { + unsigned char c = data[i]; + if (c == END || c == ESC) { + count += 2; + } else { + count++; + } + } + + // Calculate the total number of frames. + unsigned int nframes = (count + sizeof(buffer) - 1) / sizeof(buffer); + + buffer[0] = nframes; + buffer[1] = 0; + nbytes = 2; + } for (unsigned int i = 0; i < size; ++i) { unsigned char c = data[i]; @@ -151,7 +166,12 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned return status; } - nbytes = 0; + if (transport == DC_TRANSPORT_BLE) { + buffer[1]++; + nbytes = 2; + } else { + nbytes = 0; + } } // Escape the character. @@ -173,7 +193,12 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned return status; } - nbytes = 0; + if (transport == DC_TRANSPORT_BLE) { + buffer[1]++; + nbytes = 2; + } else { + nbytes = 0; + } } } @@ -195,70 +220,87 @@ static dc_status_t shearwater_common_slip_read (shearwater_common_device_t *device, unsigned char data[], unsigned int size, unsigned int *actual) { dc_status_t status = DC_STATUS_SUCCESS; + dc_transport_t transport = dc_iostream_get_transport(device->iostream); + unsigned char buffer[256]; unsigned int escaped = 0; unsigned int nbytes = 0; + // Get the packet size. + size_t packetsize = (transport == DC_TRANSPORT_BLE) ? sizeof(buffer) : 1; + // Read bytes until a complete packet has been received. If the // buffer runs out of space, bytes are dropped. The caller can // detect this condition because the return value will be larger // than the supplied buffer size. while (1) { - unsigned char c = 0; - - // Get a single character to process. - status = dc_iostream_read (device->iostream, &c, 1, NULL); + size_t transferred = 0; + status = dc_iostream_read (device->iostream, buffer, packetsize, &transferred); if (status != DC_STATUS_SUCCESS) { ERROR (device->base.context, "Failed to receive the packet."); return status; } - if (c == END || c == ESC) { - if (escaped) { - // If the END or ESC characters are escaped, then we - // have a protocol violation, and an error is reported. - ERROR (device->base.context, "SLIP frame escaped the special character %02x.", c); + size_t offset = 0; + if (transport == DC_TRANSPORT_BLE) { + if (transferred < 2) { + ERROR (device->base.context, "Invalid packet length (" DC_PRINTF_SIZE ").", transferred); return DC_STATUS_PROTOCOL; } - if (c == END) { - // If it's an END character then we're done. - // As a minor optimization, empty packets are ignored. This - // is to avoid bothering the upper layers with all the empty - // packets generated by the duplicate END characters which - // are sent to try to detect line noise. - if (nbytes) { - goto done; + offset = 2; + } + + for (size_t i = offset; i < transferred; ++i) { + unsigned char c = buffer[i]; + + if (c == END || c == ESC) { + if (escaped) { + // If the END or ESC characters are escaped, then we + // have a protocol violation, and an error is reported. + ERROR (device->base.context, "SLIP frame escaped the special character %02x.", c); + return DC_STATUS_PROTOCOL; } - } else { - // If it's an ESC character, get another character and then - // figure out what to store in the packet based on that. - escaped = 1; + + if (c == END) { + // If it's an END character then we're done. + // As a minor optimization, empty packets are ignored. This + // is to avoid bothering the upper layers with all the empty + // packets generated by the duplicate END characters which + // are sent to try to detect line noise. + if (nbytes) { + goto done; + } + } else { + // If it's an ESC character, get another character and then + // figure out what to store in the packet based on that. + escaped = 1; + } + + continue; } - continue; - } + if (escaped) { + // If it's not one of the two escaped characters, then we + // have a protocol violation. The best bet seems to be to + // leave the byte alone and just stuff it into the packet. + switch (c) { + case ESC_END: + c = END; + break; + case ESC_ESC: + c = ESC; + break; + default: + break; + } - if (escaped) { - // If it's not one of the two escaped characters, then we - // have a protocol violation. The best bet seems to be to - // leave the byte alone and just stuff it into the packet. - switch (c) { - case ESC_END: - c = END; - break; - case ESC_ESC: - c = ESC; - break; - default: - break; + escaped = 0; } - escaped = 0; + if (nbytes < size) + data[nbytes] = c; + nbytes++; } - - if (nbytes < size) - data[nbytes] = c; - nbytes++; } done: