Project

General

Profile

Download (20 KB) Statistics
| Branch: | Tag: | Revision:
1
/*
2
 * Copyright (C) 2012 by Dimitri Stolnikov <horiz0n@gmx.net>
3
 * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de>
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

    
19
#include <errno.h>
20
#include <signal.h>
21
#include <string.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <math.h>
25
#ifndef _WIN32
26
#include <unistd.h>
27
#define min(a, b) (((a) < (b)) ? (a) : (b))
28
#endif
29

    
30
//cross platform usleep()
31
#ifdef _MSC_VER
32
#include <windows.h>
33
#define usleep(t) Sleep((t)/1000)
34
#else
35
#include <unistd.h>
36
#endif
37

    
38
#include <libusb.h>
39

    
40
/*
41
 * All libusb callback functions should be marked with the LIBUSB_CALL macro
42
 * to ensure that they are compiled with the same calling convention as libusb.
43
 *
44
 * If the macro isn't available in older libusb versions, we simply define it.
45
 */
46
#ifndef LIBUSB_CALL
47
#define LIBUSB_CALL
48
#endif
49

    
50
#include "osmosdr.h"
51

    
52
typedef struct osmosdr_tuner {
53
	/* tuner interface */
54
	int (*init)(void *);
55
	int (*exit)(void *);
56
	int (*set_freq)(void *, uint32_t freq /* Hz */);
57
	int (*set_bw)(void *, int bw /* Hz */);
58
	int (*set_gain)(void *, int gain /* dB */);
59
	int (*set_gain_mode)(void *, int manual);
60
} osmosdr_tuner_t;
61

    
62
enum osmosdr_async_status {
63
	OSMOSDR_INACTIVE = 0,
64
	OSMOSDR_CANCELING,
65
	OSMOSDR_RUNNING
66
};
67

    
68
struct osmosdr_dev {
69
	libusb_context *ctx;
70
	struct libusb_device_handle *devh;
71
	uint32_t xfer_buf_num;
72
	uint32_t xfer_buf_len;
73
	struct libusb_transfer **xfer;
74
	unsigned char **xfer_buf;
75
	osmosdr_read_async_cb_t cb;
76
	void *cb_ctx;
77
	enum osmosdr_async_status async_status;
78
	/* adc context */
79
	uint32_t rate; /* Hz */
80
	uint32_t adc_clock; /* Hz */
81
	/* tuner context */
82
	osmosdr_tuner_t *tuner;
83
	uint32_t freq; /* Hz */
84
	int gain; /* dB */
85
};
86

    
87
typedef struct osmosdr_dongle {
88
	uint16_t vid;
89
	uint16_t pid;
90
	const char *name;
91
} osmosdr_dongle_t;
92

    
93
static osmosdr_dongle_t known_devices[] = {
94
	{ 0x16c0, 0x0763, "sysmocom OsmoSDR" },
95
	/* here come future modifications of the OsmoSDR */
96
};
97

    
98
#define DEFAULT_BUF_NUMBER	32
99
#define DEFAULT_BUF_LENGTH	(16 * 32 * 512)
100

    
101
#define DEF_ADC_FREQ	4000000
102

    
103
#define CTRL_IN		(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
104
#define CTRL_OUT	(LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
105
#define FUNC(group, function) ((group << 8) | function)
106

    
107
#define CTRL_TIMEOUT	300
108
#define BULK_TIMEOUT	0
109

    
110
int e4k_init(void *dev) {
111
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
112
	int res;
113

    
114
	res = libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
115
				      FUNC(3, 0), 0,
116
				      NULL, 0, CTRL_TIMEOUT);
117

    
118
	return res; /* 0 is success since we do not send any buffers out */
