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>
|
||||
<INCLUDE>fpi-usb.h</INCLUDE>
|
||||
<FILE>fpi-usb</FILE>
|
||||
fpi_usb_transfer
|
||||
|
||||
fpi_usb_transfer_cb_fn
|
||||
fpi_usb_alloc
|
||||
fpi_usb_fill_bulk_transfer
|
||||
fpi_usb_submit_transfer
|
||||
fpi_usb_cancel_transfer
|
||||
</SECTION>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "fpi-usb.h"
|
||||
#include "drivers_api.h"
|
||||
|
||||
/**
|
||||
* SECTION:fpi-usb
|
||||
|
@ -57,6 +58,14 @@ mem_error (const char *format,
|
|||
_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:
|
||||
*
|
||||
|
@ -75,3 +84,152 @@ fpi_usb_alloc(void)
|
|||
|
||||
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__
|
||||
|
||||
#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));
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue