Merge branch 'ioctl'

This commit is contained in:
Jef Driesen 2020-01-06 21:27:38 +01:00
commit a67bab58ca
17 changed files with 235 additions and 57 deletions

View File

@ -9,6 +9,7 @@ libdivecomputer_HEADERS = \
iostream.h \
serial.h \
bluetooth.h \
ble.h \
irda.h \
usbhid.h \
custom.h \

View File

@ -0,0 +1,39 @@
/*
* libdivecomputer
*
* Copyright (C) 2019 Jef Driesen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef DC_BLE_H
#define DC_BLE_H
#include "ioctl.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* Get the remote device name.
*/
#define DC_IOCTL_BLE_GET_NAME DC_IOCTL_IOR('b', 0, DC_IOCTL_SIZE_VARIABLE)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DC_BLE_H */

View File

@ -32,7 +32,6 @@ extern "C" {
typedef struct dc_custom_cbs_t {
dc_status_t (*set_timeout) (void *userdata, int timeout);
dc_status_t (*set_latency) (void *userdata, unsigned int value);
dc_status_t (*set_break) (void *userdata, unsigned int value);
dc_status_t (*set_dtr) (void *userdata, unsigned int value);
dc_status_t (*set_rts) (void *userdata, unsigned int value);
@ -42,6 +41,7 @@ typedef struct dc_custom_cbs_t {
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 (*write) (void *userdata, const void *data, size_t size, size_t *actual);
dc_status_t (*ioctl) (void *userdata, unsigned int request, void *data, size_t size);
dc_status_t (*flush) (void *userdata);
dc_status_t (*purge) (void *userdata, dc_direction_t direction);
dc_status_t (*sleep) (void *userdata, unsigned int milliseconds);

View File

@ -0,0 +1,73 @@
/*
* libdivecomputer
*
* Copyright (C) 2019 Jef Driesen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef DC_IOCTL_H
#define DC_IOCTL_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Ioctl direction bits.
*
* Note: WRITE means the application is writing and the driver is
* reading. READ means the application is reading and the driver is
* writing.
*/
#define DC_IOCTL_DIR_NONE 0u
#define DC_IOCTL_DIR_READ 1u
#define DC_IOCTL_DIR_WRITE 2u
/*
* Ioctl variable size bits.
*/
#define DC_IOCTL_SIZE_VARIABLE 0
/*
* Helper macro to encode ioctl numbers.
*/
#define DC_IOCTL_BASE(dir,type,nr,size) \
(((dir) << 30) | \
((size) << 16) | \
((type) << 8) | \
((nr) << 0))
/*
* Macros to encode ioctl numbers.
*/
#define DC_IOCTL_IO(type,nr) DC_IOCTL_BASE(DC_IOCTL_DIR_NONE, (type), (nr), 0)
#define DC_IOCTL_IOR(type,nr,size) DC_IOCTL_BASE(DC_IOCTL_DIR_READ, (type), (nr), (size))
#define DC_IOCTL_IOW(type,nr,size) DC_IOCTL_BASE(DC_IOCTL_DIR_WRITE, (type), (nr), (size))
#define DC_IOCTL_IORW(type,nr,size) DC_IOCTL_BASE(DC_IOCTL_DIR_READ | DC_IOCTL_DIR_WRITE, (type), (nr), (size))
/*
* Macros to decode ioctl numbers.
*/
#define DC_IOCTL_DIR(request) (((request) >> 30) & 0x0003)
#define DC_IOCTL_SIZE(request) (((request) >> 16) & 0x3FFF)
#define DC_IOCTL_TYPE(request) (((request) >> 8) & 0x00FF)
#define DC_IOCTL_NR(request) (((request) >> 0) & 0x00FF)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DC_IOCTL_H */

View File

@ -123,22 +123,6 @@ dc_iostream_get_transport (dc_iostream_t *iostream);
dc_status_t
dc_iostream_set_timeout (dc_iostream_t *iostream, int timeout);
/**
* Set the receive latency.
*
* The effect of this setting is highly platform and driver specific. On
* Windows it does nothing at all, on Linux it controls the low latency
* flag (e.g. only zero vs non-zero latency), and on Mac OS X it sets
* the receive latency as requested.
*
* @param[in] iostream A valid I/O stream.
* @param[in] value The latency in milliseconds.
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
* on failure.
*/
dc_status_t
dc_iostream_set_latency (dc_iostream_t *iostream, unsigned int value);
/**
* Set the state of the break condition.
*
@ -269,6 +253,19 @@ dc_iostream_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actu
dc_status_t
dc_iostream_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
/**
* Perform an I/O stream specific request.
*
* @param[in] iostream A valid I/O stream.
* @param[in] request The request to perform.
* @param[in,out] data The request specific data.
* @param[in] size The size of the request specific data.
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
* on failure.
*/
dc_status_t
dc_iostream_ioctl (dc_iostream_t *iostream, unsigned int request, void *data, size_t size);
/**
* Flush the internal output buffer and wait until the data has been
* transmitted.

View File

@ -27,6 +27,7 @@
#include "iostream.h"
#include "iterator.h"
#include "descriptor.h"
#include "ioctl.h"
#ifdef __cplusplus
extern "C" {
@ -77,6 +78,16 @@ dc_serial_iterator_new (dc_iterator_t **iterator, dc_context_t *context, dc_desc
dc_status_t
dc_serial_open (dc_iostream_t **iostream, dc_context_t *context, const char *name);
/**
* Set the receive latency in milliseconds.
*
* The effect of this setting is highly platform and driver specific. On
* Windows it does nothing at all, on Linux it controls the low latency
* flag (e.g. only zero vs non-zero latency), and on Mac OS X it sets
* the receive latency as requested.
*/
#define DC_IOCTL_SERIAL_SET_LATENCY DC_IOCTL_IOW('s', 0, sizeof(unsigned int))
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -99,7 +99,6 @@ static const dc_iterator_vtable_t dc_bluetooth_iterator_vtable = {
static const dc_iostream_vtable_t dc_bluetooth_vtable = {
sizeof(dc_socket_t),
dc_socket_set_timeout, /* set_timeout */
NULL, /* set_latency */
NULL, /* set_break */
NULL, /* set_dtr */
NULL, /* set_rts */
@ -109,6 +108,7 @@ static const dc_iostream_vtable_t dc_bluetooth_vtable = {
dc_socket_poll, /* poll */
dc_socket_read, /* read */
dc_socket_write, /* write */
dc_socket_ioctl, /* ioctl */
NULL, /* flush */
NULL, /* purge */
dc_socket_sleep, /* sleep */

View File

@ -28,7 +28,6 @@
#include "context-private.h"
static dc_status_t dc_custom_set_timeout (dc_iostream_t *abstract, int timeout);
static dc_status_t dc_custom_set_latency (dc_iostream_t *abstract, unsigned int value);
static dc_status_t dc_custom_set_break (dc_iostream_t *abstract, unsigned int value);
static dc_status_t dc_custom_set_dtr (dc_iostream_t *abstract, unsigned int value);
static dc_status_t dc_custom_set_rts (dc_iostream_t *abstract, unsigned int value);
@ -38,6 +37,7 @@ static dc_status_t dc_custom_configure (dc_iostream_t *abstract, unsigned int ba
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_write (dc_iostream_t *abstract, const void *data, size_t size, size_t *actual);
static dc_status_t dc_custom_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size);
static dc_status_t dc_custom_flush (dc_iostream_t *abstract);
static dc_status_t dc_custom_purge (dc_iostream_t *abstract, dc_direction_t direction);
static dc_status_t dc_custom_sleep (dc_iostream_t *abstract, unsigned int milliseconds);
@ -54,7 +54,6 @@ typedef struct dc_custom_t {
static const dc_iostream_vtable_t dc_custom_vtable = {
sizeof(dc_custom_t),
dc_custom_set_timeout, /* set_timeout */
dc_custom_set_latency, /* set_latency */
dc_custom_set_break, /* set_break */
dc_custom_set_dtr, /* set_dtr */
dc_custom_set_rts, /* set_rts */
@ -64,6 +63,7 @@ static const dc_iostream_vtable_t dc_custom_vtable = {
dc_custom_poll, /* poll */
dc_custom_read, /* read */
dc_custom_write, /* write */
dc_custom_ioctl, /* ioctl */
dc_custom_flush, /* flush */
dc_custom_purge, /* purge */
dc_custom_sleep, /* sleep */
@ -106,17 +106,6 @@ dc_custom_set_timeout (dc_iostream_t *abstract, int timeout)
return custom->callbacks.set_timeout (custom->userdata, timeout);
}
static dc_status_t
dc_custom_set_latency (dc_iostream_t *abstract, unsigned int value)
{
dc_custom_t *custom = (dc_custom_t *) abstract;
if (custom->callbacks.set_latency == NULL)
return DC_STATUS_SUCCESS;
return custom->callbacks.set_latency (custom->userdata, value);
}
static dc_status_t
dc_custom_set_break (dc_iostream_t *abstract, unsigned int value)
{
@ -216,6 +205,17 @@ dc_custom_write (dc_iostream_t *abstract, const void *data, size_t size, size_t
return custom->callbacks.write (custom->userdata, data, size, actual);
}
static dc_status_t
dc_custom_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size)
{
dc_custom_t *custom = (dc_custom_t *) abstract;
if (custom->callbacks.ioctl == NULL)
return DC_STATUS_SUCCESS;
return custom->callbacks.ioctl (custom->userdata, request, data, size);
}
static dc_status_t
dc_custom_flush (dc_iostream_t *abstract)
{

View File

@ -43,8 +43,6 @@ struct dc_iostream_vtable_t {
dc_status_t (*set_timeout) (dc_iostream_t *iostream, int timeout);
dc_status_t (*set_latency) (dc_iostream_t *iostream, unsigned int value);
dc_status_t (*set_break) (dc_iostream_t *iostream, unsigned int value);
dc_status_t (*set_dtr) (dc_iostream_t *iostream, unsigned int value);
@ -63,6 +61,8 @@ struct dc_iostream_vtable_t {
dc_status_t (*write) (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
dc_status_t (*ioctl) (dc_iostream_t *iostream, unsigned int request, void *data, size_t size);
dc_status_t (*flush) (dc_iostream_t *iostream);
dc_status_t (*purge) (dc_iostream_t *iostream, dc_direction_t direction);

View File

@ -23,6 +23,8 @@
#include <stdlib.h>
#include <assert.h>
#include <libdivecomputer/ioctl.h>
#include "iostream-private.h"
#include "context-private.h"
#include "platform.h"
@ -85,17 +87,6 @@ dc_iostream_set_timeout (dc_iostream_t *iostream, int timeout)
return iostream->vtable->set_timeout (iostream, timeout);
}
dc_status_t
dc_iostream_set_latency (dc_iostream_t *iostream, unsigned int value)
{
if (iostream == NULL || iostream->vtable->set_latency == NULL)
return DC_STATUS_SUCCESS;
INFO (iostream->context, "Latency: value=%i", value);
return iostream->vtable->set_latency (iostream, value);
}
dc_status_t
dc_iostream_set_break (dc_iostream_t *iostream, unsigned int value)
{
@ -236,6 +227,40 @@ out:
return status;
}
dc_status_t
dc_iostream_ioctl (dc_iostream_t *iostream, unsigned int request, void *data, size_t size)
{
dc_status_t status = DC_STATUS_SUCCESS;
if (iostream == NULL || iostream->vtable->ioctl == NULL)
return DC_STATUS_SUCCESS;
// The size should match the size encoded in the ioctl request,
// unless it's a variable size request.
if (size != DC_IOCTL_SIZE(request) &&
!(DC_IOCTL_DIR(request) != DC_IOCTL_DIR_NONE && DC_IOCTL_SIZE(request) == 0)) {
ERROR (iostream->context, "Invalid size for ioctl request 0x%08x (" DC_PRINTF_SIZE ").", request, size);
return DC_STATUS_INVALIDARGS;
}
INFO (iostream->context, "Ioctl: request=0x%08x (dir=%u, type=%u, nr=%u, size=%u)",
request,
DC_IOCTL_DIR(request), DC_IOCTL_TYPE(request),
DC_IOCTL_NR(request), DC_IOCTL_SIZE(request));
if (DC_IOCTL_DIR(request) & DC_IOCTL_DIR_WRITE) {
HEXDUMP (iostream->context, DC_LOGLEVEL_INFO, "Ioctl write", (unsigned char *) data, size);
}
status = iostream->vtable->ioctl (iostream, request, data, size);
if (DC_IOCTL_DIR(request) & DC_IOCTL_DIR_READ) {
HEXDUMP (iostream->context, DC_LOGLEVEL_INFO, "Ioctl read", (unsigned char *) data, size);
}
return status;
}
dc_status_t
dc_iostream_flush (dc_iostream_t *iostream)
{

View File

@ -91,7 +91,6 @@ static const dc_iterator_vtable_t dc_irda_iterator_vtable = {
static const dc_iostream_vtable_t dc_irda_vtable = {
sizeof(dc_socket_t),
dc_socket_set_timeout, /* set_timeout */
NULL, /* set_latency */
NULL, /* set_break */
NULL, /* set_dtr */
NULL, /* set_rts */
@ -101,6 +100,7 @@ static const dc_iostream_vtable_t dc_irda_vtable = {
dc_socket_poll, /* poll */
dc_socket_read, /* read */
dc_socket_write, /* write */
dc_socket_ioctl, /* ioctl */
NULL, /* flush */
NULL, /* purge */
dc_socket_sleep, /* sleep */

View File

@ -36,7 +36,6 @@ dc_descriptor_get_transports
dc_iostream_get_transport
dc_iostream_set_timeout
dc_iostream_set_latency
dc_iostream_set_break
dc_iostream_set_dtr
dc_iostream_set_rts
@ -46,6 +45,7 @@ dc_iostream_configure
dc_iostream_poll
dc_iostream_read
dc_iostream_write
dc_iostream_ioctl
dc_iostream_flush
dc_iostream_purge
dc_iostream_sleep

View File

@ -67,7 +67,6 @@ static dc_status_t dc_serial_iterator_next (dc_iterator_t *iterator, void *item)
static dc_status_t dc_serial_iterator_free (dc_iterator_t *iterator);
static dc_status_t dc_serial_set_timeout (dc_iostream_t *iostream, int timeout);
static dc_status_t dc_serial_set_latency (dc_iostream_t *iostream, unsigned int value);
static dc_status_t dc_serial_set_break (dc_iostream_t *iostream, unsigned int value);
static dc_status_t dc_serial_set_dtr (dc_iostream_t *iostream, unsigned int value);
static dc_status_t dc_serial_set_rts (dc_iostream_t *iostream, unsigned int value);
@ -77,6 +76,7 @@ static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int ba
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_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
static dc_status_t dc_serial_ioctl (dc_iostream_t *iostream, unsigned int request, void *data, size_t size);
static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
static dc_status_t dc_serial_purge (dc_iostream_t *iostream, dc_direction_t direction);
static dc_status_t dc_serial_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
@ -117,7 +117,6 @@ static const dc_iterator_vtable_t dc_serial_iterator_vtable = {
static const dc_iostream_vtable_t dc_serial_vtable = {
sizeof(dc_serial_t),
dc_serial_set_timeout, /* set_timeout */
dc_serial_set_latency, /* set_latency */
dc_serial_set_break, /* set_break */
dc_serial_set_dtr, /* set_dtr */
dc_serial_set_rts, /* set_rts */
@ -127,6 +126,7 @@ static const dc_iostream_vtable_t dc_serial_vtable = {
dc_serial_poll, /* poll */
dc_serial_read, /* read */
dc_serial_write, /* write */
dc_serial_ioctl, /* ioctl */
dc_serial_flush, /* flush */
dc_serial_purge, /* purge */
dc_serial_sleep, /* sleep */
@ -849,6 +849,17 @@ out:
return status;
}
static dc_status_t
dc_serial_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size)
{
switch (request) {
case DC_IOCTL_SERIAL_SET_LATENCY:
return dc_serial_set_latency (abstract, *(unsigned int *) data);
default:
return DC_STATUS_UNSUPPORTED;
}
}
static dc_status_t
dc_serial_purge (dc_iostream_t *abstract, dc_direction_t direction)
{

View File

@ -36,7 +36,6 @@ static dc_status_t dc_serial_iterator_next (dc_iterator_t *iterator, void *item)
static dc_status_t dc_serial_iterator_free (dc_iterator_t *iterator);
static dc_status_t dc_serial_set_timeout (dc_iostream_t *iostream, int timeout);
static dc_status_t dc_serial_set_latency (dc_iostream_t *iostream, unsigned int value);
static dc_status_t dc_serial_set_break (dc_iostream_t *iostream, unsigned int value);
static dc_status_t dc_serial_set_dtr (dc_iostream_t *iostream, unsigned int value);
static dc_status_t dc_serial_set_rts (dc_iostream_t *iostream, unsigned int value);
@ -46,6 +45,7 @@ static dc_status_t dc_serial_configure (dc_iostream_t *iostream, unsigned int ba
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_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
static dc_status_t dc_serial_ioctl (dc_iostream_t *iostream, unsigned int request, void *data, size_t size);
static dc_status_t dc_serial_flush (dc_iostream_t *iostream);
static dc_status_t dc_serial_purge (dc_iostream_t *iostream, dc_direction_t direction);
static dc_status_t dc_serial_sleep (dc_iostream_t *iostream, unsigned int milliseconds);
@ -92,7 +92,6 @@ static const dc_iterator_vtable_t dc_serial_iterator_vtable = {
static const dc_iostream_vtable_t dc_serial_vtable = {
sizeof(dc_serial_t),
dc_serial_set_timeout, /* set_timeout */
dc_serial_set_latency, /* set_latency */
dc_serial_set_break, /* set_break */
dc_serial_set_dtr, /* set_dtr */
dc_serial_set_rts, /* set_rts */
@ -102,6 +101,7 @@ static const dc_iostream_vtable_t dc_serial_vtable = {
dc_serial_poll, /* poll */
dc_serial_read, /* read */
dc_serial_write, /* write */
dc_serial_ioctl, /* ioctl */
dc_serial_flush, /* flush */
dc_serial_purge, /* purge */
dc_serial_sleep, /* sleep */
@ -544,12 +544,6 @@ dc_serial_set_timeout (dc_iostream_t *abstract, int timeout)
return DC_STATUS_SUCCESS;
}
static dc_status_t
dc_serial_set_latency (dc_iostream_t *abstract, unsigned int value)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
dc_serial_poll (dc_iostream_t *abstract, int timeout)
{
@ -682,6 +676,17 @@ out:
return status;
}
static dc_status_t
dc_serial_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size)
{
switch (request) {
case DC_IOCTL_SERIAL_SET_LATENCY:
return DC_STATUS_SUCCESS;
default:
return DC_STATUS_UNSUPPORTED;
}
}
static dc_status_t
dc_serial_purge (dc_iostream_t *abstract, dc_direction_t direction)
{

View File

@ -330,6 +330,12 @@ out:
return status;
}
dc_status_t
dc_socket_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size)
{
return DC_STATUS_UNSUPPORTED;
}
dc_status_t
dc_socket_sleep (dc_iostream_t *abstract, unsigned int timeout)
{

View File

@ -117,6 +117,9 @@ dc_socket_read (dc_iostream_t *iostream, void *data, size_t size, size_t *actual
dc_status_t
dc_socket_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
dc_status_t
dc_socket_ioctl (dc_iostream_t *iostream, unsigned int request, void *data, size_t size);
dc_status_t
dc_socket_sleep (dc_iostream_t *abstract, unsigned int timeout);

View File

@ -97,6 +97,7 @@ 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_write (dc_iostream_t *iostream, const void *data, size_t size, size_t *actual);
static dc_status_t dc_usbhid_ioctl (dc_iostream_t *iostream, unsigned int request, void *data, size_t size);
static dc_status_t dc_usbhid_close (dc_iostream_t *iostream);
typedef struct dc_usbhid_iterator_t {
@ -138,7 +139,6 @@ static const dc_iterator_vtable_t dc_usbhid_iterator_vtable = {
static const dc_iostream_vtable_t dc_usbhid_vtable = {
sizeof(dc_usbhid_t),
dc_usbhid_set_timeout, /* set_timeout */
NULL, /* set_latency */
NULL, /* set_break */
NULL, /* set_dtr */
NULL, /* set_rts */
@ -148,6 +148,7 @@ static const dc_iostream_vtable_t dc_usbhid_vtable = {
dc_usbhid_poll, /* poll */
dc_usbhid_read, /* read */
dc_usbhid_write, /* write */
dc_usbhid_ioctl, /* ioctl */
NULL, /* flush */
NULL, /* purge */
NULL, /* sleep */
@ -781,4 +782,10 @@ out:
return status;
}
static dc_status_t
dc_usbhid_ioctl (dc_iostream_t *abstract, unsigned int request, void *data, size_t size)
{
return DC_STATUS_UNSUPPORTED;
}
#endif