119
}
120

    
121
int e4k_exit(void *dev) { return 0; }
122

    
123
int e4k_set_freq(void *dev, uint32_t freq) {
124
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
125
	uint8_t buffer[4];
126
	int res;
127

    
128
	buffer[0] = (uint8_t)(freq >> 24);
129
	buffer[1] = (uint8_t)(freq >> 16);
130
	buffer[2] = (uint8_t)(freq >> 8);
131
	buffer[3] = (uint8_t)(freq >> 0);
132

    
133
	res = libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
134
				      FUNC(3, 5), 0,
135
				      buffer, sizeof(buffer), CTRL_TIMEOUT);
136

    
137
	if (res == sizeof(buffer)) {
138
		res = libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
139
					      FUNC(3, 9), 0,
140
					      NULL, 0, CTRL_TIMEOUT);
141
	}
142

    
143
	return res;
144
}
145

    
146
int e4k_set_bw(void *dev, int bw) { return 0; }
147

    
148
int e4k_set_lna_gain(void *dev, int32_t gain) {
149
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
150
	uint8_t buffer[4];
151
	int res;
152

    
153
	buffer[0] = (uint8_t)(gain >> 24);
154
	buffer[1] = (uint8_t)(gain >> 16);
155
	buffer[2] = (uint8_t)(gain >> 8);
156
	buffer[3] = (uint8_t)(gain >> 0);
157

    
158
	res = libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
159
				      FUNC(3, 0x0b), 0,
160
				      buffer, sizeof(buffer), CTRL_TIMEOUT);
161

    
162
	if (res == sizeof(buffer))
163
		res = 0;
164

    
165
	return res;
166
}
167

    
168
int e4k_mixer_gain_set(void *dev, int8_t gain) {
169
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
170
	uint8_t buffer[1];
171
	int res;
172

    
173
	buffer[0] = gain;
174

    
175
	res = libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
176
				      FUNC(3, 0x03), 0,
177
				      buffer, sizeof(buffer), CTRL_TIMEOUT);
178

    
179
	if (res == sizeof(buffer))
180
		res = 0;
181

    
182
	return res;
183
}
184

    
185
int e4k_set_enh_gain(void *dev, int32_t gain) {
186
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
187
	uint8_t buffer[4];
188
	int res;
189

    
190
	buffer[0] = (uint8_t)(gain >> 24);
191
	buffer[1] = (uint8_t)(gain >> 16);
192
	buffer[2] = (uint8_t)(gain >> 8);
193
	buffer[3] = (uint8_t)(gain >> 0);
194

    
195
	res = libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
196
				      FUNC(3, 0x0d), 0,
197
				      buffer, sizeof(buffer), CTRL_TIMEOUT);
198

    
199
	if (res == sizeof(buffer))
200
		res = 0;
201

    
202
	return res;
203
}
204

    
205
int e4k_set_gain(void *dev, int gain) {
206
	int8_t mixgain = (gain > 340) ? 12 : 4;
207
#if 0
208
	int enhgain = (gain - 420);
209
#endif
210
	if(e4k_set_lna_gain(dev, min(300, gain - mixgain * 10)))
211
		return -1;
212
	if(e4k_mixer_gain_set(dev, mixgain))
213
		return -1;
214
#if 0 /* enhanced mixer gain seems to have no effect */
215
	if(enhgain >= 0)
216
		if(e4k_set_enh_gain(dev, enhgain))
217
			return -1;
218
#endif
219
	return 0;
220
}
221

    
222
int e4k_set_gain_mode(void *dev, int manual) {
223
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
224
	uint8_t buffer[1];
225
	int res;
226

    
227
	buffer[0] = (uint8_t)manual;
228

    
229
	res = libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
230
				      FUNC(3, 0x0c), 0,
231
				      buffer, sizeof(buffer), CTRL_TIMEOUT);
232

    
233
	if (res == sizeof(buffer))
234
		res = 0;
235

    
236
	return res;
237
}
238

    
239
static osmosdr_tuner_t tuner = {
240
	e4k_init, e4k_exit,
241
	e4k_set_freq,
242
	e4k_set_bw, e4k_set_gain, e4k_set_gain_mode
243
};
244

    
245
int osmosdr_get_usb_strings(osmosdr_dev_t *dev, char *manufact, char *product,
246
			    char *serial)
247
{
248
	struct libusb_device_descriptor dd;
249
	libusb_device *device = NULL;
250
	const int buf_max = 256;
251
	int r = 0;
252

    
253
	if (!dev || !dev->devh)
254
		return -1;
255

    
256
	device = libusb_get_device(dev->devh);
257

    
258
	r = libusb_get_device_descriptor(device, &dd);
259
	if (r < 0)
260
		return -1;
261

    
262
	if (manufact) {
263
		memset(manufact, 0, buf_max);
264
		libusb_get_string_descriptor_ascii(dev->devh, dd.iManufacturer,
265
						   (unsigned char *)manufact,
266
						   buf_max);
267
	}
268

    
269
	if (product) {
270
		memset(product, 0, buf_max);
271
		libusb_get_string_descriptor_ascii(dev->devh, dd.iProduct,
272
						   (unsigned char *)product,
273
						   buf_max);
274
	}
275

    
276
	if (serial) {
277
		memset(serial, 0, buf_max);
278
		libusb_get_string_descriptor_ascii(dev->devh, dd.iSerialNumber,
279
						   (unsigned char *)serial,
280
						   buf_max);
281
	}
282

    
283
	return 0;
284
}
285

    
286
int osmosdr_set_center_freq(osmosdr_dev_t *dev, uint32_t freq)
287
{
288
	int r = -2;
289

    
290
	if (!dev || !dev->tuner)
291
		return -1;
292

    
293
	if (dev->tuner->set_freq)
294
		r = dev->tuner->set_freq(dev, freq);
295

    
296
	if (!r)
297
		dev->freq = freq;
298
	else
299
		dev->freq = 0;
300

    
301
	return r;
302
}
303

    
304
uint32_t osmosdr_get_center_freq(osmosdr_dev_t *dev)
305
{
306
	if (!dev || !dev->tuner)
307
		return 0;
308

    
309
	return dev->freq;
310
}
311

    
312
int osmosdr_get_tuner_gains(osmosdr_dev_t *dev, int *gains)
313
{
314
	/* all gain values are expressed in tenths of a dB */
315
	const int e4k_gains[] = { -10, 15, 40, 65, 90, 115, 140, 165, 190, 215,
316
				  240, 290, 340, 420 };
317
	int len = sizeof(e4k_gains);
318

    
319
	if (!dev)
320
		return -1;
321

    
322
	if (!gains) { /* no buffer provided, just return the count */
323
		return len / sizeof(int);
324
	} else {
325
		if (len)
326
			memcpy(gains, e4k_gains, len);
327

    
328
		return len / sizeof(int);
329
	}
330
}
331

    
332
int osmosdr_set_tuner_gain(osmosdr_dev_t *dev, int gain)
333
{
334
	int r = -2;
335

    
336
	if (!dev || !dev->tuner)
337
		return -1;
338

    
339
	if (dev->tuner->set_gain)
340
		r = dev->tuner->set_gain((void *)dev, gain);
341

    
342
	if (!r)
343
		dev->gain = gain;
344
	else
345
		dev->gain = 0;
346

    
347
	return r;
348
}
349

    
350
int osmosdr_get_tuner_gain(osmosdr_dev_t *dev)
351
{
352
	if (!dev || !dev->tuner)
353
		return 0;
354

    
355
	return dev->gain;
356
}
357

    
358
int osmosdr_set_tuner_gain_mode(osmosdr_dev_t *dev, int mode)
359
{
360
	int r = -2;
361

    
362
	if (!dev || !dev->tuner)
363
		return -1;
364

    
365
	if (dev->tuner->set_gain_mode)
366
		r = dev->tuner->set_gain_mode((void *)dev, mode);
367

    
368
	return r;
369
}
370

    
371
int osmosdr_set_tuner_lna_gain(osmosdr_dev_t *dev, int gain)
372
{
373
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
374
	uint8_t buffer[4];
375

    
376
	buffer[0] = (gain >> 24);
377
	buffer[1] = (gain >> 16);
378
	buffer[2] = (gain >> 8);
379
	buffer[3] = (gain >> 0);
380

    
381
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
382
				       FUNC(3, 0x0b), 0,
383
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
384
}
385

    
386
int osmosdr_set_tuner_mixer_gain(osmosdr_dev_t *dev, int gain)
387
{
388
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
389
	uint8_t buffer[1];
390

    
391
	buffer[0] = gain / 10;
392

    
393
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
394
				       FUNC(3, 0x03), 0,
395
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
396
}
397

    
398
int osmosdr_set_tuner_mixer_enh(osmosdr_dev_t *dev, int enh)
399
{
400
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
401
	uint8_t buffer[4];
402

    
403
	buffer[0] = (enh >> 24);
404
	buffer[1] = (enh >> 16);
405
	buffer[2] = (enh >> 8);
406
	buffer[3] = (enh >> 0);
407

    
408
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
409
				       FUNC(3, 0x0d), 0,
410
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
411
}
412

    
413
int osmosdr_set_tuner_if_gain(osmosdr_dev_t *dev, int stage, int gain)
414
{
415
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
416
	uint8_t buffer[5];
417

    
418
	buffer[0] = stage;
419
	gain /= 10;
420
	buffer[1] = (gain >> 24);
421
	buffer[2] = (gain >> 16);
422
	buffer[3] = (gain >> 8);
423
	buffer[4] = (gain >> 0);
424

    
425
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
426
				       FUNC(3, 0x02), 0,
427
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
428
}
429

    
430
/* two raised to the power of n */
431
#define TWO_POW(n)		(1ULL<<(n))
432

    
433
uint32_t osmosdr_get_sample_rates(osmosdr_dev_t *dev, uint32_t *rates)
434
{
435
	int n;
436

    
437
	if (!dev)
438
		return -1;
439

    
440
	if (!rates) { /* no buffer provided, just return the count */
441
		return 5;
442
	} else {
443
		for (n = 6; n > 1; n--) /* 64 to 4 */
444
			*(rates++) = dev->adc_clock / TWO_POW(n);
445

    
446
		return 5;
447
	}
448

    
449
	return 0;
450
}
451

    
452
int osmosdr_set_sample_rate(osmosdr_dev_t *dev, uint32_t samp_rate)
453
{
454
	int n, decim = 3;
455
	int r = 0;
456
	unsigned int req_decim = 0;
457

    
458
	if (!dev)
459
		return -1;
460

    
461
	/* TODO: implement arbitrary rates by steering the master clock */
462

    
463
	req_decim = dev->adc_clock / samp_rate;
464

    
465
	for (n = 2; n <= 6; n++) { /* 4 to 64 */
466
		if (TWO_POW(n) == req_decim) {
467
			decim = n;
468
			break;
469
		}
470
	}
471

    
472
	samp_rate = dev->adc_clock / TWO_POW(decim);
473

    
474
	r = osmosdr_set_fpga_decimation(dev, decim);
475
	if (r >= 0) {
476
		if (dev->tuner && dev->tuner->set_bw)
477
			dev->tuner->set_bw(dev, samp_rate);
478

    
479
		dev->rate = samp_rate;
480
	} else {
481
		dev->rate = 0;
482
	}
483

    
484
	return r;
485
}
486

    
487
uint32_t osmosdr_get_sample_rate(osmosdr_dev_t *dev)
488
{
489
	if (!dev)
490
		return 0;
491

    
492
	return dev->rate;
493
}
494

    
495
int osmosdr_set_fpga_reg(osmosdr_dev_t *dev, uint8_t reg, uint32_t value)
496
{
497
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
498
	uint8_t buffer[5];
499

    
500
	buffer[0] = reg;
501
	buffer[1] = (uint8_t)(value >> 24);
502
	buffer[2] = (uint8_t)(value >> 16);
503
	buffer[3] = (uint8_t)(value >> 8);
504
	buffer[4] = (uint8_t)(value >> 0);
505

    
506
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
507
				       FUNC(1, 0x01), 0,
508
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
509
}
510

    
511
int osmosdr_set_fpga_decimation(osmosdr_dev_t *dev, int dec)
512
{
513
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
514
	uint8_t buffer[1];
515

    
516
	if((dec < 0) || (dec > 6))
517
		return -1;
518

    
519
	buffer[0] = dec;
520

    
521
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
522
				       FUNC(1, 0x02), 0,
523
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
524
}
525

    
526
int osmosdr_set_fpga_iq_swap(osmosdr_dev_t *dev, int sw)
527
{
528
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
529
	uint8_t buffer[1];
530

    
531
	if((sw < 0) || (sw > 1))
532
		return -1;
533

    
534
	buffer[0] = sw;
535

    
536
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
537
				       FUNC(1, 0x03), 0,
538
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
539
}
540

    
541
int osmosdr_set_fpga_iq_gain(osmosdr_dev_t *dev, uint16_t igain, uint16_t qgain)
542
{
543
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
544
	uint8_t buffer[4];
545

    
546
	buffer[0] = (uint8_t)(igain >> 8);
547
	buffer[1] = (uint8_t)(igain >> 0);
548
	buffer[2] = (uint8_t)(qgain >> 8);
549
	buffer[3] = (uint8_t)(qgain >> 0);
550

    
551
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
552
				       FUNC(1, 0x04), 0,
553
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
554
}
555

    
556
int osmosdr_set_fpga_iq_ofs(osmosdr_dev_t *dev, int16_t iofs, int16_t qofs)
557
{
558
	osmosdr_dev_t* devt = (osmosdr_dev_t*)dev;
559
	uint8_t buffer[4];
560

    
561
	buffer[0] = (uint8_t)(iofs >> 8);
562
	buffer[1] = (uint8_t)(iofs >> 0);
563
	buffer[2] = (uint8_t)(qofs >> 8);
564
	buffer[3] = (uint8_t)(qofs >> 0);
565

    
566
	return libusb_control_transfer(devt->devh, CTRL_OUT, 0x07,
567
				       FUNC(1, 0x05), 0,
568
				       buffer, sizeof(buffer), CTRL_TIMEOUT);
569
}
570

    
571
static osmosdr_dongle_t *find_known_device(uint16_t vid, uint16_t pid)
572
{
573
	unsigned int i;
574
	osmosdr_dongle_t *device = NULL;
575

    
576
	for (i = 0; i < sizeof(known_devices)/sizeof(osmosdr_dongle_t); i++ ) {
577
		if (known_devices[i].vid == vid && known_devices[i].pid == pid) {
578
			device = &known_devices[i];
579
			break;
580
		}
581
	}
582

    
583
	return device;
584
}
585

    
586
uint32_t osmosdr_get_device_count(void)
587
{
588
	int i;
589
	libusb_context *ctx;
590
	libusb_device **list;
591
	struct libusb_device_descriptor dd;
592
	uint32_t device_count = 0;
593
	ssize_t cnt;
594

    
595
	libusb_init(&ctx);
596

    
597
	cnt = libusb_get_device_list(ctx, &list);
598

    
599
	for (i = 0; i < cnt; i++) {
600
		libusb_get_device_descriptor(list[i], &dd);
601

    
602
		if (find_known_device(dd.idVendor, dd.idProduct))
603
			device_count++;
604
	}
605

    
606
	libusb_free_device_list(list, 1);
607

    
608
	libusb_exit(ctx);
609

    
610
	return device_count;
611
}
612

    
613
const char *osmosdr_get_device_name(uint32_t index)
614
{
615
	int i;
616
	libusb_context *ctx;
617
	libusb_device **list;
618
	struct libusb_device_descriptor dd;
619
	osmosdr_dongle_t *device = NULL;
620
	uint32_t device_count = 0;
621
	ssize_t cnt;
622

    
623
	libusb_init(&ctx);
624

    
625
	cnt = libusb_get_device_list(ctx, &list);
626

    
627
	for (i = 0; i < cnt; i++) {
628
		libusb_get_device_descriptor(list[i], &dd);
629

    
630
		device = find_known_device(dd.idVendor, dd.idProduct);
631

    
632
		if (device) {
633
			device_count++;
634

    
635
			if (index == device_count - 1)
636
				break;
637

    
638
			device = NULL;
639
		}
640
	}
641

    
642
	libusb_free_device_list(list, 1);
643

    
644
	libusb_exit(ctx);
645

    
646
	if (device)
647
		return device->name;
648
	else
649
		return "";
650
}
651

    
652
int osmosdr_get_device_usb_strings(uint32_t index, char *manufact,
653
				   char *product, char *serial)
