|
|
@ -139,6 +139,12 @@ static rtlsdr_device_t devices[] = { |
|
|
|
#define DEFAULT_BUF_NUMBER 32 |
|
|
|
#define DEFAULT_BUF_NUMBER 32 |
|
|
|
#define DEFAULT_BUF_LENGTH (16 * 16384) |
|
|
|
#define DEFAULT_BUF_LENGTH (16 * 16384) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum rtlsdr_async_status { |
|
|
|
|
|
|
|
RTLSDR_INACTIVE = 0, |
|
|
|
|
|
|
|
RTLSDR_CANCELING, |
|
|
|
|
|
|
|
RTLSDR_RUNNING |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct rtlsdr_dev { |
|
|
|
struct rtlsdr_dev { |
|
|
|
libusb_context *ctx; |
|
|
|
libusb_context *ctx; |
|
|
|
struct libusb_device_handle *devh; |
|
|
|
struct libusb_device_handle *devh; |
|
|
@ -148,7 +154,7 @@ struct rtlsdr_dev { |
|
|
|
unsigned char **xfer_buf; |
|
|
|
unsigned char **xfer_buf; |
|
|
|
rtlsdr_read_async_cb_t cb; |
|
|
|
rtlsdr_read_async_cb_t cb; |
|
|
|
void *cb_ctx; |
|
|
|
void *cb_ctx; |
|
|
|
int run_async; |
|
|
|
enum rtlsdr_async_status async_status; |
|
|
|
rtlsdr_tuner_t *tuner; |
|
|
|
rtlsdr_tuner_t *tuner; |
|
|
|
int rate; /* Hz */ |
|
|
|
int rate; /* Hz */ |
|
|
|
}; |
|
|
|
}; |
|
|
@ -269,7 +275,7 @@ uint16_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_ |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
|
|
|
|
|
|
|
|
if (r < 0) |
|
|
|
if (r < 0) |
|
|
|
fprintf(stderr, "%s failed\n", __FUNCTION__); |
|
|
|
fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); |
|
|
|
|
|
|
|
|
|
|
|
reg = (data[1] << 8) | data[0]; |
|
|
|
reg = (data[1] << 8) | data[0]; |
|
|
|
|
|
|
|
|
|
|
@ -293,7 +299,7 @@ void rtlsdr_write_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint16_t |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
|
|
|
|
|
|
|
|
if (r < 0) |
|
|
|
if (r < 0) |
|
|
|
fprintf(stderr, "%s failed\n", __FUNCTION__); |
|
|
|
fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint16_t rtlsdr_demod_read_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint8_t len) |
|
|
|
uint16_t rtlsdr_demod_read_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint8_t len) |
|
|
@ -308,7 +314,7 @@ uint16_t rtlsdr_demod_read_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, u |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
|
|
|
|
|
|
|
|
if (r < 0) |
|
|
|
if (r < 0) |
|
|
|
fprintf(stderr, "%s failed\n", __FUNCTION__); |
|
|
|
fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); |
|
|
|
|
|
|
|
|
|
|
|
reg = (data[1] << 8) | data[0]; |
|
|
|
reg = (data[1] << 8) | data[0]; |
|
|
|
|
|
|
|
|
|
|
@ -332,7 +338,7 @@ void rtlsdr_demod_write_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT); |
|
|
|
|
|
|
|
|
|
|
|
if (r < 0) |
|
|
|
if (r < 0) |
|
|
|
fprintf(stderr, "%s failed\n", __FUNCTION__); |
|
|
|
fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); |
|
|
|
|
|
|
|
|
|
|
|
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); |
|
|
|
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); |
|
|
|
} |
|
|
|
} |
|
|
@ -567,61 +573,6 @@ rtlsdr_device_t *find_known_device(uint16_t vid, uint16_t pid) |
|
|
|
return device; |
|
|
|
return device; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev->xfer) { |
|
|
|
|
|
|
|
dev->xfer = malloc(dev->xfer_buf_num * |
|
|
|
|
|
|
|
sizeof(struct libusb_transfer *)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) |
|
|
|
|
|
|
|
dev->xfer[i] = libusb_alloc_transfer(0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev->xfer_buf) { |
|
|
|
|
|
|
|
dev->xfer_buf = malloc(dev->xfer_buf_num * |
|
|
|
|
|
|
|
sizeof(unsigned char *)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) |
|
|
|
|
|
|
|
dev->xfer_buf[i] = malloc(dev->xfer_buf_len); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) { |
|
|
|
|
|
|
|
if (dev->xfer[i]) { |
|
|
|
|
|
|
|
libusb_cancel_transfer(dev->xfer[i]); |
|
|
|
|
|
|
|
libusb_free_transfer(dev->xfer[i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (dev->xfer_buf[i]) |
|
|
|
|
|
|
|
free(dev->xfer_buf[i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dev->xfer) { |
|
|
|
|
|
|
|
free(dev->xfer); |
|
|
|
|
|
|
|
dev->xfer = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dev->xfer_buf) { |
|
|
|
|
|
|
|
free(dev->xfer_buf); |
|
|
|
|
|
|
|
dev->xfer_buf = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t rtlsdr_get_device_count(void) |
|
|
|
uint32_t rtlsdr_get_device_count(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i; |
|
|
|
int i; |
|
|
@ -813,8 +764,6 @@ int rtlsdr_close(rtlsdr_dev_t *dev) |
|
|
|
|
|
|
|
|
|
|
|
rtlsdr_deinit_baseband(dev);
|
|
|
|
rtlsdr_deinit_baseband(dev);
|
|
|
|
|
|
|
|
|
|
|
|
_rtlsdr_free_async_buffers(dev); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
libusb_release_interface(dev->devh, 0); |
|
|
|
libusb_release_interface(dev->devh, 0); |
|
|
|
libusb_close(dev->devh); |
|
|
|
libusb_close(dev->devh); |
|
|
|
|
|
|
|
|
|
|
@ -855,8 +804,7 @@ static void LIBUSB_CALL _libusb_callback(struct libusb_transfer *xfer) |
|
|
|
libusb_submit_transfer(xfer); /* resubmit transfer */ |
|
|
|
libusb_submit_transfer(xfer); /* resubmit transfer */ |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
/*fprintf(stderr, "transfer status: %d\n", xfer->status);*/ |
|
|
|
/*fprintf(stderr, "transfer status: %d\n", xfer->status);*/ |
|
|
|
if (dev->run_async) |
|
|
|
rtlsdr_cancel_async(dev); /* abort async loop */ |
|
|
|
dev->run_async = 0; /* abort async loop */ |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -865,6 +813,63 @@ int rtlsdr_wait_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx) |
|
|
|
return rtlsdr_read_async(dev, cb, ctx, 0, 0); |
|
|
|
return rtlsdr_read_async(dev, cb, ctx, 0, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev->xfer) { |
|
|
|
|
|
|
|
dev->xfer = malloc(dev->xfer_buf_num * |
|
|
|
|
|
|
|
sizeof(struct libusb_transfer *)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) |
|
|
|
|
|
|
|
dev->xfer[i] = libusb_alloc_transfer(0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev->xfer_buf) { |
|
|
|
|
|
|
|
dev->xfer_buf = malloc(dev->xfer_buf_num * |
|
|
|
|
|
|
|
sizeof(unsigned char *)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) |
|
|
|
|
|
|
|
dev->xfer_buf[i] = malloc(dev->xfer_buf_len); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev) |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dev->xfer) { |
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) { |
|
|
|
|
|
|
|
if (dev->xfer[i]) { |
|
|
|
|
|
|
|
libusb_free_transfer(dev->xfer[i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
free(dev->xfer); |
|
|
|
|
|
|
|
dev->xfer = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dev->xfer_buf) { |
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) { |
|
|
|
|
|
|
|
if (dev->xfer_buf[i]) |
|
|
|
|
|
|
|
free(dev->xfer_buf[i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
free(dev->xfer_buf); |
|
|
|
|
|
|
|
dev->xfer_buf = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, |
|
|
|
int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, |
|
|
|
uint32_t buf_num, uint32_t buf_len) |
|
|
|
uint32_t buf_num, uint32_t buf_len) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -877,8 +882,6 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, |
|
|
|
dev->cb = cb; |
|
|
|
dev->cb = cb; |
|
|
|
dev->cb_ctx = ctx; |
|
|
|
dev->cb_ctx = ctx; |
|
|
|
|
|
|
|
|
|
|
|
_rtlsdr_free_async_buffers(dev); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (buf_num > 0) |
|
|
|
if (buf_num > 0) |
|
|
|
dev->xfer_buf_num = buf_num; |
|
|
|
dev->xfer_buf_num = buf_num; |
|
|
|
else |
|
|
|
else |
|
|
@ -904,22 +907,40 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, |
|
|
|
libusb_submit_transfer(dev->xfer[i]); |
|
|
|
libusb_submit_transfer(dev->xfer[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
dev->run_async = 1; |
|
|
|
dev->async_status = RTLSDR_RUNNING; |
|
|
|
|
|
|
|
|
|
|
|
while (dev->run_async) { |
|
|
|
while (RTLSDR_INACTIVE != dev->async_status) { |
|
|
|
r = libusb_handle_events_timeout(dev->ctx, &tv); |
|
|
|
r = libusb_handle_events_timeout(dev->ctx, &tv); |
|
|
|
if (r < 0) { |
|
|
|
if (r < 0) { |
|
|
|
/*fprintf(stderr, "handle_events returned: %d\n", r);*/ |
|
|
|
/*fprintf(stderr, "handle_events returned: %d\n", r);*/ |
|
|
|
|
|
|
|
if (r == LIBUSB_ERROR_INTERRUPTED) /* stray signal */ |
|
|
|
|
|
|
|
continue; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (RTLSDR_CANCELING == dev->async_status) { |
|
|
|
|
|
|
|
dev->async_status = RTLSDR_INACTIVE; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dev->xfer) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) { |
|
|
|
for(i = 0; i < dev->xfer_buf_num; ++i) { |
|
|
|
if (dev->xfer[i]) { |
|
|
|
if (!dev->xfer[i]) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dev->xfer[i]->status == LIBUSB_TRANSFER_COMPLETED) { |
|
|
|
libusb_cancel_transfer(dev->xfer[i]); |
|
|
|
libusb_cancel_transfer(dev->xfer[i]); |
|
|
|
|
|
|
|
dev->async_status = RTLSDR_CANCELING; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (RTLSDR_INACTIVE == dev->async_status) |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_rtlsdr_free_async_buffers(dev); |
|
|
|
|
|
|
|
|
|
|
|
return r; |
|
|
|
return r; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -928,8 +949,8 @@ int rtlsdr_cancel_async(rtlsdr_dev_t *dev) |
|
|
|
if (!dev) |
|
|
|
if (!dev) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
|
|
if (dev->run_async) { |
|
|
|
if (RTLSDR_RUNNING == dev->async_status) { |
|
|
|
dev->run_async = 0; |
|
|
|
dev->async_status = RTLSDR_CANCELING; |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|