1#![allow(dead_code)]
11use std::sync::Arc;
12use std::os::raw::{c_int, c_void, c_uchar, c_char};
13use std::option::Option;
14use std::string::String;
15use std::ffi::CStr;
16use std::ptr;
17use std::str;
18
19
20pub enum SamplingMode {
30 None = 0,
31 IADC = 1,
32 QADC = 2,
33 Error = 3,
34}
35
36pub const DEFAULT_FC: i32 = 80_000_000;
39pub const DEFAULT_RS: i32 = 1_024_000;
40pub const DEFAULT_READ_SIZE: i32 = 1024;
41pub const CRYSTAL_FREQ: i32 = 28800000;
42pub const DEFAULT_SAMPLE_RATE: i32 = 2048000;
43pub const DEFAULT_ASYNC_BUF_NUMBER: i32 = 32;
44pub const DEFAULT_BUF_LENGTH: i32 = (16 * 16384);
45pub const MIN_BUF_LENGTH: i32 = 512;
46pub const MAX_BUF_LENGTH: i32 = (256 * 16384);
47pub const MAX_STR_SIZE: usize = 35;
51
52const STR_OFFSET_START: usize = 0x09;
54const EEPROM_SIZE: i32 = 256;
55const NO_VALID_EEPROM_HEADER: i32 = -13;
57const STRING_VALUE_TOO_LONG: i32 = -14;
58const STRING_DESCRIPTOR_INVALID: i32 = -15;
59const STRING__DESCRIPTOR_TOO_LONG: i32 = -16;
60
61const ERROR_ONKNOWN: i32 = -98;
63const LIBUSB_ERROR_ONKNOWN: i32 = -99;
64
65enum RTLSDRDev { }
67type RTLSDRDevT = RTLSDRDev;
68
69#[derive(Copy, Clone)]
70pub struct Device {
71 dev: *mut RTLSDRDevT,
72}
73
74unsafe impl Send for Device {}
75unsafe impl Sync for Device {}
76
77#[derive(Debug)]
79pub struct HwInfo {
80 pub vendor_id: u16,
81 pub product_id: u16,
82 pub manufact: String,
83 pub product: String,
84 pub serial: String,
85 pub have_serial: bool,
86 pub enable_ir: bool,
87 pub remote_wakeup: bool,
88}
89
90#[derive(Copy, Clone)]
91#[repr(u32)]
92#[derive(Debug)]
93enum RTLSDRTuner {
94 Unknown = 0,
95 E4000 = 1,
96 FC0012 = 2,
97 FC0013 = 3,
98 FC2580 = 4,
99 R820T = 5,
100 R828D = 6,
101}
102
103#[derive(Copy, Clone)]
104#[derive(Debug)]
105pub enum Error {
106 NoError,
107 Io,
108 InvalidParam,
109 Access,
110 NoDevice,
111 NotFound,
112 Busy,
113 Timeout,
114 Overflow,
115 Pipe,
116 Interrupted,
117 NoMem,
118 NotSupported,
119 NoValidEEPROMHeader,
120 StringValueTooLong,
121 StringDescriptorInvalid,
122 StringDescriptorTooLong,
123 Unknown,
124}
125
126
127
128pub type ReadAsyncCbT = Option<unsafe extern "C" fn(buf: *mut c_uchar, len: u32, ctx: *mut c_void)>;
130
131#[link(name = "rtlsdr")]
132extern "C" {
133 fn rtlsdr_get_device_count() -> u32;
134 fn rtlsdr_get_device_name(index: u32) -> *const c_char;
135 fn rtlsdr_get_device_usb_strings(index: u32,
136 manufact: *mut c_char,
137 product: *mut c_char,
138 serial: *mut c_char)
139 -> c_int;
140 fn rtlsdr_get_index_by_serial(serial: *const c_char) -> c_int;
141
142 fn rtlsdr_open(dev: *mut *mut RTLSDRDevT, index: u32) -> c_int;
143 fn rtlsdr_close(dev: *mut RTLSDRDevT) -> c_int;
144 fn rtlsdr_set_xtal_freq(dev: *mut RTLSDRDevT, rtl_freq: u32, tuner_freq: u32) -> c_int;
145 fn rtlsdr_get_xtal_freq(dev: *mut RTLSDRDevT,
146 rtl_freq: *mut u32,
147 tuner_freq: *mut u32)
148 -> c_int;
149 fn rtlsdr_get_usb_strings(dev: *mut RTLSDRDevT,
150 manufact: *mut c_char,
151 product: *mut c_char,
152 serial: *mut c_char)
153 -> c_int;
154 fn rtlsdr_write_eeprom(dev: *mut RTLSDRDevT, data: *mut u8, offset: u8, len: u16) -> c_int;
155 fn rtlsdr_read_eeprom(dev: *mut RTLSDRDevT, data: *mut u8, offset: u8, len: u16) -> c_int;
156 fn rtlsdr_set_center_freq(dev: *mut RTLSDRDevT, freq: u32) -> c_int;
157 fn rtlsdr_get_center_freq(dev: *mut RTLSDRDevT) -> c_int;
158 fn rtlsdr_set_freq_correction(dev: *mut RTLSDRDevT, ppm: c_int) -> c_int;
159 fn rtlsdr_get_freq_correction(dev: *mut RTLSDRDevT) -> c_int;
160 fn rtlsdr_get_tuner_type(dev: *mut RTLSDRDevT) -> RTLSDRTuner;
161 fn rtlsdr_get_tuner_gains(dev: *mut RTLSDRDevT, gains: *mut c_int) -> c_int;
162 fn rtlsdr_set_tuner_gain(dev: *mut RTLSDRDevT, gain: c_int) -> c_int;
163 fn rtlsdr_set_tuner_bandwidth(dev: *mut RTLSDRDevT, bw: u32) -> c_int;
164 fn rtlsdr_get_tuner_gain(dev: *mut RTLSDRDevT) -> c_int;
165 fn rtlsdr_set_tuner_if_gain(dev: *mut RTLSDRDevT, stage: c_int, gain: c_int) -> c_int;
166 fn rtlsdr_set_tuner_gain_mode(dev: *mut RTLSDRDevT, manual: c_int) -> c_int;
167 fn rtlsdr_set_sample_rate(dev: *mut RTLSDRDevT, rate: u32) -> c_int;
168 fn rtlsdr_get_sample_rate(dev: *mut RTLSDRDevT) -> c_int;
169 fn rtlsdr_set_testmode(dev: *mut RTLSDRDevT, on: c_int) -> c_int;
170 fn rtlsdr_set_agc_mode(dev: *mut RTLSDRDevT, on: c_int) -> c_int;
171 fn rtlsdr_set_direct_sampling(dev: *mut RTLSDRDevT, on: c_int) -> c_int;
172 fn rtlsdr_get_direct_sampling(dev: *mut RTLSDRDevT) -> c_int;
173 fn rtlsdr_set_offset_tuning(dev: *mut RTLSDRDevT, on: c_int) -> c_int;
174 fn rtlsdr_get_offset_tuning(dev: *mut RTLSDRDevT) -> c_int;
175 fn rtlsdr_reset_buffer(dev: *mut RTLSDRDevT) -> c_int;
176 fn rtlsdr_read_sync(dev: *mut RTLSDRDevT,
177 buf: *mut c_void,
178 len: c_int,
179 n_read: *mut c_int)
180 -> c_int;
181 fn rtlsdr_wait_async(dev: *mut RTLSDRDevT, cb: ReadAsyncCbT, ctx: *mut c_void) -> c_int;
182 fn rtlsdr_read_async(dev: *mut RTLSDRDevT,
183 cb: ReadAsyncCbT,
184 ctx: *mut c_void,
185 buf_num: u32,
186 buf_len: u32)
187 -> c_int;
188 fn rtlsdr_cancel_async(dev: *mut RTLSDRDevT) -> c_int;
189}
190
191fn get_err_msg(e: c_int) -> Error {
193 match e {
194 0 => Error::NoError,
195 -1 => Error::Io,
196 -2 => Error::InvalidParam,
197 -3 => Error::Access,
198 -4 => Error::NoDevice,
199 -5 => Error::NotFound,
200 -6 => Error::Busy,
201 -7 => Error::Timeout,
202 -8 => Error::Overflow,
203 -9 => Error::Pipe,
204 -10 => Error::Interrupted,
205 -11 => Error::NoMem,
206 -12 => Error::NotSupported,
207 NO_VALID_EEPROM_HEADER => Error::NoValidEEPROMHeader,
208 STRING_VALUE_TOO_LONG => Error::StringValueTooLong,
209 STRING_DESCRIPTOR_INVALID => Error::StringDescriptorInvalid,
210 STRING__DESCRIPTOR_TOO_LONG => Error::StringDescriptorTooLong,
211 _ => Error::Unknown,
212 }
213}
214
215fn from_tuner_type(t: RTLSDRTuner) -> String {
216 match t {
217 RTLSDRTuner::Unknown => String::from("Unknown"),
218 RTLSDRTuner::E4000 => String::from("E4000"),
219 RTLSDRTuner::FC0012 => String::from("FC0012"),
220 RTLSDRTuner::FC0013 => String::from("FC0013"),
221 RTLSDRTuner::FC2580 => String::from("FC2580"),
222 RTLSDRTuner::R820T => String::from("R820T"),
223 RTLSDRTuner::R828D => String::from("R828D"),
224 }
225}
226
227fn from_pchar(p: *const c_char) -> String {
228 let c_str = unsafe { CStr::from_ptr(p) };
229 String::from(str::from_utf8(c_str.to_bytes()).unwrap())
230}
231
232
233pub fn get_device_count() -> i32 {
235 unsafe { rtlsdr_get_device_count() as i32 }
236}
237
238pub fn get_device_name(index: i32) -> String {
240 unsafe { CStr::from_ptr(rtlsdr_get_device_name(index as u32)).to_string_lossy().into_owned() }
241}
242
243pub fn get_device_usb_strings(index: i32) -> (String, String, String, Error) {
245 unsafe {
246 let m: [c_char; 256] = [0; 256];
247 let p: [c_char; 256] = [0; 256];
248 let s: [c_char; 256] = [0; 256];
249 let err = rtlsdr_get_device_usb_strings(index as u32,
250 m.as_ptr() as *mut c_char,
251 p.as_ptr() as *mut c_char,
252 s.as_ptr() as *mut c_char);
253 (from_pchar(m.as_ptr()), from_pchar(p.as_ptr()), from_pchar(s.as_ptr()), get_err_msg(err))
254 }
255}
256
257pub fn get_index_by_serial(serial: String) -> i32 {
259 unsafe { rtlsdr_get_index_by_serial(serial.as_ptr() as *const c_char) as i32 }
260}
261
262pub fn open(index: i32) -> (Arc<Device>, Error) {
264 unsafe {
265 let mut dev: *mut RTLSDRDevT = std::ptr::null_mut();
266 let err = rtlsdr_open(&mut dev as *mut *mut RTLSDRDevT, index as u32);
267 (Arc::new(Device { dev: dev }), get_err_msg(err))
268 }
269}
270
271fn get_string_descriptors(data: &Vec<u8>) -> (String, String, String, Error) {
273 let mut pos = STR_OFFSET_START;
274 let mut strings: Vec<String> = Vec::new();
275
276 for _ in 0..3 {
277 let l = data[pos] as usize;
278 if l > (MAX_STR_SIZE * 2) as usize + 2 {
279 return ("".to_string(),
280 "".to_string(),
281 "".to_string(),
282 get_err_msg(STRING_VALUE_TOO_LONG));
283 }
284 if data[pos + 1] != 0x03 {
285 return ("".to_string(),
286 "".to_string(),
287 "".to_string(),
288 get_err_msg(STRING_DESCRIPTOR_INVALID));
289 }
290
291 let mut j: usize = 2;
292 let mut s = String::new();
293 while j < l {
294 s.push(data[pos + j] as char);
295 j += 2;
296 }
297 strings.push(s);
298 pos += j;
299 }
300 (strings[0].clone(), strings[1].clone(), strings[2].clone(), get_err_msg(0))
301}
302
303fn set_string_descriptors(info: &HwInfo, data: &mut Vec<u8>) -> Error {
305 let mlen = info.manufact.len();
306 let plen = info.product.len();
307 let slen = info.serial.len();
308
309 if mlen > MAX_STR_SIZE || plen > MAX_STR_SIZE || slen > MAX_STR_SIZE {
310 return get_err_msg(STRING__DESCRIPTOR_TOO_LONG);
311 }
312
313 let mut pos = STR_OFFSET_START;
314 let strings = [&info.manufact, &info.product, &info.serial];
315 for s in strings.iter() {
316 data[pos] = ((s.len() * 2) + 2) as u8;
317 data[pos + 1] = 0x03u8;
318 pos += 2;
319
320 for b in s.as_bytes().iter() {
321 data[pos] = *b;
322 data[pos + 1] = 0x00u8;
323 pos += 2;
324 }
325 }
326
327 return get_err_msg(0);
328}
329
330impl Device {
331 pub fn close(&self) -> Error {
333 unsafe { get_err_msg(rtlsdr_close(self.dev)) }
334 }
335
336 pub fn set_xtal_freq(&self, rtl_freq_hz: i32, tuner_freq_hz: i32) -> Error {
345 unsafe {
346 get_err_msg(rtlsdr_set_xtal_freq(self.dev, rtl_freq_hz as u32, tuner_freq_hz as u32))
347 }
348 }
349
350 pub fn get_xtal_freq(&self) -> (i32, i32, Error) {
353 let mut rtl_freq_hz: u32 = 0;
354 let mut tuner_freq_hz: u32 = 0;
355 unsafe {
356 let err = rtlsdr_get_xtal_freq(self.dev,
357 &mut rtl_freq_hz as *mut u32,
358 &mut tuner_freq_hz as *mut u32);
359 (rtl_freq_hz as i32, tuner_freq_hz as i32, get_err_msg(err))
360 }
361 }
362
363 pub fn get_usb_strings(&self) -> (String, String, String, Error) {
366 let m: [c_char; 256] = [0; 256];
367 let p: [c_char; 256] = [0; 256];
368 let s: [c_char; 256] = [0; 256];
369 unsafe {
370 let err = rtlsdr_get_usb_strings(self.dev,
371 m.as_ptr() as *mut c_char,
372 p.as_ptr() as *mut c_char,
373 s.as_ptr() as *mut c_char);
374 (from_pchar(m.as_ptr()),
375 from_pchar(p.as_ptr()),
376 from_pchar(s.as_ptr()),
377 get_err_msg(err))
378 }
379 }
380
381 pub fn write_eeprom(&self, data: Vec<u8>, offset: u8) -> Error {
383 unsafe {
384 let mut err = rtlsdr_write_eeprom(self.dev,
385 data.as_ptr() as *mut u8,
386 offset,
387 data.len() as u16);
388 if err >= 0 {
389 err = 0;
390 }
391 get_err_msg(err)
392 }
393 }
394
395 pub fn read_eeprom(&self, offset: u8, len: u16) -> (Vec<u8>, Error) {
397 let mut v = vec![0u8; len as usize];
398 unsafe {
399 let mut err = rtlsdr_read_eeprom(self.dev, v.as_mut_ptr() as *mut u8, offset, len);
400 if err >= 0 {
401 err = 0;
402 }
403 (v, get_err_msg(err))
404 }
405
406 }
407
408 pub fn set_center_freq(&self, freq_hz: i32) -> Error {
410 unsafe { get_err_msg(rtlsdr_set_center_freq(self.dev, freq_hz as u32)) }
411 }
412
413 pub fn get_center_freq(&self) -> i32 {
415 unsafe { rtlsdr_get_center_freq(self.dev) as i32 }
416 }
417
418 pub fn set_freq_correction(&self, ppm: i32) -> Error {
420 unsafe { get_err_msg(rtlsdr_set_freq_correction(self.dev, ppm)) }
421 }
422
423 pub fn get_freq_correction(&self) -> i32 {
425 unsafe { rtlsdr_get_freq_correction(self.dev) }
426 }
427
428 pub fn get_tuner_type(&self) -> String {
430 unsafe { from_tuner_type(rtlsdr_get_tuner_type(self.dev)) }
431 }
432
433 pub fn get_tuner_gains(&self) -> (Vec<i32>, Error) {
436 unsafe {
437 let mut i = rtlsdr_get_tuner_gains(self.dev, ptr::null_mut());
438 if i <= 0 {
439 return (Vec::new(), get_err_msg(i));
441 }
442 println!("rtlsdr_get_tuner_gains count: {}", i);
443 let mut v = vec![0; i as usize];
444 i = rtlsdr_get_tuner_gains(self.dev, v.as_mut_ptr());
445 let err = if i <= 0 {
446 Error::Unknown
447 } else {
448 Error::NoError
449 };
450 (v, err)
451 }
452 }
453
454 pub fn set_tuner_gain(&self, gain: i32) -> Error {
464 unsafe { get_err_msg(rtlsdr_set_tuner_gain(self.dev, gain)) }
465 }
466
467 pub fn get_tuner_gain(&self) -> i32 {
471 unsafe { rtlsdr_get_tuner_gain(self.dev) }
472 }
473
474 pub fn set_tuner_bandwidth(&self, bw_hz: i32) -> Error {
476 unsafe { get_err_msg(rtlsdr_set_tuner_bandwidth(self.dev, bw_hz as u32)) }
477 }
478
479 pub fn set_tuner_if_gain(&self, stage: i32, gains_tenths_db: i32) -> Error {
484 unsafe { get_err_msg(rtlsdr_set_tuner_if_gain(self.dev, stage, gains_tenths_db)) }
485
486 }
487
488 pub fn set_tuner_gain_mode(&self, manual_mode: bool) -> Error {
491 unsafe { get_err_msg(rtlsdr_set_tuner_gain_mode(self.dev, manual_mode as i32)) }
492
493 }
494
495 pub fn set_sample_rate(&self, rate_hz: i32) -> Error {
500 unsafe { get_err_msg(rtlsdr_set_sample_rate(self.dev, rate_hz as u32)) }
501 }
502
503 pub fn get_sample_rate(&self) -> i32 {
505 unsafe { rtlsdr_get_sample_rate(self.dev) }
506 }
507
508 pub fn set_testmode(&self, test_mode: bool) -> Error {
513 unsafe { get_err_msg(rtlsdr_set_testmode(self.dev, test_mode as i32)) }
514 }
515
516 pub fn set_agc_mode(&self, agc_mode: bool) -> Error {
518 unsafe { get_err_msg(rtlsdr_set_agc_mode(self.dev, agc_mode as i32)) }
519 }
520
521 pub fn set_direct_sampling(&self, mode: SamplingMode) -> Error {
527 unsafe { get_err_msg(rtlsdr_set_direct_sampling(self.dev, mode as i32)) }
528 }
529
530 pub fn get_direct_sampling(&self) -> SamplingMode {
532 unsafe {
533 match rtlsdr_get_direct_sampling(self.dev) {
534 0 => SamplingMode::None,
535 1 => SamplingMode::IADC,
536 2 => SamplingMode::QADC,
537 _ => SamplingMode::Error,
538 }
539 }
540 }
541
542 pub fn set_offset_tuning(&self, enable: bool) -> Error {
545 unsafe { get_err_msg(rtlsdr_set_offset_tuning(self.dev, enable as i32)) }
546 }
547
548 pub fn get_offset_tuning(&self) -> Error {
550 unsafe { get_err_msg(rtlsdr_get_offset_tuning(self.dev)) }
551 }
552
553 pub fn reset_buffer(&self) -> Error {
555 unsafe { get_err_msg(rtlsdr_reset_buffer(self.dev)) }
556 }
557
558 pub fn read_sync(&self, len: i32) -> (Vec<u8>, i32, Error) {
561 let mut buf = vec![0u8; len as usize];
562 let mut n_read: i32 = 0;
563 unsafe {
564 let err = rtlsdr_read_sync(self.dev,
565 buf.as_mut_ptr() as *mut c_void,
566 len,
567 &mut n_read as *mut c_int);
568 (buf, n_read, get_err_msg(err))
569 }
570
571 }
572
573 pub fn read_async(&self,
582 f: ReadAsyncCbT,
583 ctx: *mut c_void,
584 buf_num: i32,
585 buf_len: i32)
586 -> Error {
587 unsafe { get_err_msg(rtlsdr_read_async(self.dev, f, ctx, buf_num as u32, buf_len as u32)) }
588 }
589
590 pub fn cancel_async(&self) -> Error {
592 unsafe { get_err_msg(rtlsdr_cancel_async(self.dev)) }
593
594 }
595
596 pub fn get_hw_info(&self) -> (HwInfo, Error) {
598 let mut have_serial = false;
599 let mut remote_wakeup = false;
600 let mut enable_ir = false;
601 let mut vendor_id = 0u16;
602 let mut product_id = 0u16;
603 let mut m: String = "".to_string();
604 let mut p: String = "".to_string();
605 let mut s: String = "".to_string();
606
607 let (data, mut err) = self.read_eeprom(0, EEPROM_SIZE as u16);
608 if let Some(Error::NoError) = Some(err) {
611 if (data[0] != 0x28) || (data[1] != 0x32) {
612 err = get_err_msg(NO_VALID_EEPROM_HEADER);
613 } else {
614 vendor_id = (data[3] as u16) << 8 | data[2] as u16;
615 product_id = (data[5] as u16) << 8 | data[4] as u16;
616 if data[6] == 0xA5 {
619 have_serial = true;
620 }
621 if (data[7] & 0x01) == 0x01 {
622 remote_wakeup = true;
623 }
624 if (data[7] & 0x02) == 0x02 {
625 enable_ir = true;
626 }
627
628 let (mm, pp, ss, e) = get_string_descriptors(&data);
629 m = mm;
630 p = pp;
631 s = ss;
632 err = e;
633 }
634 }
635
636 let info = HwInfo {
637 have_serial: have_serial,
638 vendor_id: vendor_id,
639 product_id: product_id,
640 remote_wakeup: remote_wakeup,
641 enable_ir: enable_ir,
642 manufact: m,
643 product: p,
644 serial: s,
645 };
646
647 (info, err)
648 }
649
650 pub fn set_hw_info(&self, info: &HwInfo) -> Error {
652 let mlen = info.manufact.len();
653 let plen = info.product.len();
654 let slen = info.serial.len();
655 let stored_len = STR_OFFSET_START + ((2 * mlen) + 2) + ((2 * plen) + 2) + ((2 * slen) + 2);
656 let mut data = vec![0u8; stored_len];
657
658 data[0] = 0x28u8;
659 data[1] = 0x32u8;
660 data[2] = info.vendor_id as u8;
661 data[3] = (info.vendor_id >> 8) as u8;
662 data[4] = info.product_id as u8;
663 data[5] = (info.product_id >> 8) as u8;
664
665 if info.have_serial == true {
666 data[6] = 0xA5u8;
667 }
668 if info.remote_wakeup == true {
669 data[7] = data[7] | 0x01;
670 }
671 if info.enable_ir == true {
672 data[7] = data[7] | 0x02;
673 }
674
675 let mut err = set_string_descriptors(&info, &mut data);
676 if let Some(Error::NoError) = Some(err) {
677 err = self.write_eeprom(data, 0);
678 }
679
680 return err;
681 }
682}