lib: Add USB transfer helpers
Those helpers will provide more arguments in their callbacks, and handle the libusb_transfer lifecycle, making it easier to use for drivers.
This commit is contained in:
parent
192c4f3cfc
commit
96f2e07cdd
3 changed files with 208 additions and 0 deletions
|
@ -197,5 +197,11 @@ FP_INSTANCE_DATA
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<INCLUDE>fpi-usb.h</INCLUDE>
|
<INCLUDE>fpi-usb.h</INCLUDE>
|
||||||
<FILE>fpi-usb</FILE>
|
<FILE>fpi-usb</FILE>
|
||||||
|
fpi_usb_transfer
|
||||||
|
|
||||||
|
fpi_usb_transfer_cb_fn
|
||||||
fpi_usb_alloc
|
fpi_usb_alloc
|
||||||
|
fpi_usb_fill_bulk_transfer
|
||||||
|
fpi_usb_submit_transfer
|
||||||
|
fpi_usb_cancel_transfer
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fpi-usb.h"
|
#include "fpi-usb.h"
|
||||||
|
#include "drivers_api.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:fpi-usb
|
* SECTION:fpi-usb
|
||||||
|
@ -57,6 +58,14 @@ mem_error (const char *format,
|
||||||
_exit (1);
|
_exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct fpi_usb_transfer {
|
||||||
|
struct libusb_transfer *transfer;
|
||||||
|
fpi_ssm *ssm;
|
||||||
|
struct fp_dev *dev;
|
||||||
|
fpi_usb_transfer_cb_fn callback;
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_usb_alloc:
|
* fpi_usb_alloc:
|
||||||
*
|
*
|
||||||
|
@ -75,3 +84,152 @@ fpi_usb_alloc(void)
|
||||||
|
|
||||||
return transfer;
|
return transfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fpi_usb_transfer *
|
||||||
|
fpi_usb_transfer_new(struct fp_dev *dev,
|
||||||
|
fpi_ssm *ssm,
|
||||||
|
fpi_usb_transfer_cb_fn callback,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
fpi_usb_transfer *transfer;
|
||||||
|
|
||||||
|
transfer = g_new0(fpi_usb_transfer, 1);
|
||||||
|
transfer->transfer = fpi_usb_alloc();
|
||||||
|
transfer->dev = dev;
|
||||||
|
transfer->ssm = ssm;
|
||||||
|
transfer->callback = callback;
|
||||||
|
transfer->user_data = user_data;
|
||||||
|
|
||||||
|
return transfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_usb_transfer_free(fpi_usb_transfer *transfer)
|
||||||
|
{
|
||||||
|
if (transfer == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_free(transfer->transfer->buffer);
|
||||||
|
libusb_free_transfer(transfer->transfer);
|
||||||
|
g_free(transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_usb_transfer_cb (struct libusb_transfer *transfer)
|
||||||
|
{
|
||||||
|
fpi_usb_transfer *t;
|
||||||
|
|
||||||
|
g_assert(transfer);
|
||||||
|
g_assert(transfer->user_data);
|
||||||
|
|
||||||
|
t = transfer->user_data;
|
||||||
|
BUG_ON(transfer->callback == NULL);
|
||||||
|
(t->callback) (transfer, t->dev, t->ssm, t->user_data);
|
||||||
|
fpi_usb_transfer_free(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_usb_fill_bulk_transfer:
|
||||||
|
* @dev: a struct #fp_dev fingerprint device
|
||||||
|
* @ssm: the current #fpi_ssm state machine
|
||||||
|
* @endpoint: the USB end point
|
||||||
|
* @buffer: a buffer allocated with g_malloc() or another GLib function.
|
||||||
|
* Note that the returned #fpi_usb_transfer will own this buffer, so it
|
||||||
|
* should not be freed manually.
|
||||||
|
* @length: the size of @buffer
|
||||||
|
* @callback: the callback function that will be called once the fpi_usb_submit_transfer()
|
||||||
|
* call finishes.
|
||||||
|
* @user_data: a user data pointer to pass to the callback
|
||||||
|
* @timeout: timeout for the transfer in milliseconds, or 0 for no timeout
|
||||||
|
*
|
||||||
|
* This function is similar to calling [`libusb_alloc_transfer(0)`](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga13cc69ea40c702181c430c950121c000)]
|
||||||
|
* followed by calling [`libusb_fill_bulk_transfer()`](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gad4ddb1a5c6c7fefc979a44d7300b95d7).
|
||||||
|
* The #fpi_usb_transfer_cb_fn callback will however provide more arguments
|
||||||
|
* relevant to libfprint drivers, making it a good replacement for the raw libusb
|
||||||
|
* calls.
|
||||||
|
*
|
||||||
|
* Returns: a #fpi_usb_transfer transfer struct, to be passed to
|
||||||
|
* fpi_usb_submit_transfer().
|
||||||
|
*/
|
||||||
|
fpi_usb_transfer *
|
||||||
|
fpi_usb_fill_bulk_transfer (struct fp_dev *dev,
|
||||||
|
fpi_ssm *ssm,
|
||||||
|
unsigned char endpoint,
|
||||||
|
unsigned char *buffer,
|
||||||
|
int length,
|
||||||
|
fpi_usb_transfer_cb_fn callback,
|
||||||
|
void *user_data,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
fpi_usb_transfer *transfer;
|
||||||
|
|
||||||
|
g_return_val_if_fail (dev != NULL, NULL);
|
||||||
|
g_return_val_if_fail (callback != NULL, NULL);
|
||||||
|
|
||||||
|
transfer = fpi_usb_transfer_new(dev,
|
||||||
|
ssm,
|
||||||
|
callback,
|
||||||
|
user_data);
|
||||||
|
|
||||||
|
libusb_fill_bulk_transfer(transfer->transfer,
|
||||||
|
fpi_dev_get_usb_dev(dev),
|
||||||
|
endpoint,
|
||||||
|
buffer,
|
||||||
|
length,
|
||||||
|
fpi_usb_transfer_cb,
|
||||||
|
transfer,
|
||||||
|
timeout);
|
||||||
|
|
||||||
|
return transfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_usb_submit_transfer:
|
||||||
|
* @transfer: a #fpi_usb_transfer struct
|
||||||
|
*
|
||||||
|
* Start a transfer to the device with the provided #fpi_usb_transfer.
|
||||||
|
* On error, the #fpi_usb_transfer struct will be freed, otherwise it will
|
||||||
|
* be freed once the callback provided to fpi_usb_fill_bulk_transfer() has
|
||||||
|
* been called.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, or the same errors as [libusb_submit_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gabb0932601f2c7dad2fee4b27962848ce)
|
||||||
|
* on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fpi_usb_submit_transfer(fpi_usb_transfer *transfer)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
g_return_val_if_fail (transfer != NULL, LIBUSB_ERROR_INVALID_PARAM);
|
||||||
|
|
||||||
|
r = libusb_submit_transfer(transfer->transfer);
|
||||||
|
if (r < 0)
|
||||||
|
fpi_usb_transfer_free(transfer);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_usb_cancel_transfer:
|
||||||
|
* @transfer: a #fpi_usb_transfer struct
|
||||||
|
*
|
||||||
|
* Cancel a transfer to the device with the provided #fpi_usb_transfer.
|
||||||
|
* Note that this will not complete the cancellation, as your transfer
|
||||||
|
* callback will be called with the `LIBUSB_TRANSFER_CANCELLED` status,
|
||||||
|
* as [libusb_cancel_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54)
|
||||||
|
* would.
|
||||||
|
*
|
||||||
|
* You should not access anything but the given struct #libusb_transfer
|
||||||
|
* in the callback before checking whether `LIBUSB_TRANSFER_CANCELLED` has
|
||||||
|
* been called, as that might cause memory access violations.
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, or the same errors as [libusb_cancel_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54)
|
||||||
|
* on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
fpi_usb_cancel_transfer(fpi_usb_transfer *transfer)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (transfer != NULL, LIBUSB_ERROR_NOT_FOUND);
|
||||||
|
|
||||||
|
return libusb_cancel_transfer(transfer->transfer);
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,51 @@
|
||||||
#define __FPI_USB_H__
|
#define __FPI_USB_H__
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
#include "fpi-dev.h"
|
||||||
|
#include "fpi-ssm.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_usb_transfer:
|
||||||
|
*
|
||||||
|
* A structure containing the arguments passed to fpi_usb_fill_bulk_transfer()
|
||||||
|
* to be used with fpi_usb_submit_transfer().
|
||||||
|
*/
|
||||||
|
typedef struct fpi_usb_transfer fpi_usb_transfer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_usb_transfer_cb_fn:
|
||||||
|
* @transfer: a struct #libusb_transfer
|
||||||
|
* @dev: the struct #fp_dev on which the operation was performed
|
||||||
|
* @ssm: the #fpi_ssm state machine
|
||||||
|
* @user_data: the user data passed to fpi_usb_fill_bulk_transfer()
|
||||||
|
*
|
||||||
|
* This callback will be called in response to a libusb bulk transfer
|
||||||
|
* triggered via fpi_usb_fill_bulk_transfer() finishing. Note that the
|
||||||
|
* struct #libusb_transfer does not need to be freed, as it will be
|
||||||
|
* freed after the callback returns, similarly to
|
||||||
|
* the [LIBUSB_TRANSFER_FREE_TRANSFER flag](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gga1fb47dd0f7c209b60a3609ff0c03d56dacf3f064997b283a14097c9f4d6f8ccc1).
|
||||||
|
*
|
||||||
|
* Note that the cancelled status of the transfer should be checked
|
||||||
|
* first thing, as the @dev, @ssm and @user_data pointers might not
|
||||||
|
* be pointing to valid values anymore. See fpi_usb_cancel_transfer()
|
||||||
|
* for more information.
|
||||||
|
*/
|
||||||
|
typedef void(*fpi_usb_transfer_cb_fn) (struct libusb_transfer *transfer,
|
||||||
|
struct fp_dev *dev,
|
||||||
|
fpi_ssm *ssm,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
struct libusb_transfer *fpi_usb_alloc(void) __attribute__((returns_nonnull));
|
struct libusb_transfer *fpi_usb_alloc(void) __attribute__((returns_nonnull));
|
||||||
|
|
||||||
|
fpi_usb_transfer *fpi_usb_fill_bulk_transfer (struct fp_dev *dev,
|
||||||
|
fpi_ssm *ssm,
|
||||||
|
unsigned char endpoint,
|
||||||
|
unsigned char *buffer,
|
||||||
|
int length,
|
||||||
|
fpi_usb_transfer_cb_fn callback,
|
||||||
|
void *user_data,
|
||||||
|
unsigned int timeout);
|
||||||
|
int fpi_usb_submit_transfer (fpi_usb_transfer *transfer);
|
||||||
|
int fpi_usb_cancel_transfer (fpi_usb_transfer *transfer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue