| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QtBluetooth/QBluetoothAddress>
 | 
					
						
							|  |  |  | #include <QtBluetooth/QBluetoothSocket>
 | 
					
						
							|  |  |  | #include <QEventLoop>
 | 
					
						
							|  |  |  | #include <QTimer>
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:11:02 +03:00
										 |  |  | #include <QDebug>
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 11:47:48 -07:00
										 |  |  | #include <libdivecomputer/version.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(SSRF_CUSTOM_SERIAL)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							|  |  |  | 	#include <winsock2.h>
 | 
					
						
							|  |  |  | 	#include <windows.h>
 | 
					
						
							|  |  |  | 	#include <ws2bth.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | #include <libdivecomputer/custom_serial.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | typedef struct serial_t { | 
					
						
							|  |  |  | 	/* Library context. */ | 
					
						
							|  |  |  | 	dc_context_t *context; | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * RFCOMM socket used for Bluetooth Serial communication. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							|  |  |  | 	SOCKET socket; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	QBluetoothSocket *socket; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	long timeout; | 
					
						
							|  |  |  | } serial_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qt_serial_open(serial_t **out, dc_context_t *context, const char* devaddr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (out == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Allocate memory.
 | 
					
						
							|  |  |  | 	serial_t *serial_port = (serial_t *) malloc (sizeof (serial_t)); | 
					
						
							|  |  |  | 	if (serial_port == NULL) { | 
					
						
							|  |  |  | 		return DC_STATUS_NOMEMORY; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Library context.
 | 
					
						
							|  |  |  | 	serial_port->context = context; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Default to blocking reads.
 | 
					
						
							|  |  |  | 	serial_port->timeout = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							| 
									
										
										
										
											2015-08-18 21:37:11 +03:00
										 |  |  | 	// Create a RFCOMM socket
 | 
					
						
							|  |  |  | 	serial_port->socket = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-10 07:19:03 +03:00
										 |  |  | 	if (serial_port->socket == INVALID_SOCKET) { | 
					
						
							|  |  |  | 		free(serial_port); | 
					
						
							| 
									
										
										
										
											2015-08-18 21:37:11 +03:00
										 |  |  | 		return DC_STATUS_IO; | 
					
						
							| 
									
										
										
										
											2015-09-10 07:19:03 +03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-18 21:37:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	SOCKADDR_BTH socketBthAddress; | 
					
						
							|  |  |  | 	int socketBthAddressBth = sizeof (socketBthAddress); | 
					
						
							|  |  |  | 	char *address = strdup(devaddr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ZeroMemory(&socketBthAddress, socketBthAddressBth); | 
					
						
							|  |  |  | 	qDebug() << "Trying to connect to address " << devaddr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (WSAStringToAddressA(address, | 
					
						
							|  |  |  | 				AF_BTH, | 
					
						
							|  |  |  | 				NULL, | 
					
						
							|  |  |  | 				(LPSOCKADDR) &socketBthAddress, | 
					
						
							|  |  |  | 				&socketBthAddressBth | 
					
						
							|  |  |  | 				) != 0) { | 
					
						
							|  |  |  | 		qDebug() << "FAiled to convert the address " << address; | 
					
						
							|  |  |  | 		free(address); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return DC_STATUS_IO; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	free(address); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	socketBthAddress.addressFamily = AF_BTH; | 
					
						
							|  |  |  | 	socketBthAddress.port = BT_PORT_ANY; | 
					
						
							|  |  |  | 	memset(&socketBthAddress.serviceClassId, 0, sizeof(socketBthAddress.serviceClassId)); | 
					
						
							|  |  |  | 	socketBthAddress.serviceClassId = SerialPortServiceClass_UUID; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Try to connect to the device
 | 
					
						
							|  |  |  | 	if (::connect(serial_port->socket, | 
					
						
							|  |  |  | 		      (struct sockaddr *) &socketBthAddress, | 
					
						
							|  |  |  | 		      socketBthAddressBth | 
					
						
							|  |  |  | 		      ) != 0) { | 
					
						
							|  |  |  | 		qDebug() << "Failed to connect to device"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return DC_STATUS_NODEVICE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	qDebug() << "Succesfully connected to device"; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	// Create a RFCOMM socket
 | 
					
						
							|  |  |  | 	serial_port->socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wait until the connection succeeds or until an error occurs
 | 
					
						
							|  |  |  | 	QEventLoop loop; | 
					
						
							|  |  |  | 	loop.connect(serial_port->socket, SIGNAL(connected()), SLOT(quit())); | 
					
						
							|  |  |  | 	loop.connect(serial_port->socket, SIGNAL(error(QBluetoothSocket::SocketError)), SLOT(quit())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create a timer. If the connection doesn't succeed after five seconds or no error occurs then stop the opening step
 | 
					
						
							|  |  |  | 	QTimer timer; | 
					
						
							|  |  |  | 	int msec = 5000; | 
					
						
							|  |  |  | 	timer.setSingleShot(true); | 
					
						
							|  |  |  | 	loop.connect(&timer, SIGNAL(timeout()), SLOT(quit())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-13 23:37:49 +03:00
										 |  |  | #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	// First try to connect on RFCOMM channel 1. This is the default channel for most devices
 | 
					
						
							|  |  |  | 	QBluetoothAddress remoteDeviceAddress(devaddr); | 
					
						
							| 
									
										
										
										
											2015-09-29 21:12:55 +02:00
										 |  |  | 	serial_port->socket->connectToService(remoteDeviceAddress, 1, QIODevice::ReadWrite | QIODevice::Unbuffered); | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	timer.start(msec); | 
					
						
							|  |  |  | 	loop.exec(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (serial_port->socket->state() == QBluetoothSocket::ConnectingState) { | 
					
						
							|  |  |  | 		// It seems that the connection on channel 1 took more than expected. Wait another 15 seconds
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:11:02 +03:00
										 |  |  | 		qDebug() << "The connection on RFCOMM channel number 1 took more than expected. Wait another 15 seconds."; | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		timer.start(3 * msec); | 
					
						
							|  |  |  | 		loop.exec(); | 
					
						
							|  |  |  | 	} else if (serial_port->socket->state() == QBluetoothSocket::UnconnectedState) { | 
					
						
							|  |  |  | 		// Try to connect on channel number 5. Maybe this is a Shearwater Petrel2 device.
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:11:02 +03:00
										 |  |  | 		qDebug() << "Connection on channel 1 failed. Trying on channel number 5."; | 
					
						
							| 
									
										
										
										
											2015-09-29 21:12:55 +02:00
										 |  |  | 		serial_port->socket->connectToService(remoteDeviceAddress, 5, QIODevice::ReadWrite | QIODevice::Unbuffered); | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		timer.start(msec); | 
					
						
							|  |  |  | 		loop.exec(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (serial_port->socket->state() == QBluetoothSocket::ConnectingState) { | 
					
						
							|  |  |  | 			// It seems that the connection on channel 5 took more than expected. Wait another 15 seconds
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:11:02 +03:00
										 |  |  | 			qDebug() << "The connection on RFCOMM channel number 5 took more than expected. Wait another 15 seconds."; | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 			timer.start(3 * msec); | 
					
						
							|  |  |  | 			loop.exec(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-18 23:14:00 +03:00
										 |  |  | #elif defined(Q_OS_ANDROID) || (QT_VERSION >= 0x050500 && defined(Q_OS_MAC))
 | 
					
						
							| 
									
										
										
										
											2015-07-13 23:37:49 +03:00
										 |  |  | 	// Try to connect to the device using the uuid of the Serial Port Profile service
 | 
					
						
							|  |  |  | 	QBluetoothAddress remoteDeviceAddress(devaddr); | 
					
						
							|  |  |  | 	serial_port->socket->connectToService(remoteDeviceAddress, QBluetoothUuid(QBluetoothUuid::SerialPort)); | 
					
						
							|  |  |  | 	timer.start(msec); | 
					
						
							|  |  |  | 	loop.exec(); | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-13 23:37:49 +03:00
										 |  |  | 	if (serial_port->socket->state() == QBluetoothSocket::ConnectingState || | 
					
						
							|  |  |  | 	    serial_port->socket->state() == QBluetoothSocket::ServiceLookupState) { | 
					
						
							|  |  |  | 		// It seems that the connection step took more than expected. Wait another 20 seconds.
 | 
					
						
							|  |  |  | 		qDebug() << "The connection step took more than expected. Wait another 20 seconds"; | 
					
						
							|  |  |  | 		timer.start(4 * msec); | 
					
						
							|  |  |  | 		loop.exec(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	if (serial_port->socket->state() != QBluetoothSocket::ConnectedState) { | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Get the latest error and try to match it with one from libdivecomputer
 | 
					
						
							|  |  |  | 		QBluetoothSocket::SocketError err = serial_port->socket->error(); | 
					
						
							| 
									
										
										
										
											2015-07-06 17:11:02 +03:00
										 |  |  | 		qDebug() << "Failed to connect to device " << devaddr << ". Device state " << serial_port->socket->state() << ". Error: " << err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-09 18:34:49 +03:00
										 |  |  | 		free (serial_port); | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		switch(err) { | 
					
						
							|  |  |  | 		case QBluetoothSocket::HostNotFoundError: | 
					
						
							|  |  |  | 		case QBluetoothSocket::ServiceNotFoundError: | 
					
						
							|  |  |  | 			return DC_STATUS_NODEVICE; | 
					
						
							|  |  |  | 		case QBluetoothSocket::UnsupportedProtocolError: | 
					
						
							|  |  |  | 			return DC_STATUS_PROTOCOL; | 
					
						
							| 
									
										
										
										
											2015-07-08 10:58:31 -07:00
										 |  |  | #if QT_VERSION >= 0x050400
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		case QBluetoothSocket::OperationError: | 
					
						
							|  |  |  | 			return DC_STATUS_UNSUPPORTED; | 
					
						
							| 
									
										
										
										
											2015-07-08 10:58:31 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		case QBluetoothSocket::NetworkError: | 
					
						
							|  |  |  | 			return DC_STATUS_IO; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return QBluetoothSocket::UnknownSocketError; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	*out = serial_port; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return DC_STATUS_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qt_serial_close(serial_t *device) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | 	if (device == NULL) | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		return DC_STATUS_SUCCESS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							| 
									
										
										
										
											2015-08-18 21:37:50 +03:00
										 |  |  | 	// Cleanup
 | 
					
						
							|  |  |  | 	closesocket(device->socket); | 
					
						
							|  |  |  | 	free(device); | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	if (device->socket == NULL) { | 
					
						
							|  |  |  | 		free(device); | 
					
						
							|  |  |  | 		return DC_STATUS_SUCCESS; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	device->socket->close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	delete device->socket; | 
					
						
							|  |  |  | 	free(device); | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return DC_STATUS_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qt_serial_read(serial_t *device, void* data, unsigned int size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							|  |  |  | 	if (device == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 21:38:17 +03:00
										 |  |  | 	unsigned int nbytes = 0; | 
					
						
							|  |  |  | 	int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (nbytes < size) { | 
					
						
							|  |  |  | 		rc = recv (device->socket, (char *) data + nbytes, size - nbytes, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (rc < 0) { | 
					
						
							|  |  |  | 			return -1; // Error during recv call.
 | 
					
						
							|  |  |  | 		} else if (rc == 0) { | 
					
						
							|  |  |  | 			break; // EOF reached.
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		nbytes += rc; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 21:38:17 +03:00
										 |  |  | 	return nbytes; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	if (device == NULL || device->socket == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 13:59:14 -07:00
										 |  |  | 	unsigned int nbytes = 0; | 
					
						
							|  |  |  | 	int rc; | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 23:33:15 +02:00
										 |  |  | 	while(nbytes < size && device->socket->state() == QBluetoothSocket::ConnectedState) | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		rc = device->socket->read((char *) data + nbytes, size - nbytes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (rc < 0) { | 
					
						
							|  |  |  | 			if (errno == EINTR || errno == EAGAIN) | 
					
						
							|  |  |  | 			    continue; // Retry.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return -1; // Something really bad happened :-(
 | 
					
						
							|  |  |  | 		} else if (rc == 0) { | 
					
						
							|  |  |  | 			// Wait until the device is available for read operations
 | 
					
						
							|  |  |  | 			QEventLoop loop; | 
					
						
							| 
									
										
										
										
											2015-09-22 23:33:14 +02:00
										 |  |  | 			QTimer timer; | 
					
						
							|  |  |  | 			timer.setSingleShot(true); | 
					
						
							|  |  |  | 			loop.connect(&timer, SIGNAL(timeout()), SLOT(quit())); | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 			loop.connect(device->socket, SIGNAL(readyRead()), SLOT(quit())); | 
					
						
							| 
									
										
										
										
											2015-09-22 23:33:14 +02:00
										 |  |  | 			timer.start(device->timeout); | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 			loop.exec(); | 
					
						
							| 
									
										
										
										
											2015-09-22 23:33:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (!timer.isActive()) | 
					
						
							|  |  |  | 				return nbytes; | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		nbytes += rc; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nbytes; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qt_serial_write(serial_t *device, const void* data, unsigned int size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							|  |  |  | 	if (device == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 21:38:47 +03:00
										 |  |  | 	unsigned int nbytes = 0; | 
					
						
							|  |  |  | 	int rc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (nbytes < size) { | 
					
						
							|  |  |  | 	    rc = send(device->socket, (char *) data + nbytes, size - nbytes, 0); | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 21:38:47 +03:00
										 |  |  | 	    if (rc < 0) { | 
					
						
							|  |  |  | 	       return -1; // Error during send call.
 | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	    nbytes += rc; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nbytes; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	if (device == NULL || device->socket == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 13:59:14 -07:00
										 |  |  | 	unsigned int nbytes = 0; | 
					
						
							|  |  |  | 	int rc; | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 23:33:15 +02:00
										 |  |  | 	while(nbytes < size && device->socket->state() == QBluetoothSocket::ConnectedState) | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		rc = device->socket->write((char *) data + nbytes, size - nbytes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (rc < 0) { | 
					
						
							|  |  |  | 			if (errno == EINTR || errno == EAGAIN) | 
					
						
							|  |  |  | 			    continue; // Retry.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return -1; // Something really bad happened :-(
 | 
					
						
							|  |  |  | 		} else if (rc == 0) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		nbytes += rc; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nbytes; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qt_serial_flush(serial_t *device, int queue) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:07:42 -08:00
										 |  |  | 	(void)queue; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | 	if (device == NULL) | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if !defined(Q_OS_WIN)
 | 
					
						
							|  |  |  | 	if (device->socket == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	// TODO: add implementation
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return DC_STATUS_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qt_serial_get_received(serial_t *device) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							|  |  |  | 	if (device == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO use WSAIoctl to get the information
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	if (device == NULL || device->socket == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return device->socket->bytesAvailable(); | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int qt_serial_get_transmitted(serial_t *device) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #if defined(Q_OS_WIN)
 | 
					
						
							|  |  |  | 	if (device == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO add implementation
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 	if (device == NULL || device->socket == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return device->socket->bytesToWrite(); | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 20:17:45 +03:00
										 |  |  | static int qt_serial_set_timeout(serial_t *device, long timeout) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (device == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	device->timeout = timeout; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return DC_STATUS_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-18 20:51:10 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | const dc_serial_operations_t qt_serial_ops = { | 
					
						
							|  |  |  | 	.open = qt_serial_open, | 
					
						
							|  |  |  | 	.close = qt_serial_close, | 
					
						
							|  |  |  | 	.read = qt_serial_read, | 
					
						
							|  |  |  | 	.write = qt_serial_write, | 
					
						
							|  |  |  | 	.flush = qt_serial_flush, | 
					
						
							|  |  |  | 	.get_received = qt_serial_get_received, | 
					
						
							| 
									
										
										
										
											2015-08-18 20:17:45 +03:00
										 |  |  | 	.get_transmitted = qt_serial_get_transmitted, | 
					
						
							|  |  |  | 	.set_timeout = qt_serial_set_timeout | 
					
						
							| 
									
										
										
										
											2015-07-06 17:07:34 +03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void dc_serial_init (dc_serial_t *serial, void *data, const dc_serial_operations_t *ops); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | dc_status_t dc_serial_qt_open(dc_serial_t **out, dc_context_t *context, const char *devaddr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (out == NULL) | 
					
						
							|  |  |  | 		return DC_STATUS_INVALIDARGS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Allocate memory.
 | 
					
						
							|  |  |  | 	dc_serial_t *serial_device = (dc_serial_t *) malloc (sizeof (dc_serial_t)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (serial_device == NULL) { | 
					
						
							|  |  |  | 		return DC_STATUS_NOMEMORY; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Initialize data and function pointers
 | 
					
						
							|  |  |  | 	dc_serial_init(serial_device, NULL, &qt_serial_ops); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Open the serial device.
 | 
					
						
							|  |  |  | 	dc_status_t rc = (dc_status_t)qt_serial_open (&serial_device->port, context, devaddr); | 
					
						
							|  |  |  | 	if (rc != DC_STATUS_SUCCESS) { | 
					
						
							|  |  |  | 		free (serial_device); | 
					
						
							|  |  |  | 		return rc; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set the type of the device
 | 
					
						
							|  |  |  | 	serial_device->type = DC_TRANSPORT_BLUETOOTH; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*out = serial_device; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return DC_STATUS_SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-07 11:47:48 -07:00
										 |  |  | #endif
 |