Update the operations in 'custom_io' to consistent calling conventions
The serial ops used a legacy calling convention that passed in just the pointer to the userdata pointer (ie the first argument to the functions was "void **userdata"). That's actually very inconvenient, because the custom IO data can not only contain other interesting information that was filled in by the custom IO provider, it also made it harder to chain these things together, as exemplified by the core to emulate serial over the packet interface in the subsurface bluetooth code. This also adds the 'dc_context_t' field that is passed to the packet routine open. That can allow the open routine to override the 'custom_io' details of the context at open time (to allow nested custom_io operation). Note that callers of the open function need to be aware that the 'custom_io' can be changed by the act of opening a custom_io, and the value shouldn't be cached in some local variable. Finally, this adds a new user-supplied opaque pointer dc_user_device_t *user_device; to the custom_io descriptor. The 'user_device' data is filled in when registering the custom_io with data that the custom IO open() routines can use. This is different from the existing 'userdata' in that the 'user_device' is filled in before dc_open_device() is called (and "open" can then use it to limit what kinds of devices it looks for, for example). In contrast, the existing 'userdata' field is filled in by the "xyz_open()" routines, and contains the data necessary for the IO itself. The SSRF_CUSTOM_IO define is updated to v2 to indicate the new interfaces. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
3aa40c6135
commit
208807180a
@ -31,6 +31,9 @@ extern "C" {
|
||||
|
||||
typedef struct dc_context_t dc_context_t;
|
||||
|
||||
/* Opaque libdivecomputer *user* data structure */
|
||||
typedef struct dc_user_device_t dc_user_device_t;
|
||||
|
||||
typedef enum dc_loglevel_t {
|
||||
DC_LOGLEVEL_NONE,
|
||||
DC_LOGLEVEL_ERROR,
|
||||
@ -49,7 +52,7 @@ dc_status_t
|
||||
dc_context_free (dc_context_t *context);
|
||||
|
||||
dc_status_t
|
||||
dc_context_set_custom_io (dc_context_t *context, dc_custom_io_t *custom_io);
|
||||
dc_context_set_custom_io (dc_context_t *context, dc_custom_io_t *custom_io, dc_user_device_t *);
|
||||
|
||||
dc_status_t
|
||||
dc_context_set_loglevel (dc_context_t *context, dc_loglevel_t loglevel);
|
||||
|
||||
@ -63,24 +63,47 @@ typedef enum dc_line_t {
|
||||
#endif /* __SERIAL_TYPES__ */
|
||||
|
||||
struct dc_context_t;
|
||||
struct dc_user_device_t;
|
||||
|
||||
/*
|
||||
* Two different pointers to user-supplied data.
|
||||
*
|
||||
* The 'userdata' pointer is for the IO routines themselves,
|
||||
* generally filled in by the 'xyz_open()' routine with whatever
|
||||
* file descriptor etc information.
|
||||
*
|
||||
* The 'user_device' pointer is set when registering the
|
||||
* custom IO with the download context, and has whatever
|
||||
* data the downloader needs.
|
||||
*
|
||||
* The two are very different. The userdata is "per instance",
|
||||
* and when nesting custom IO handlers, each level would
|
||||
* generally have its own userdata, that would be specific
|
||||
* to that particular set of IO routines.
|
||||
*
|
||||
* In contrast, the user_device is filled in when the
|
||||
* download context is created, before open() is even called,
|
||||
* and isn't specific to the IO routines, but to the download
|
||||
* as a whole.
|
||||
*/
|
||||
typedef struct dc_custom_io_t
|
||||
{
|
||||
void *userdata;
|
||||
struct dc_user_device_t *user_device;
|
||||
|
||||
// Custom serial (generally BT rfcomm)
|
||||
dc_status_t (*serial_open) (void **userdata, const char *name);
|
||||
dc_status_t (*serial_close) (void **userdata);
|
||||
dc_status_t (*serial_read) (void **userdata, void* data, size_t size, size_t *actual);
|
||||
dc_status_t (*serial_write) (void **userdata, const void* data, size_t size, size_t *actual);
|
||||
dc_status_t (*serial_purge) (void **userdata, dc_direction_t);
|
||||
dc_status_t (*serial_get_available) (void **userdata, size_t *value);
|
||||
dc_status_t (*serial_set_timeout) (void **userdata, long timeout);
|
||||
dc_status_t (*serial_configure) (void **userdata, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||
dc_status_t (*serial_set_dtr) (void **userdata, int level);
|
||||
dc_status_t (*serial_set_rts) (void **userdata, int level);
|
||||
dc_status_t (*serial_set_halfduplex) (void **userdata, unsigned int value);
|
||||
dc_status_t (*serial_set_break) (void **userdata, unsigned int level);
|
||||
dc_status_t (*serial_open) (struct dc_custom_io_t *io, struct dc_context_t *, const char *name);
|
||||
dc_status_t (*serial_close) (struct dc_custom_io_t *io);
|
||||
dc_status_t (*serial_read) (struct dc_custom_io_t *io, void* data, size_t size, size_t *actual);
|
||||
dc_status_t (*serial_write) (struct dc_custom_io_t *io, const void* data, size_t size, size_t *actual);
|
||||
dc_status_t (*serial_purge) (struct dc_custom_io_t *io, dc_direction_t);
|
||||
dc_status_t (*serial_get_available) (struct dc_custom_io_t *io, size_t *value);
|
||||
dc_status_t (*serial_set_timeout) (struct dc_custom_io_t *io, long timeout);
|
||||
dc_status_t (*serial_configure) (struct dc_custom_io_t *io, unsigned int baudrate, unsigned int databits, dc_parity_t parity, dc_stopbits_t stopbits, dc_flowcontrol_t flowcontrol);
|
||||
dc_status_t (*serial_set_dtr) (struct dc_custom_io_t *io, int level);
|
||||
dc_status_t (*serial_set_rts) (struct dc_custom_io_t *io, int level);
|
||||
dc_status_t (*serial_set_halfduplex) (struct dc_custom_io_t *io, unsigned int value);
|
||||
dc_status_t (*serial_set_break) (struct dc_custom_io_t *io, unsigned int level);
|
||||
//dc_serial_set_latency (dc_serial_t *device, unsigned int milliseconds) - Unused
|
||||
//dc_serial_get_lines (dc_serial_t *device, unsigned int *value) - Unused
|
||||
//dc_serial_flush (dc_serial_t *device) - No device interaction
|
||||
|
||||
@ -28,7 +28,7 @@ extern "C" {
|
||||
|
||||
/* use these defines to detect Subsurface specific features */
|
||||
#define SSRF_LIBDC_VERSION 2
|
||||
#define SSRF_CUSTOM_IO 1
|
||||
#define SSRF_CUSTOM_IO 2
|
||||
|
||||
#define DC_VERSION "@DC_VERSION@"
|
||||
#define DC_VERSION_MAJOR @DC_VERSION_MAJOR@
|
||||
|
||||
@ -81,7 +81,7 @@ _dc_context_custom_io (dc_context_t *context);
|
||||
dc_status_t _rc; \
|
||||
if (c) { \
|
||||
if (c->serial_##function) \
|
||||
_rc = c->serial_##function(&c->userdata, ##__VA_ARGS__); \
|
||||
_rc = c->serial_##function(c, ##__VA_ARGS__); \
|
||||
else \
|
||||
_rc = DC_STATUS_SUCCESS; \
|
||||
block ;\
|
||||
|
||||
@ -47,6 +47,7 @@ struct dc_context_t {
|
||||
#endif
|
||||
#endif
|
||||
dc_custom_io_t *custom_io;
|
||||
dc_user_device_t *user_device;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_LOGGING
|
||||
@ -213,12 +214,13 @@ dc_context_free (dc_context_t *context)
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_context_set_custom_io (dc_context_t *context, dc_custom_io_t *custom_io)
|
||||
dc_context_set_custom_io (dc_context_t *context, dc_custom_io_t *custom_io, dc_user_device_t *user_device)
|
||||
{
|
||||
if (context == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
context->custom_io = custom_io;
|
||||
custom_io->user_device = user_device;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
|
||||
device->baudrate = 0;
|
||||
device->nbits = 0;
|
||||
|
||||
RETURN_IF_CUSTOM_SERIAL(context, *out = device, open, name);
|
||||
RETURN_IF_CUSTOM_SERIAL(context, *out = device, open, context, name);
|
||||
|
||||
// Open the device in non-blocking mode, to return immediately
|
||||
// without waiting for the modem connection to complete.
|
||||
|
||||
@ -157,7 +157,7 @@ dc_serial_open (dc_serial_t **out, dc_context_t *context, const char *name)
|
||||
device->baudrate = 0;
|
||||
device->nbits = 0;
|
||||
|
||||
RETURN_IF_CUSTOM_SERIAL(context, *out = device, open, name);
|
||||
RETURN_IF_CUSTOM_SERIAL(context, *out = device, open, context, name);
|
||||
|
||||
// Open the device.
|
||||
device->hFile = CreateFileA (devname,
|
||||
|
||||
@ -119,7 +119,7 @@ dc_usbhid_custom_io (dc_context_t *context, unsigned int vid, unsigned int pid)
|
||||
return status;
|
||||
|
||||
custom.userdata = (void *)usbhid;
|
||||
dc_context_set_custom_io(context, &custom);
|
||||
dc_context_set_custom_io(context, &custom, NULL);
|
||||
|
||||
dc_usbhid_set_timeout(usbhid, 10);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user