diff options
Diffstat (limited to 'core/qtserialbluetooth.cpp')
-rw-r--r-- | core/qtserialbluetooth.cpp | 180 |
1 files changed, 176 insertions, 4 deletions
diff --git a/core/qtserialbluetooth.cpp b/core/qtserialbluetooth.cpp index ab05a1c73..e6b004f03 100644 --- a/core/qtserialbluetooth.cpp +++ b/core/qtserialbluetooth.cpp @@ -37,6 +37,7 @@ void addBtUuid(QBluetoothUuid uuid) extern "C" { typedef struct qt_serial_t { + dc_custom_io_t *ops; /* * RFCOMM socket used for Bluetooth Serial communication. */ @@ -48,15 +49,169 @@ typedef struct qt_serial_t { long timeout; } qt_serial_t; +#ifdef BLE_SUPPORT + +static dc_status_t ble_serial_open(void **userdata, const char* devaddr); +static dc_status_t ble_serial_close(void **userdata); +static dc_status_t ble_serial_read(void **userdata, void* data, size_t size, size_t *actual); +static dc_status_t ble_serial_write(void **userdata, const void* data, size_t size, size_t *actual); +static dc_status_t ble_serial_purge(void **userdata, dc_direction_t queue); +static dc_status_t ble_serial_get_available(void **userdata, size_t *available); + +static dc_custom_io_t ble_serial_ops = { + .userdata = NULL, + + .serial_open = ble_serial_open, + .serial_close = ble_serial_close, + .serial_read = ble_serial_read, + .serial_write = ble_serial_write, + .serial_purge = ble_serial_purge, + .serial_get_available = ble_serial_get_available, + .serial_set_timeout = NULL, // the regular qt_set_timeout is fine +// These doesn't make sense over bluetooth +// NULL means NOP + .serial_configure = NULL, + .serial_set_dtr = NULL, + .serial_set_rts = NULL, + .serial_set_halfduplex = NULL, + .serial_set_break = NULL, + + .packet_size = 20, + .packet_open = qt_ble_open, + .packet_close = qt_ble_close, + .packet_read = qt_ble_read, + .packet_write = qt_ble_write, +}; + +static struct qt_serial_t serial_over_ble = { + .ops = &ble_serial_ops, +}; + + +static dc_status_t ble_serial_open(void **userdata, const char* devaddr) +{ + *userdata = &serial_over_ble; + return qt_ble_open(&ble_serial_ops, NULL, devaddr); +} + +#define BUFSZ 1024 +static struct { + unsigned int out_bytes, in_bytes, in_pos; + unsigned char in[BUFSIZ]; + unsigned char out[BUFSIZ]; +} buffer; + +static dc_status_t ble_serial_flush_write(void) +{ + int bytes = buffer.out_bytes; + + if (!bytes) + return DC_STATUS_SUCCESS; + buffer.out_bytes = 0; + ble_serial_ops.packet_write(&ble_serial_ops, buffer.out, bytes, NULL); +} + +static dc_status_t ble_serial_flush_read(void) +{ + buffer.in_bytes = buffer.in_pos = 0; + return DC_STATUS_SUCCESS; +} + +static dc_status_t ble_serial_close(void **userdata) +{ + ble_serial_flush_write(); + *userdata = NULL; + return qt_ble_close(&ble_serial_ops); +} + +static dc_status_t ble_serial_read(void **userdata, void* data, size_t size, size_t *actual) +{ + int len; + + if (buffer.in_pos >= buffer.in_bytes) { + dc_status_t rc; + size_t received; + + ble_serial_flush_write(); + rc = ble_serial_ops.packet_read(&ble_serial_ops, buffer.in, sizeof(buffer.in), &received); + if (rc != DC_STATUS_SUCCESS) + return rc; + if (!received) + return DC_STATUS_IO; + buffer.in_pos = 0; + buffer.in_bytes = received; + } + + len = buffer.in_bytes - buffer.in_pos; + if (len > size) + len = size; + + memcpy(data, buffer.in + buffer.in_pos, len); + buffer.in_pos += len; + if (actual) + *actual = len; + return DC_STATUS_SUCCESS; +} + +static dc_status_t ble_serial_write(void **userdata, const void* data, size_t size, size_t *actual) +{ + dc_status_t rc = DC_STATUS_SUCCESS; + size_t transferred = 0; + + ble_serial_flush_read(); + while (size) { + int len = sizeof(buffer.out) - buffer.out_bytes; + + if (len > size) + len = size; + memcpy(buffer.out + buffer.out_bytes, data, len); + buffer.out_bytes += len; + + if (buffer.out_bytes == sizeof(buffer.out)) { + rc = ble_serial_flush_write(); + if (rc != DC_STATUS_SUCCESS) + break; + } + transferred += len; + data = (const void *) (len + (const char *)data); + size -= len; + } + if (actual) + *actual = transferred; + return DC_STATUS_SUCCESS; +} + +static dc_status_t ble_serial_purge(void **userdata, dc_direction_t queue) +{ + /* Do we care? */ + return DC_STATUS_SUCCESS; +} + +static dc_status_t ble_serial_get_available(void **userdata, size_t *available) +{ + *available = buffer.in_bytes - buffer.in_pos; + return DC_STATUS_SUCCESS; +} + +#endif + + static dc_status_t qt_serial_open(void **userdata, const char* devaddr) { +#ifdef BLE_SUPPORT + if (!strncmp(devaddr, "LE:", 3)) + return ble_serial_open(userdata, devaddr); +#endif + // Allocate memory. qt_serial_t *serial_port = (qt_serial_t *) malloc (sizeof (qt_serial_t)); if (serial_port == NULL) { return DC_STATUS_NOMEMORY; } + serial_port->ops = NULL; + // Default to blocking reads. serial_port->timeout = -1; @@ -205,6 +360,9 @@ static dc_status_t qt_serial_close(void **userdata) if (device == NULL) return DC_STATUS_SUCCESS; + if (device && device->ops) + return device->ops->serial_close(userdata); + #if defined(Q_OS_WIN) // Cleanup closesocket(device->socket); @@ -230,6 +388,9 @@ static dc_status_t qt_serial_read(void **userdata, void* data, size_t size, size { qt_serial_t *device = (qt_serial_t*) *userdata; + if (device && device->ops) + return device->ops->serial_read(userdata, data, size, actual); + #if defined(Q_OS_WIN) if (device == NULL) return DC_STATUS_INVALIDARGS; @@ -291,6 +452,9 @@ static dc_status_t qt_serial_write(void **userdata, const void* data, size_t siz { qt_serial_t *device = (qt_serial_t*) *userdata; + if (device && device->ops) + return device->ops->serial_write(userdata, data, size, actual); + #if defined(Q_OS_WIN) if (device == NULL) return DC_STATUS_INVALIDARGS; @@ -336,9 +500,13 @@ static dc_status_t qt_serial_write(void **userdata, const void* data, size_t siz return DC_STATUS_SUCCESS; } -static dc_status_t qt_serial_flush(void **userdata, dc_direction_t queue) +static dc_status_t qt_serial_purge(void **userdata, dc_direction_t queue) { qt_serial_t *device = (qt_serial_t*) *userdata; + + if (device && device->ops) + return device->ops->serial_purge(userdata, queue); + (void)queue; if (device == NULL) return DC_STATUS_INVALIDARGS; @@ -351,9 +519,13 @@ static dc_status_t qt_serial_flush(void **userdata, dc_direction_t queue) return DC_STATUS_SUCCESS; } -static dc_status_t qt_serial_get_received(void **userdata, size_t *available) +static dc_status_t qt_serial_get_available(void **userdata, size_t *available) { qt_serial_t *device = (qt_serial_t*) *userdata; + + if (device && device->ops) + return device->ops->serial_get_available(userdata, available); + #if defined(Q_OS_WIN) if (device == NULL) return DC_STATUS_INVALIDARGS; @@ -409,8 +581,8 @@ dc_custom_io_t qt_serial_ops = { .serial_close = qt_serial_close, .serial_read = qt_serial_read, .serial_write = qt_serial_write, - .serial_purge = qt_serial_flush, - .serial_get_available = qt_serial_get_received, + .serial_purge = qt_serial_purge, + .serial_get_available = qt_serial_get_available, .serial_set_timeout = qt_serial_set_timeout, // These doesn't make sense over bluetooth // NULL means NOP |