1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2015 Wei Jiang
5  * Copyright (c) 2015-2017 Josh Blum
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 
23 #include "SoapyHackRF.hpp"
24 #include <SoapySDR/Registry.hpp>
25 
26 static std::map<std::string, SoapySDR::Kwargs> _cachedResults;
27 
find_HackRF(const SoapySDR::Kwargs & args)28 static std::vector<SoapySDR::Kwargs> find_HackRF(const SoapySDR::Kwargs &args)
29 {
30 	SoapyHackRFSession Sess;
31 
32 	std::vector<SoapySDR::Kwargs> results;
33 
34 	hackrf_device_list_t *list;
35 
36 	list =hackrf_device_list();
37 
38 	if (list->devicecount > 0) {
39 
40 		for (int i = 0; i < list->devicecount; i++) {
41 
42 			hackrf_device* device = NULL;
43 			uint8_t board_id = BOARD_ID_INVALID;
44 			read_partid_serialno_t read_partid_serialno;
45 
46 			hackrf_device_list_open(list, i, &device);
47 
48 			SoapySDR::Kwargs options;
49 
50 			if (device!=NULL) {
51 
52 				hackrf_board_id_read(device, &board_id);
53 
54 				options["device"] = hackrf_board_id_name((hackrf_board_id) board_id);
55 
56 				char version_str[100];
57 
58 				hackrf_version_string_read(device, &version_str[0], 100);
59 
60 				options["version"] = version_str;
61 
62 				hackrf_board_partid_serialno_read(device, &read_partid_serialno);
63 
64 				char part_id_str[100];
65 
66 				sprintf(part_id_str, "%08x%08x", read_partid_serialno.part_id[0], read_partid_serialno.part_id[1]);
67 
68 				options["part_id"] = part_id_str;
69 
70 				char serial_str[100];
71 				sprintf(serial_str, "%08x%08x%08x%08x", read_partid_serialno.serial_no[0],
72 						read_partid_serialno.serial_no[1], read_partid_serialno.serial_no[2],
73 						read_partid_serialno.serial_no[3]);
74 				options["serial"] = serial_str;
75 
76 				//generate a displayable label string with trimmed serial
77 				size_t ofs = 0;
78 				while (ofs < sizeof(serial_str) and serial_str[ofs] == '0') ofs++;
79 				char label_str[100];
80 				sprintf(label_str, "%s #%d %s", options["device"].c_str(), i, serial_str+ofs);
81 				options["label"] = label_str;
82 
83 				//filter based on serial and idx
84 				const bool serialMatch = args.count("serial") == 0 or args.at("serial") == options["serial"];
85 				const bool idxMatch = args.count("hackrf") == 0 or std::stoi(args.at("hackrf")) == i;
86 				if (serialMatch and idxMatch)
87 				{
88 					results.push_back(options);
89 					_cachedResults[serial_str] = options;
90 				}
91 
92 				hackrf_close(device);
93 			}
94 
95 		}
96 
97 	}
98 
99 	hackrf_device_list_free(list);
100 
101 	//fill in the cached results for claimed handles
102 	for (const auto &serial : HackRF_getClaimedSerials())
103 	{
104 		if (_cachedResults.count(serial) == 0) continue;
105 		if (args.count("serial") != 0 and args.at("serial") != serial) continue;
106 		results.push_back(_cachedResults.at(serial));
107 	}
108 
109 	return results;
110 }
111 
make_HackRF(const SoapySDR::Kwargs & args)112 static SoapySDR::Device *make_HackRF(const SoapySDR::Kwargs &args)
113 {
114     return new SoapyHackRF(args);
115 }
116 
117 static SoapySDR::Registry register_hackrf("hackrf", &find_HackRF, &make_HackRF, SOAPY_SDR_ABI_VERSION);
118