654
{
655
	int r = -2;
656
	int i;
657
	libusb_context *ctx;
658
	libusb_device **list;
659
	struct libusb_device_descriptor dd;
660
	osmosdr_dev_t devt;
661
	uint32_t device_count = 0;
662
	ssize_t cnt;
663

    
664
	libusb_init(&ctx);
665

    
666
	cnt = libusb_get_device_list(ctx, &list);
667

    
668
	for (i = 0; i < cnt; i++) {
669
		libusb_get_device_descriptor(list[i], &dd);
670

    
671
		if (find_known_device(dd.idVendor, dd.idProduct))
672
			device_count++;
673

    
674
		if (index == device_count - 1) {
675
			r = libusb_open(list[i], &devt.devh);
676
			if (!r) {
677
				r = osmosdr_get_usb_strings(&devt,
678
							    manufact,
679
							    product,
680
							    serial);
681
				libusb_close(devt.devh);
682
			}
683
			break;
684
		}
685
	}
686

    
687
	libusb_free_device_list(list, 1);
688

    
689
	libusb_exit(ctx);
690

    
691
	return r;
692
}
693

    
694
int osmosdr_open(osmosdr_dev_t **out_dev, uint32_t index)
695
{
696
	int r;
697
	int i;
698
	libusb_device **list;
699
	osmosdr_dev_t *dev = NULL;
700
	libusb_device *device = NULL;
701
	uint32_t device_count = 0;
702
	struct libusb_device_descriptor dd;
703
	ssize_t cnt;
704

    
705
	dev = malloc(sizeof(osmosdr_dev_t));
706
	if (NULL == dev)
707
		return -ENOMEM;
708

    
709
	memset(dev, 0, sizeof(osmosdr_dev_t));
710

    
711
	libusb_init(&dev->ctx);
712

    
713
	cnt = libusb_get_device_list(dev->ctx, &list);
714

    
715
	for (i = 0; i < cnt; i++) {
716
		device = list[i];
717

    
718
		libusb_get_device_descriptor(list[i], &dd);
719

    
720
		if (find_known_device(dd.idVendor, dd.idProduct))
721
			device_count++;
722

    
723
		if (index == device_count - 1)
724
			break;
725

    
726
		device = NULL;
727
	}
728

    
729
	if (!device) {
730
		r = -1;
731
		goto err;
732
	}
733

    
734
	r = libusb_open(device, &dev->devh);
735
	if (r < 0) {
736
		libusb_free_device_list(list, 1);
737
		fprintf(stderr, "usb_open error %d\n", r);
738
		goto err;
739
	}
740

    
741
	libusb_free_device_list(list, 1);
742

    
743
	r = libusb_claim_interface(dev->devh, 0);
744
	if (r < 0) {
745
		fprintf(stderr, "usb_claim_interface error %d\n", r);
746
		goto err;
747
	}
748

    
749
	dev->adc_clock = DEF_ADC_FREQ;
750

    
751
	dev->tuner = &tuner; /* so far we have only one tuner */
752

    
753
	if (dev->tuner->init) {
754
		r = dev->tuner->init(dev);
755
	}
756

    
757
	*out_dev = dev;
758

    
759
	return 0;
760
err:
761
	if (dev) {
762
		if (dev->ctx)
763
			libusb_exit(dev->ctx);
764

    
765
		free(dev);
766
	}
767

    
768
	return r;
769
}
770

    
771
int osmosdr_close(osmosdr_dev_t *dev)
772
{
773
	if (!dev)
774
		return -1;
775

    
776
	/* block until all async operations have been completed (if any) */
777
	while (OSMOSDR_INACTIVE != dev->async_status)
778
		usleep(10);
779

    
780
	libusb_release_interface(dev->devh, 0);
781
	libusb_close(dev->devh);
782

    
783
	libusb_exit(dev->ctx);
784

    
785
	free(dev);
786

    
787
	return 0;
788
}
789

    
790
int osmosdr_reset_buffer(osmosdr_dev_t *dev)
791
{
792
	if (!dev)
793
		return -1;
794

    
795
	/* TODO: implement */
796

    
797
	return 0;
798
}
799

    
800
int osmosdr_read_sync(osmosdr_dev_t *dev, void *buf, int len, int *n_read)
801
{
802
	if (!dev)
803
		return -1;
804

    
805
	return libusb_bulk_transfer(dev->devh, 0x86, buf, len, n_read, BULK_TIMEOUT);
806
}
807

    
808
static void LIBUSB_CALL _libusb_callback(struct libusb_transfer *xfer)
809
{
810
	osmosdr_dev_t *dev = (osmosdr_dev_t *)xfer->user_data;
811

    
812
	if (LIBUSB_TRANSFER_COMPLETED == xfer->status) {
813
		if (dev->cb)
814
			dev->cb(xfer->buffer, xfer->actual_length, dev->cb_ctx);
815

    
816
		libusb_submit_transfer(xfer); /* resubmit transfer */
817
	} else if (LIBUSB_TRANSFER_CANCELLED == xfer->status) {
818
		/* nothing to do */
819
	} else {
820
		/*fprintf(stderr, "transfer status: %d\n", xfer->status);*/
821
	}
822
}
823

    
824
static int _osmosdr_alloc_async_buffers(osmosdr_dev_t *dev)
825
{
826
	unsigned int i;
827

    
828
	if (!dev)
829
		return -1;
830

    
831
	if (!dev->xfer) {
832
		dev->xfer = malloc(dev->xfer_buf_num *
833
				   sizeof(struct libusb_transfer *));
834

    
835
		for(i = 0; i < dev->xfer_buf_num; ++i)
836
			dev->xfer[i] = libusb_alloc_transfer(0);
837
	}
838

    
839
	if (!dev->xfer_buf) {
840
		dev->xfer_buf = malloc(dev->xfer_buf_num *
841
					   sizeof(unsigned char *));
842

    
843
		for(i = 0; i < dev->xfer_buf_num; ++i)
844
			dev->xfer_buf[i] = malloc(dev->xfer_buf_len);
845
	}
846

    
847
	return 0;
848
}
849

    
850
static int _osmosdr_free_async_buffers(osmosdr_dev_t *dev)
851
{
852
	unsigned int i;
853

    
854
	if (!dev)
855
		return -1;
856

    
857
	if (dev->xfer) {
858
		for(i = 0; i < dev->xfer_buf_num; ++i) {
859
			if (dev->xfer[i]) {
860
				libusb_free_transfer(dev->xfer[i]);
861
			}
862
		}
863

    
864
		free(dev->xfer);
865
		dev->xfer = NULL;
866
	}
867

    
868
	if (dev->xfer_buf) {
869
		for(i = 0; i < dev->xfer_buf_num; ++i) {
870
			if (dev->xfer_buf[i])
871
				free(dev->xfer_buf[i]);
872
		}
873

    
874
		free(dev->xfer_buf);
875
		dev->xfer_buf = NULL;
876
	}
877

    
878
	return 0;
879
}
880

    
881
int osmosdr_read_async(osmosdr_dev_t *dev, osmosdr_read_async_cb_t cb, void *ctx,
882
		       uint32_t buf_num, uint32_t buf_len)
