Merge branch 'poll'
This commit is contained in:
commit
be0e32b43b
@ -39,6 +39,7 @@ typedef struct dc_custom_cbs_t {
|
|||||||
dc_status_t (*get_lines) (void *userdata, unsigned int *value);
|
dc_status_t (*get_lines) (void *userdata, unsigned int *value);
|
||||||
dc_status_t (*get_available) (void *userdata, size_t *value);
|
dc_status_t (*get_available) (void *userdata, size_t *value);
|
||||||
dc_status_t (*configure) (void *userdata, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
dc_status_t (*configure) (void *userdata, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||||
|
dc_status_t (*poll) (void *userdata, int timeout);
|
||||||
dc_status_t (*read) (void *userdata, void *data, size_t size, size_t *actual);
|
dc_status_t (*read) (void *userdata, void *data, size_t size, size_t *actual);
|
||||||
dc_status_t (*write) (void *userdata, const void *data, size_t size, size_t *actual);
|
dc_status_t (*write) (void *userdata, const void *data, size_t size, size_t *actual);
|
||||||
dc_status_t (*flush) (void *userdata);
|
dc_status_t (*flush) (void *userdata);
|
||||||
|
|||||||
@ -211,6 +211,36 @@ dc_iostream_get_available (dc_iostream_t *iostream, size_t *value);
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
dc_iostream_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
dc_iostream_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll the I/O stream for available data.
|
||||||
|
*
|
||||||
|
* There are three distinct modes available:
|
||||||
|
*
|
||||||
|
* 1. Blocking (timeout < 0):
|
||||||
|
*
|
||||||
|
* The poll operation is blocked until one or more bytes have been
|
||||||
|
* received. If no bytes are received, the operation will block
|
||||||
|
* forever.
|
||||||
|
*
|
||||||
|
* 2. Non-blocking (timeout == 0):
|
||||||
|
*
|
||||||
|
* The poll operation returns immediately, even if no bytes have
|
||||||
|
* been received.
|
||||||
|
*
|
||||||
|
* 3. Timeout (timeout > 0):
|
||||||
|
*
|
||||||
|
* The poll operation is blocked until one or more bytes have been
|
||||||
|
* received. If no bytes are received within the specified amount of
|
||||||
|
* time, the operation will return with a timeout.
|
||||||
|
*
|
||||||
|
* @param[in] iostream A valid I/O stream.
|
||||||
|
* @param[in] timeout The timeout in milliseconds.
|
||||||
|
* @returns #DC_STATUS_SUCCESS on success, #DC_STATUS_TIMEOUT on
|
||||||
|
* timeout, or another #dc_status_t code on failure.
|
||||||
|
*/
|
||||||
|
dc_status_t
|
||||||
|
dc_iostream_poll (dc_iostream_t *iostream, int timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read data from the I/O stream.
|
* Read data from the I/O stream.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -106,6 +106,7 @@ static const dc_iostream_vtable_t dc_bluetooth_vtable = {
|
|||||||
NULL, /* get_lines */
|
NULL, /* get_lines */
|
||||||
dc_socket_get_available, /* get_available */
|
dc_socket_get_available, /* get_available */
|
||||||
NULL, /* configure */
|
NULL, /* configure */
|
||||||
|
dc_socket_poll, /* poll */
|
||||||
dc_socket_read, /* read */
|
dc_socket_read, /* read */
|
||||||
dc_socket_write, /* write */
|
dc_socket_write, /* write */
|
||||||
NULL, /* flush */
|
NULL, /* flush */
|
||||||
|
|||||||
13
src/custom.c
13
src/custom.c
@ -35,6 +35,7 @@ static dc_status_t dc_custom_set_rts (dc_iostream_t *abstract, unsigned int valu
|
|||||||
static dc_status_t dc_custom_get_lines (dc_iostream_t *abstract, unsigned int *value);
|
static dc_status_t dc_custom_get_lines (dc_iostream_t *abstract, unsigned int *value);
|
||||||
static dc_status_t dc_custom_get_available (dc_iostream_t *abstract, size_t *value);
|
static dc_status_t dc_custom_get_available (dc_iostream_t *abstract, size_t *value);
|
||||||
static dc_status_t dc_custom_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
static dc_status_t dc_custom_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||||
|
static dc_status_t dc_custom_poll (dc_iostream_t *abstract, int timeout);
|
||||||
static dc_status_t dc_custom_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual);
|
static dc_status_t dc_custom_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_custom_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual);
|
static dc_status_t dc_custom_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_custom_flush (dc_iostream_t *abstract);
|
static dc_status_t dc_custom_flush (dc_iostream_t *abstract);
|
||||||
@ -60,6 +61,7 @@ static const dc_iostream_vtable_t dc_custom_vtable = {
|
|||||||
dc_custom_get_lines, /* get_lines */
|
dc_custom_get_lines, /* get_lines */
|
||||||
dc_custom_get_available, /* get_available */
|
dc_custom_get_available, /* get_available */
|
||||||
dc_custom_configure, /* configure */
|
dc_custom_configure, /* configure */
|
||||||
|
dc_custom_poll, /* poll */
|
||||||
dc_custom_read, /* read */
|
dc_custom_read, /* read */
|
||||||
dc_custom_write, /* write */
|
dc_custom_write, /* write */
|
||||||
dc_custom_flush, /* flush */
|
dc_custom_flush, /* flush */
|
||||||
@ -181,6 +183,17 @@ dc_custom_configure (dc_iostream_t *abstract, unsigned int baudrate, unsigned in
|
|||||||
return custom->callbacks.configure (custom->userdata, baudrate, databits, parity, stopbits, flowcontrol);
|
return custom->callbacks.configure (custom->userdata, baudrate, databits, parity, stopbits, flowcontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
dc_custom_poll (dc_iostream_t *abstract, int timeout)
|
||||||
|
{
|
||||||
|
dc_custom_t *custom = (dc_custom_t *) abstract;
|
||||||
|
|
||||||
|
if (custom->callbacks.poll == NULL)
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
return custom->callbacks.poll (custom->userdata, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_custom_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
dc_custom_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -326,15 +326,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (delay && device->available == 0) {
|
if (delay && device->available == 0) {
|
||||||
unsigned int count = delay / 100;
|
dc_iostream_poll (device->iostream, delay);
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
|
||||||
size_t available = 0;
|
|
||||||
status = dc_iostream_get_available (device->iostream, &available);
|
|
||||||
if (status == DC_STATUS_SUCCESS && available > 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
dc_iostream_sleep (device->iostream, 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd != EXIT) {
|
if (cmd != EXIT) {
|
||||||
|
|||||||
@ -57,6 +57,8 @@ struct dc_iostream_vtable_t {
|
|||||||
|
|
||||||
dc_status_t (*configure) (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
dc_status_t (*configure) (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||||
|
|
||||||
|
dc_status_t (*poll) (dc_iostream_t *iostream, int timeout);
|
||||||
|
|
||||||
dc_status_t (*read) (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
dc_status_t (*read) (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
||||||
|
|
||||||
dc_status_t (*write) (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
dc_status_t (*write) (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
||||||
|
|||||||
@ -183,6 +183,17 @@ dc_iostream_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned
|
|||||||
return iostream->vtable->configure (iostream, baudrate, databits, parity, stopbits, flowcontrol);
|
return iostream->vtable->configure (iostream, baudrate, databits, parity, stopbits, flowcontrol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
dc_iostream_poll (dc_iostream_t *iostream, int timeout)
|
||||||
|
{
|
||||||
|
if (iostream == NULL || iostream->vtable->poll == NULL)
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
INFO (iostream->context, "Poll: value=%i", timeout);
|
||||||
|
|
||||||
|
return iostream->vtable->poll (iostream, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_iostream_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual)
|
dc_iostream_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -98,6 +98,7 @@ static const dc_iostream_vtable_t dc_irda_vtable = {
|
|||||||
NULL, /* get_lines */
|
NULL, /* get_lines */
|
||||||
dc_socket_get_available, /* get_available */
|
dc_socket_get_available, /* get_available */
|
||||||
NULL, /* configure */
|
NULL, /* configure */
|
||||||
|
dc_socket_poll, /* poll */
|
||||||
dc_socket_read, /* read */
|
dc_socket_read, /* read */
|
||||||
dc_socket_write, /* write */
|
dc_socket_write, /* write */
|
||||||
NULL, /* flush */
|
NULL, /* flush */
|
||||||
|
|||||||
@ -43,6 +43,7 @@ dc_iostream_set_rts
|
|||||||
dc_iostream_get_available
|
dc_iostream_get_available
|
||||||
dc_iostream_get_lines
|
dc_iostream_get_lines
|
||||||
dc_iostream_configure
|
dc_iostream_configure
|
||||||
|
dc_iostream_poll
|
||||||
dc_iostream_read
|
dc_iostream_read
|
||||||
dc_iostream_write
|
dc_iostream_write
|
||||||
dc_iostream_flush
|
dc_iostream_flush
|
||||||
|
|||||||
@ -177,13 +177,11 @@ mares_nemo_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
|
|||||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||||
|
|
||||||
// Wait until some data arrives.
|
// Wait until some data arrives.
|
||||||
size_t available = 0;
|
while (dc_iostream_poll (device->iostream, 100) == DC_STATUS_TIMEOUT) {
|
||||||
while (dc_iostream_get_available (device->iostream, &available) == DC_STATUS_SUCCESS && available == 0) {
|
|
||||||
if (device_is_cancelled (abstract))
|
if (device_is_cancelled (abstract))
|
||||||
return DC_STATUS_CANCELLED;
|
return DC_STATUS_CANCELLED;
|
||||||
|
|
||||||
device_event_emit (abstract, DC_EVENT_WAITING, NULL);
|
device_event_emit (abstract, DC_EVENT_WAITING, NULL);
|
||||||
dc_iostream_sleep (device->iostream, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive the header of the package.
|
// Receive the header of the package.
|
||||||
|
|||||||
@ -74,6 +74,7 @@ static dc_status_t dc_serial_set_rts (dc_iostream_t *iostream, unsigned int valu
|
|||||||
static dc_status_t dc_serial_get_lines (dc_iostream_t *iostream, unsigned int *value);
|
static dc_status_t dc_serial_get_lines (dc_iostream_t *iostream, unsigned int *value);
|
||||||
static dc_status_t dc_serial_get_available (dc_iostream_t *iostream, size_t *value);
|
static dc_status_t dc_serial_get_available (dc_iostream_t *iostream, size_t *value);
|
||||||
static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||||
|
static dc_status_t dc_serial_poll (dc_iostream_t *iostream, int timeout);
|
||||||
static dc_status_t dc_serial_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
static dc_status_t dc_serial_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_serial_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
static dc_status_t dc_serial_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
|
static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
|
||||||
@ -123,6 +124,7 @@ static const dc_iostream_vtable_t dc_serial_vtable = {
|
|||||||
dc_serial_get_lines, /* get_lines */
|
dc_serial_get_lines, /* get_lines */
|
||||||
dc_serial_get_available, /* get_available */
|
dc_serial_get_available, /* get_available */
|
||||||
dc_serial_configure, /* configure */
|
dc_serial_configure, /* configure */
|
||||||
|
dc_serial_poll, /* poll */
|
||||||
dc_serial_read, /* read */
|
dc_serial_read, /* read */
|
||||||
dc_serial_write, /* write */
|
dc_serial_write, /* write */
|
||||||
dc_serial_flush, /* flush */
|
dc_serial_flush, /* flush */
|
||||||
@ -663,6 +665,42 @@ dc_serial_set_latency (dc_iostream_t *abstract, unsigned int milliseconds)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
dc_serial_poll (dc_iostream_t *abstract, int timeout)
|
||||||
|
{
|
||||||
|
dc_serial_t *device = (dc_serial_t *) abstract;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO (&fds);
|
||||||
|
FD_SET (device->fd, &fds);
|
||||||
|
|
||||||
|
struct timeval tv, *ptv = NULL;
|
||||||
|
if (timeout > 0) {
|
||||||
|
tv.tv_sec = (timeout / 1000);
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
ptv = &tv;
|
||||||
|
} else if (timeout == 0) {
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
ptv = &tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = select (device->fd + 1, &fds, NULL, NULL, ptv);
|
||||||
|
} while (rc < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
int errcode = errno;
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
return syserror (errcode);
|
||||||
|
} else if (rc == 0) {
|
||||||
|
return DC_STATUS_TIMEOUT;
|
||||||
|
} else {
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_serial_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
dc_serial_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -43,6 +43,7 @@ static dc_status_t dc_serial_set_rts (dc_iostream_t *iostream, unsigned int valu
|
|||||||
static dc_status_t dc_serial_get_lines (dc_iostream_t *iostream, unsigned int *value);
|
static dc_status_t dc_serial_get_lines (dc_iostream_t *iostream, unsigned int *value);
|
||||||
static dc_status_t dc_serial_get_available (dc_iostream_t *iostream, size_t *value);
|
static dc_status_t dc_serial_get_available (dc_iostream_t *iostream, size_t *value);
|
||||||
static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||||
|
static dc_status_t dc_serial_poll (dc_iostream_t *iostream, int timeout);
|
||||||
static dc_status_t dc_serial_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
static dc_status_t dc_serial_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_serial_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
static dc_status_t dc_serial_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
|
static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
|
||||||
@ -75,6 +76,11 @@ typedef struct dc_serial_t {
|
|||||||
*/
|
*/
|
||||||
DCB dcb;
|
DCB dcb;
|
||||||
COMMTIMEOUTS timeouts;
|
COMMTIMEOUTS timeouts;
|
||||||
|
|
||||||
|
HANDLE hReadWrite, hPoll;
|
||||||
|
OVERLAPPED overlapped;
|
||||||
|
DWORD events;
|
||||||
|
BOOL pending;
|
||||||
} dc_serial_t;
|
} dc_serial_t;
|
||||||
|
|
||||||
static const dc_iterator_vtable_t dc_serial_iterator_vtable = {
|
static const dc_iterator_vtable_t dc_serial_iterator_vtable = {
|
||||||
@ -93,6 +99,7 @@ static const dc_iostream_vtable_t dc_serial_vtable = {
|
|||||||
dc_serial_get_lines, /* get_lines */
|
dc_serial_get_lines, /* get_lines */
|
||||||
dc_serial_get_available, /* get_available */
|
dc_serial_get_available, /* get_available */
|
||||||
dc_serial_configure, /* configure */
|
dc_serial_configure, /* configure */
|
||||||
|
dc_serial_poll, /* poll */
|
||||||
dc_serial_read, /* read */
|
dc_serial_read, /* read */
|
||||||
dc_serial_write, /* write */
|
dc_serial_write, /* write */
|
||||||
dc_serial_flush, /* flush */
|
dc_serial_flush, /* flush */
|
||||||
@ -282,18 +289,41 @@ dc_serial_open (dc_iostream_t **out, dc_context_t *context, const char *name)
|
|||||||
return DC_STATUS_NOMEMORY;
|
return DC_STATUS_NOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default values.
|
||||||
|
memset(&device->overlapped, 0, sizeof(device->overlapped));
|
||||||
|
device->events = 0;
|
||||||
|
device->pending = FALSE;
|
||||||
|
|
||||||
|
// Create a manual reset event for I/O.
|
||||||
|
device->hReadWrite = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||||
|
if (device->hReadWrite == INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
SYSERROR (context, errcode);
|
||||||
|
status = syserror (errcode);
|
||||||
|
goto error_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a manual reset event for polling.
|
||||||
|
device->hPoll = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||||
|
if (device->hPoll == INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
SYSERROR (context, errcode);
|
||||||
|
status = syserror (errcode);
|
||||||
|
goto error_free_readwrite;
|
||||||
|
}
|
||||||
|
|
||||||
// Open the device.
|
// Open the device.
|
||||||
device->hFile = CreateFileA (devname,
|
device->hFile = CreateFileA (devname,
|
||||||
GENERIC_READ | GENERIC_WRITE, 0,
|
GENERIC_READ | GENERIC_WRITE, 0,
|
||||||
NULL, // No security attributes.
|
NULL, // No security attributes.
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
0, // Non-overlapped I/O.
|
FILE_FLAG_OVERLAPPED,
|
||||||
NULL);
|
NULL);
|
||||||
if (device->hFile == INVALID_HANDLE_VALUE) {
|
if (device->hFile == INVALID_HANDLE_VALUE) {
|
||||||
DWORD errcode = GetLastError ();
|
DWORD errcode = GetLastError ();
|
||||||
SYSERROR (context, errcode);
|
SYSERROR (context, errcode);
|
||||||
status = syserror (errcode);
|
status = syserror (errcode);
|
||||||
goto error_free;
|
goto error_free_poll;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current communication settings and timeouts,
|
// Retrieve the current communication settings and timeouts,
|
||||||
@ -308,12 +338,24 @@ dc_serial_open (dc_iostream_t **out, dc_context_t *context, const char *name)
|
|||||||
goto error_close;
|
goto error_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable event monitoring.
|
||||||
|
if (!SetCommMask (device->hFile, EV_RXCHAR)) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
SYSERROR (context, errcode);
|
||||||
|
status = syserror (errcode);
|
||||||
|
goto error_close;
|
||||||
|
}
|
||||||
|
|
||||||
*out = (dc_iostream_t *) device;
|
*out = (dc_iostream_t *) device;
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
error_close:
|
error_close:
|
||||||
CloseHandle (device->hFile);
|
CloseHandle (device->hFile);
|
||||||
|
error_free_poll:
|
||||||
|
CloseHandle (device->hPoll);
|
||||||
|
error_free_readwrite:
|
||||||
|
CloseHandle (device->hReadWrite);
|
||||||
error_free:
|
error_free:
|
||||||
dc_iostream_deallocate ((dc_iostream_t *) device);
|
dc_iostream_deallocate ((dc_iostream_t *) device);
|
||||||
return status;
|
return status;
|
||||||
@ -325,6 +367,9 @@ dc_serial_close (dc_iostream_t *abstract)
|
|||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
dc_serial_t *device = (dc_serial_t *) abstract;
|
dc_serial_t *device = (dc_serial_t *) abstract;
|
||||||
|
|
||||||
|
// Disable event monitoring.
|
||||||
|
SetCommMask (device->hFile, 0);
|
||||||
|
|
||||||
// Restore the initial communication settings and timeouts.
|
// Restore the initial communication settings and timeouts.
|
||||||
if (!SetCommState (device->hFile, &device->dcb) ||
|
if (!SetCommState (device->hFile, &device->dcb) ||
|
||||||
!SetCommTimeouts (device->hFile, &device->timeouts)) {
|
!SetCommTimeouts (device->hFile, &device->timeouts)) {
|
||||||
@ -340,6 +385,9 @@ dc_serial_close (dc_iostream_t *abstract)
|
|||||||
dc_status_set_error(&status, syserror (errcode));
|
dc_status_set_error(&status, syserror (errcode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CloseHandle (device->hPoll);
|
||||||
|
CloseHandle (device->hReadWrite);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,6 +550,64 @@ dc_serial_set_latency (dc_iostream_t *abstract, unsigned int value)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
dc_serial_poll (dc_iostream_t *abstract, int timeout)
|
||||||
|
{
|
||||||
|
dc_serial_t *device = (dc_serial_t *) abstract;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
COMSTAT stats;
|
||||||
|
if (!ClearCommError (device->hFile, NULL, &stats)) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
return syserror (errcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.cbInQue)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!device->pending) {
|
||||||
|
memset(&device->overlapped, 0, sizeof(device->overlapped));
|
||||||
|
device->overlapped.hEvent = device->hPoll;
|
||||||
|
device->events = 0;
|
||||||
|
if (!WaitCommEvent (device->hFile, &device->events, &device->overlapped)) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
if (errcode != ERROR_IO_PENDING) {
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
return syserror (errcode);
|
||||||
|
}
|
||||||
|
device->pending = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device->pending) {
|
||||||
|
DWORD errcode = 0;
|
||||||
|
DWORD rc = WaitForSingleObject (device->hPoll, timeout >= 0 ? (DWORD) timeout : INFINITE);
|
||||||
|
switch (rc) {
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
break;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
return DC_STATUS_TIMEOUT;
|
||||||
|
default:
|
||||||
|
errcode = GetLastError ();
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
return syserror (errcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD dummy = 0;
|
||||||
|
if (!GetOverlappedResult (device->hFile, &device->overlapped, &dummy, TRUE)) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
return syserror (errcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
device->pending = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_serial_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
dc_serial_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
||||||
{
|
{
|
||||||
@ -509,7 +615,19 @@ dc_serial_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual
|
|||||||
dc_serial_t *device = (dc_serial_t *) abstract;
|
dc_serial_t *device = (dc_serial_t *) abstract;
|
||||||
DWORD dwRead = 0;
|
DWORD dwRead = 0;
|
||||||
|
|
||||||
if (!ReadFile (device->hFile, data, size, &dwRead, NULL)) {
|
OVERLAPPED overlapped = {0};
|
||||||
|
overlapped.hEvent = device->hReadWrite;
|
||||||
|
|
||||||
|
if (!ReadFile (device->hFile, data, size, NULL, &overlapped)) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
if (errcode != ERROR_IO_PENDING) {
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
status = syserror (errcode);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetOverlappedResult (device->hFile, &overlapped, &dwRead, TRUE)) {
|
||||||
DWORD errcode = GetLastError ();
|
DWORD errcode = GetLastError ();
|
||||||
SYSERROR (abstract->context, errcode);
|
SYSERROR (abstract->context, errcode);
|
||||||
status = syserror (errcode);
|
status = syserror (errcode);
|
||||||
@ -534,7 +652,19 @@ dc_serial_write (dc_iostream_t *abstract, const void *data, size_t size, size_t
|
|||||||
dc_serial_t *device = (dc_serial_t *) abstract;
|
dc_serial_t *device = (dc_serial_t *) abstract;
|
||||||
DWORD dwWritten = 0;
|
DWORD dwWritten = 0;
|
||||||
|
|
||||||
if (!WriteFile (device->hFile, data, size, &dwWritten, NULL)) {
|
OVERLAPPED overlapped = {0};
|
||||||
|
overlapped.hEvent = device->hReadWrite;
|
||||||
|
|
||||||
|
if (!WriteFile (device->hFile, data, size, NULL, &overlapped)) {
|
||||||
|
DWORD errcode = GetLastError ();
|
||||||
|
if (errcode != ERROR_IO_PENDING) {
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
status = syserror (errcode);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetOverlappedResult (device->hFile, &overlapped, &dwWritten, TRUE)) {
|
||||||
DWORD errcode = GetLastError ();
|
DWORD errcode = GetLastError ();
|
||||||
SYSERROR (abstract->context, errcode);
|
SYSERROR (abstract->context, errcode);
|
||||||
status = syserror (errcode);
|
status = syserror (errcode);
|
||||||
|
|||||||
36
src/socket.c
36
src/socket.c
@ -186,6 +186,42 @@ dc_socket_get_available (dc_iostream_t *abstract, size_t *value)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
dc_socket_poll (dc_iostream_t *abstract, int timeout)
|
||||||
|
{
|
||||||
|
dc_socket_t *socket = (dc_socket_t *) abstract;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
fd_set fds;
|
||||||
|
FD_ZERO (&fds);
|
||||||
|
FD_SET (socket->fd, &fds);
|
||||||
|
|
||||||
|
struct timeval tv, *ptv = NULL;
|
||||||
|
if (timeout > 0) {
|
||||||
|
tv.tv_sec = (timeout / 1000);
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
ptv = &tv;
|
||||||
|
} else if (timeout == 0) {
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
ptv = &tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = select (socket->fd + 1, &fds, NULL, NULL, ptv);
|
||||||
|
} while (rc < 0 && S_ERRNO == S_EINTR);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
s_errcode_t errcode = S_ERRNO;
|
||||||
|
SYSERROR (abstract->context, errcode);
|
||||||
|
return dc_socket_syserror(errcode);
|
||||||
|
} else if (rc == 0) {
|
||||||
|
return DC_STATUS_TIMEOUT;
|
||||||
|
} else {
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_socket_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
dc_socket_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -108,6 +108,9 @@ dc_socket_set_timeout (dc_iostream_t *iostream, int timeout);
|
|||||||
dc_status_t
|
dc_status_t
|
||||||
dc_socket_get_available (dc_iostream_t *iostream, size_t *value);
|
dc_socket_get_available (dc_iostream_t *iostream, size_t *value);
|
||||||
|
|
||||||
|
dc_status_t
|
||||||
|
dc_socket_poll (dc_iostream_t *iostream, int timeout);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
dc_socket_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
dc_socket_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
||||||
|
|
||||||
|
|||||||
@ -94,6 +94,7 @@ static dc_status_t dc_usbhid_iterator_next (dc_iterator_t *iterator, void *item)
|
|||||||
static dc_status_t dc_usbhid_iterator_free (dc_iterator_t *iterator);
|
static dc_status_t dc_usbhid_iterator_free (dc_iterator_t *iterator);
|
||||||
|
|
||||||
static dc_status_t dc_usbhid_set_timeout (dc_iostream_t *iostream, int timeout);
|
static dc_status_t dc_usbhid_set_timeout (dc_iostream_t *iostream, int timeout);
|
||||||
|
static dc_status_t dc_usbhid_poll (dc_iostream_t *iostream, int timeout);
|
||||||
static dc_status_t dc_usbhid_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
static dc_status_t dc_usbhid_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_usbhid_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
static dc_status_t dc_usbhid_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
|
||||||
static dc_status_t dc_usbhid_close (dc_iostream_t *iostream);
|
static dc_status_t dc_usbhid_close (dc_iostream_t *iostream);
|
||||||
@ -144,6 +145,7 @@ static const dc_iostream_vtable_t dc_usbhid_vtable = {
|
|||||||
NULL, /* get_lines */
|
NULL, /* get_lines */
|
||||||
NULL, /* get_available */
|
NULL, /* get_available */
|
||||||
NULL, /* configure */
|
NULL, /* configure */
|
||||||
|
dc_usbhid_poll, /* poll */
|
||||||
dc_usbhid_read, /* read */
|
dc_usbhid_read, /* read */
|
||||||
dc_usbhid_write, /* write */
|
dc_usbhid_write, /* write */
|
||||||
NULL, /* flush */
|
NULL, /* flush */
|
||||||
@ -685,6 +687,12 @@ dc_usbhid_set_timeout (dc_iostream_t *abstract, int timeout)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t
|
||||||
|
dc_usbhid_poll (dc_iostream_t *abstract, int timeout)
|
||||||
|
{
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_usbhid_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
dc_usbhid_read (dc_iostream_t *abstract, void *data, size_t size, size_t *actual)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -309,14 +309,13 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
|
|||||||
{
|
{
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
dc_device_t *abstract = (dc_device_t *) device;
|
dc_device_t *abstract = (dc_device_t *) device;
|
||||||
size_t available = 0;
|
|
||||||
|
|
||||||
// Enable progress notifications.
|
// Enable progress notifications.
|
||||||
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
||||||
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);
|
device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);
|
||||||
|
|
||||||
// Waiting for greeting message.
|
// Waiting for greeting message.
|
||||||
while (dc_iostream_get_available (device->iostream, &available) == DC_STATUS_SUCCESS && available == 0) {
|
while (dc_iostream_poll (device->iostream, 300) == DC_STATUS_TIMEOUT) {
|
||||||
if (device_is_cancelled (abstract))
|
if (device_is_cancelled (abstract))
|
||||||
return DC_STATUS_CANCELLED;
|
return DC_STATUS_CANCELLED;
|
||||||
|
|
||||||
@ -330,8 +329,6 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
|
|||||||
ERROR (abstract->context, "Failed to reject the packet.");
|
ERROR (abstract->context, "Failed to reject the packet.");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_iostream_sleep (device->iostream, 300);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the ID string.
|
// Read the ID string.
|
||||||
@ -385,12 +382,11 @@ uwatec_memomouse_dump_internal (uwatec_memomouse_device_t *device, dc_buffer_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the data packet.
|
// Wait for the data packet.
|
||||||
while (dc_iostream_get_available (device->iostream, &available) == DC_STATUS_SUCCESS && available == 0) {
|
while (dc_iostream_poll (device->iostream, 100) == DC_STATUS_TIMEOUT) {
|
||||||
if (device_is_cancelled (abstract))
|
if (device_is_cancelled (abstract))
|
||||||
return DC_STATUS_CANCELLED;
|
return DC_STATUS_CANCELLED;
|
||||||
|
|
||||||
device_event_emit (&device->base, DC_EVENT_WAITING, NULL);
|
device_event_emit (&device->base, DC_EVENT_WAITING, NULL);
|
||||||
dc_iostream_sleep (device->iostream, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the current system time.
|
// Fetch the current system time.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user