/******************************************************************************!
* \file fft-usb.c
* \author Sebastien Beaugrand
* \sa http://beaugrand.chez.com/
* \copyright CeCILL 2.1 Free Software license
******************************************************************************/
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#include "debug.h"
#define VENDOR_ID 0x4242
#define DEVICE_ID 0x0002
#define EP_ADDR (LIBUSB_ENDPOINT_IN | 1) // lsusb -v | grep bEndpointAddress
#define BUFF_SIZE 8 // wMaxPacketSize
struct libusb_device_handle* gDev = NULL;
struct libusb_transfer* gTransfer = NULL;
unsigned char* gTransferBuff = NULL;
uint16_t* gBuff;
uint32_t gSize;
/******************************************************************************!
* \fn sockQuit
******************************************************************************/
void sockQuit()
{
if (gTransfer != NULL) {
libusb_cancel_transfer(gTransfer);
libusb_free_transfer(gTransfer);
gTransfer = NULL;
}
if (gTransferBuff != NULL) {
free(gTransferBuff);
gTransferBuff = NULL;
}
if (gDev != NULL) {
libusb_release_interface(gDev, 0);
libusb_close(gDev);
gDev = NULL;
libusb_exit(NULL);
}
}
/******************************************************************************!
* \fn status
******************************************************************************/
void status(const char* str, int code)
{
if (code < 0) {
ERROR("%s (err=%d)\n", str, code);
sockQuit();
exit(EXIT_FAILURE);
} else {
DEBUG("%s: %d", str, code);
}
}
/******************************************************************************!
* \fn callback
******************************************************************************/
void callback(struct libusb_transfer* transfer)
{
static struct timeval tv;
static time_t offset = 0;
static uint32_t uint4;
if (gettimeofday(&tv, NULL) < 0) {
ERRNO("gettimeofday");
exit(EXIT_FAILURE);
}
if (offset == 0) {
offset = tv.tv_sec;
}
gBuff[gSize++] = (uint16_t) (tv.tv_sec - offset);
uint4 = (uint32_t) tv.tv_usec;
gBuff[gSize++] = uint4 >> 16;
gBuff[gSize++] = uint4 & 0xFFFFu;
gBuff[gSize++] = (transfer->buffer[0] << 8) + transfer->buffer[0];
libusb_submit_transfer(transfer);
}
/******************************************************************************!
* \fn sockInit
******************************************************************************/
void sockInit(int argc, char* argv[])
{
int r;
if (argc != 3) {
ERROR("Usage: %s <frequence-min> <frequence-max>", argv[0]);
exit(EXIT_FAILURE);
}
r = libusb_init(NULL);
status("libusb_init", r);
gDev = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, DEVICE_ID);
status("libusb_open_device_with_vid_pid", (gDev == NULL) ? -1 : 0);
if (libusb_kernel_driver_active(gDev, 0)) {
r = libusb_detach_kernel_driver(gDev, 0);
status("libusb_detach_kernel_driver", r);
}
r = libusb_claim_interface(gDev, 0);
status("libusb_claim_interface", r);
gTransfer = libusb_alloc_transfer(0);
status("libusb_alloc_transfer", (gTransfer == NULL) ? -1 : 0);
gTransferBuff = (unsigned char*) malloc(BUFF_SIZE);
libusb_fill_interrupt_transfer(gTransfer, gDev, EP_ADDR,
gTransferBuff, BUFF_SIZE, callback, NULL, 0);
r = libusb_submit_transfer(gTransfer);
status("libusb_submit_transfer", r);
}
/******************************************************************************!
* \fn sockRead
******************************************************************************/
ssize_t sockRead(unsigned char* buff, size_t size)
{
static uint32_t count = 0;
int r;
gBuff = (uint16_t*) buff;
size = size >> 1;
gBuff[0] = count >> 16;
gBuff[1] = count & 0xFFFFu;
gSize = 4;
while (gSize != size) {
r = libusb_handle_events(NULL);
if (r < 0) {
status("libusb_handle_events", r);
}
}
gSize -= 4;
gSize = gSize << 1;
gBuff[2] = gSize >> 16;
gBuff[3] = gSize & 0xFFFFu;
++count;
return gSize;
}