883
{
884
	unsigned int i;
885
	int r = 0;
886
	struct timeval tv = { 1, 0 };
887
	enum osmosdr_async_status next_status = OSMOSDR_INACTIVE;
888

    
889
	if (!dev)
890
		return -1;
891

    
892
	if (OSMOSDR_INACTIVE != dev->async_status)
893
		return -2;
894

    
895
	dev->async_status = OSMOSDR_RUNNING;
896

    
897
	dev->cb = cb;
898
	dev->cb_ctx = ctx;
899

    
900
	if (buf_num > 0)
901
		dev->xfer_buf_num = buf_num;
902
	else
903
		dev->xfer_buf_num = DEFAULT_BUF_NUMBER;
904

    
905
	if (buf_len > 0 && buf_len % 512 == 0) /* len must be multiple of 512 */
906
		dev->xfer_buf_len = buf_len;
907
	else
908
		dev->xfer_buf_len = DEFAULT_BUF_LENGTH;
909

    
910
	_osmosdr_alloc_async_buffers(dev);
911

    
912
	for(i = 0; i < dev->xfer_buf_num; ++i) {
913
		libusb_fill_bulk_transfer(dev->xfer[i],
914
					  dev->devh,
915
					  0x86,
916
					  dev->xfer_buf[i],
917
					  dev->xfer_buf_len,
918
					  _libusb_callback,
919
					  (void *)dev,
920
					  BULK_TIMEOUT);
921

    
922
		libusb_submit_transfer(dev->xfer[i]);
923
	}
924

    
925
	while (OSMOSDR_INACTIVE != dev->async_status) {
926
		r = libusb_handle_events_timeout(dev->ctx, &tv);
927
		if (r < 0) {
928
			/*fprintf(stderr, "handle_events returned: %d\n", r);*/
929
			if (r == LIBUSB_ERROR_INTERRUPTED) /* stray signal */
930
				continue;
931
			break;
932
		}
933

    
934
		if (OSMOSDR_CANCELING == dev->async_status) {
935
			next_status = OSMOSDR_INACTIVE;
936

    
937
			if (!dev->xfer)
938
				break;
939

    
940
			for(i = 0; i < dev->xfer_buf_num; ++i) {
941
				if (!dev->xfer[i])
942
					continue;
943

    
944
				if (LIBUSB_TRANSFER_CANCELLED !=
945
						dev->xfer[i]->status) {
946
					libusb_cancel_transfer(dev->xfer[i]);
947
					next_status = OSMOSDR_CANCELING;
948
				}
949
			}
950

    
951
			if (OSMOSDR_INACTIVE == next_status)
952
				break;
953
		}
954
	}
955

    
956
	_osmosdr_free_async_buffers(dev);
957

    
958
	dev->async_status = next_status;
959

    
960
	return r;
961
}
962

    
963
int osmosdr_cancel_async(osmosdr_dev_t *dev)
964
{
965
	if (!dev)
966
		return -1;
967

    
968
	/* if streaming, try to cancel gracefully */
969
	if (OSMOSDR_RUNNING == dev->async_status) {
970
		dev->async_status = OSMOSDR_CANCELING;
971
		return 0;
972
	}
973

    
974
	/* if called while in pending state, change the state forcefully */
975
	if (OSMOSDR_INACTIVE != dev->async_status) {
976
		dev->async_status = OSMOSDR_INACTIVE;
977
		return 0;
978
	}
979

    
980
	return -2;
981
}
(3-3/4)
Add picture from clipboard (Maximum size: 48.8 MB)