1 /*
2 * Hamlib WiNRADiO backend - main file for interface through /dev/winradio API
3 * Copyright (C) 2001 pab@users.sourceforge.net
4 * Derived from hamlib code (C) 2000-2009 Stephane Fillod.
5 *
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 #include "winradio.h" /* config.h */
24
25 #include <stdlib.h>
26 #include <string.h> /* String function definitions */
27 #ifdef HAVE_SYS_IOCTL_H
28 #include <sys/ioctl.h>
29 #endif
30 #include <math.h>
31
32 #include "hamlib/rig.h"
33 #include "serial.h"
34 #include "misc.h"
35 #include "register.h"
36
37
38
39 #ifdef WINRADIO_IOCTL
40
41 #include <linradio/wrapi.h>
42 #include <linradio/radio_ioctl.h>
43
44 #define DEFAULT_WINRADIO_PATH "/dev/winradio0"
45
wr_rig_init(RIG * rig)46 int wr_rig_init(RIG *rig)
47 {
48 rig->state.rigport.type.rig = RIG_PORT_DEVICE;
49 strncpy(rig->state.rigport.pathname, DEFAULT_WINRADIO_PATH,
50 HAMLIB_FILPATHLEN - 1);
51
52 return RIG_OK;
53 }
54
wr_set_freq(RIG * rig,vfo_t vfo,freq_t freq)55 int wr_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
56 {
57 unsigned long f;
58
59 if (freq > GHz(4.2))
60 {
61 return -RIG_EINVAL;
62 }
63
64 f = (unsigned long)freq;
65
66 if (ioctl(rig->state.rigport.fd, RADIO_SET_FREQ, &f)) { return -RIG_EINVAL; }
67
68 return RIG_OK;
69 }
70
wr_get_freq(RIG * rig,vfo_t vfo,freq_t * freq)71 int wr_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
72 {
73 unsigned long f;
74
75 if (ioctl(rig->state.rigport.fd, RADIO_GET_FREQ, &f) < 0) { return -RIG_EINVAL; }
76
77 *freq = (freq_t)f;
78 return RIG_OK;
79 }
80
wr_set_mode(RIG * rig,vfo_t vfo,rmode_t mode,pbwidth_t width)81 int wr_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
82 {
83 unsigned long m;
84
85 switch (mode)
86 {
87 case RIG_MODE_AM: m = RMD_AM; break;
88
89 case RIG_MODE_CW: m = RMD_CW; break;
90
91 case RIG_MODE_LSB: m = RMD_LSB; break;
92
93 case RIG_MODE_USB: m = RMD_USB; break;
94
95 case RIG_MODE_WFM: m = RMD_FMW; break;
96
97 case RIG_MODE_FM:
98 switch (width)
99 {
100 case RIG_PASSBAND_NORMAL:
101 case (int)kHz(17):
102 case (int)kHz(15): m = RMD_FMN; break;
103
104 case (int)kHz(6): m = RMD_FM6; break;
105
106 case (int)kHz(50): m = RMD_FMM; break;
107
108 default: return -RIG_EINVAL;
109 }
110
111 break;
112
113 default: return -RIG_EINVAL;
114 }
115
116 if (ioctl(rig->state.rigport.fd, RADIO_SET_MODE, &m)) { return -RIG_EINVAL; }
117
118 return RIG_OK;
119 }
120
wr_get_mode(RIG * rig,vfo_t vfo,rmode_t * mode,pbwidth_t * width)121 int wr_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
122 {
123 unsigned long m;
124
125 if (ioctl(rig->state.rigport.fd, RADIO_GET_MODE, &m)) { return -RIG_EINVAL; }
126
127 *width = RIG_PASSBAND_NORMAL;
128
129 switch (m)
130 {
131 case RMD_CW: *mode = RIG_MODE_CW; break;
132
133 case RMD_AM: *mode = RIG_MODE_AM; break;
134
135 case RMD_FMN: *mode = RIG_MODE_FM; break; /* 15kHz or 17kHz on WR-3100 */
136
137 case RMD_FM6: *mode = RIG_MODE_FM; break; /* 6kHz */
138
139 case RMD_FMM: *mode = RIG_MODE_FM; break; /* 50kHz */
140
141 case RMD_FMW: *mode = RIG_MODE_WFM; break;
142
143 case RMD_LSB: *mode = RIG_MODE_LSB; break;
144
145 case RMD_USB: *mode = RIG_MODE_USB; break;
146
147 default: return -RIG_EINVAL;
148 }
149
150 if (*width == RIG_PASSBAND_NORMAL)
151 {
152 *width = rig_passband_normal(rig, *mode);
153 }
154
155 return RIG_OK;
156 }
157
wr_set_powerstat(RIG * rig,powerstat_t status)158 int wr_set_powerstat(RIG *rig, powerstat_t status)
159 {
160 unsigned long p = 1;
161 p = status == RIG_POWER_ON ? 1 : 0;
162
163 if (ioctl(rig->state.rigport.fd, RADIO_SET_POWER, &p)) { return -RIG_EINVAL; }
164
165 return RIG_OK;
166 }
wr_get_powerstat(RIG * rig,powerstat_t * status)167 int wr_get_powerstat(RIG *rig, powerstat_t *status)
168 {
169 unsigned long p;
170
171 if (ioctl(rig->state.rigport.fd, RADIO_GET_POWER, &p)) { return -RIG_EINVAL; }
172
173 *status = p ? RIG_POWER_ON : RIG_POWER_OFF;
174 return RIG_OK;
175 }
176
wr_set_func(RIG * rig,vfo_t vfo,setting_t func,int status)177 int wr_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
178 {
179 switch (func)
180 {
181 case RIG_FUNC_FAGC:
182 {
183 unsigned long v = status ? 1 : 0;
184
185 if (ioctl(rig->state.rigport.fd, RADIO_SET_AGC, &v)) { return -RIG_EINVAL; }
186
187 return RIG_OK;
188 }
189
190 default:
191 return -RIG_EINVAL;
192 }
193 }
194
wr_get_func(RIG * rig,vfo_t vfo,setting_t func,int * status)195 int wr_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
196 {
197 switch (func)
198 {
199 case RIG_FUNC_FAGC:
200 {
201 unsigned long v;
202
203 if (ioctl(rig->state.rigport.fd, RADIO_GET_AGC, &v)) { return -RIG_EINVAL; }
204
205 *status = v;
206 return RIG_OK;
207 }
208
209 default:
210 return -RIG_EINVAL;
211 }
212 }
213
214
wr_set_level(RIG * rig,vfo_t vfo,setting_t level,value_t val)215 int wr_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
216 {
217 switch (level)
218 {
219 case RIG_LEVEL_AF:
220 {
221 unsigned long v;
222
223 if (ioctl(rig->state.rigport.fd, RADIO_GET_MAXVOL, &v)) { return -RIG_EINVAL; }
224
225 v *= val.f;
226
227 if (ioctl(rig->state.rigport.fd, RADIO_SET_VOL, &v)) { return -RIG_EINVAL; }
228
229 return RIG_OK;
230 }
231
232 case RIG_LEVEL_ATT:
233 {
234 unsigned long v = val.i ? 1 : 0;
235
236 if (ioctl(rig->state.rigport.fd, RADIO_SET_ATTN, &v)) { return -RIG_EINVAL; }
237
238 return RIG_OK;
239 }
240
241 case RIG_LEVEL_IF:
242 {
243 long v = val.i;
244
245 if (ioctl(rig->state.rigport.fd, RADIO_SET_IFS, &v)) { return -RIG_EINVAL; }
246
247 return RIG_OK;
248 }
249
250 case RIG_LEVEL_RF:
251 {
252 long v = val.f * 100; /* iMaxIFGain on wHWVer > RHV_3150 */
253
254 if (ioctl(rig->state.rigport.fd, RADIO_SET_IFG, &v)) { return -RIG_EINVAL; }
255
256 return RIG_OK;
257 }
258
259 default:
260 return -RIG_EINVAL;
261 }
262 }
263
wr_get_level(RIG * rig,vfo_t vfo,setting_t level,value_t * val)264 int wr_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
265 {
266 switch (level)
267 {
268 case RIG_LEVEL_AF:
269 {
270 unsigned long v, mv;
271
272 if (ioctl(rig->state.rigport.fd, RADIO_GET_MAXVOL, &mv)) { return -RIG_EINVAL; }
273
274 if (ioctl(rig->state.rigport.fd, RADIO_GET_VOL, &v)) { return -RIG_EINVAL; }
275
276 val->f = (float)v / mv;
277 return RIG_OK;
278 }
279
280 case RIG_LEVEL_ATT:
281 {
282 unsigned long v;
283
284 if (ioctl(rig->state.rigport.fd, RADIO_GET_VOL, &v)) { return -RIG_EINVAL; }
285
286 val->i = v ? rig->state.attenuator[0] : 0;
287 return RIG_OK;
288 }
289
290 case RIG_LEVEL_STRENGTH:
291 {
292 unsigned long v;
293
294 if (ioctl(rig->state.rigport.fd, RADIO_GET_SS, &v)) { return -RIG_EINVAL; }
295
296 val->i = v - 60; /* 0..120, Hamlib assumes S9 = 0dB */
297 return RIG_OK;
298 }
299
300 case RIG_LEVEL_IF:
301 {
302 long v;
303
304 if (ioctl(rig->state.rigport.fd, RADIO_GET_IFS, &v)) { return -RIG_EINVAL; }
305
306 val->i = v;
307 return RIG_OK;
308 }
309
310 case RIG_LEVEL_RF:
311 {
312 long v;
313
314 if (ioctl(rig->state.rigport.fd, RADIO_GET_IFG, &v)) { return -RIG_EINVAL; }
315
316 val->f = (float)v / 100; /* iMaxIFGain on wHWVer > RHV_3150 */
317 return RIG_OK;
318 }
319
320 default:
321 return -RIG_EINVAL;
322 }
323 }
324
325 /*
326 * FIXME: static buf does not allow reentrancy!
327 */
wr_get_info(RIG * rig)328 const char *wr_get_info(RIG *rig)
329 {
330 static char buf[100];
331
332 if (ioctl(rig->state.rigport.fd, RADIO_GET_DESCR, buf) < 0) { return "?"; }
333
334 return buf;
335 }
336
337 #endif /* WINRADIO_IOCTL */
338
DECLARE_INITRIG_BACKEND(winradio)339 DECLARE_INITRIG_BACKEND(winradio)
340 {
341 rig_debug(RIG_DEBUG_VERBOSE, "%s: _init called\n", __func__);
342
343 #ifdef WINRADIO_IOCTL
344 rig_register(&wr1000_caps);
345 rig_register(&wr1500_caps);
346 rig_register(&wr1550_caps);
347 rig_register(&wr3100_caps);
348 rig_register(&wr3150_caps);
349 rig_register(&wr3500_caps);
350 rig_register(&wr3700_caps);
351 #endif /* WINRADIO_IOCTL */
352
353 /* Receivers with DLL only available under Windows */
354 #ifdef _WIN32
355 #ifdef __CYGWIN__
356 rig_register(&g303_caps);
357 rig_register(&g305_caps);
358 #endif
359 #endif
360
361 /* Available on Linux and MS Windows */
362 #ifndef OTHER_POSIX
363 rig_register(&g313_caps);
364 #endif
365
366 return RIG_OK;
367 }
368