1 /*
2  *  Hamlib CI-V backend - main file
3  *  Copyright (c) 2000-2016 by Stephane Fillod
4  *
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 // cppcheck-suppress *
26 #include <stdio.h>
27 // cppcheck-suppress *
28 #include <stdlib.h>
29 // cppcheck-suppress *
30 #include <string.h>     /* String function definitions */
31 // cppcheck-suppress *
32 #include <unistd.h>     /* UNIX standard function definitions */
33 // cppcheck-suppress *
34 #include <math.h>
35 
36 #include <hamlib/rig.h>
37 #include <serial.h>
38 #include <misc.h>
39 #include <cal.h>
40 #include <token.h>
41 #include <register.h>
42 
43 #include "icom.h"
44 #include "icom_defs.h"
45 #include "frame.h"
46 
47 static int set_vfo_curr(RIG *rig, vfo_t vfo, vfo_t curr_vfo);
48 static int icom_set_default_vfo(RIG *rig);
49 static int icom_get_spectrum_vfo(RIG *rig, vfo_t vfo);
50 static int icom_get_spectrum_edge_frequency_range(RIG *rig, vfo_t vfo,
51         int *range_id);
52 
53 const cal_table_float_t icom_default_swr_cal =
54 {
55     5,
56     {
57         {0, 1.0f},
58         {48, 1.5f},
59         {80, 2.0f},
60         {120, 3.0f},
61         {240, 6.0f}
62     }
63 };
64 
65 const cal_table_float_t icom_default_alc_cal =
66 {
67     2,
68     {
69         {0, 0.0f},
70         {120, 1.0f}
71     }
72 };
73 
74 const cal_table_float_t icom_default_rfpower_meter_cal =
75 {
76     13,
77     {
78         { 0, 0.0f },
79         { 21, 5.0f },
80         { 43, 10.0f },
81         { 65, 15.0f },
82         { 83, 20.0f },
83         { 95, 25.0f },
84         { 105, 30.0f },
85         { 114, 35.0f },
86         { 124, 40.0f },
87         { 143, 50.0f },
88         { 183, 75.0f },
89         { 213, 100.0f },
90         { 255, 120.0f }
91     }
92 };
93 
94 const cal_table_float_t icom_default_comp_meter_cal =
95 {
96     3,
97     {
98         {0, 0.0f},
99         {130, 15.0f},
100         {241, 30.0f}
101     }
102 };
103 
104 const cal_table_float_t icom_default_vd_meter_cal =
105 {
106     3,
107     {
108         {0, 0.0f},
109         {13, 10.0f},
110         {241, 16.0f}
111     }
112 };
113 
114 const cal_table_float_t icom_default_id_meter_cal =
115 {
116     4,
117     {
118         {0, 0.0f},
119         {97, 10.0f},
120         {146, 15.0f},
121         {241, 25.0f}
122     }
123 };
124 
125 const struct ts_sc_list r8500_ts_sc_list[] =
126 {
127     {10, 0x00},
128     {50, 0x01},
129     {100, 0x02},
130     {kHz(1), 0x03},
131     {12500, 0x04},
132     {kHz(5), 0x05},
133     {kHz(9), 0x06},
134     {kHz(10), 0x07},
135     {12500, 0x08},
136     {kHz(20), 0x09},
137     {kHz(25), 0x10},
138     {kHz(100), 0x11},
139     {MHz(1), 0x12},
140     {0, 0x13},            /* programmable tuning step not supported */
141     {0, 0},
142 };
143 
144 const struct ts_sc_list ic737_ts_sc_list[] =
145 {
146     {10, 0x00},
147     {kHz(1), 0x01},
148     {kHz(2), 0x02},
149     {kHz(3), 0x03},
150     {kHz(4), 0x04},
151     {kHz(5), 0x05},
152     {kHz(6), 0x06},
153     {kHz(7), 0x07},
154     {kHz(8), 0x08},
155     {kHz(9), 0x09},
156     {kHz(10), 0x10},
157     {0, 0},
158 };
159 
160 const struct ts_sc_list r75_ts_sc_list[] =
161 {
162     {10, 0x00},
163     {100, 0x01},
164     {kHz(1), 0x02},
165     {kHz(5), 0x03},
166     {6250, 0x04},
167     {kHz(9), 0x05},
168     {kHz(10), 0x06},
169     {12500, 0x07},
170     {kHz(20), 0x08},
171     {kHz(25), 0x09},
172     {kHz(100), 0x10},
173     {MHz(1), 0x11},
174     {0, 0},
175 };
176 
177 const struct ts_sc_list r7100_ts_sc_list[] =
178 {
179     {100, 0x00},
180     {kHz(1), 0x01},
181     {kHz(5), 0x02},
182     {kHz(10), 0x03},
183     {12500, 0x04},
184     {kHz(20), 0x05},
185     {kHz(25), 0x06},
186     {kHz(100), 0x07},
187     {0, 0},
188 };
189 
190 const struct ts_sc_list r9000_ts_sc_list[] =
191 {
192     {10, 0x00},
193     {100, 0x01},
194     {kHz(1), 0x02},
195     {kHz(5), 0x03},
196     {kHz(9), 0x04},
197     {kHz(10), 0x05},
198     {12500, 0x06},
199     {kHz(20), 0x07},
200     {kHz(25), 0x08},
201     {kHz(100), 0x09},
202     {0, 0},
203 };
204 
205 const struct ts_sc_list r9500_ts_sc_list[] =
206 {
207     {1, 0x00},
208     {10, 0x01},
209     {100, 0x02},
210     {kHz(1), 0x03},
211     {kHz(2.5), 0x04},
212     {kHz(5), 0x05},
213     {6250, 0x06},
214     {kHz(9), 0x07},
215     {kHz(10), 0x08},
216     {12500, 0x09},
217     {kHz(20), 0x10},
218     {kHz(25), 0x11},
219     {kHz(100), 0x12},
220     {MHz(1), 0x13},
221     {0, 0},
222 };
223 
224 const struct ts_sc_list ic718_ts_sc_list[] =
225 {
226     {10, 0x00},
227     {kHz(1), 0x01},
228     {kHz(5), 0x01},
229     {kHz(9), 0x01},
230     {kHz(10), 0x04},
231     {kHz(100), 0x05},
232     {0, 0},
233 };
234 
235 const struct ts_sc_list ic756_ts_sc_list[] =
236 {
237     {10, 0x00},
238     {kHz(1), 0x01},
239     {kHz(5), 0x02},
240     {kHz(9), 0x03},
241     {kHz(10), 0x04},
242     {0, 0},
243 };
244 
245 const struct ts_sc_list ic756pro_ts_sc_list[] =
246 {
247     {10, 0x00},           /* 1 if step turned off */
248     {100, 0x01},
249     {kHz(1), 0x02},
250     {kHz(5), 0x03},
251     {kHz(9), 0x04},
252     {kHz(10), 0x05},
253     {kHz(12.5), 0x06},
254     {kHz(20), 0x07},
255     {kHz(25), 0x08},
256     {0, 0},
257 };
258 
259 const struct ts_sc_list ic706_ts_sc_list[] =
260 {
261     {10, 0x00},
262     {100, 0x01},
263     {kHz(1), 0x02},
264     {kHz(5), 0x03},
265     {kHz(9), 0x04},
266     {kHz(10), 0x05},
267     {12500, 0x06},
268     {kHz(20), 0x07},
269     {kHz(25), 0x08},
270     {kHz(100), 0x09},
271     {0, 0},
272 };
273 
274 const struct ts_sc_list ic7000_ts_sc_list[] =
275 {
276     {10, 0x00},
277     {100, 0x01},
278     {kHz(1), 0x02},
279     {kHz(5), 0x03},
280     {kHz(9), 0x04},
281     {kHz(10), 0x05},
282     {12500, 0x06},
283     {kHz(20), 0x07},
284     {kHz(25), 0x08},
285     {kHz(100), 0x09},
286     {MHz(1), 0x10},
287     {0, 0},
288 };
289 
290 const struct ts_sc_list ic7100_ts_sc_list[] =
291 {
292     {10, 0x00},
293     {100, 0x01},
294     {kHz(1), 0x02},
295     {kHz(5), 0x03},
296     {kHz(6.25), 0x04},
297     {kHz(9), 0x05},
298     {kHz(10), 0x06},
299     {kHz(12.5), 0x07},
300     {kHz(20), 0x08},
301     {kHz(25), 0x09},
302     {kHz(50), 0x0A},
303     {kHz(100), 0x0B},
304     {MHz(1), 0x0C},
305     {0, 0x00},
306 };
307 
308 const struct ts_sc_list ic7200_ts_sc_list[] =
309 {
310     {10, 0x00},
311     {100, 0x01},
312     {kHz(1), 0x02},
313     {kHz(5), 0x03},
314     {kHz(9), 0x04},
315     {kHz(10), 0x05},
316     {0, 0},
317 };
318 
319 const struct ts_sc_list ic7300_ts_sc_list[] =
320 {
321     {1, 0x00},            /* Manual says "Send/read the tuning step OFF" */
322     {100, 0x01},
323     {kHz(1), 0x02},
324     {kHz(5), 0x03},
325     {kHz(9), 0x04},
326     {kHz(10), 0x05},
327     {kHz(12.5), 0x06},
328     {kHz(20), 0x07},
329     {kHz(25), 0x08},
330     {0, 0},
331 };
332 
333 const struct ts_sc_list ic910_ts_sc_list[] =
334 {
335     {Hz(1), 0x00},
336     {Hz(10), 0x01},
337     {Hz(50), 0x02},
338     {Hz(100), 0x03},
339     {kHz(1), 0x04},
340     {kHz(5), 0x05},
341     {kHz(6.25), 0x06},
342     {kHz(10), 0x07},
343     {kHz(12.5), 0x08},
344     {kHz(20), 0x09},
345     {kHz(25), 0x10},
346     {kHz(100), 0x11},
347     {0, 0},
348 };
349 
350 const struct ts_sc_list r8600_ts_sc_list[] =
351 {
352     {10, 0x00},
353     {100, 0x01},
354     {kHz(1), 0x02},
355     {kHz(2.5), 0x03},
356     {3125, 0x04},
357     {kHz(5), 0x05},
358     {6250, 0x06},
359     {8330, 0x07},
360     {kHz(9), 0x08},
361     {kHz(10), 0x09},
362     {kHz(12.5), 0x10},
363     {kHz(20), 0x11},
364     {kHz(25), 0x12},
365     {kHz(100), 0x13},
366     {0, 0x14},            /* programmable tuning step not supported */
367     {0, 0},
368 };
369 
370 const struct ts_sc_list ic705_ts_sc_list[] =
371 {
372     {10, 0x00},
373     {100, 0x01},
374     {500, 0x02},
375     {kHz(1), 0x03},
376     {kHz(5), 0x04},
377     {kHz(6.25), 0x05},
378     {kHz(8.33), 0x06},
379     {kHz(9), 0x07},
380     {kHz(10), 0x08},
381     {kHz(12.5), 0x09},
382     {kHz(20), 0x10},
383     {kHz(25), 0x11},
384     {kHz(50), 0x12},
385     {kHz(100), 0x13},
386     {0, 0},
387 };
388 
389 const struct ts_sc_list ic9700_ts_sc_list[] =
390 {
391     {10, 0x00},
392     {100, 0x01},
393     {500, 0x02},
394     {kHz(1), 0x03},
395     {kHz(5), 0x04},
396     {kHz(6.25), 0x05},
397     {kHz(10), 0x06},
398     {kHz(12.5), 0x07},
399     {kHz(20), 0x08},
400     {kHz(25), 0x09},
401     {kHz(50), 0x10},
402     {kHz(100), 0x11},
403     {0, 0},
404 };
405 
406 /* rtty filter list for some DSP rigs ie PRO */
407 #define RTTY_FIL_NB 5
408 const pbwidth_t rtty_fil[] =
409 {
410     Hz(250),
411     Hz(300),
412     Hz(350),
413     Hz(500),
414     kHz(1),
415     0,
416 };
417 
418 struct icom_addr
419 {
420     rig_model_t model;
421     unsigned char re_civ_addr;
422 };
423 
424 
425 #define TOK_CIVADDR TOKEN_BACKEND(1)
426 #define TOK_MODE731 TOKEN_BACKEND(2)
427 #define TOK_NOXCHG TOKEN_BACKEND(3)
428 
429 const struct confparams icom_cfg_params[] =
430 {
431     {
432         TOK_CIVADDR, "civaddr", "CI-V address", "Transceiver's CI-V address",
433         "0", RIG_CONF_NUMERIC, {.n = {0, 0xff, 1}}
434     },
435     {
436         TOK_MODE731, "mode731", "CI-V 731 mode", "CI-V operating frequency "
437         "data length, needed for IC731 and IC735",
438         "0", RIG_CONF_CHECKBUTTON
439     },
440     {
441         TOK_NOXCHG, "no_xchg", "No VFO XCHG",
442         "Don't Use VFO XCHG to set other VFO mode and Frequency",
443         "0", RIG_CONF_CHECKBUTTON
444     },
445     {RIG_CONF_END, NULL,}
446 };
447 
448 /*
449  *  Lookup table for icom_get_ext_func
450  */
451 const struct confparams icom_ext_funcs[] =
452 {
453     { TOK_DIGI_SEL_FUNC, "digi_sel", "DIGI-SEL enable", "", "", RIG_CONF_CHECKBUTTON, {} },
454     { RIG_CONF_END, NULL, }
455 };
456 
457 /*
458  *  Lookup table for icom_get_ext_level
459  */
460 const struct confparams icom_ext_levels[] =
461 {
462     { TOK_DIGI_SEL_LEVEL, "digi_sel_level", "DIGI-SEL level", "", "", RIG_CONF_NUMERIC, { .n = { 0, 255, 1 } } },
463     { TOK_DRIVE_GAIN, "drive_gain", "Drive gain", "", "", RIG_CONF_NUMERIC, { .n = { 0, 255, 1 } } },
464     { TOK_SCOPE_MSS, "SPECTRUM_SELECT", "Spectrum Scope Main/Sub", "", "", RIG_CONF_COMBO, { .c = { .combostr = { "Main", "Sub", NULL } } } },
465     { TOK_SCOPE_SDS, "SPECTRUM_DUAL", "Spectrum Scope Single/Dual", "", "", RIG_CONF_COMBO, { .c = { .combostr = { "Single", "Dual", NULL } } } },
466     { TOK_SCOPE_EDG, "SPECTRUM_EDGE", "Spectrum Scope Edge", "Edge selection for fixed scope mode", "", RIG_CONF_COMBO, { .c = { .combostr = { "1", "2", "3", "4", NULL } } } },
467     { TOK_SCOPE_STX, "SPECTRUM_TX", "Spectrum Scope TX operation", "", "", RIG_CONF_CHECKBUTTON, {} },
468     { TOK_SCOPE_CFQ, "SPECTRUM_CENTER", "Spectrum Scope Center Frequency Type", "", "", RIG_CONF_COMBO, { .c = { .combostr = { "Filter center", "Carrier point center", "Carrier point center (Abs. Freq.)", NULL } } } },
469     { TOK_SCOPE_VBW, "SPECTRUM_VBW", "Spectrum Scope VBW", "Video Band Width", "", RIG_CONF_COMBO, { .c = { .combostr = { "Narrow", "Wide", NULL } } } },
470     { TOK_SCOPE_RBW, "SPECTRUM_RBW", "Spectrum Scope RBW", "Resolution Band Width", "", RIG_CONF_COMBO, { .c = { .combostr = { "Wide", "Mid", "Narrow", NULL } } } },
471     { RIG_CONF_END, NULL, }
472 };
473 
474 /*
475  *  Lookup table for icom_get_ext_parm
476  */
477 const struct confparams icom_ext_parms[] =
478 {
479     { TOK_DSTAR_DSQL, "dsdsql", "D-STAR CSQL Status", "", "", RIG_CONF_CHECKBUTTON, {} },
480     { TOK_DSTAR_CALL_SIGN, "dscals", "D-STAR Call sign", "", "", RIG_CONF_BINARY, {} },
481     { TOK_DSTAR_MESSAGE, "dsrmes", "D-STAR Rx Message", "", "", RIG_CONF_STRING, {} },
482     { TOK_DSTAR_STATUS, "dsstat", "D-STAR Rx Status", "", "", RIG_CONF_BINARY, {} },
483     { TOK_DSTAR_GPS_DATA, "dsgpsd", "D-STAR GPS Data", "", "", RIG_CONF_BINARY, {} },
484     { TOK_DSTAR_GPS_MESS, "dsgpsm", "D-STAR GPS Message", "", "", RIG_CONF_STRING, {} },
485     { TOK_DSTAR_CODE, "dscode", "D-STAR CSQL Code", "", "", RIG_CONF_NUMERIC, {} },
486     { TOK_DSTAR_TX_DATA, "dstdat", "D-STAR Tx Data", "", "", RIG_CONF_BINARY, {} },
487     { TOK_DSTAR_MY_CS, "dsmycs", "D-STAR MY Call Sign", "", "", RIG_CONF_STRING, {} },
488     { TOK_DSTAR_TX_CS, "dstxcs", "D-STAR Tx Call Sign", "", "", RIG_CONF_BINARY, {} },
489     { TOK_DSTAR_TX_MESS, "dstmes", "D-STAR Tx Message", "", "", RIG_CONF_STRING, {} },
490     { RIG_CONF_END, NULL, }
491 };
492 
493 /*
494  *  Lookup table for icom_get_ext_* & icom_set_ext_* functions
495  */
496 
497 const struct cmdparams icom_ext_cmd[] =
498 {
499     { {.t = TOK_DSTAR_DSQL}, CMD_PARAM_TYPE_TOKEN, C_CTL_DIG, S_DIG_DSCSQL, SC_MOD_RW, 1, {0}, CMD_DAT_BOL, 1 },
500     { {.t = TOK_DSTAR_CALL_SIGN}, CMD_PARAM_TYPE_TOKEN, C_CTL_DIG, S_DIG_DSCALS, SC_MOD_RW12, 2, {0}, CMD_DAT_BUF, 38 },
501     { {.t = TOK_DSTAR_MESSAGE}, CMD_PARAM_TYPE_TOKEN, C_CTL_DIG, S_DIG_DSMESS, SC_MOD_RW12, 2, {0}, CMD_DAT_STR, 32 },
502     { {.t = TOK_DSTAR_STATUS}, CMD_PARAM_TYPE_TOKEN, C_CTL_DIG, S_DIG_DSRSTS, SC_MOD_RW12, 2, {0}, CMD_DAT_BUF, 1 },
503     { {.t = TOK_DSTAR_GPS_DATA}, CMD_PARAM_TYPE_TOKEN, C_CTL_DIG, S_DIG_DSGPSD, SC_MOD_RW12, 2, {0}, CMD_DAT_BUF, 52 },
504     { {.t = TOK_DSTAR_GPS_MESS}, CMD_PARAM_TYPE_TOKEN, C_CTL_DIG, S_DIG_DSGPSM, SC_MOD_RW12, 2, {0}, CMD_DAT_STR, 52 },
505     { {.t = TOK_DSTAR_CODE}, CMD_PARAM_TYPE_TOKEN, C_CTL_DIG, S_DIG_DSCSQL, SC_MOD_RW12, 2, {0}, CMD_DAT_FLT, 1 },
506     { {.t = TOK_DSTAR_TX_DATA}, CMD_PARAM_TYPE_TOKEN, C_CTL_DSD, S_DSD_DSTXDT, SC_MOD_RW, 1, {0}, CMD_DAT_BUF, 30 },
507     { {.t = TOK_DSTAR_MY_CS}, CMD_PARAM_TYPE_TOKEN, C_CTL_DVT, S_DVT_DSMYCS, SC_MOD_RW, 1, {0}, CMD_DAT_STR, 12 },
508     { {.t = TOK_DSTAR_TX_CS}, CMD_PARAM_TYPE_TOKEN, C_CTL_DVT, S_DVT_DSTXCS, SC_MOD_RW, 1, {0}, CMD_DAT_STR, 24 },
509     { {.t = TOK_DSTAR_TX_MESS}, CMD_PARAM_TYPE_TOKEN, C_CTL_DVT, S_DVT_DSTXMS, SC_MOD_RW, 1, {0}, CMD_DAT_STR, 20 },
510     { {.t = TOK_DRIVE_GAIN}, CMD_PARAM_TYPE_TOKEN, C_CTL_LVL, S_LVL_DRIVE, SC_MOD_RW, 0, {0}, CMD_DAT_FLT, 2 },
511     { {.t = TOK_DIGI_SEL_FUNC}, CMD_PARAM_TYPE_TOKEN, C_CTL_FUNC, S_FUNC_DIGISEL, SC_MOD_RW, 0, {0}, CMD_DAT_BOL, 1 },
512     { {.t = TOK_DIGI_SEL_LEVEL}, CMD_PARAM_TYPE_TOKEN, C_CTL_LVL, S_LVL_DIGI, SC_MOD_RW, 0, {0}, CMD_DAT_FLT, 2 },
513     { {0} }
514 };
515 
516 /*
517  * Please, if the default CI-V address of your rig is listed as UNKNOWN_ADDR,
518  * send the value to <fillods@users.sourceforge.net> for inclusion. Thanks --SF
519  */
520 static const struct icom_addr icom_addr_list[] =
521 {
522     {RIG_MODEL_IC703, 0x68},
523     {RIG_MODEL_IC706, 0x48},
524     {RIG_MODEL_IC706MKII, 0x4e},
525     {RIG_MODEL_IC706MKIIG, 0x58},
526     {RIG_MODEL_IC271, 0x20},
527     {RIG_MODEL_IC275, 0x10},
528     {RIG_MODEL_IC375, 0x12},
529     {RIG_MODEL_IC471, 0x22},
530     {RIG_MODEL_IC475, 0x14},
531     {RIG_MODEL_IC575, 0x16},
532     {RIG_MODEL_IC707, 0x3e},
533     {RIG_MODEL_IC725, 0x28},
534     {RIG_MODEL_IC726, 0x30},
535     {RIG_MODEL_IC728, 0x38},
536     {RIG_MODEL_IC729, 0x3a},
537     {RIG_MODEL_IC731, 0x02},  /* need confirmation */
538     {RIG_MODEL_IC735, 0x04},
539     {RIG_MODEL_IC736, 0x40},
540     {RIG_MODEL_IC7410, 0x80},
541     {RIG_MODEL_IC746, 0x56},
542     {RIG_MODEL_IC746PRO, 0x66},
543     {RIG_MODEL_IC737, 0x3c},
544     {RIG_MODEL_IC738, 0x44},
545     {RIG_MODEL_IC751, 0x1c},
546     {RIG_MODEL_IC751A, 0x1c},
547     {RIG_MODEL_IC756, 0x50},
548     {RIG_MODEL_IC756PRO, 0x5c},
549     {RIG_MODEL_IC756PROII, 0x64},
550     {RIG_MODEL_IC756PROIII, 0x6e},
551     {RIG_MODEL_IC7600, 0x7a},
552     {RIG_MODEL_IC761, 0x1e},
553     {RIG_MODEL_IC765, 0x2c},
554     {RIG_MODEL_IC775, 0x46},
555     {RIG_MODEL_IC7800, 0x6a},
556     {RIG_MODEL_IC785x, 0x8e},
557     {RIG_MODEL_IC781, 0x26},
558     {RIG_MODEL_IC820, 0x42},
559     {RIG_MODEL_IC821H, 0x4c},
560     {RIG_MODEL_IC910, 0x60},
561     {RIG_MODEL_IC9100, 0x7c},
562     {RIG_MODEL_IC9700, 0xa2},
563     {RIG_MODEL_IC970, 0x2e},
564     {RIG_MODEL_IC1271, 0x24},
565     {RIG_MODEL_IC1275, 0x18},
566     {RIG_MODEL_ICR10, 0x52},
567     {RIG_MODEL_ICR20, 0x6c},
568     {RIG_MODEL_ICR6, 0x7e},
569     {RIG_MODEL_ICR71, 0x1a},
570     {RIG_MODEL_ICR72, 0x32},
571     {RIG_MODEL_ICR75, 0x5a},
572     {RIG_MODEL_ICRX7, 0x78},
573     {RIG_MODEL_IC78, 0x62},
574     {RIG_MODEL_ICR7000, 0x08},
575     {RIG_MODEL_ICR7100, 0x34},
576     {RIG_MODEL_ICR8500, 0x4a},
577     {RIG_MODEL_ICR9000, 0x2a},
578     {RIG_MODEL_ICR9500, 0x72},
579     {RIG_MODEL_MINISCOUT, 0x94},
580     {RIG_MODEL_IC718, 0x5e},
581     {RIG_MODEL_OS535, 0x80},  /* same address as IC-7410 */
582     {RIG_MODEL_ICID1, 0x01},
583     {RIG_MODEL_IC7000, 0x70},
584     {RIG_MODEL_IC7100, 0x88},
585     {RIG_MODEL_IC7200, 0x76},
586     {RIG_MODEL_IC7610, 0x98},
587     {RIG_MODEL_IC7700, 0x74},
588     {RIG_MODEL_PERSEUS, 0xE1},
589     {RIG_MODEL_X108G, 0x70},
590     {RIG_MODEL_ICR8600, 0x96},
591     {RIG_MODEL_ICR30, 0x9c},
592     {RIG_MODEL_NONE, 0},
593 };
594 
595 /*
596  * This is a generic icom_init function.
597  * You might want to define yours, so you can customize it for your rig
598  *
599  * Basically, it sets up *priv
600  * REM: serial port is already open (rig->state.rigport.fd)
601  */
icom_init(RIG * rig)602 int icom_init(RIG *rig)
603 {
604     struct icom_priv_data *priv;
605     struct icom_priv_caps *priv_caps;
606     struct rig_caps *caps;
607     int i;
608 
609     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
610 
611     if (!rig->caps)
612     {
613         RETURNFUNC(-RIG_EINVAL);
614     }
615 
616     caps = rig->caps;
617 
618     if (!caps->priv)
619     {
620         RETURNFUNC(-RIG_ECONF);
621     }
622 
623     priv_caps = (struct icom_priv_caps *) caps->priv;
624 
625 
626     rig->state.priv = (struct icom_priv_data *) calloc(1,
627                       sizeof(struct icom_priv_data));
628 
629     if (!rig->state.priv)
630     {
631         /* whoops! memory shortage! */
632         RETURNFUNC(-RIG_ENOMEM);
633     }
634 
635     priv = rig->state.priv;
636 
637     priv->spectrum_scope_count = 0;
638 
639     for (i = 0; caps->spectrum_scopes[i].name != NULL; i++)
640     {
641         priv->spectrum_scope_cache[i].spectrum_data = NULL;
642 
643         if (priv_caps->spectrum_scope_caps.spectrum_line_length < 1)
644         {
645             rig_debug(RIG_DEBUG_ERR, "%s: no spectrum scope line length defined\n",
646                       __func__);
647             RETURNFUNC(-RIG_ECONF);
648         }
649 
650         priv->spectrum_scope_cache[i].spectrum_data = calloc(1,
651                 priv_caps->spectrum_scope_caps.spectrum_line_length);
652 
653         if (!priv->spectrum_scope_cache[i].spectrum_data)
654         {
655             RETURNFUNC(-RIG_ENOMEM);
656         }
657 
658         priv->spectrum_scope_count++;
659     }
660 
661     /* TODO: CI-V address should be customizable */
662 
663     /*
664      * init the priv_data from static struct
665      *          + override with preferences
666      */
667 
668     priv->re_civ_addr = priv_caps->re_civ_addr;
669     priv->civ_731_mode = priv_caps->civ_731_mode;
670     priv->no_xchg = priv_caps->no_xchg;
671     priv->tx_vfo = RIG_VFO_NONE;
672     priv->rx_vfo = RIG_VFO_NONE;
673     rig->state.current_vfo = RIG_VFO_NONE;
674     priv->filter = RIG_PASSBAND_NOCHANGE;
675     priv->x25cmdfails = 0;
676     priv->x1cx03cmdfails = 0;
677 
678     rig_debug(RIG_DEBUG_TRACE, "%s: done\n", __func__);
679 
680     RETURNFUNC(RIG_OK);
681 }
682 
683 /*
684  * ICOM Generic icom_cleanup routine
685  * the serial port is closed by the frontend
686  */
icom_cleanup(RIG * rig)687 int icom_cleanup(RIG *rig)
688 {
689     struct icom_priv_data *priv;
690     int i;
691 
692     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
693 
694     if (!rig)
695     {
696         RETURNFUNC(-RIG_EINVAL);
697     }
698 
699     priv = rig->state.priv;
700 
701     for (i = 0; rig->caps->spectrum_scopes[i].name != NULL; i++)
702     {
703         if (priv->spectrum_scope_cache[i].spectrum_data)
704         {
705             free(priv->spectrum_scope_cache[i].spectrum_data);
706             priv->spectrum_scope_cache[i].spectrum_data = NULL;
707         }
708     }
709 
710     if (rig->state.priv)
711     {
712         free(rig->state.priv);
713     }
714 
715     rig->state.priv = NULL;
716 
717     RETURNFUNC(RIG_OK);
718 }
719 
720 /**
721  * Returns 1 when USB ECHO is off
722  * Returns 0 when USB ECHO is on
723  * \return Returns < 0 when error occurs (e.g. timeout, nimple, navail)
724  */
icom_get_usb_echo_off(RIG * rig)725 int icom_get_usb_echo_off(RIG *rig)
726 {
727     int retval;
728     unsigned char ackbuf[MAXFRAMELEN];
729     int ack_len = sizeof(ackbuf);
730     struct rig_state *rs = &rig->state;
731     int retry_save = rs->rigport.retry;
732     struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
733 
734 
735     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
736 
737     // reduce the retry here so it's quicker
738     rs->rigport.retry = 0;
739     // Check for echo on first by assuming echo is off and checking the answer
740     priv->serial_USB_echo_off = 1;
741 
742     rig_debug(RIG_DEBUG_VERBOSE, "%s: retry temp set to %d\n", __func__,
743               rs->rigport.retry);
744 
745     retval = icom_transaction(rig, C_RD_FREQ, -1, NULL, 0, ackbuf, &ack_len);
746 
747     // if rig is not powered on we get no data and TIMEOUT
748     if (ack_len == 0 && retval == -RIG_ETIMEOUT) { RETURNFUNC(retval); }
749 
750     rig_debug(RIG_DEBUG_VERBOSE, "%s: ack_len=%d\n", __func__, ack_len);
751 
752     if (ack_len == 1) // then we got an echo of the cmd
753     {
754         struct rig_state *rs = &rig->state;
755         unsigned char buf[16];
756         priv->serial_USB_echo_off = 0;
757         rig_debug(RIG_DEBUG_VERBOSE, "%s: USB echo on detected\n", __func__);
758         // we should have a freq response so we'll read it and don't really care
759         // flushing doesn't always work as it depends on timing
760         read_icom_frame(&rs->rigport, buf, sizeof(buf));
761     }
762     else
763     {
764         rig_debug(RIG_DEBUG_VERBOSE, "%s: USB echo off detected\n", __func__);
765     }
766 
767     rs->rigport.retry = retry_save;
768     RETURNFUNC(priv->serial_USB_echo_off);
769 }
770 
771 
772 /*
773  * ICOM rig open routine
774  * Detect echo state of USB serial port
775  */
776 int
icom_rig_open(RIG * rig)777 icom_rig_open(RIG *rig)
778 {
779     int retval = RIG_OK;
780     int satmode = 0;
781     struct rig_state *rs = &rig->state;
782     struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
783 
784     ENTERFUNC;
785 
786     rig_debug(RIG_DEBUG_VERBOSE, "%s: %s v%s\n", __func__, rig->caps->model_name,
787               rig->caps->version);
788     retval = icom_get_usb_echo_off(rig);
789 
790     if (retval == RIG_OK) // then echo is on so let's try freq now
791     {
792         // some rigs like the IC7100 still echo when in standby
793         // so asking for freq now should timeout if such a rig
794         freq_t tfreq;
795         retval = rig_get_freq(rig, RIG_VFO_A, &tfreq);
796     }
797 
798     if (retval != RIG_OK && priv->poweron == 0 && rs->auto_power_on)
799     {
800         // maybe we need power on?
801         rig_debug(RIG_DEBUG_VERBOSE, "%s trying power on\n", __func__);
802         retval = abs(rig_set_powerstat(rig, 1));
803 
804         // this is only a fatal error if powerstat is implemented
805         // if not iplemented than we're at an error here
806         if (retval != RIG_OK && retval != RIG_ENIMPL && retval != RIG_ENAVAIL)
807         {
808             rig_debug(RIG_DEBUG_WARN, "%s: unexpected retval here: %s\n",
809                       __func__, rigerror(retval));
810 
811             rig_debug(RIG_DEBUG_WARN, "%s: rig_set_powerstat failed: =%s\n", __func__,
812                       rigerror(retval));
813             RETURNFUNC(retval);
814         }
815 
816         // Now that we're powered up let's try again
817         retval = icom_get_usb_echo_off(rig);
818 
819         if (retval < 0)
820         {
821             rig_debug(RIG_DEBUG_ERR, "%s: Unable to determine USB echo status\n", __func__);
822             RETURNFUNC(retval);
823         }
824     }
825 
826     icom_set_default_vfo(rig);
827     priv->poweron = 1;
828 
829     if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
830     {
831         // retval is important here -- used below
832         retval = rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode);
833         rig->state.cache.satmode = satmode;
834         rig_debug(RIG_DEBUG_VERBOSE, "%s: satmode=%d\n", __func__, satmode);
835 
836         // RIG_OK return means this rig has satmode capabiltiy and Main/Sub VFOs
837         // Should we also set/force VFOA for Main&Sub here?
838         if (retval == RIG_OK && satmode)
839         {
840             priv->rx_vfo = RIG_VFO_MAIN;
841             priv->tx_vfo = RIG_VFO_SUB;
842         }
843         else if (retval == RIG_OK && !satmode)
844         {
845             priv->rx_vfo = RIG_VFO_MAIN;
846             priv->tx_vfo = RIG_VFO_MAIN;
847         }
848     }
849 
850 #if 0 // do not do this here -- needs to be done when ranges are requested instead as this is very slow
851     icom_get_freq_range(rig); // try get to get rig range capability dyamically
852 #endif
853 
854     RETURNFUNC(RIG_OK);
855 }
856 
857 /*
858  * ICOM rig close routine
859  */
860 int
icom_rig_close(RIG * rig)861 icom_rig_close(RIG *rig)
862 {
863     int retval = RIG_OK;
864     // Nothing to do yet
865     struct rig_state *rs = &rig->state;
866     struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
867 
868     rig_debug(RIG_DEBUG_TRACE, "%s: called\n", __func__);
869 
870     if (priv->poweron != 0 && rs->auto_power_off)
871     {
872         // maybe we need power off?
873         rig_debug(RIG_DEBUG_VERBOSE, "%s trying power off\n", __func__);
874         retval = abs(rig_set_powerstat(rig, 0));
875 
876         // this is only a fatal error if powerstat is implemented
877         // if not iplemented than we're at an error here
878         if (retval != RIG_OK && retval != RIG_ENIMPL && retval != RIG_ENAVAIL)
879         {
880             rig_debug(RIG_DEBUG_WARN, "%s: unexpected retval here: %s\n",
881                       __func__, rigerror(retval));
882 
883             rig_debug(RIG_DEBUG_WARN, "%s: rig_set_powerstat failed: =%s\n", __func__,
884                       rigerror(retval));
885             RETURNFUNC(retval);
886         }
887 
888     }
889 
890     RETURNFUNC(RIG_OK);
891 }
892 
893 /*
894  * Set default when vfo == RIG_VFO_NONE
895  * Clients should be setting VFO as 1st things but some don't
896  * So they will get defaults of Main/VFOA as the selected VFO
897  * and we force that selection
898  */
icom_set_default_vfo(RIG * rig)899 static int icom_set_default_vfo(RIG *rig)
900 {
901     int retval;
902 
903     rig_debug(RIG_DEBUG_TRACE, "%s: called, curr_vfo=%s\n", __func__,
904               rig_strvfo(rig->state.current_vfo));
905 
906     if (VFO_HAS_MAIN_SUB_A_B_ONLY)
907     {
908         rig_debug(RIG_DEBUG_TRACE, "%s: setting default as MAIN/VFOA\n",
909                   __func__);
910         TRACE;
911         retval = rig_set_vfo(rig, RIG_VFO_MAIN);  // we'll default to Main in this case
912 
913         if (retval != RIG_OK)
914         {
915             RETURNFUNC(retval);
916         }
917 
918         TRACE;
919         retval = rig_set_vfo(rig, RIG_VFO_A);  // we'll default to Main in this case
920 
921         if (retval != RIG_OK)
922         {
923             RETURNFUNC(retval);
924         }
925 
926         rig->state.current_vfo = RIG_VFO_MAIN;
927         RETURNFUNC(RIG_OK);
928     }
929 
930     if (VFO_HAS_MAIN_SUB_ONLY)
931     {
932         rig_debug(RIG_DEBUG_TRACE, "%s: setting default as MAIN\n",
933                   __func__);
934         TRACE;
935         retval = rig_set_vfo(rig, RIG_VFO_MAIN);  // we'll default to Main in this case
936         rig->state.current_vfo = RIG_VFO_MAIN;
937     }
938     else if (VFO_HAS_A_B)
939     {
940         rig_debug(RIG_DEBUG_TRACE, "%s: setting default as VFOA\n",
941                   __func__);
942         TRACE;
943         retval = RIG_OK;
944 
945         if (rig->state.current_vfo != RIG_VFO_A)
946         {
947             retval = rig_set_vfo(rig,
948                                  RIG_VFO_A);     // we'll default to VFOA for all others
949             rig->state.current_vfo = RIG_VFO_A;
950         }
951     }
952     else
953     {
954         // we don't have any VFO selection
955         rig_debug(RIG_DEBUG_TRACE, "%s: Unknown VFO setup so setting default as VFOA\n",
956                   __func__);
957 
958         rig->state.current_vfo = RIG_VFO_A;
959         retval = RIG_OK;
960     }
961 
962     if (retval != RIG_OK)
963     {
964         RETURNFUNC(retval);
965     }
966 
967     rig_debug(RIG_DEBUG_TRACE, "%s: curr_vfo now %s\n", __func__,
968               rig_strvfo(rig->state.current_vfo));
969 
970     RETURNFUNC(RIG_OK);
971 }
972 
973 // return true if band is changing from last set_freq
974 // Assumes rig is currently on the VFO being changed
975 // This handles the case case Main/Sub cannot be on the same band
icom_band_changing(RIG * rig,freq_t test_freq)976 int icom_band_changing(RIG *rig, freq_t test_freq)
977 {
978     freq_t curr_freq, freq1, freq2;
979     int retval;
980 
981     // We should be sitting on the VFO we want to change so just get it's frequency
982     retval = rig_get_freq(rig, RIG_VFO_CURR, &curr_freq);
983 
984     if (retval != RIG_OK)
985     {
986         rig_debug(RIG_DEBUG_ERR, "%s: rig_get_freq failed??\n", __func__);
987         RETURNFUNC(0); // I guess we need to say no change in this case
988     }
989 
990     // Make our HF=0, 2M = 1, 70cm = 4, and 23cm=12
991     freq1 = floor(curr_freq / 1e8);
992     freq2 = floor(test_freq / 1e8);
993 
994     rig_debug(RIG_DEBUG_TRACE, "%s: lastfreq=%.0f, thisfreq=%.0f\n", __func__,
995               freq1, freq2);
996 
997     if (freq1 != freq2)
998     {
999         rig_debug(RIG_DEBUG_TRACE, "%s: Band change detected\n", __func__);
1000         RETURNFUNC(1);
1001     }
1002 
1003     rig_debug(RIG_DEBUG_TRACE, "%s: Band change not detected\n", __func__);
1004     RETURNFUNC(0);
1005 }
1006 
1007 /*
1008  * icom_set_freq
1009  * Assumes rig!=NULL, rig->state.priv!=NULL
1010  */
icom_set_freq(RIG * rig,vfo_t vfo,freq_t freq)1011 int icom_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
1012 {
1013     struct icom_priv_data *priv;
1014     struct rig_state *rs;
1015     unsigned char freqbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
1016     int freq_len, ack_len = sizeof(ackbuf), retval;
1017     int cmd, subcmd;
1018     freq_t curr_freq;
1019 
1020     rig_debug(RIG_DEBUG_VERBOSE, "%s called %s=%" PRIfreq "\n", __func__,
1021               rig_strvfo(vfo), freq);
1022     rs = &rig->state;
1023     priv = (struct icom_priv_data *) rs->priv;
1024 
1025     if (rig->state.current_vfo == RIG_VFO_NONE)
1026     {
1027         icom_set_default_vfo(rig);
1028     }
1029 
1030     if (vfo == RIG_VFO_CURR)
1031     {
1032         vfo = rig->state.current_vfo;
1033         rig_debug(RIG_DEBUG_TRACE, "%s: currVFO asked for so vfo set to %s\n", __func__,
1034                   rig_strvfo(vfo));
1035     }
1036 
1037     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_FREQ))
1038     {
1039         TRACE;
1040         rig_debug(RIG_DEBUG_TRACE, "%s: set_vfo_curr=%s\n", __func__,
1041                   rig_strvfo(rig->state.current_vfo));
1042         retval = set_vfo_curr(rig, vfo, rig->state.current_vfo);
1043 
1044         if (retval != RIG_OK)
1045         {
1046             RETURNFUNC(retval);
1047         }
1048     }
1049 
1050     retval = rig_get_freq(rig, vfo, &curr_freq);
1051 
1052     if (retval != RIG_OK)
1053     {
1054         RETURNFUNC(retval);
1055     }
1056 
1057     freq_len = priv->civ_731_mode ? 4 : 5;
1058     /*
1059      * to_bcd requires nibble len
1060      */
1061     to_bcd(freqbuf, freq, freq_len * 2);
1062 
1063     // mike
1064     if (rig->caps->targetable_vfo & RIG_TARGETABLE_FREQ)
1065     {
1066         vfo_t vfo_unselected = RIG_VFO_B | RIG_VFO_SUB | RIG_VFO_SUB_B | RIG_VFO_MAIN_B;
1067 
1068         // if we are on the "other" vfo already then we have to allow for that
1069         if (rig->state.current_vfo & vfo_unselected)
1070         {
1071             TRACE;
1072             vfo_unselected = RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_SUB_A | RIG_VFO_MAIN_A;
1073         }
1074 
1075         rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): vfo=%s, currvfo=%s\n", __func__, __LINE__,
1076                   rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo));
1077         subcmd  = 0x00;
1078 
1079         // if we ask for unselected but we're not on unselected subcmd2 changes
1080         if ((vfo & vfo_unselected) && !(rig->state.current_vfo & vfo_unselected))
1081         {
1082             TRACE;
1083             subcmd = 0x01;  // get unselected VFO
1084         }
1085 
1086         cmd = 0x25;
1087         retval = icom_transaction(rig, cmd, subcmd, freqbuf, freq_len, ackbuf,
1088                                   &ack_len);
1089     }
1090     else
1091     {
1092         cmd = C_SET_FREQ;
1093         subcmd = -1;
1094         retval = icom_transaction(rig, cmd, subcmd, freqbuf, freq_len, ackbuf,
1095                                   &ack_len);
1096     }
1097 
1098     hl_usleep(50 * 1000); // pause for transceive message and we'll flush it
1099 
1100     if (retval != RIG_OK)
1101     {
1102         // We might have a failed command if we're changing bands
1103         // For example, IC9700 setting Sub=VHF when Main=VHF will fail
1104         // So we'll try a VFO swap and see if that helps things
1105         rig_debug(RIG_DEBUG_VERBOSE, "%s: special check for vfo swap\n", __func__);
1106 
1107         if (icom_band_changing(rig, freq))
1108         {
1109             if (rig_has_vfo_op(rig, RIG_OP_XCHG))
1110             {
1111                 if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
1112                 {
1113                     rig_debug(RIG_DEBUG_ERR, "%s: vfo_op XCHG failed: %s\n", __func__,
1114                               rigerror(retval));
1115                     RETURNFUNC(retval);
1116                 }
1117 
1118                 // Try the command again
1119                 retval = icom_transaction(rig, cmd, subcmd, freqbuf, freq_len, ackbuf,
1120                                           &ack_len);
1121 
1122                 // Swap back if we got an error otherwise we fall through for more processing
1123                 if (retval != RIG_OK)
1124                 {
1125                     int retval2;
1126                     rig_debug(RIG_DEBUG_ERR, "%s: 2nd set freq failed: %s\n", __func__,
1127                               rigerror(retval));
1128 
1129                     if (RIG_OK != (retval2 = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
1130                     {
1131                         rig_debug(RIG_DEBUG_ERR, "%s: 2nd vfo_op XCHG failed: %s\n", __func__,
1132                                   rigerror(retval));
1133                         RETURNFUNC(retval2);
1134                     }
1135 
1136                     RETURNFUNC(retval);
1137                 }
1138             }
1139         }
1140 
1141         if (retval != RIG_OK)
1142         {
1143             rig_debug(RIG_DEBUG_ERR, "%s: set freq failed: %s\n", __func__,
1144                       rigerror(retval));
1145             RETURNFUNC(retval);
1146         }
1147     }
1148 
1149     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
1150     {
1151         //  if we don't get ACK/NAK some serial corruption occurred
1152         // so we'll call it a timeout for retry purposes
1153         RETURNFUNC(-RIG_ETIMEOUT);
1154     }
1155 
1156     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
1157     {
1158         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
1159                   ackbuf[0], ack_len);
1160         RETURNFUNC(-RIG_ERJCTED);
1161     }
1162 
1163     priv->curr_freq = freq;
1164 
1165     switch (vfo)
1166     {
1167     case RIG_VFO_A: priv->vfoa_freq = freq; break;
1168 
1169     case RIG_VFO_MAIN_A: priv->maina_freq = freq; break;
1170 
1171     case RIG_VFO_SUB_A: priv->suba_freq = freq; break;
1172 
1173     case RIG_VFO_B: priv->vfob_freq = freq; break;
1174 
1175     case RIG_VFO_MAIN_B: priv->mainb_freq = freq;
1176 
1177     case RIG_VFO_SUB_B: priv->subb_freq = freq;
1178 
1179     case RIG_VFO_MAIN: priv->main_freq = freq; break;
1180 
1181     case RIG_VFO_SUB: priv->sub_freq = freq; break;
1182 
1183     case RIG_VFO_CURR: break;
1184 
1185     default:
1186         rig_debug(RIG_DEBUG_ERR, "%s: unknown VFO?  VFO=%s\n", __func__,
1187                   rig_strvfo(vfo));
1188     }
1189 
1190     RETURNFUNC(RIG_OK);
1191 }
1192 
1193 /*
1194  * icom_get_freq
1195  * Assumes rig!=NULL, rig->state.priv!=NULL, freq!=NULL, Main=VFOA, Sub=VFOB
1196  * Note: old rig may return less than 4/5 bytes for get_freq
1197  */
icom_get_freq(RIG * rig,vfo_t vfo,freq_t * freq)1198 int icom_get_freq(RIG *rig, vfo_t vfo, freq_t *freq)
1199 {
1200     struct icom_priv_data *priv;
1201     struct rig_state *rs;
1202     unsigned char freqbuf[MAXFRAMELEN];
1203     int freqbuf_offset = 1;
1204     unsigned char ackbuf[MAXFRAMELEN];
1205     int freq_len, retval = -RIG_EINTERNAL;
1206     int cmd, subcmd;
1207     int ack_len = sizeof(ackbuf);
1208     int civ_731_mode = 0; // even these rigs have 5-byte channels
1209     vfo_t vfo_save = rig->state.current_vfo;
1210 
1211     rig_debug(RIG_DEBUG_VERBOSE, "%s called for %s, curr_vfo=%s\n", __func__,
1212               rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo));
1213     rs = &rig->state;
1214     priv = (struct icom_priv_data *) rs->priv;
1215 
1216     cmd = C_RD_FREQ;
1217     subcmd = -1;
1218 
1219     if (vfo == RIG_VFO_MEM && (priv->civ_731_mode
1220                                || rig->caps->rig_model == RIG_MODEL_IC706))
1221     {
1222         rig_debug(RIG_DEBUG_TRACE, "%s: VFO=MEM so turning off civ_731\n", __func__);
1223         civ_731_mode = 1;
1224         priv->civ_731_mode = 0;
1225 
1226     }
1227 
1228     // Pick the appropriate VFO when VFO_TX is requested
1229     if (vfo == RIG_VFO_TX)
1230     {
1231         if (priv->x1cx03cmdfails == 0) // we can try this command to avoid vfo swapping
1232         {
1233             cmd = 0x1c;
1234             subcmd = 0x03;
1235             retval = icom_transaction(rig, cmd, subcmd, NULL, 0, ackbuf,
1236                                       &ack_len);
1237 
1238             if (retval == RIG_OK) // then we're done!!
1239             {
1240                 *freq = from_bcd(&ackbuf[2], (priv->civ_731_mode ? 4 : 5) * 2);
1241                 RETURNFUNC(retval);
1242             }
1243 
1244             priv->x1cx03cmdfails = 1;
1245         }
1246 
1247         rig_debug(RIG_DEBUG_TRACE, "%s: VFO_TX requested, vfo=%s\n", __func__,
1248                   rig_strvfo(vfo));
1249 
1250         if (priv->split_on)
1251         {
1252             vfo = (rig->state.vfo_list & RIG_VFO_B) ? RIG_VFO_B : RIG_VFO_SUB;
1253         }
1254         else
1255         {
1256             vfo = (rig->state.vfo_list & RIG_VFO_B) ? RIG_VFO_A : RIG_VFO_MAIN;
1257         }
1258     }
1259 
1260 #if 0 // does not work with rigs without VFO_A
1261 
1262     if (vfo == RIG_VFO_CURR)
1263     {
1264         vfo = rig->state.current_vfo;
1265 
1266         if (vfo == RIG_VFO_NONE) { vfo = RIG_VFO_A; }
1267 
1268         rig_debug(RIG_DEBUG_VERBOSE, "%s: CurrVFO changed to %s\n", __func__,
1269                   rig_strvfo(vfo));
1270     }
1271 
1272 #endif
1273 
1274 
1275 
1276 #if 0
1277 
1278     // Pick the appropriate VFO when VFO_RX or VFO_TX is requested
1279     if (vfo == RIG_VFO_RX && rig->state.current_vfo)
1280     {
1281         vfo = vfo_fixup(rig, vfo);
1282         rig_debug(RIG_DEBUG_TRACE, "%s: vfo_fixup vfo=%s\n", __func__, rig_strvfo(vfo));
1283         vfo = (rig->state.vfo_list & RIG_VFO_B) ? RIG_VFO_A : RIG_VFO_MAIN;
1284         rig_debug(RIG_DEBUG_ERR, "%s: VFO_RX requested, new vfo=%s\n", __func__,
1285                   rig_strvfo(vfo));
1286     }
1287     else if (vfo == RIG_VFO_TX)
1288     {
1289         vfo = vfo_fixup(rig, vfo)
1290               rig_debug(RIG_DEBUG_TRACE, "%s: vfo_fixup vfo=%s\n", __func__, rig_strvfo(vfo));
1291 
1292         if (rig->state.vfo_list == VFO_HAS_MAIN_SUB_A_B_ONLY)
1293         {
1294             vfo = RIG_VFO_A;
1295 
1296             if (priv->split_on) { vfo = RIG_VFO_B; }
1297             else if (rig->state.cache.satmode) { vfo = RIG_VFO_SUB; }
1298         }
1299 
1300         rig_debug(RIG_DEBUG_ERR, "%s: VFO_TX requested, new vfo=%s\n", __func__,
1301                   rig_strvfo(vfo));
1302     }
1303 
1304 #endif
1305 
1306     rig_debug(RIG_DEBUG_VERBOSE, "%s: using vfo=%s\n", __func__,
1307               rig_strvfo(vfo));
1308 
1309     if (rig->state.current_vfo == RIG_VFO_NONE)
1310     {
1311         // we default to VFOA/MAIN as appropriate
1312         vfo = (rig->state.vfo_list & RIG_VFO_B) ? RIG_VFO_A : RIG_VFO_MAIN;
1313         TRACE;
1314         retval = rig_set_vfo(rig, vfo);
1315 
1316         if (retval != RIG_OK)
1317         {
1318             rig_debug(RIG_DEBUG_ERR, "%s: set_vfo failed? retval=%s\n", __func__,
1319                       rigerror(retval));
1320         }
1321     }
1322 
1323     // we'll use 0x25 command to get unselected frequency
1324     // we have to assume current_vfo is accurate to determine what "other" means
1325     if (priv->x25cmdfails == 0)
1326     {
1327         int cmd2 = 0x25;
1328         int subcmd2 = 0x00;
1329         vfo_t vfo_unselected = RIG_VFO_B | RIG_VFO_SUB | RIG_VFO_SUB_B | RIG_VFO_MAIN_B;
1330 
1331         // if we are on the "other" vfo already then we have to allow for that
1332         if (rig->state.current_vfo & vfo_unselected)
1333         {
1334             vfo_unselected = RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_SUB_A | RIG_VFO_MAIN_A;
1335         }
1336 
1337         // if we ask for unselected but we're not on unselected subcmd2 changes
1338         if ((vfo & vfo_unselected) && !(rig->state.current_vfo & vfo_unselected))
1339         {
1340             subcmd2 = 0x01;  // get unselected VFO
1341         }
1342 
1343         retval = icom_transaction(rig, cmd2, subcmd2, NULL, 0, freqbuf, &freq_len);
1344 
1345         if (retval != RIG_OK)
1346         {
1347             priv->x25cmdfails = 1;
1348             rig_debug(RIG_DEBUG_WARN,
1349                       "%s: rig does not support 0x25 CI-V cmd\n", __func__);
1350         }
1351 
1352         freq_len--; // 0x25 cmd is 1 byte longer than 0x03 cmd
1353         freqbuf_offset = 2;
1354     }
1355 
1356     if (priv->x25cmdfails) // then we're doing this the hard way....swap+read
1357     {
1358         freqbuf_offset = 1;
1359         TRACE;
1360         retval = set_vfo_curr(rig, vfo, rig->state.current_vfo);
1361 
1362         if (retval != RIG_OK)
1363         {
1364             if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; }
1365 
1366             RETURNFUNC(retval);
1367         }
1368 
1369         retval = icom_transaction(rig, cmd, subcmd, NULL, 0, freqbuf, &freq_len);
1370         TRACE;
1371         set_vfo_curr(rig, vfo_save, rig->state.current_vfo);
1372     }
1373 
1374 #if 0
1375     else if (!priv->x25cmdfails
1376              && (vfo & (RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_MAIN_A | RIG_VFO_SUB_A)))
1377     {
1378         // we can use the 0x03 command for the default VFO
1379         retval = icom_transaction(rig, cmd, subcmd, NULL, 0, freqbuf, &freq_len);
1380     }
1381 
1382 #endif
1383 
1384     if (retval != RIG_OK)
1385     {
1386         if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; }
1387 
1388         RETURNFUNC(retval);
1389     }
1390 
1391     /*
1392      * freqbuf should contain Cn,Data area
1393      */
1394     freq_len--;
1395 
1396     /*
1397      * is it a blank mem channel ?
1398      */
1399     if (freq_len == 1 && freqbuf[1] == 0xff)
1400     {
1401         *freq = RIG_FREQ_NONE;
1402 
1403         if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; }
1404 
1405         RETURNFUNC(RIG_OK);
1406     }
1407 
1408     if (freq_len != 4 && freq_len != 5)
1409     {
1410         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n",
1411                   __func__, freq_len);
1412 
1413         if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; }
1414 
1415         RETURNFUNC(-RIG_ERJCTED);
1416     }
1417 
1418     if (freq_len != (priv->civ_731_mode ? 4 : 5))
1419     {
1420         rig_debug(RIG_DEBUG_WARN, "%s: freq len (%d) differs from expected\n",
1421                   __func__, freq_len);
1422     }
1423 
1424     /*
1425      * from_bcd requires nibble len
1426      */
1427     *freq = from_bcd(freqbuf + freqbuf_offset, freq_len * 2);
1428 
1429     if (vfo == RIG_VFO_MEM && civ_731_mode) { priv->civ_731_mode = 1; }
1430 
1431     switch (vfo)
1432     {
1433     case RIG_VFO_A: priv->vfoa_freq = *freq; break;
1434 
1435     case RIG_VFO_MAIN_A: priv->maina_freq = *freq; break;
1436 
1437     case RIG_VFO_SUB_A: priv->suba_freq = *freq; break;
1438 
1439     case RIG_VFO_B: priv->vfob_freq = *freq; break;
1440 
1441     case RIG_VFO_MAIN_B: priv->mainb_freq = *freq; break;
1442 
1443     case RIG_VFO_SUB_B: priv->subb_freq = *freq; break;
1444 
1445     case RIG_VFO_MAIN: priv->main_freq = *freq; break;
1446 
1447     case RIG_VFO_SUB: priv->sub_freq = *freq; break;
1448 
1449     case RIG_VFO_CURR: break;
1450 
1451     default:
1452         rig_debug(RIG_DEBUG_ERR, "%s: unknown VFO?  VFO=%s\n", __func__,
1453                   rig_strvfo(vfo));
1454     }
1455 
1456     rig_debug(RIG_DEBUG_VERBOSE, "%s exit vfo=%s, curr_vfo=%s\n", __func__,
1457               rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo));
1458     RETURNFUNC(RIG_OK);
1459 }
1460 
icom_get_rit_new(RIG * rig,vfo_t vfo,shortfreq_t * ts)1461 int icom_get_rit_new(RIG *rig, vfo_t vfo, shortfreq_t *ts)
1462 {
1463     unsigned char tsbuf[MAXFRAMELEN];
1464     int ts_len, retval;
1465 
1466     retval =
1467         icom_transaction(rig, C_CTL_RIT, S_RIT_FREQ, NULL, 0, tsbuf, &ts_len);
1468 
1469     if (retval != RIG_OK)
1470     {
1471         RETURNFUNC(retval);
1472     }
1473 
1474     /*
1475      * tsbuf nibbles should contain 10,1,1000,100 hz digits and 00=+, 01=- bit
1476      */
1477     rig_debug(RIG_DEBUG_VERBOSE, "%s: ts_len=%d\n", __func__, ts_len);
1478 
1479     if (ts_len != 5)
1480     {
1481         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n", __func__, ts_len);
1482         RETURNFUNC(-RIG_ERJCTED);
1483     }
1484 
1485     *ts = (shortfreq_t) from_bcd(tsbuf + 2, 4);
1486 
1487     if (tsbuf[4] != 0)
1488     {
1489         *ts *= -1;
1490     }
1491 
1492     RETURNFUNC(RIG_OK);
1493 }
1494 
1495 // The Icom rigs have only one register for both RIT and Delta TX
1496 // you can turn one or both on -- but both end up just being in sync.
icom_set_it_new(RIG * rig,vfo_t vfo,shortfreq_t ts,int set_xit)1497 static int icom_set_it_new(RIG *rig, vfo_t vfo, shortfreq_t ts, int set_xit)
1498 {
1499     unsigned char tsbuf[8];
1500     unsigned char ackbuf[16];
1501     int ack_len;
1502     int retval;
1503 
1504     rig_debug(RIG_DEBUG_VERBOSE, "%s: ts=%d\n", __func__, (int) ts);
1505 
1506     to_bcd(tsbuf, abs((int) ts), 4);
1507     // set sign bit
1508     tsbuf[2] = (ts < 0) ? 1 : 0;
1509 
1510     retval = icom_transaction(rig, C_CTL_RIT, S_RIT_FREQ, tsbuf, 3, ackbuf,
1511                               &ack_len);
1512 
1513     if (retval != RIG_OK)
1514     {
1515         RETURNFUNC(retval);
1516     }
1517 
1518 #if 0 // why is this here?  We have another function to turn it on/off
1519 
1520     if (ts == 0)          // Turn off both RIT/XIT
1521     {
1522         if (rig->caps->has_get_func & RIG_FUNC_XIT)
1523         {
1524             rig_debug(RIG_DEBUG_TRACE, "%s: turning of XIT too\n", __func__);
1525             retval = icom_set_func(rig, vfo, RIG_FUNC_XIT, 0);
1526 
1527             if (retval != RIG_OK)
1528             {
1529                 RETURNFUNC(retval);
1530             }
1531         }
1532         else          // some rigs don't have XIT like the 9700
1533         {
1534             rig_debug(RIG_DEBUG_TRACE,
1535                       "%s: rig does not have xit command enabled\n", __func__);
1536         }
1537 
1538         retval = icom_set_func(rig, vfo, RIG_FUNC_RIT, 0);
1539     }
1540     else
1541     {
1542         retval =
1543             icom_set_func(rig, vfo, set_xit ? RIG_FUNC_XIT : RIG_FUNC_RIT, 1);
1544     }
1545 
1546 #endif
1547 
1548     RETURNFUNC(retval);
1549 }
1550 
icom_set_rit_new(RIG * rig,vfo_t vfo,shortfreq_t ts)1551 int icom_set_rit_new(RIG *rig, vfo_t vfo, shortfreq_t ts)
1552 {
1553     RETURNFUNC(icom_set_it_new(rig, vfo, ts, 0));
1554 }
1555 
icom_set_xit_new(RIG * rig,vfo_t vfo,shortfreq_t ts)1556 int icom_set_xit_new(RIG *rig, vfo_t vfo, shortfreq_t ts)
1557 {
1558     RETURNFUNC(icom_set_it_new(rig, vfo, ts, 1));
1559 }
1560 
1561 /* icom_get_dsp_flt
1562     returns the dsp filter width in hz or 0 if the command is not implemented or error.
1563     This allows the default parameters to be assigned from the get_mode routine if the command is not implemented.
1564     Assumes rig != null and the current mode is in mode.
1565 
1566     Has been tested for IC-746pro,  Should work on the all dsp rigs ie pro models.
1567     The 746 documentation says it has the get_if_filter, but doesn't give any decoding information ? Please test.
1568 */
1569 
icom_get_dsp_flt(RIG * rig,rmode_t mode)1570 pbwidth_t icom_get_dsp_flt(RIG *rig, rmode_t mode)
1571 {
1572 
1573     int retval, res_len, rfstatus;
1574     unsigned char resbuf[MAXFRAMELEN];
1575     value_t rfwidth;
1576     unsigned char fw_sub_cmd = RIG_MODEL_IC7200 == rig->caps->rig_model ? 0x02 :
1577                                S_MEM_FILT_WDTH;
1578     struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
1579 
1580     rig_debug(RIG_DEBUG_VERBOSE, "%s called, mode=%s\n", __func__,
1581               rig_strrmode(mode));
1582 
1583     if (rig_has_get_func(rig, RIG_FUNC_RF)
1584             && (mode & (RIG_MODE_RTTY | RIG_MODE_RTTYR)))
1585     {
1586         if (!rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_RF, &rfstatus)
1587                 && (rfstatus))
1588         {
1589             retval = rig_get_ext_parm(rig, TOK_RTTY_FLTR, &rfwidth);
1590 
1591             if (retval != RIG_OK || rfwidth.i >= RTTY_FIL_NB)
1592             {
1593                 return (0);    /* use default */
1594             }
1595             else
1596             {
1597                 return (rtty_fil[rfwidth.i]);
1598             }
1599         }
1600     }
1601 
1602     if (RIG_MODEL_X108G == rig->caps->rig_model)
1603     {
1604         priv->no_1a_03_cmd = 1;
1605     }
1606 
1607     if (priv->no_1a_03_cmd)
1608     {
1609         return (0);
1610     }
1611 
1612     retval = icom_transaction(rig, C_CTL_MEM, fw_sub_cmd, 0, 0,
1613                               resbuf, &res_len);
1614 
1615     if (-RIG_ERJCTED == retval)
1616     {
1617         priv->no_1a_03_cmd = -1;  /* do not keep asking */
1618         return (0);
1619     }
1620 
1621     if (retval != RIG_OK)
1622     {
1623         rig_debug(RIG_DEBUG_ERR, "%s: protocol error (%#.2x), "
1624                   "len=%d\n", __func__, resbuf[0], res_len);
1625         return (0);        /* use default */
1626     }
1627 
1628     if (res_len == 3 && resbuf[0] == C_CTL_MEM)
1629     {
1630         int i;
1631         i = (int) from_bcd(resbuf + 2, 2);
1632         rig_debug(RIG_DEBUG_TRACE, "%s: i=%d, [0]=%02x, [1]=%02x, [2]=%02x, [3]=%02x\n",
1633                   __func__, i, resbuf[0], resbuf[1], resbuf[2], resbuf[3]);
1634 
1635         if (mode & RIG_MODE_AM)
1636         {
1637             return ((i + 1) * 200); /* Ic_7800 */
1638         }
1639         else if (mode &
1640                  (RIG_MODE_CW | RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_RTTY |
1641                   RIG_MODE_RTTYR | RIG_MODE_PKTUSB | RIG_MODE_PKTLSB))
1642         {
1643             rig_debug(RIG_DEBUG_TRACE, "%s: using width=%d\n", __func__, i);
1644             RETURNFUNC(i < 10 ? (i + 1) * 50 : (i - 4) * 100);
1645         }
1646     }
1647 
1648     RETURNFUNC(0);
1649 }
1650 
icom_set_dsp_flt(RIG * rig,rmode_t mode,pbwidth_t width)1651 int icom_set_dsp_flt(RIG *rig, rmode_t mode, pbwidth_t width)
1652 {
1653     int retval, rfstatus;
1654     unsigned char ackbuf[MAXFRAMELEN];
1655     unsigned char flt_ext;
1656     value_t rfwidth;
1657     int ack_len = sizeof(ackbuf), flt_idx;
1658     unsigned char fw_sub_cmd = RIG_MODEL_IC7200 == rig->caps->rig_model ? 0x02 :
1659                                S_MEM_FILT_WDTH;
1660 
1661     ENTERFUNC;
1662 
1663     if (RIG_PASSBAND_NOCHANGE == width)
1664     {
1665         RETURNFUNC(RIG_OK);
1666     }
1667 
1668     if (width == RIG_PASSBAND_NORMAL)
1669     {
1670         width = rig_passband_normal(rig, mode);
1671     }
1672 
1673     if (rig_has_get_func(rig, RIG_FUNC_RF)
1674             && (mode & (RIG_MODE_RTTY | RIG_MODE_RTTYR)))
1675     {
1676         if (!rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_RF, &rfstatus)
1677                 && (rfstatus))
1678         {
1679             int i;
1680 
1681             for (i = 0; i < RTTY_FIL_NB; i++)
1682             {
1683                 if (rtty_fil[i] == width)
1684                 {
1685                     rfwidth.i = i;
1686                     RETURNFUNC(rig_set_ext_parm(rig, TOK_RTTY_FLTR, rfwidth));
1687                 }
1688             }
1689 
1690             /* not found */
1691             RETURNFUNC(-RIG_EINVAL);
1692         }
1693     }
1694 
1695     if (mode & RIG_MODE_AM)
1696     {
1697         flt_idx = (width / 200) - 1;  /* TBC: Ic_7800? */
1698     }
1699     else if (mode & (RIG_MODE_CW | RIG_MODE_USB | RIG_MODE_LSB | RIG_MODE_RTTY |
1700                      RIG_MODE_RTTYR))
1701     {
1702         if (width == 0)
1703         {
1704             width = 1;
1705         }
1706 
1707         flt_idx =
1708             width <= 500 ? ((width + 49) / 50) - 1 : ((width + 99) / 100) + 4;
1709     }
1710     else
1711     {
1712         RETURNFUNC(RIG_OK);
1713     }
1714 
1715     to_bcd(&flt_ext, flt_idx, 2);
1716 
1717     retval = icom_transaction(rig, C_CTL_MEM, fw_sub_cmd, &flt_ext, 1,
1718                               ackbuf, &ack_len);
1719 
1720     if (retval != RIG_OK)
1721     {
1722         rig_debug(RIG_DEBUG_ERR, "%s: protocol error (%#.2x), "
1723                   "len=%d\n", __func__, ackbuf[0], ack_len);
1724         RETURNFUNC(retval);
1725     }
1726 
1727     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
1728     {
1729         rig_debug(RIG_DEBUG_ERR, "%s: command not supported ? (%#.2x), "
1730                   "len=%d\n", __func__, ackbuf[0], ack_len);
1731         RETURNFUNC(retval);
1732     }
1733 
1734     RETURNFUNC(RIG_OK);
1735 }
1736 
icom_set_mode_x26(RIG * rig,vfo_t vfo,rmode_t mode,int datamode,int filter)1737 static int icom_set_mode_x26(RIG *rig, vfo_t vfo, rmode_t mode, int datamode,
1738                              int filter)
1739 {
1740     struct icom_priv_data *priv = rig->state.priv;
1741     int retval;
1742     unsigned char buf[3];
1743 
1744     ENTERFUNC;
1745 
1746     if (priv->x26cmdfails) { RETURNFUNC(-RIG_ENAVAIL); }
1747 
1748     int cmd2 = 0x26;
1749     int subcmd2 = 0x00;
1750     vfo_t vfo_unselected = RIG_VFO_B | RIG_VFO_SUB | RIG_VFO_SUB_B | RIG_VFO_MAIN_B;
1751 
1752     // if we are on the "other" vfo already then we have to allow for that
1753     if (rig->state.current_vfo & vfo_unselected)
1754     {
1755         vfo_unselected = RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_SUB_A | RIG_VFO_MAIN_A;
1756     }
1757 
1758     // if we ask for unselected but we're not on unselected subcmd2 changes
1759     if ((vfo & vfo_unselected) && !(rig->state.current_vfo & vfo_unselected))
1760     {
1761         subcmd2 = 0x01;  // get unselected VFO
1762     }
1763 
1764     buf[0] = mode;
1765     buf[1] = datamode;
1766     // filter fixed to filter 1 due to IC7300 bug defaulting to filter 2 on mode changed -- yuck!!
1767     // buf[2] = filter // if Icom ever fixed this
1768     buf[2] = 1;
1769 
1770     retval = icom_transaction(rig, cmd2, subcmd2, buf, 3, NULL, NULL);
1771 
1772     if (retval != RIG_OK)
1773     {
1774         priv->x26cmdfails = 1;
1775         rig_debug(RIG_DEBUG_WARN,
1776                   "%s: rig does not support 0x26 CI-V cmd\n", __func__);
1777         return -RIG_ENAVAIL;
1778     }
1779 
1780     RETURNFUNC(RIG_OK);
1781 }
1782 
1783 /*
1784  * icom_set_mode_with_data
1785  */
icom_set_mode_with_data(RIG * rig,vfo_t vfo,rmode_t mode,pbwidth_t width)1786 int icom_set_mode_with_data(RIG *rig, vfo_t vfo, rmode_t mode,
1787                             pbwidth_t width)
1788 {
1789     int retval;
1790     unsigned char ackbuf[MAXFRAMELEN];
1791     int ack_len = sizeof(ackbuf);
1792     rmode_t icom_mode;
1793     rmode_t tmode;
1794     pbwidth_t twidth;
1795     //struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
1796     unsigned char dm_sub_cmd =
1797         rig->caps->rig_model == RIG_MODEL_IC7200  ? 0x04 : S_MEM_DATA_MODE;
1798     int filter_byte = rig->caps->rig_model == RIG_MODEL_IC7100
1799                       || rig->caps->rig_model == RIG_MODEL_IC7200
1800                       || rig->caps->rig_model == RIG_MODEL_IC7300
1801                       || rig->caps->rig_model == RIG_MODEL_IC7600
1802                       || rig->caps->rig_model == RIG_MODEL_IC7610
1803                       || rig->caps->rig_model == RIG_MODEL_IC7700
1804                       || rig->caps->rig_model == RIG_MODEL_IC7800
1805                       || rig->caps->rig_model == RIG_MODEL_IC785x
1806                       || rig->caps->rig_model == RIG_MODEL_IC9100
1807                       || rig->caps->rig_model == RIG_MODEL_IC9700
1808                       || rig->caps->rig_model == RIG_MODEL_IC705;
1809 
1810     ENTERFUNC;
1811 
1812     // if our current mode and width is not changing do nothing
1813     retval = rig_get_mode(rig, vfo, &tmode, &twidth);
1814 
1815     if (retval != RIG_OK)
1816     {
1817         rig_debug(RIG_DEBUG_ERR, "%s: get_mode failed: %s\n", __func__,
1818                   rigerror(retval));
1819         RETURNFUNC(retval);
1820     }
1821 
1822     if (tmode == mode && width == RIG_PASSBAND_NOCHANGE)
1823     {
1824         rig_debug(RIG_DEBUG_TRACE, "%s: mode/width not changing\n", __func__);
1825         RETURNFUNC(RIG_OK);
1826     }
1827     // looks like we need to change it
1828 
1829     switch (mode)
1830     {
1831 
1832     case RIG_MODE_PKTUSB:
1833         // xFE xFE x6E xE0 x1A x06 x01 xFD switches mod input from MIC to ACC
1834         // This apparently works for IC-756ProIII but nobody has asked for it yet
1835         icom_mode = RIG_MODE_USB;
1836         break;
1837 
1838     case RIG_MODE_PKTLSB:
1839         icom_mode = RIG_MODE_LSB;
1840         break;
1841 
1842     case RIG_MODE_PKTFM:
1843         icom_mode = RIG_MODE_FM;
1844         break;
1845 
1846     case RIG_MODE_PKTAM:
1847         icom_mode = RIG_MODE_AM;
1848         break;
1849 
1850     default:
1851         icom_mode = mode;
1852         break;
1853     }
1854 
1855     rig_debug(RIG_DEBUG_VERBOSE, "%s mode=%d, width=%d, curr_vfo=%s\n", __func__,
1856               (int)icom_mode,
1857               (int)width, rig_strvfo(rig->state.current_vfo));
1858 
1859     // we only need to change base mode if we aren't using cmd 26 later
1860     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_MODE))
1861     {
1862         retval = icom_set_mode(rig, vfo, icom_mode, width);
1863     }
1864     else
1865     {
1866         retval = RIG_OK;
1867     }
1868 
1869     hl_usleep(50 * 1000); // pause for possible transceive message which we'll flush
1870 
1871     if (RIG_OK == retval)
1872     {
1873         unsigned char datamode[2];
1874         unsigned char mode_icom; // Not used, we only need the width
1875         signed char width_icom;
1876 
1877         TRACE;
1878 
1879         switch (mode)
1880         {
1881         case RIG_MODE_PKTUSB:
1882         case RIG_MODE_PKTLSB:
1883         case RIG_MODE_PKTFM:
1884         case RIG_MODE_PKTAM:
1885             datamode[0] = 0x01;
1886             datamode[1] = 0x02; // default to filter 2
1887             break;
1888 
1889         default:
1890             datamode[0] = 0x00;
1891             datamode[1] = 0x02; // default to filter 2
1892             break;
1893         }
1894 
1895         rig2icom_mode(rig, vfo, mode, width, &mode_icom, &width_icom);
1896 
1897         if (filter_byte)   // then we need the filter width byte too
1898         {
1899             TRACE;
1900 
1901             if (datamode[0] == 0) { datamode[1] = 0; } // the only good combo possible according to manual
1902 
1903             rig_debug(RIG_DEBUG_TRACE, "%s(%d) mode_icom=%d, datamode[0]=%d, filter=%d\n",
1904                       __func__, __LINE__, mode_icom, datamode[0], datamode[1]);
1905             retval = icom_set_mode_x26(rig, vfo, mode_icom, datamode[0], datamode[1]);
1906 
1907             if (retval != RIG_OK)
1908             {
1909                 retval =
1910                     icom_transaction(rig, C_CTL_MEM, dm_sub_cmd, datamode, 2, ackbuf, &ack_len);
1911             }
1912         }
1913         else
1914         {
1915             TRACE;
1916             retval =
1917                 icom_transaction(rig, C_CTL_MEM, dm_sub_cmd, datamode, 1, ackbuf, &ack_len);
1918         }
1919 
1920         if (retval != RIG_OK)
1921         {
1922             rig_debug(RIG_DEBUG_ERR, "%s: protocol error (%#.2x), len=%d\n",
1923                       __func__, ackbuf[0], ack_len);
1924         }
1925         else
1926         {
1927             if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
1928             {
1929                 rig_debug(RIG_DEBUG_ERR,
1930                           "%s: command not supported ? (%#.2x), len=%d\n",
1931                           __func__, ackbuf[0], ack_len);
1932             }
1933         }
1934     }
1935 
1936     RETURNFUNC(retval);
1937 }
1938 
1939 /*
1940  * icom_set_mode
1941  * Assumes rig!=NULL, rig->state.priv!=NULL
1942  */
icom_set_mode(RIG * rig,vfo_t vfo,rmode_t mode,pbwidth_t width)1943 int icom_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width)
1944 {
1945     struct icom_priv_data *priv;
1946     const struct icom_priv_caps *priv_caps;
1947     const struct icom_priv_data *priv_data;
1948     struct rig_state *rs;
1949     unsigned char ackbuf[MAXFRAMELEN];
1950     unsigned char icmode;
1951     signed char icmode_ext;
1952     int ack_len = sizeof(ackbuf), retval, err;
1953     int swapvfos = 0;
1954 
1955     rig_debug(RIG_DEBUG_VERBOSE,
1956               "%s called vfo=%s, mode=%s, width=%d, current_vfo=%s\n", __func__,
1957               rig_strvfo(vfo), rig_strrmode(mode), (int)width,
1958               rig_strvfo(rig->state.current_vfo));
1959     rs = &rig->state;
1960     priv = (struct icom_priv_data *) rs->priv;
1961 
1962     priv_caps = (const struct icom_priv_caps *) rig->caps->priv;
1963     priv_data = (const struct icom_priv_data *) rig->state.priv;
1964 
1965     if (priv_caps->r2i_mode != NULL)  /* call priv code if defined */
1966     {
1967         err = priv_caps->r2i_mode(rig, vfo, mode, width, &icmode, &icmode_ext);
1968     }
1969     else              /* else call default */
1970     {
1971         err = rig2icom_mode(rig, vfo, mode, width, &icmode, &icmode_ext);
1972     }
1973 
1974     if (width == RIG_PASSBAND_NOCHANGE) { icmode_ext = priv_data->filter; }
1975 
1976     if (err < 0)
1977     {
1978         rig_debug(RIG_DEBUG_ERR, "%s: Error on rig2icom err=%d\n", __func__, err);
1979         RETURNFUNC(err);
1980     }
1981 
1982     rig_debug(RIG_DEBUG_VERBOSE, "%s: icmode=%d, icmode_ext=%d\n", __func__, icmode,
1983               icmode_ext);
1984 
1985     /* IC-731, IC-735, IC-7000 don't support passband data */
1986     /* IC-726 & IC-475A/E also limited support - only on CW */
1987     /* TODO: G4WJS CW wide/narrow are possible with above two radios */
1988     if (priv->civ_731_mode || rig->caps->rig_model == RIG_MODEL_OS456
1989             || rig->caps->rig_model == RIG_MODEL_IC726
1990             || rig->caps->rig_model == RIG_MODEL_IC475
1991             || rig->caps->rig_model == RIG_MODEL_IC7000)
1992     {
1993         icmode_ext = -1;
1994     }
1995 
1996     // some Icom rigs have seperate modes for VFOB/Sub
1997     // switching to VFOB should not matter for the other rigs
1998     // This needs to be improved for RIG_TARGETABLE_MODE rigs
1999     if ((vfo == RIG_VFO_B || vfo == RIG_VFO_SUB)
2000             && ((rig->state.current_vfo == RIG_VFO_A
2001                  || rig->state.current_vfo == RIG_VFO_MAIN)
2002                 || rig->state.current_vfo == RIG_VFO_CURR))
2003     {
2004         TRACE;
2005 
2006         if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_MODE))
2007         {
2008             swapvfos = 1;
2009             rig_set_vfo(rig, RIG_VFO_B);
2010         }
2011     }
2012 
2013     rig_debug(RIG_DEBUG_VERBOSE, "%s: #2 icmode=%d, icmode_ext=%d\n", __func__,
2014               icmode, icmode_ext);
2015     retval = icom_transaction(rig, C_SET_MODE, icmode,
2016                               (unsigned char *) &icmode_ext,
2017                               (icmode_ext == -1 ? 0 : 1), ackbuf, &ack_len);
2018 
2019     if (swapvfos)
2020     {
2021         TRACE;
2022         rig_set_vfo(rig, RIG_VFO_A);
2023     }
2024 
2025     if (retval != RIG_OK)
2026     {
2027         RETURNFUNC(retval);
2028     }
2029 
2030     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
2031     {
2032         //  if we don't get ACK/NAK some serial corruption occurred
2033         // so we'll call it a timeout for retry purposes
2034         RETURNFUNC(-RIG_ETIMEOUT);
2035     }
2036 
2037     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
2038     {
2039         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
2040                   ackbuf[0], ack_len);
2041         RETURNFUNC(-RIG_ERJCTED);
2042     }
2043 
2044     /* DSP filter setting ($1A$03), but not supported by every rig,
2045      * and some models like IC910/Omni VI Plus have a different meaning for
2046      * this subcommand
2047      */
2048     if (rig->caps->rig_model == RIG_MODEL_IC7000)
2049     {
2050         icom_set_dsp_flt(rig, mode, width);
2051     }
2052 
2053     RETURNFUNC(RIG_OK);
2054 }
2055 
2056 /*
2057  * icom_get_mode_with_data
2058  *
2059  * newer Icom rigs support data mode with ACC-1 audio input and MIC muted
2060  */
icom_get_mode_with_data(RIG * rig,vfo_t vfo,rmode_t * mode,pbwidth_t * width)2061 int icom_get_mode_with_data(RIG *rig, vfo_t vfo, rmode_t *mode,
2062                             pbwidth_t *width)
2063 {
2064     unsigned char databuf[MAXFRAMELEN];
2065     int data_len, retval;
2066     unsigned char dm_sub_cmd = RIG_MODEL_IC7200 == rig->caps->rig_model ? 0x04 :
2067                                S_MEM_DATA_MODE;
2068     struct rig_state *rs;
2069     struct icom_priv_data *priv;
2070 
2071     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
2072 
2073     rs = &rig->state;
2074     priv = (struct icom_priv_data *) rs->priv;
2075 
2076     retval = icom_get_mode(rig, vfo, mode, width);
2077 
2078     if (retval != RIG_OK)
2079     {
2080         RETURNFUNC(retval);
2081     }
2082 
2083     rig_debug(RIG_DEBUG_VERBOSE, "%s mode=%d\n", __func__, (int)*mode);
2084 
2085     switch (*mode)
2086     {
2087     case RIG_MODE_USB:
2088     case RIG_MODE_LSB:
2089     case RIG_MODE_AM:
2090     case RIG_MODE_FM:
2091 
2092         /*
2093          * fetch data mode on/off
2094          */
2095         if (rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
2096         {
2097             // then we already got data mode so we fake the databuf answer
2098             databuf[2] = priv->datamode;
2099             data_len = 3;
2100         }
2101         else
2102         {
2103             retval =
2104                 icom_transaction(rig, C_CTL_MEM, dm_sub_cmd, 0, 0, databuf,
2105                                  &data_len);
2106 
2107             if (retval != RIG_OK)
2108             {
2109                 rig_debug(RIG_DEBUG_ERR, "%s: protocol error (%#.2x), len=%d\n",
2110                           __func__, databuf[0], data_len);
2111                 RETURNFUNC(-RIG_ERJCTED);
2112             }
2113         }
2114 
2115         /*
2116          * databuf should contain Cn,Sc,D0[,D1]
2117          */
2118         data_len -= 2;
2119 
2120         if (1 > data_len || data_len > 2)
2121         {
2122             /* manual says 1 byte answer
2123                but at least IC756 ProIII
2124                sends 2 - second byte
2125                appears to be same as
2126                second byte from 04 command
2127                which is filter preset
2128                number, whatever it is we
2129                ignore it */
2130             rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n", __func__,
2131                       data_len);
2132             RETURNFUNC(-RIG_ERJCTED);
2133         }
2134 
2135         rig_debug(RIG_DEBUG_VERBOSE, "%s databuf[2]=%d, mode=%d\n", __func__,
2136                   (int)databuf[2], (int)*mode);
2137 
2138         if (databuf[2])       /* 0x01/0x02/0x03 -> data mode, 0x00 -> not data mode */
2139         {
2140             switch (*mode)
2141             {
2142             case RIG_MODE_USB:
2143                 *mode = RIG_MODE_PKTUSB;
2144                 break;
2145 
2146             case RIG_MODE_LSB:
2147                 *mode = RIG_MODE_PKTLSB;
2148                 break;
2149 
2150             case RIG_MODE_AM:
2151                 *mode = RIG_MODE_PKTAM;
2152                 break;
2153 
2154             case RIG_MODE_FM:
2155                 *mode = RIG_MODE_PKTFM;
2156                 break;
2157 
2158             default:
2159                 break;
2160             }
2161         }
2162 
2163     default:
2164         break;
2165     }
2166 
2167     RETURNFUNC(retval);
2168 }
2169 
2170 /*
2171  * icom_get_mode
2172  * Assumes rig!=NULL, rig->state.priv!=NULL, mode!=NULL, width!=NULL
2173  *
2174  * TODO: some IC781's, when sending mode info, in wide filter mode, no
2175  *  width data is send along, making the frame 1 byte short.
2176  *  (Thank to Mel, VE2DC for this info)
2177  */
icom_get_mode(RIG * rig,vfo_t vfo,rmode_t * mode,pbwidth_t * width)2178 int icom_get_mode(RIG *rig, vfo_t vfo, rmode_t *mode, pbwidth_t *width)
2179 {
2180     unsigned char modebuf[MAXFRAMELEN];
2181     const struct icom_priv_caps *priv_caps;
2182     struct icom_priv_data *priv_data;
2183     int mode_len, retval;
2184 
2185     rig_debug(RIG_DEBUG_VERBOSE, "%s called vfo=%s\n", __func__, rig_strvfo(vfo));
2186     priv_caps = (const struct icom_priv_caps *) rig->caps->priv;
2187     priv_data = (struct icom_priv_data *) rig->state.priv;
2188 
2189     *width = 0;
2190 
2191     // IC7800 can set but not read with 0x26
2192     if ((rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
2193             && rig->caps->rig_model != RIG_MODEL_IC7800)
2194     {
2195         int vfosel = 0x00;
2196 
2197         if (vfo & (RIG_VFO_B | RIG_VFO_SUB | RIG_VFO_SUB_B | RIG_VFO_MAIN_B)) { vfosel = 0x01; }
2198 
2199         // use cache for the non-selected VFO -- can't get it by VFO
2200         // this avoids vfo swapping but accurate answers for these rigs
2201         *width = rig->state.cache.widthMainB;
2202 
2203         if (vfo == RIG_VFO_SUB_B) { *width = rig->state.cache.widthSubB; }
2204 
2205         // then get non-selected VFO mode/width
2206         retval = icom_transaction(rig, 0x26, vfosel, NULL, 0, modebuf, &mode_len);
2207         rig_debug(RIG_DEBUG_TRACE,
2208                   "%s: mode_len=%d, modebuf=%02x %02x %02x %02x %02x\n", __func__, mode_len,
2209                   modebuf[0], modebuf[1], modebuf[2], modebuf[3], modebuf[4]);
2210         // mode_len=5, modebuf=26 01 01 01 01
2211         // last 3 bytes are mode, datamode, filter (1-3)
2212         priv_data->datamode = modebuf[3];
2213         priv_data->filter = modebuf[4];
2214         modebuf[1] = modebuf[2]; // copy mode to 2-byte format
2215         modebuf[2] = modebuf[4]; // copy filter to 2-byte format
2216         mode_len = 2;
2217     }
2218     else
2219     {
2220         retval = icom_transaction(rig, C_RD_MODE, -1, NULL, 0, modebuf, &mode_len);
2221     }
2222 
2223     if (--mode_len == 3)
2224     {
2225         priv_data->filter = modebuf[2];
2226         rig_debug(RIG_DEBUG_TRACE,
2227                   "%s: modebuf[0]=0x%02x, modebuf[1]=0x%02x, modebuf[2]=0x%02x, mode_len=%d, filter=%d\n",
2228                   __func__, modebuf[0],
2229                   modebuf[1], modebuf[2], mode_len, priv_data->filter);
2230     }
2231     else
2232     {
2233         rig_debug(RIG_DEBUG_TRACE,
2234                   "%s: modebuf[0]=0x%02x, modebuf[1]=0x%02x, mode_len=%d\n", __func__, modebuf[0],
2235                   modebuf[1], mode_len);
2236     }
2237 
2238     if (retval != RIG_OK)
2239     {
2240         RETURNFUNC(retval);
2241     }
2242 
2243     /*
2244      * modebuf should contain Cn,Data area
2245      */
2246     // when mode gets here it should be 2 or 1
2247     // mode_len--;
2248 
2249     if (mode_len != 2 && mode_len != 1)
2250     {
2251         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n",
2252                   __func__, mode_len);
2253         RETURNFUNC(-RIG_ERJCTED);
2254     }
2255 
2256     if (priv_caps->i2r_mode != NULL)  /* call priv code if defined */
2257     {
2258         priv_caps->i2r_mode(rig, modebuf[1],
2259                             mode_len == 2 ? modebuf[2] : -1, mode, width);
2260     }
2261     else              /* else call default */
2262     {
2263         icom2rig_mode(rig, modebuf[1],
2264                       mode_len == 2 ? modebuf[2] : -1, mode, width);
2265     }
2266 
2267     /* IC910H has different meaning of command 1A, subcommand 03. So do
2268      * not ask for DSP filter settings */
2269     /* Likewise, don't ask if we happen to be an Omni VI Plus */
2270     /* Likewise, don't ask if we happen to be an IC-R30 */
2271     /* Likewise, don't ask if we happen to be an IC-706* */
2272     if ((rig->caps->rig_model == RIG_MODEL_IC910) ||
2273             (rig->caps->rig_model == RIG_MODEL_OMNIVIP) ||
2274             (rig->caps->rig_model == RIG_MODEL_IC706) ||
2275             (rig->caps->rig_model == RIG_MODEL_IC706MKII) ||
2276             (rig->caps->rig_model == RIG_MODEL_IC706MKIIG) ||
2277             (rig->caps->rig_model == RIG_MODEL_ICR30))
2278     {
2279         RETURNFUNC(RIG_OK);
2280     }
2281 
2282     /* Most rigs RETURNFUNC(1-wide, 2-normal,3-narrow
2283      * For DSP rigs these are presets, can be programmed for 30 - 41 bandwidths, depending on mode.
2284      * Lets check for dsp filters
2285      */
2286 
2287     // if we already set width we won't update with except during set_vfo or set_mode
2288     // reason is we can't get width without swapping vfos -- yuck!!
2289     if (vfo & (RIG_VFO_A | RIG_VFO_MAIN | RIG_VFO_SUB_A | RIG_VFO_MAIN_A |
2290                RIG_VFO_CURR))
2291     {
2292         // then we get what was asked for
2293         if (vfo == RIG_VFO_NONE && rig->state.current_vfo == RIG_VFO_NONE)
2294         {
2295             rig_debug(RIG_DEBUG_TRACE, "%s(%d): forcing default VFO_A\n", __func__,
2296                       __LINE__);
2297             TRACE;
2298             rig_set_vfo(rig, RIG_VFO_A); // force VFOA
2299         }
2300 
2301         retval = icom_get_dsp_flt(rig, *mode);
2302         *width = retval;
2303 
2304         if (retval == 0)
2305         {
2306             rig_debug(RIG_DEBUG_TRACE,
2307                       "%s: vfo=%s returning mode=%s, width not available\n", __func__,
2308                       rig_strvfo(vfo), rig_strrmode(*mode));
2309         }
2310     }
2311     else if (rig->state.cache.widthMainB == 0)
2312     {
2313         // we need to swap vfos to get the bandwidth -- yuck
2314         // so we read it once and will let set_mode and transceive capability (4.3 hamlib) update it
2315         vfo_t vfosave = rig->state.current_vfo;
2316 
2317         if (vfosave != vfo)
2318         {
2319             // right now forcing VFOA/B arrangement -- reverse not supported yet
2320             // If VFOB width is ever different than VFOA
2321             // we need to figure out how to read VFOB without swapping VFOs
2322             //TRACE;
2323             //rig_set_vfo(rig, RIG_VFO_B);
2324             retval = icom_get_dsp_flt(rig, *mode);
2325             *width = retval;
2326 
2327             if (*width == 0) { *width = rig->state.cache.widthMainA; } // we'll use VFOA's width
2328 
2329             // dont' really care about cache time here
2330             // this is just to prevent vfo swapping while getting width
2331             rig->state.cache.widthMainB = retval;
2332             rig_debug(RIG_DEBUG_TRACE, "%s(%d): vfosave=%s, currvfo=%s\n", __func__,
2333                       __LINE__, rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo));
2334             //TRACE;
2335             //rig_set_vfo(rig, RIG_VFO_A);
2336             rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s returning mode=%s, width=%d\n", __func__,
2337                       rig_strvfo(vfo), rig_strrmode(*mode), (int)*width);
2338         }
2339         else
2340         {
2341             rig_debug(RIG_DEBUG_WARN,
2342                       "%s: vfo arrangement not supported yet, vfo=%s, currvfo=%s\n", __func__,
2343                       rig_strvfo(vfo), rig_strvfo(vfosave));
2344         }
2345     }
2346 
2347 
2348     RETURNFUNC(RIG_OK);
2349 }
2350 
2351 #ifdef XXREMOVEDXX
2352 // not implemented yet
2353 /*
2354  * icom_get_vfo
2355  * The IC-9700 has introduced the ability to see MAIN/SUB selection
2356  * Maybe we'll see this in future ICOMs or firmware upgrades
2357  * Command 0x07 0XD2 -- but as of version 1.05 it doesn't work
2358  * We will, by default, force Main=VFOA and Sub=VFOB, and may want
2359  * an option to not force that behavior
2360  * Assumes rig!=NULL, rig->state.priv!=NULL
2361  */
icom_get_vfo(RIG * rig,vfo_t * vfo)2362 int icom_get_vfo(RIG *rig, vfo_t *vfo)
2363 {
2364     unsigned char ackbuf[MAXFRAMELEN];
2365     int ack_len = sizeof(ackbuf), retval;
2366     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
2367 
2368     retval = icom_transaction(rig, C_SET_VFO, S_SUB_SEL, NULL, 0,
2369                               ackbuf, &ack_len);
2370 
2371     if (retval != RIG_OK)
2372     {
2373         RETURNFUNC(retval);
2374     }
2375 
2376     if (ack_len != 3)
2377     {
2378         rig_debug(RIG_DEBUG_ERR, "%s wrong frame len=%d\n", __func__, ack_len);
2379         RETURNFUNC(-RIG_ERJCTED);
2380     }
2381 
2382     *vfo = ackbuf[2] == 0 ? RIG_VFO_A : RIG_VFO_B;
2383     RETURNFUNC(RIG_OK);
2384 }
2385 #endif
2386 
2387 /*
2388  * icom_get_vfo
2389  * Assumes rig!=NULL, rig->state.priv!=NULL
2390  */
icom_set_vfo(RIG * rig,vfo_t vfo)2391 int icom_set_vfo(RIG *rig, vfo_t vfo)
2392 {
2393     unsigned char ackbuf[MAXFRAMELEN];
2394     int ack_len = sizeof(ackbuf), icvfo, retval;
2395     struct rig_state *rs = &rig->state;
2396     struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
2397 
2398     rig_debug(RIG_DEBUG_VERBOSE, "%s called vfo=%s\n", __func__, rig_strvfo(vfo));
2399 
2400     if (vfo == RIG_VFO_CURR)
2401     {
2402         rig_debug(RIG_DEBUG_TRACE, "%s: Asking for currVFO,  currVFO=%s\n", __func__,
2403                   rig_strvfo(rig->state.current_vfo));
2404         RETURNFUNC(RIG_OK);
2405     }
2406 
2407     if (vfo == RIG_VFO_MAIN && VFO_HAS_A_B_ONLY)
2408     {
2409         vfo = RIG_VFO_A;
2410         rig_debug(RIG_DEBUG_TRACE,
2411                   "%s: Rig does not have MAIN/SUB so Main changed to %s\n",
2412                   __func__, rig_strvfo(vfo));
2413     }
2414     else if ((vfo == RIG_VFO_SUB) && (VFO_HAS_A_B_ONLY
2415                                       || (VFO_HAS_MAIN_SUB_A_B_ONLY && !priv->split_on && !rig->state.cache.satmode)))
2416     {
2417         // if rig doesn't have Main/Sub
2418         // or if rig has both Main/Sub and A/B -- e.g. 9700
2419         // and we dont' have split or satmode turned on
2420         // then we dont' use Sub -- instead we use Main/VFOB
2421         vfo = RIG_VFO_B;
2422         rig_debug(RIG_DEBUG_TRACE,
2423                   "%s: Rig does not have MAIN/SUB so Sub changed to %s\n",
2424                   __func__, rig_strvfo(vfo));
2425     }
2426     else if (vfo == RIG_VFO_TX)
2427     {
2428         rig_debug(RIG_DEBUG_TRACE, "%s: vfo line#%d vfo=%s\n", __func__, __LINE__,
2429                   rig_strvfo(vfo));
2430         vfo = RIG_VFO_A;
2431 
2432         if (VFO_HAS_A_B_ONLY && rig->state.cache.satmode) { vfo = RIG_VFO_B; }
2433         else if (VFO_HAS_MAIN_SUB_ONLY) { vfo = RIG_VFO_SUB; }
2434         else if (VFO_HAS_MAIN_SUB_A_B_ONLY && rig->state.cache.satmode) { vfo = RIG_VFO_SUB; }
2435     }
2436 
2437     else if ((vfo == RIG_VFO_A || vfo == RIG_VFO_MAIN) && VFO_HAS_DUAL)
2438     {
2439         rig_debug(RIG_DEBUG_TRACE, "%s: vfo line#%d vfo=%s, split=%d\n", __func__,
2440                   __LINE__, rig_strvfo(vfo), rig->state.cache.split);
2441         // If we're being asked for A/Main but we are a MainA/MainB rig change it
2442         vfo = RIG_VFO_MAIN;
2443 
2444         if (rig->state.cache.split == RIG_SPLIT_ON && !rig->state.cache.satmode) { vfo = RIG_VFO_A; }
2445 
2446         // Seems the IC821H reverses Main/Sub when in satmode
2447         if (rig->caps->rig_model == RIG_MODEL_IC821H && rig->state.cache.satmode) { vfo = RIG_VFO_SUB; }
2448     }
2449     else if ((vfo == RIG_VFO_B || vfo == RIG_VFO_SUB) && VFO_HAS_DUAL)
2450     {
2451         rig_debug(RIG_DEBUG_TRACE, "%s: vfo line#%d vfo=%s\n", __func__, __LINE__,
2452                   rig_strvfo(vfo));
2453         // If we're being asked for B/Sub but we are a MainA/MainB rig change it
2454         vfo = RIG_VFO_SUB;
2455 
2456         // If we're in satmode for rigs like IC9700 we want the 2nd VFO
2457         if (rig->state.cache.satmode)
2458         {
2459             vfo = RIG_VFO_SUB_A;
2460         }
2461         else if (rig->state.cache.split == RIG_SPLIT_ON) { vfo = RIG_VFO_B; }
2462 
2463         // Seems the IC821H reverses Main/Sub when in satmode
2464         if (rig->caps->rig_model == RIG_MODEL_IC821H && rig->state.cache.satmode) { vfo = RIG_VFO_MAIN; }
2465     }
2466     else if ((vfo == RIG_VFO_A || vfo == RIG_VFO_B) && !VFO_HAS_A_B
2467              && VFO_HAS_MAIN_SUB)
2468     {
2469         // If we're being asked for A/B but we are a Main/Sub rig change it
2470         vfo_t vfo_old = vfo;
2471         vfo = vfo == RIG_VFO_A ? RIG_VFO_MAIN : RIG_VFO_SUB;
2472         rig_debug(RIG_DEBUG_ERR, "%s: Rig does not have VFO A/B?\n", __func__);
2473         rig_debug(RIG_DEBUG_ERR, "%s: Mapping %s=%s\n", __func__, rig_strvfo(vfo_old),
2474                   rig_strvfo(vfo));
2475     }
2476 
2477 
2478     if ((vfo == RIG_VFO_MAIN || vfo == RIG_VFO_SUB) && !VFO_HAS_MAIN_SUB)
2479     {
2480         rig_debug(RIG_DEBUG_ERR, "%s: Rig does not have VFO Main/Sub?\n",
2481                   __func__);
2482         RETURNFUNC(-RIG_EINVAL);
2483     }
2484 
2485     if (vfo != rig->state.current_vfo)
2486     {
2487         rig_debug(RIG_DEBUG_TRACE, "%s: VFO changing from %s to %s\n", __func__,
2488                   rig_strvfo(rig->state.current_vfo), rig_strvfo(vfo));
2489         priv->curr_freq = 0; // reset curr_freq so set_freq works 1st time
2490     }
2491 
2492     rig_debug(RIG_DEBUG_TRACE, "%s: line#%d\n", __func__, __LINE__);
2493 
2494     switch (vfo)
2495     {
2496     case RIG_VFO_A:
2497         icvfo = S_VFOA;
2498         break;
2499 
2500     case RIG_VFO_B:
2501         icvfo = S_VFOB;
2502         break;
2503 
2504     case RIG_VFO_MAIN:
2505         icvfo = S_MAIN;
2506         break;
2507 
2508     case RIG_VFO_SUB:
2509         icvfo = S_SUB;
2510 
2511         // If split is on these rigs can only split on Main/VFOB
2512         if (VFO_HAS_MAIN_SUB_A_B_ONLY && priv->split_on) { icvfo = S_VFOB; }
2513 
2514         // If not split or satmode then we must want VFOB
2515         if (VFO_HAS_MAIN_SUB_A_B_ONLY && !priv->split_on && !rig->state.cache.satmode) { icvfo = S_VFOB; }
2516 
2517         rig_debug(RIG_DEBUG_TRACE, "%s: Sub asked for, ended up with vfo=%s\n",
2518                   __func__, icvfo == S_SUB ? "Sub" : "VFOB");
2519 
2520         break;
2521 
2522     case RIG_VFO_TX:
2523         icvfo = priv->split_on ? S_VFOB : S_VFOA;
2524         vfo = priv->split_on ? RIG_VFO_B : RIG_VFO_A;
2525         rig_debug(RIG_DEBUG_TRACE, "%s: RIG_VFO_TX changing vfo to %s\n", __func__,
2526                   rig_strvfo(vfo));
2527         break;
2528 
2529     case RIG_VFO_VFO:
2530         retval = icom_transaction(rig, C_SET_VFO, -1, NULL, 0,
2531                                   ackbuf, &ack_len);
2532 
2533         if (retval != RIG_OK)
2534         {
2535             RETURNFUNC(retval);
2536         }
2537 
2538         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
2539         {
2540             //  if we don't get ACK/NAK some serial corruption occurred
2541             // so we'll call it a timeout for retry purposes
2542             RETURNFUNC(-RIG_ETIMEOUT);
2543         }
2544 
2545         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
2546         {
2547             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
2548                       ackbuf[0], ack_len);
2549             RETURNFUNC(-RIG_ERJCTED);
2550         }
2551 
2552         rig->state.current_vfo = vfo;
2553         RETURNFUNC(RIG_OK);
2554 
2555     case RIG_VFO_MEM:
2556         retval = icom_transaction(rig, C_SET_MEM, -1, NULL, 0,
2557                                   ackbuf, &ack_len);
2558 
2559         if (retval != RIG_OK)
2560         {
2561             RETURNFUNC(retval);
2562         }
2563 
2564         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
2565         {
2566             //  if we don't get ACK/NAK some serial corruption occurred
2567             // so we'll call it a timeout for retry purposes
2568             RETURNFUNC(-RIG_ETIMEOUT);
2569         }
2570 
2571         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
2572         {
2573             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
2574                       ackbuf[0], ack_len);
2575             RETURNFUNC(-RIG_ERJCTED);
2576         }
2577 
2578         rig->state.current_vfo = vfo;
2579         RETURNFUNC(RIG_OK);
2580 
2581     case RIG_VFO_MAIN_A:    // we need to select Main before setting VFO
2582     case RIG_VFO_MAIN_B:
2583         rig_debug(RIG_DEBUG_VERBOSE, "%s: MainA/B logic\n", __func__);
2584         retval = icom_transaction(rig, C_SET_VFO, S_MAIN, NULL, 0,
2585                                   ackbuf, &ack_len);
2586 
2587         if (retval != RIG_OK)
2588         {
2589             RETURNFUNC(retval);
2590         }
2591 
2592         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
2593         {
2594             //  if we don't get ACK/NAK some serial corruption occurred
2595             // so we'll call it a timeout for retry purposes
2596             RETURNFUNC(-RIG_ETIMEOUT);
2597         }
2598 
2599         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
2600         {
2601             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
2602                       ackbuf[0], ack_len);
2603             RETURNFUNC(-RIG_ERJCTED);
2604         }
2605 
2606         icvfo = vfo == RIG_VFO_MAIN_A ? S_VFOA : S_VFOB;
2607 
2608         break;
2609 
2610     case RIG_VFO_SUB_A: // we need to select Sub before setting VFO
2611     case RIG_VFO_SUB_B:
2612         rig_debug(RIG_DEBUG_VERBOSE, "%s: SubA/B logic\n", __func__);
2613         retval = icom_transaction(rig, C_SET_VFO, S_SUB, NULL, 0,
2614                                   ackbuf, &ack_len);
2615 
2616         if (retval != RIG_OK)
2617         {
2618             RETURNFUNC(retval);
2619         }
2620 
2621         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
2622         {
2623             //  if we don't get ACK/NAK some serial corruption occurred
2624             // so we'll call it a timeout for retry purposes
2625             RETURNFUNC(-RIG_ETIMEOUT);
2626         }
2627 
2628         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
2629         {
2630             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
2631                       ackbuf[0], ack_len);
2632             RETURNFUNC(-RIG_ERJCTED);
2633         }
2634 
2635         // If SUB_A then we'll assume we're done and probably not in sat mode
2636         // If rig has SUB_B active this may be a problem
2637         if (vfo == RIG_VFO_SUB_A) { return RIG_OK; }
2638 
2639         icvfo = vfo == RIG_VFO_SUB_A ? S_VFOA : S_VFOB;
2640 
2641         break;
2642 
2643     default:
2644         rig_debug(RIG_DEBUG_ERR, "%s: unsupported VFO %s\n", __func__,
2645                   rig_strvfo(vfo));
2646         RETURNFUNC(-RIG_EINVAL);
2647     }
2648 
2649     rig_debug(RIG_DEBUG_TRACE, "%s: line#%d\n", __func__, __LINE__);
2650     retval = icom_transaction(rig, C_SET_VFO, icvfo, NULL, 0,
2651                               ackbuf, &ack_len);
2652     rig_debug(RIG_DEBUG_TRACE, "%s: line#%d\n", __func__, __LINE__);
2653 
2654     if (retval != RIG_OK)
2655     {
2656         RETURNFUNC(retval);
2657     }
2658 
2659     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
2660     {
2661         //  if we don't get ACK/NAK some serial corruption occurred
2662         // so we'll call it a timeout for retry purposes
2663         RETURNFUNC(-RIG_ETIMEOUT);
2664     }
2665 
2666     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
2667     {
2668         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
2669                   ackbuf[0], ack_len);
2670         RETURNFUNC(-RIG_ERJCTED);
2671     }
2672 
2673     rig->state.current_vfo = vfo;
2674     rig_debug(RIG_DEBUG_TRACE, "%s: line#%d curr_vfo=%s\n", __func__, __LINE__,
2675               rig_strvfo(rig->state.current_vfo));
2676     RETURNFUNC(RIG_OK);
2677 }
2678 
icom_set_cmd(RIG * rig,vfo_t vfo,struct cmdparams * par,value_t val)2679 int icom_set_cmd(RIG *rig, vfo_t vfo, struct cmdparams *par, value_t val)
2680 {
2681     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
2682 
2683     unsigned char cmdbuf[MAXFRAMELEN];
2684     int cmdlen = 0;
2685     unsigned char ackbuf[MAXFRAMELEN];
2686     int ack_len = 0;
2687 
2688     if (!(par->submod & SC_MOD_WR)) { RETURNFUNC(-RIG_EINVAL); }
2689 
2690     if ((par->submod & SC_MOD_RW12) == SC_MOD_RW12)
2691     {
2692         cmdbuf[0] = 0x01;
2693         cmdlen = 1;
2694     }
2695     else
2696     {
2697         cmdlen = par->sublen;
2698         memcpy(cmdbuf, par->subext, cmdlen);
2699     }
2700 
2701     int wrd = val.i;
2702     int i;
2703 
2704     switch (par->dattyp)
2705     {
2706     case CMD_DAT_WRD:
2707         for (i = 1; i <= par->datlen; i++)
2708         {
2709             cmdbuf[cmdlen + par->datlen - i] = wrd & 0xff;
2710             wrd >>= 8;
2711         }
2712 
2713         break;
2714 
2715     case CMD_DAT_BUF:
2716         memcpy(&cmdbuf[cmdlen], val.b.d, par->datlen);
2717         break;
2718 
2719     case CMD_DAT_INT:
2720     case CMD_DAT_BOL:
2721         to_bcd_be(&cmdbuf[cmdlen], val.i, (par->datlen * 2));
2722         break;
2723 
2724     case CMD_DAT_FLT:
2725         to_bcd_be(&cmdbuf[cmdlen], (int) val.f, (par->datlen * 2));
2726         break;
2727 
2728     case CMD_DAT_LVL:
2729         to_bcd_be(&cmdbuf[cmdlen], (int)(val.f * 255.0), (par->datlen * 2));
2730         break;
2731 
2732     case CMD_DAT_TIM: // returned as seconds since midnight
2733         to_bcd_be(&cmdbuf[cmdlen],
2734                   ((((int)val.i / 3600) * 100) + (((int)val.i / 60) % 60)), (par->datlen * 2));
2735         break;
2736 
2737     default:
2738         break;
2739     }
2740 
2741     cmdlen += par->datlen;
2742     RETURNFUNC(icom_transaction(rig, par->command, par->subcmd, cmdbuf, cmdlen,
2743                                 ackbuf,
2744                                 &ack_len));
2745 }
2746 
icom_get_cmd(RIG * rig,vfo_t vfo,struct cmdparams * par,value_t * val)2747 int icom_get_cmd(RIG *rig, vfo_t vfo, struct cmdparams *par, value_t *val)
2748 {
2749 
2750     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
2751 
2752     unsigned char ssc = 0x02;
2753     unsigned char resbuf[MAXFRAMELEN];
2754     int reslen = sizeof(resbuf);
2755     int retval;
2756 
2757     if (!(par->submod & SC_MOD_RD)) { RETURNFUNC(-RIG_EINVAL); }
2758 
2759     if ((par->submod & SC_MOD_RW12) == SC_MOD_RW12)
2760     {
2761         retval = icom_get_raw_buf(rig, par->command, par->subcmd, 1, &ssc, &reslen,
2762                                   resbuf);
2763     }
2764     else
2765     {
2766         retval = icom_get_raw_buf(rig, par->command, par->subcmd,
2767                                   par->sublen, (unsigned char *)par->subext, &reslen, resbuf);
2768     }
2769 
2770     if (retval != RIG_OK)
2771     {
2772         RETURNFUNC(retval);
2773     }
2774 
2775     switch (par->dattyp)
2776     {
2777     case CMD_DAT_WRD:
2778     {
2779         int wrd = 0;
2780         int i;
2781 
2782         for (i = 0; i < par->datlen; i++)
2783         {
2784             wrd = (wrd << 8) + resbuf[i];
2785         }
2786 
2787         val->i = wrd;
2788     }
2789     break;
2790 
2791     case CMD_DAT_STR:
2792         if (strlen(val->s) < reslen)
2793         {
2794             RETURNFUNC(-RIG_EINTERNAL);
2795         }
2796 
2797         memcpy(val->s, resbuf, reslen);
2798         val->s[reslen] = 0;
2799         break;
2800 
2801     case CMD_DAT_BUF:
2802         if (reslen > val->b.l)
2803         {
2804             RETURNFUNC(-RIG_EINTERNAL);
2805         }
2806 
2807         memcpy(val->b.d, resbuf, reslen);
2808         val->b.l = reslen;
2809         break;
2810 
2811     case CMD_DAT_INT:
2812         val->i = from_bcd_be(resbuf, (reslen * 2));
2813         break;
2814 
2815     case CMD_DAT_FLT:
2816         val->f = (float) from_bcd_be(resbuf, (reslen * 2));
2817         break;
2818 
2819     case CMD_DAT_LVL:
2820         val->f = (float) from_bcd_be(resbuf, (reslen * 2)) / 255.0;
2821         break;
2822 
2823     case CMD_DAT_BOL:
2824         val->i = (from_bcd_be(resbuf, (reslen * 2)) == 0) ? 0 : 1;
2825         break;
2826 
2827     case CMD_DAT_TIM:
2828         val->i = (from_bcd_be(resbuf, 2) * 3600) + (from_bcd_be(&resbuf[1], 2) * 60);
2829         break;
2830 
2831     default:
2832         val->i = 0;
2833         break;
2834     }
2835 
2836     RETURNFUNC(RIG_OK);
2837 }
2838 
2839 /*
2840  * icom_set_level
2841  * Assumes rig!=NULL, rig->state.priv!=NULL
2842  */
icom_set_level(RIG * rig,vfo_t vfo,setting_t level,value_t val)2843 int icom_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val)
2844 {
2845     struct rig_state *rs;
2846     unsigned char cmdbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
2847     int cmd_len, ack_len = sizeof(ackbuf);
2848     int lvl_cn, lvl_sc;       /* Command Number, Subcommand */
2849     int icom_val;
2850     int i, retval;
2851     const struct icom_priv_caps *priv_caps =
2852         (const struct icom_priv_caps *) rig->caps->priv;
2853 
2854     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
2855 
2856     const struct cmdparams *extcmds = priv_caps->extcmds;
2857 
2858     for (i = 0; extcmds && extcmds[i].id.s != 0; i++)
2859     {
2860         if (extcmds[i].cmdparamtype == CMD_PARAM_TYPE_LEVEL && extcmds[i].id.s == level)
2861         {
2862             RETURNFUNC(icom_set_cmd(rig, vfo, (struct cmdparams *)&extcmds[i], val));
2863         }
2864     }
2865 
2866     rs = &rig->state;
2867 
2868     /*
2869      * Many levels of float type are in [0.0..1.0] range
2870      */
2871     if (RIG_LEVEL_IS_FLOAT(level))
2872     {
2873         icom_val = val.f * 255;
2874     }
2875     else
2876     {
2877         icom_val = val.i;
2878     }
2879 
2880     /* convert values to 0 .. 255 range */
2881     if (rig->caps->rig_model == RIG_MODEL_ICR75)
2882     {
2883         switch (level)
2884         {
2885         case RIG_LEVEL_NR:
2886             icom_val = val.f * 240;
2887             break;
2888 
2889         case RIG_LEVEL_PBT_IN:
2890         case RIG_LEVEL_PBT_OUT:
2891             icom_val = (val.f / 10.0) + 128;
2892 
2893             if (icom_val > 255)
2894             {
2895                 icom_val = 255;
2896             }
2897 
2898             break;
2899 
2900         default:
2901             break;
2902         }
2903     }
2904 
2905     switch (level)
2906     {
2907     case RIG_LEVEL_KEYSPD:
2908         if (val.i < 6)
2909         {
2910             icom_val = 6;
2911         }
2912         else if (val.i > 48)
2913         {
2914             icom_val = 48;
2915         }
2916 
2917         icom_val = (int) lroundf(((float) icom_val - 6.0f) * (255.0f / 42.0f));
2918         break;
2919 
2920     case RIG_LEVEL_CWPITCH:
2921         if (val.i < 300)
2922         {
2923             icom_val = 300;
2924         }
2925         else if (val.i >= 900)
2926         {
2927             icom_val = 900;
2928         }
2929 
2930         icom_val = (int) lroundf(((float) icom_val - 300) * (255.0f / 600.0f));
2931         break;
2932 
2933     default:
2934         break;
2935     }
2936 
2937     /*
2938      * Most of the time, the data field is a 3 digit BCD,
2939      * but in *big endian* order: 0000..0255
2940      * (from_bcd is little endian)
2941      */
2942     cmd_len = 2;
2943     to_bcd_be(cmdbuf, (long long) icom_val, cmd_len * 2);
2944 
2945     switch (level)
2946     {
2947     case RIG_LEVEL_PREAMP:
2948         lvl_cn = C_CTL_FUNC;
2949         lvl_sc = S_FUNC_PAMP;
2950         cmd_len = 1;
2951 
2952         if (val.i == 0)
2953         {
2954             cmdbuf[0] = 0;    /* 0=OFF */
2955             break;
2956         }
2957 
2958         for (i = 0; i < HAMLIB_MAXDBLSTSIZ; i++)
2959         {
2960             if (rs->preamp[i] == val.i)
2961             {
2962                 break;
2963             }
2964         }
2965 
2966         if (i == HAMLIB_MAXDBLSTSIZ || rs->preamp[i] == 0)
2967         {
2968             rig_debug(RIG_DEBUG_ERR, "%s: unsupported preamp set_level %ddB\n",
2969                       __func__, val.i);
2970             RETURNFUNC(-RIG_EINVAL);
2971         }
2972 
2973         cmdbuf[0] = i + 1;    /* 1=P.AMP1, 2=P.AMP2 */
2974         break;
2975 
2976     case RIG_LEVEL_ATT:
2977         lvl_cn = C_CTL_ATT;
2978         /* attenuator level is dB, in BCD mode */
2979         lvl_sc = (val.i / 10) << 4 | (val.i % 10);
2980         cmd_len = 0;
2981         break;
2982 
2983     case RIG_LEVEL_AF:
2984         lvl_cn = C_CTL_LVL;
2985         lvl_sc = S_LVL_AF;
2986         break;
2987 
2988     case RIG_LEVEL_RF:
2989         lvl_cn = C_CTL_LVL;
2990         lvl_sc = S_LVL_RF;
2991         break;
2992 
2993     case RIG_LEVEL_SQL:
2994         lvl_cn = C_CTL_LVL;
2995         lvl_sc = S_LVL_SQL;
2996         break;
2997 
2998     case RIG_LEVEL_IF:
2999         lvl_cn = C_CTL_LVL;
3000         lvl_sc = S_LVL_IF;
3001         break;
3002 
3003     case RIG_LEVEL_APF:
3004         lvl_cn = C_CTL_LVL;
3005         lvl_sc = S_LVL_APF;
3006         break;
3007 
3008     case RIG_LEVEL_NR:
3009         lvl_cn = C_CTL_LVL;
3010         lvl_sc = S_LVL_NR;
3011         break;
3012 
3013     case RIG_LEVEL_NB:
3014         lvl_cn = C_CTL_LVL;
3015         lvl_sc = S_LVL_NB;
3016         break;
3017 
3018     case RIG_LEVEL_PBT_IN:
3019         lvl_cn = C_CTL_LVL;
3020         lvl_sc = S_LVL_PBTIN;
3021         break;
3022 
3023     case RIG_LEVEL_PBT_OUT:
3024         lvl_cn = C_CTL_LVL;
3025         lvl_sc = S_LVL_PBTOUT;
3026         break;
3027 
3028     case RIG_LEVEL_CWPITCH:
3029         lvl_cn = C_CTL_LVL;
3030         lvl_sc = S_LVL_CWPITCH;
3031 
3032         /* use 'set mode' call for CWPITCH on IC-R75 */
3033         if (rig->caps->rig_model == RIG_MODEL_ICR75)
3034         {
3035             lvl_cn = C_CTL_MEM;
3036             lvl_sc = S_MEM_MODE_SLCT;
3037             cmd_len = 3;
3038             cmdbuf[0] = S_PRM_CWPITCH;
3039             to_bcd_be(cmdbuf + 1, (long long) icom_val, 4);
3040         }
3041 
3042         break;
3043 
3044     case RIG_LEVEL_RFPOWER:
3045         lvl_cn = C_CTL_LVL;
3046         lvl_sc = S_LVL_RFPOWER;
3047         break;
3048 
3049     case RIG_LEVEL_MICGAIN:
3050         lvl_cn = C_CTL_LVL;
3051         lvl_sc = S_LVL_MICGAIN;
3052         break;
3053 
3054     case RIG_LEVEL_KEYSPD:
3055         lvl_cn = C_CTL_LVL;
3056         lvl_sc = S_LVL_KEYSPD;
3057         break;
3058 
3059     case RIG_LEVEL_NOTCHF_RAW:
3060         lvl_cn = C_CTL_LVL;
3061         lvl_sc = S_LVL_NOTCHF;
3062         break;
3063 
3064     case RIG_LEVEL_COMP:
3065         lvl_cn = C_CTL_LVL;
3066         lvl_sc = S_LVL_COMP;
3067         break;
3068 
3069     case RIG_LEVEL_AGC:
3070         lvl_cn = C_CTL_FUNC;
3071         lvl_sc = S_FUNC_AGC;
3072         cmd_len = 1;
3073 
3074         if (priv_caps->agc_levels_present)
3075         {
3076             int found = 0;
3077 
3078             for (i = 0;
3079                     i <= RIG_AGC_LAST && priv_caps->agc_levels[i].level >= 0; i++)
3080             {
3081                 if (priv_caps->agc_levels[i].level == val.i)
3082                 {
3083                     cmdbuf[0] = priv_caps->agc_levels[i].icom_level;
3084                     found = 1;
3085                     break;
3086                 }
3087             }
3088 
3089             if (!found)
3090             {
3091                 RETURNFUNC(-RIG_EINVAL);
3092             }
3093         }
3094         else
3095         {
3096             // Legacy mapping that does not apply to all rigs
3097             switch (val.i)
3098             {
3099             case RIG_AGC_SLOW:
3100                 cmdbuf[0] = D_AGC_SLOW;
3101                 break;
3102 
3103             case RIG_AGC_MEDIUM:
3104                 cmdbuf[0] = D_AGC_MID;
3105                 break;
3106 
3107             case RIG_AGC_FAST:
3108                 cmdbuf[0] = D_AGC_FAST;
3109                 break;
3110 
3111             case RIG_AGC_SUPERFAST:
3112                 cmdbuf[0] = D_AGC_SUPERFAST;
3113                 break;
3114 
3115             default:
3116                 rig_debug(RIG_DEBUG_ERR, "%s: unsupported LEVEL_AGC %d\n",
3117                           __func__, val.i);
3118                 RETURNFUNC(-RIG_EINVAL);
3119             }
3120         }
3121 
3122         break;
3123 
3124     case RIG_LEVEL_BKINDL:
3125         lvl_cn = C_CTL_LVL;
3126         lvl_sc = S_LVL_BKINDL;
3127         break;
3128 
3129     case RIG_LEVEL_BALANCE:
3130         lvl_cn = C_CTL_LVL;
3131         lvl_sc = S_LVL_BALANCE;
3132         break;
3133 
3134     case RIG_LEVEL_VOXGAIN:
3135         if (rig->caps->rig_model == RIG_MODEL_IC910)
3136         {
3137             /* IC-910H */
3138             lvl_cn = C_CTL_MEM;
3139             lvl_sc = S_MEM_VOXGAIN;
3140         }
3141         else
3142         {
3143             lvl_cn = C_CTL_LVL;
3144             lvl_sc = S_LVL_VOXGAIN;
3145         }
3146 
3147         break;
3148 
3149     case RIG_LEVEL_ANTIVOX:
3150         if (rig->caps->rig_model == RIG_MODEL_IC910)
3151         {
3152             /* IC-910H */
3153             lvl_cn = C_CTL_MEM;
3154             lvl_sc = S_MEM_ANTIVOX;
3155         }
3156         else
3157         {
3158             lvl_cn = C_CTL_LVL;
3159             lvl_sc = S_LVL_ANTIVOX;
3160         }
3161 
3162         break;
3163 
3164     case RIG_LEVEL_MONITOR_GAIN:
3165         lvl_cn = C_CTL_LVL;
3166         lvl_sc = S_LVL_MON;
3167         break;
3168 
3169     case RIG_LEVEL_SPECTRUM_MODE:
3170         lvl_cn = C_CTL_SCP;
3171         lvl_sc = S_SCP_MOD;
3172         cmd_len = 2;
3173 
3174         switch (val.i)
3175         {
3176         case RIG_SPECTRUM_MODE_CENTER:
3177             icom_val = SCOPE_MODE_CENTER;
3178             break;
3179 
3180         case RIG_SPECTRUM_MODE_FIXED:
3181             icom_val = SCOPE_MODE_FIXED;
3182             break;
3183 
3184         case RIG_SPECTRUM_MODE_CENTER_SCROLL:
3185             icom_val = SCOPE_MODE_SCROLL_C;
3186             break;
3187 
3188         case RIG_SPECTRUM_MODE_FIXED_SCROLL:
3189             icom_val = SCOPE_MODE_SCROLL_F;
3190             break;
3191 
3192         default:
3193             rig_debug(RIG_DEBUG_ERR, "%s: unsupported spectrum mode %d\n", __func__, val.i);
3194             RETURNFUNC(-RIG_EINVAL);
3195         }
3196 
3197         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3198         cmdbuf[1] = icom_val;
3199         break;
3200 
3201     case RIG_LEVEL_SPECTRUM_SPAN:
3202         lvl_cn = C_CTL_SCP;
3203         lvl_sc = S_SCP_SPN;
3204         cmd_len = 6;
3205 
3206         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3207         // Spectrum span is represented as a +/- value for Icom rigs
3208         to_bcd(cmdbuf + 1, val.i / 2, 5 * 2);
3209         break;
3210 
3211     case RIG_LEVEL_SPECTRUM_SPEED:
3212         lvl_cn = C_CTL_SCP;
3213         lvl_sc = S_SCP_SWP;
3214         cmd_len = 2;
3215 
3216         if (val.i < 0)
3217         {
3218             val.i = 0;
3219         }
3220         else if (val.i > 2)
3221         {
3222             val.i = 2;
3223         }
3224 
3225         switch (val.i)
3226         {
3227         case 0:
3228             icom_val = SCOPE_SPEED_SLOW;
3229             break;
3230 
3231         case 1:
3232             icom_val = SCOPE_SPEED_MID;
3233             break;
3234 
3235         case 2:
3236             icom_val = SCOPE_SPEED_FAST;
3237             break;
3238         }
3239 
3240         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3241         cmdbuf[1] = icom_val;
3242         break;
3243 
3244     case RIG_LEVEL_SPECTRUM_REF:
3245     {
3246         float icom_db = (roundf(val.f * 2.0f) / 2.0f) * 100.0f;
3247 
3248         lvl_cn = C_CTL_SCP;
3249         lvl_sc = S_SCP_REF;
3250         cmd_len = 4;
3251 
3252         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3253 
3254         // Spectrum reference level is represented at 0.01dB accuracy, but needs to be rounded to nearest 0.5dB
3255         to_bcd_be(cmdbuf + 1, abs((int) icom_db), 2 * 2);
3256 
3257         // Sign
3258         cmdbuf[3] = (icom_db < 0) ? 1 : 0;
3259         break;
3260     }
3261 
3262     case RIG_LEVEL_SPECTRUM_EDGE_LOW:
3263     case RIG_LEVEL_SPECTRUM_EDGE_HIGH:
3264     {
3265         int range_id;
3266         value_t edge_number_value;
3267         value_t opposite_edge_value;
3268         setting_t level_opposite_edge =
3269             (level == RIG_LEVEL_SPECTRUM_EDGE_LOW) ?
3270             RIG_LEVEL_SPECTRUM_EDGE_HIGH : RIG_LEVEL_SPECTRUM_EDGE_LOW;
3271 
3272         lvl_cn = C_CTL_SCP;
3273         lvl_sc = S_SCP_FEF;
3274         cmd_len = 12;
3275 
3276         // Modify the frequency range currently active
3277         retval = icom_get_spectrum_edge_frequency_range(rig, vfo, &range_id);
3278 
3279         if (retval != RIG_OK)
3280         {
3281             rig_debug(RIG_DEBUG_ERR, "%s: error getting spectrum edge frequency range\n",
3282                       __func__);
3283             RETURNFUNC(retval);
3284         }
3285 
3286         // Modify the edge number currently active
3287         retval = icom_get_ext_level(rig, vfo, TOK_SCOPE_EDG, &edge_number_value);
3288 
3289         if (retval != RIG_OK)
3290         {
3291             RETURNFUNC(retval);
3292         }
3293 
3294         // Get the current opposite edge frequency
3295         retval = icom_get_level(rig, vfo, level_opposite_edge, &opposite_edge_value);
3296 
3297         if (retval != RIG_OK)
3298         {
3299             RETURNFUNC(retval);
3300         }
3301 
3302         to_bcd(cmdbuf, range_id, 1 * 2);
3303         to_bcd(cmdbuf + 1, edge_number_value.i + 1, 1 * 2);
3304 
3305         if (level == RIG_LEVEL_SPECTRUM_EDGE_LOW)
3306         {
3307             to_bcd(cmdbuf + 2, val.i, 5 * 2);
3308             to_bcd(cmdbuf + 7, opposite_edge_value.i, 5 * 2);
3309         }
3310         else
3311         {
3312             to_bcd(cmdbuf + 2, opposite_edge_value.i, 5 * 2);
3313             to_bcd(cmdbuf + 7, val.i, 5 * 2);
3314         }
3315 
3316         break;
3317     }
3318 
3319     case RIG_LEVEL_SPECTRUM_ATT:
3320         lvl_cn = C_CTL_SCP;
3321         lvl_sc = S_SCP_ATT;
3322         cmd_len = 2;
3323 
3324         for (i = 0; i < HAMLIB_MAXDBLSTSIZ; i++)
3325         {
3326             if (rig->caps->spectrum_attenuator[i] == val.i)
3327             {
3328                 break;
3329             }
3330         }
3331 
3332         if (val.i != 0 && (i == HAMLIB_MAXDBLSTSIZ
3333                            || rig->caps->spectrum_attenuator[i] == 0))
3334         {
3335             rig_debug(RIG_DEBUG_ERR, "%s: unsupported spectrum attenuator level %ddB\n",
3336                       __func__, val.i);
3337             RETURNFUNC(-RIG_EINVAL);
3338         }
3339 
3340         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3341         to_bcd(cmdbuf + 1, val.i, 5 * 2);
3342         break;
3343 
3344     default:
3345         rig_debug(RIG_DEBUG_ERR, "%s: unsupported set_level %s\n", __func__,
3346                   rig_strlevel(level));
3347         RETURNFUNC(-RIG_EINVAL);
3348     }
3349 
3350     retval = icom_transaction(rig, lvl_cn, lvl_sc, cmdbuf, cmd_len, ackbuf,
3351                               &ack_len);
3352 
3353     if (retval != RIG_OK)
3354     {
3355         RETURNFUNC(retval);
3356     }
3357 
3358     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
3359     {
3360         //  if we don't get ACK/NAK some serial corruption occurred
3361         // so we'll call it a timeout for retry purposes
3362         RETURNFUNC(-RIG_ETIMEOUT);
3363     }
3364 
3365     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
3366     {
3367         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
3368                   ackbuf[0], ack_len);
3369         RETURNFUNC(-RIG_ERJCTED);
3370     }
3371 
3372     RETURNFUNC(RIG_OK);
3373 }
3374 
3375 /*
3376  * icom_get_level
3377  * Assumes rig!=NULL, rig->state.priv!=NULL, val!=NULL
3378  *
3379  */
icom_get_level(RIG * rig,vfo_t vfo,setting_t level,value_t * val)3380 int icom_get_level(RIG *rig, vfo_t vfo, setting_t level, value_t *val)
3381 {
3382     struct rig_state *rs;
3383     unsigned char cmdbuf[MAXFRAMELEN], respbuf[MAXFRAMELEN];
3384     int cmd_len, resp_len;
3385     int lvl_cn, lvl_sc;       /* Command Number, Subcommand */
3386     int icom_val;
3387     int cmdhead;
3388     int retval;
3389     const struct icom_priv_caps *priv_caps =
3390         (const struct icom_priv_caps *) rig->caps->priv;
3391 
3392     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
3393 
3394     const struct cmdparams *extcmds = priv_caps->extcmds;
3395     int i;
3396 
3397     for (i = 0; extcmds && extcmds[i].id.s != 0; i++)
3398     {
3399         rig_debug(RIG_DEBUG_TRACE, "%s: i=%d\n", __func__, i);
3400 
3401         if (extcmds[i].cmdparamtype == CMD_PARAM_TYPE_LEVEL && extcmds[i].id.s == level)
3402         {
3403             RETURNFUNC(icom_get_cmd(rig, vfo, (struct cmdparams *)&extcmds[i], val));
3404         }
3405     }
3406 
3407     rig_debug(RIG_DEBUG_TRACE, "%s: no extcmd found\n", __func__);
3408 
3409     rs = &rig->state;
3410 
3411     cmd_len = 0;
3412 
3413     switch (level)
3414     {
3415     case RIG_LEVEL_STRENGTH:
3416     case RIG_LEVEL_RAWSTR:
3417         lvl_cn = C_RD_SQSM;
3418         lvl_sc = S_SML;
3419         break;
3420 
3421     case RIG_LEVEL_ALC:
3422         lvl_cn = C_RD_SQSM;
3423         lvl_sc = S_ALC;
3424         break;
3425 
3426     case RIG_LEVEL_SWR:
3427         lvl_cn = C_RD_SQSM;
3428         lvl_sc = S_SWR;
3429         break;
3430 
3431     case RIG_LEVEL_RFPOWER_METER:
3432     case RIG_LEVEL_RFPOWER_METER_WATTS:
3433         lvl_cn = C_RD_SQSM;
3434         lvl_sc = S_RFML;
3435         break;
3436 
3437     case RIG_LEVEL_COMP_METER:
3438         lvl_cn = C_RD_SQSM;
3439         lvl_sc = S_CMP;
3440         break;
3441 
3442     case RIG_LEVEL_VD_METER:
3443         lvl_cn = C_RD_SQSM;
3444         lvl_sc = S_VD;
3445         break;
3446 
3447     case RIG_LEVEL_ID_METER:
3448         lvl_cn = C_RD_SQSM;
3449         lvl_sc = S_ID;
3450         break;
3451 
3452     case RIG_LEVEL_PREAMP:
3453         lvl_cn = C_CTL_FUNC;
3454         lvl_sc = S_FUNC_PAMP;
3455         break;
3456 
3457     case RIG_LEVEL_ATT:
3458         lvl_cn = C_CTL_ATT;
3459         lvl_sc = -1;
3460         break;
3461 
3462     case RIG_LEVEL_AF:
3463         lvl_cn = C_CTL_LVL;
3464         lvl_sc = S_LVL_AF;
3465         break;
3466 
3467     case RIG_LEVEL_RF:
3468         lvl_cn = C_CTL_LVL;
3469         lvl_sc = S_LVL_RF;
3470         break;
3471 
3472     case RIG_LEVEL_SQL:
3473         lvl_cn = C_CTL_LVL;
3474         lvl_sc = S_LVL_SQL;
3475         break;
3476 
3477     case RIG_LEVEL_IF:
3478         lvl_cn = C_CTL_LVL;
3479         lvl_sc = S_LVL_IF;
3480         break;
3481 
3482     case RIG_LEVEL_APF:
3483         lvl_cn = C_CTL_LVL;
3484         lvl_sc = S_LVL_APF;
3485         break;
3486 
3487     case RIG_LEVEL_NR:
3488         lvl_cn = C_CTL_LVL;
3489         lvl_sc = S_LVL_NR;
3490         break;
3491 
3492     case RIG_LEVEL_NB:
3493         lvl_cn = C_CTL_LVL;
3494         lvl_sc = S_LVL_NB;
3495         break;
3496 
3497     case RIG_LEVEL_PBT_IN:
3498         lvl_cn = C_CTL_LVL;
3499         lvl_sc = S_LVL_PBTIN;
3500         break;
3501 
3502     case RIG_LEVEL_PBT_OUT:
3503         lvl_cn = C_CTL_LVL;
3504         lvl_sc = S_LVL_PBTOUT;
3505         break;
3506 
3507     case RIG_LEVEL_CWPITCH:
3508         lvl_cn = C_CTL_LVL;
3509         lvl_sc = S_LVL_CWPITCH;
3510 
3511         /* use 'set mode' call for CWPITCH on IC-R75 */
3512         if (rig->caps->rig_model == RIG_MODEL_ICR75)
3513         {
3514             lvl_cn = C_CTL_MEM;
3515             lvl_sc = S_MEM_MODE_SLCT;
3516             cmd_len = 1;
3517             cmdbuf[0] = S_PRM_CWPITCH;
3518         }
3519 
3520         break;
3521 
3522     case RIG_LEVEL_RFPOWER:
3523         lvl_cn = C_CTL_LVL;
3524         lvl_sc = S_LVL_RFPOWER;
3525         break;
3526 
3527     case RIG_LEVEL_MICGAIN:
3528         lvl_cn = C_CTL_LVL;
3529         lvl_sc = S_LVL_MICGAIN;
3530         break;
3531 
3532     case RIG_LEVEL_KEYSPD:
3533         lvl_cn = C_CTL_LVL;
3534         lvl_sc = S_LVL_KEYSPD;
3535         break;
3536 
3537     case RIG_LEVEL_NOTCHF_RAW:
3538         lvl_cn = C_CTL_LVL;
3539         lvl_sc = S_LVL_NOTCHF;
3540         break;
3541 
3542     case RIG_LEVEL_COMP:
3543         lvl_cn = C_CTL_LVL;
3544         lvl_sc = S_LVL_COMP;
3545         break;
3546 
3547     case RIG_LEVEL_AGC:
3548         lvl_cn = C_CTL_FUNC;
3549         lvl_sc = S_FUNC_AGC;
3550         break;
3551 
3552     case RIG_LEVEL_BKINDL:
3553         lvl_cn = C_CTL_LVL;
3554         lvl_sc = S_LVL_BKINDL;
3555         break;
3556 
3557     case RIG_LEVEL_BALANCE:
3558         lvl_cn = C_CTL_LVL;
3559         lvl_sc = S_LVL_BALANCE;
3560         break;
3561 
3562     case RIG_LEVEL_VOXGAIN: /* IC-910H */
3563         if (rig->caps->rig_model == RIG_MODEL_IC910)
3564         {
3565             /* IC-910H */
3566             lvl_cn = C_CTL_MEM;
3567             lvl_sc = S_MEM_VOXGAIN;
3568         }
3569         else
3570         {
3571             lvl_cn = C_CTL_LVL;
3572             lvl_sc = S_LVL_VOXGAIN;
3573         }
3574 
3575         break;
3576 
3577     case RIG_LEVEL_ANTIVOX:
3578         if (rig->caps->rig_model == RIG_MODEL_IC910)
3579         {
3580             /* IC-910H */
3581             lvl_cn = C_CTL_MEM;
3582             lvl_sc = S_MEM_ANTIVOX;
3583         }
3584         else
3585         {
3586             lvl_cn = C_CTL_LVL;
3587             lvl_sc = S_LVL_ANTIVOX;
3588         }
3589 
3590         break;
3591 
3592     case RIG_LEVEL_MONITOR_GAIN:
3593         lvl_cn = C_CTL_LVL;
3594         lvl_sc = S_LVL_MON;
3595         break;
3596 
3597     case RIG_LEVEL_SPECTRUM_MODE:
3598         lvl_cn = C_CTL_SCP;
3599         lvl_sc = S_SCP_MOD;
3600         cmd_len = 1;
3601         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3602         break;
3603 
3604     case RIG_LEVEL_SPECTRUM_SPAN:
3605         lvl_cn = C_CTL_SCP;
3606         lvl_sc = S_SCP_SPN;
3607 
3608         cmd_len = 1;
3609         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3610         break;
3611 
3612     case RIG_LEVEL_SPECTRUM_SPEED:
3613         lvl_cn = C_CTL_SCP;
3614         lvl_sc = S_SCP_SWP;
3615 
3616         cmd_len = 1;
3617         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3618         break;
3619 
3620     case RIG_LEVEL_SPECTRUM_REF:
3621         lvl_cn = C_CTL_SCP;
3622         lvl_sc = S_SCP_REF;
3623 
3624         cmd_len = 1;
3625         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3626         break;
3627 
3628     case RIG_LEVEL_SPECTRUM_EDGE_LOW:
3629     case RIG_LEVEL_SPECTRUM_EDGE_HIGH:
3630     {
3631         int range_id;
3632         value_t edge_number_value;
3633 
3634         lvl_cn = C_CTL_SCP;
3635         lvl_sc = S_SCP_FEF;
3636         cmd_len = 2;
3637 
3638         // Get the frequency range currently active
3639         retval = icom_get_spectrum_edge_frequency_range(rig, vfo, &range_id);
3640 
3641         if (retval != RIG_OK)
3642         {
3643             rig_debug(RIG_DEBUG_ERR, "%s: error getting spectrum edge frequency range\n",
3644                       __func__);
3645             RETURNFUNC(retval);
3646         }
3647 
3648         // Get the edge number currently active
3649         retval = icom_get_ext_level(rig, vfo, TOK_SCOPE_EDG, &edge_number_value);
3650 
3651         if (retval != RIG_OK)
3652         {
3653             RETURNFUNC(retval);
3654         }
3655 
3656         to_bcd(cmdbuf, range_id, 1 * 2);
3657         to_bcd(cmdbuf + 1, edge_number_value.i + 1, 1 * 2);
3658         break;
3659     }
3660 
3661     case RIG_LEVEL_SPECTRUM_ATT:
3662         lvl_cn = C_CTL_SCP;
3663         lvl_sc = S_SCP_ATT;
3664         cmd_len = 1;
3665 
3666         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
3667         break;
3668 
3669     default:
3670         rig_debug(RIG_DEBUG_ERR, "%s: unsupported get_level %s\n", __func__,
3671                   rig_strlevel(level));
3672         RETURNFUNC(-RIG_EINVAL);
3673     }
3674 
3675     /* use cmdbuf and cmd_len for 'set mode' subcommand */
3676     retval = icom_transaction(rig, lvl_cn, lvl_sc, cmdbuf, cmd_len, respbuf,
3677                               &resp_len);
3678 
3679     if (retval != RIG_OK)
3680     {
3681         RETURNFUNC(retval);
3682     }
3683 
3684     /*
3685      * strbuf should contain Cn,Sc,Data area
3686      */
3687     cmdhead = ((lvl_sc == -1) ? 1 : 2) + cmd_len;
3688     resp_len -= cmdhead;
3689 
3690     if (respbuf[0] != lvl_cn)
3691     {
3692         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
3693                   respbuf[0], resp_len);
3694         RETURNFUNC(-RIG_ERJCTED);
3695     }
3696 
3697     /*
3698      * The result is a 3 digit BCD, but in *big endian* order: 0000..0255
3699      * (from_bcd is little endian)
3700      */
3701     icom_val = from_bcd_be(respbuf + cmdhead, resp_len * 2);
3702 
3703     switch (level)
3704     {
3705     case RIG_LEVEL_STRENGTH:
3706         val->i = round(rig_raw2val(icom_val, &rig->caps->str_cal));
3707         break;
3708 
3709     case RIG_LEVEL_RAWSTR:
3710         /* raw value */
3711         val->i = icom_val;
3712         break;
3713 
3714     case RIG_LEVEL_AGC:
3715         if (priv_caps->agc_levels_present)
3716         {
3717             int found = 0;
3718 
3719             for (i = 0;
3720                     i <= RIG_AGC_LAST && priv_caps->agc_levels[i].level >= 0; i++)
3721             {
3722                 if (priv_caps->agc_levels[i].icom_level == icom_val)
3723                 {
3724                     val->i = priv_caps->agc_levels[i].level;
3725                     found = 1;
3726                     break;
3727                 }
3728             }
3729 
3730             if (!found)
3731             {
3732                 rig_debug(RIG_DEBUG_ERR, "%s: unexpected AGC 0x%02x\n", __func__,
3733                           icom_val);
3734                 RETURNFUNC(-RIG_EPROTO);
3735             }
3736         }
3737         else
3738         {
3739             switch (icom_val)
3740             {
3741             case D_AGC_SLOW:
3742                 val->i = RIG_AGC_SLOW;
3743                 break;
3744 
3745             case D_AGC_MID:
3746                 val->i = RIG_AGC_MEDIUM;
3747                 break;
3748 
3749             case D_AGC_FAST:
3750                 val->i = RIG_AGC_FAST;
3751                 break;
3752 
3753             case D_AGC_SUPERFAST:
3754                 val->i = RIG_AGC_SUPERFAST;
3755                 break;
3756 
3757             default:
3758                 rig_debug(RIG_DEBUG_ERR, "%s: unexpected AGC 0x%02x\n", __func__,
3759                           icom_val);
3760                 RETURNFUNC(-RIG_EPROTO);
3761             }
3762         }
3763 
3764         break;
3765 
3766     case RIG_LEVEL_ALC:
3767         if (rig->caps->alc_cal.size == 0)
3768         {
3769             val->f = rig_raw2val_float(icom_val, &icom_default_alc_cal);
3770         }
3771         else
3772         {
3773             val->f = rig_raw2val_float(icom_val, &rig->caps->alc_cal);
3774         }
3775 
3776         break;
3777 
3778     case RIG_LEVEL_SWR:
3779         if (rig->caps->swr_cal.size == 0)
3780         {
3781             val->f = rig_raw2val_float(icom_val, &icom_default_swr_cal);
3782         }
3783         else
3784         {
3785             val->f = rig_raw2val_float(icom_val, &rig->caps->swr_cal);
3786         }
3787 
3788         break;
3789 
3790     case RIG_LEVEL_RFPOWER_METER:
3791 
3792         // rig table in Watts needs to be divided by 100
3793         if (rig->caps->rfpower_meter_cal.size == 0)
3794         {
3795             val->f =
3796                 rig_raw2val_float(icom_val, &icom_default_rfpower_meter_cal) * 0.01;
3797         }
3798         else
3799         {
3800             val->f =
3801                 rig_raw2val_float(icom_val, &rig->caps->rfpower_meter_cal) * 0.01;
3802         }
3803 
3804         break;
3805 
3806     case RIG_LEVEL_RFPOWER_METER_WATTS:
3807 
3808         // All Icom backends should be in Watts now
3809         if (rig->caps->rfpower_meter_cal.size == 0)
3810         {
3811             val->f =
3812                 rig_raw2val_float(icom_val, &icom_default_rfpower_meter_cal);
3813             rig_debug(RIG_DEBUG_TRACE, "%s: using rig table to convert %d to %.01f\n",
3814                       __func__, icom_val, val->f);
3815         }
3816         else
3817         {
3818             val->f =
3819                 rig_raw2val_float(icom_val, &rig->caps->rfpower_meter_cal);
3820             rig_debug(RIG_DEBUG_TRACE,
3821                       "%s: using default icom table to convert %d to %.01f\n", __func__, icom_val,
3822                       val->f);
3823         }
3824 
3825         break;
3826 
3827     case RIG_LEVEL_COMP_METER:
3828         if (rig->caps->comp_meter_cal.size == 0)
3829         {
3830             val->f = rig_raw2val_float(icom_val, &icom_default_comp_meter_cal);
3831         }
3832         else
3833         {
3834             val->f = rig_raw2val_float(icom_val, &rig->caps->comp_meter_cal);
3835         }
3836 
3837         break;
3838 
3839     case RIG_LEVEL_VD_METER:
3840         if (rig->caps->vd_meter_cal.size == 0)
3841         {
3842             val->f = rig_raw2val_float(icom_val, &icom_default_vd_meter_cal);
3843         }
3844         else
3845         {
3846             val->f = rig_raw2val_float(icom_val, &rig->caps->vd_meter_cal);
3847         }
3848 
3849         break;
3850 
3851     case RIG_LEVEL_ID_METER:
3852         if (rig->caps->id_meter_cal.size == 0)
3853         {
3854             val->f = rig_raw2val_float(icom_val, &icom_default_id_meter_cal);
3855         }
3856         else
3857         {
3858             val->f = rig_raw2val_float(icom_val, &rig->caps->id_meter_cal);
3859         }
3860 
3861         break;
3862 
3863     case RIG_LEVEL_CWPITCH:
3864         val->i = (int) lroundf(300.0f + ((float) icom_val * 600.0f / 255.0f));
3865         break;
3866 
3867     case RIG_LEVEL_KEYSPD:
3868         val->i = (int) lroundf((float) icom_val * (42.0f / 255.0f) + 6.0f);
3869         break;
3870 
3871     case RIG_LEVEL_PREAMP:
3872         if (icom_val == 0)
3873         {
3874             val->i = 0;
3875             break;
3876         }
3877 
3878         if (icom_val > HAMLIB_MAXDBLSTSIZ || rs->preamp[icom_val - 1] == 0)
3879         {
3880             rig_debug(RIG_DEBUG_ERR, "%s: unsupported preamp get_level %ddB\n",
3881                       __func__, icom_val);
3882             RETURNFUNC(-RIG_EPROTO);
3883         }
3884 
3885         val->i = rs->preamp[icom_val - 1];
3886         break;
3887 
3888     case RIG_LEVEL_SPECTRUM_MODE:
3889         switch (icom_val)
3890         {
3891         case SCOPE_MODE_CENTER:
3892             val->i = RIG_SPECTRUM_MODE_CENTER;
3893             break;
3894 
3895         case SCOPE_MODE_FIXED:
3896             val->i = RIG_SPECTRUM_MODE_FIXED;
3897             break;
3898 
3899         case SCOPE_MODE_SCROLL_C:
3900             val->i = RIG_SPECTRUM_MODE_CENTER_SCROLL;
3901             break;
3902 
3903         case SCOPE_MODE_SCROLL_F:
3904             val->i = RIG_SPECTRUM_MODE_FIXED_SCROLL;
3905             break;
3906 
3907         default:
3908             rig_debug(RIG_DEBUG_ERR, "%s: unsupported spectrum mode %d\n", __func__,
3909                       icom_val);
3910             RETURNFUNC(-RIG_EINVAL);
3911         }
3912 
3913         break;
3914 
3915     case RIG_LEVEL_SPECTRUM_SPAN:
3916         icom_val = (int) from_bcd(respbuf + cmdhead, resp_len * 2);
3917         // Spectrum span is represented as a +/- value for Icom rigs
3918         val->i = icom_val * 2;
3919         break;
3920 
3921     case RIG_LEVEL_SPECTRUM_SPEED:
3922         switch (icom_val)
3923         {
3924         case SCOPE_SPEED_SLOW:
3925             val->i = 0;
3926             break;
3927 
3928         case SCOPE_SPEED_MID:
3929             val->i = 1;
3930             break;
3931 
3932         case SCOPE_SPEED_FAST:
3933             val->i = 2;
3934             break;
3935 
3936         default:
3937             rig_debug(RIG_DEBUG_ERR, "%s: unsupported spectrum speed %d\n", __func__,
3938                       icom_val);
3939             RETURNFUNC(-RIG_EINVAL);
3940         }
3941 
3942         break;
3943 
3944     case RIG_LEVEL_SPECTRUM_REF:
3945     {
3946         unsigned char *icom_ref = respbuf + cmdhead;
3947 
3948         // Spectrum reference level is represented at 0.01dB accuracy, but is rounded to nearest 0.5dB
3949         float db = (float) from_bcd_be(icom_ref, 2 * 2) / 100.0f;
3950 
3951         // Sign
3952         if (icom_ref[2] != 0)
3953         {
3954             db = -db;
3955         }
3956 
3957         val->f = db;
3958         break;
3959     }
3960 
3961     case RIG_LEVEL_SPECTRUM_EDGE_LOW:
3962         val->i = (int) from_bcd(respbuf + cmdhead, 5 * 2);
3963         break;
3964 
3965     case RIG_LEVEL_SPECTRUM_EDGE_HIGH:
3966         val->i = (int) from_bcd(respbuf + cmdhead + 5, 5 * 2);
3967         break;
3968 
3969     /* RIG_LEVEL_ATT/RIG_LEVEL_SPECTRUM_ATT: returned value is already an integer in dB (coded in BCD) */
3970     default:
3971         if (RIG_LEVEL_IS_FLOAT(level))
3972         {
3973             val->f = (float) icom_val / 255;
3974         }
3975         else
3976         {
3977             val->i = icom_val;
3978         }
3979     }
3980 
3981     /* convert values from 0 .. 255 range */
3982     if (rig->caps->rig_model == RIG_MODEL_ICR75)
3983     {
3984         switch (level)
3985         {
3986         case RIG_LEVEL_NR:
3987             val->f = (float) icom_val / 240;
3988             break;
3989 
3990         case RIG_LEVEL_PBT_IN:
3991         case RIG_LEVEL_PBT_OUT:
3992             if (icom_val == 255)
3993             {
3994                 val->f = 1280.0;
3995             }
3996             else
3997             {
3998                 val->f = (float)(icom_val - 128) * 10.0;
3999             }
4000 
4001             break;
4002 
4003         default:
4004             break;
4005         }
4006     }
4007 
4008     rig_debug(RIG_DEBUG_TRACE, "%s: %d %d %d %f\n", __func__, resp_len,
4009               icom_val, val->i, val->f);
4010 
4011     RETURNFUNC(RIG_OK);
4012 }
4013 
icom_set_ext_level(RIG * rig,vfo_t vfo,token_t token,value_t val)4014 int icom_set_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t val)
4015 {
4016     const struct confparams *cfp = rig->caps->extlevels;
4017     unsigned char cmdbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
4018     int cmd_len, ack_len = sizeof(ackbuf);
4019     int lvl_cn, lvl_sc;       /* Command Number, Subcommand */
4020     int i, retval;
4021 
4022     rig_debug(RIG_DEBUG_VERBOSE, "%s called: token=%ld int=%d float=%f\n", __func__,
4023               token, val.i, val.f);
4024 
4025     switch (token)
4026     {
4027     case TOK_SCOPE_MSS:
4028         if (val.i < 0 || val.i > 1)
4029         {
4030             RETURNFUNC(-RIG_EINVAL);
4031         }
4032 
4033         lvl_cn = C_CTL_SCP;
4034         lvl_sc = S_SCP_MSS;
4035         cmd_len = 1;
4036         cmdbuf[0] = val.i;
4037         break;
4038 
4039     case TOK_SCOPE_SDS:
4040         if (val.i < 0 || val.i > 1)
4041         {
4042             RETURNFUNC(-RIG_EINVAL);
4043         }
4044 
4045         lvl_cn = C_CTL_SCP;
4046         lvl_sc = S_SCP_SDS;
4047         cmd_len = 1;
4048         cmdbuf[0] = val.i;
4049         break;
4050 
4051     case TOK_SCOPE_STX:
4052 
4053         // TODO: Should be a func?
4054         if (val.i < 0 || val.i > 1)
4055         {
4056             RETURNFUNC(-RIG_EINVAL);
4057         }
4058 
4059         lvl_cn = C_CTL_SCP;
4060         lvl_sc = S_SCP_STX;
4061         cmd_len = 1;
4062         cmdbuf[0] = val.i;
4063         break;
4064 
4065     case TOK_SCOPE_CFQ:
4066         if (val.i < 0 || val.i > 2)
4067         {
4068             RETURNFUNC(-RIG_EINVAL);
4069         }
4070 
4071         lvl_cn = C_CTL_SCP;
4072         lvl_sc = S_SCP_CFQ;
4073         cmd_len = 1;
4074         cmdbuf[0] = val.i;
4075         break;
4076 
4077     case TOK_SCOPE_EDG:
4078         if (val.i < 0 || val.i > 3)
4079         {
4080             RETURNFUNC(-RIG_EINVAL);
4081         }
4082 
4083         lvl_cn = C_CTL_SCP;
4084         lvl_sc = S_SCP_EDG;
4085         cmd_len = 2;
4086         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
4087         cmdbuf[1] = val.i + 1;
4088         break;
4089 
4090     case TOK_SCOPE_VBW:
4091         if (val.i < 0 || val.i > 1)
4092         {
4093             RETURNFUNC(-RIG_EINVAL);
4094         }
4095 
4096         lvl_cn = C_CTL_SCP;
4097         lvl_sc = S_SCP_VBW;
4098         cmd_len = 2;
4099         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
4100         cmdbuf[1] = val.i;
4101         break;
4102 
4103     case TOK_SCOPE_RBW:
4104         if (val.i < 0 || val.i > 2)
4105         {
4106             RETURNFUNC(-RIG_EINVAL);
4107         }
4108 
4109         lvl_cn = C_CTL_SCP;
4110         lvl_sc = S_SCP_RBW;
4111         cmd_len = 2;
4112         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
4113         cmdbuf[1] = val.i;
4114         break;
4115 
4116     default:
4117         cfp = (cfp == NULL) ? icom_ext_levels : cfp;
4118 
4119         for (i = 0; (cfp[i].token != RIG_CONF_END) || (cfp != icom_ext_levels);)
4120         {
4121             if (cfp[i].token == RIG_CONF_END)
4122             {
4123                 cfp = icom_ext_levels;
4124                 i = 0;
4125             }
4126             else if (cfp[i].token == token)
4127             {
4128                 RETURNFUNC(icom_set_ext_cmd(rig, vfo, token, val));
4129             }
4130             else { i++; }
4131         }
4132 
4133         rig_debug(RIG_DEBUG_ERR, "%s: unsupported set_ext_level token: %ld\n", __func__,
4134                   token);
4135         RETURNFUNC(-RIG_EINVAL);
4136     }
4137 
4138     retval = icom_transaction(rig, lvl_cn, lvl_sc, cmdbuf, cmd_len, ackbuf,
4139                               &ack_len);
4140 
4141     if (retval != RIG_OK)
4142     {
4143         RETURNFUNC(retval);
4144     }
4145 
4146     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
4147     {
4148         // if we don't get ACK/NAK some serial corruption occurred
4149         // so we'll call it a timeout for retry purposes
4150         RETURNFUNC(-RIG_ETIMEOUT);
4151     }
4152 
4153     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
4154     {
4155         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
4156                   ackbuf[0], ack_len);
4157         RETURNFUNC(-RIG_ERJCTED);
4158     }
4159 
4160     RETURNFUNC(RIG_OK);
4161 }
4162 
icom_get_ext_level(RIG * rig,vfo_t vfo,token_t token,value_t * val)4163 int icom_get_ext_level(RIG *rig, vfo_t vfo, token_t token, value_t *val)
4164 {
4165     const struct confparams *cfp = rig->caps->extlevels;
4166     unsigned char cmdbuf[MAXFRAMELEN], respbuf[MAXFRAMELEN];
4167     int cmd_len, resp_len;
4168     int lvl_cn, lvl_sc;       /* Command Number, Subcommand */
4169     int icom_val;
4170     int cmdhead;
4171     int retval;
4172     int i;
4173 
4174     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4175 
4176     cmd_len = 0;
4177     lvl_sc = -1;
4178 
4179     switch (token)
4180     {
4181     case TOK_SCOPE_MSS:
4182         lvl_cn = C_CTL_SCP;
4183         lvl_sc = S_SCP_MSS;
4184         break;
4185 
4186     case TOK_SCOPE_SDS:
4187         lvl_cn = C_CTL_SCP;
4188         lvl_sc = S_SCP_SDS;
4189         break;
4190 
4191     case TOK_SCOPE_STX:
4192         // TODO: Should be a func?
4193         lvl_cn = C_CTL_SCP;
4194         lvl_sc = S_SCP_STX;
4195         break;
4196 
4197     case TOK_SCOPE_CFQ:
4198         lvl_cn = C_CTL_SCP;
4199         lvl_sc = S_SCP_CFQ;
4200         break;
4201 
4202     case TOK_SCOPE_EDG:
4203         lvl_cn = C_CTL_SCP;
4204         lvl_sc = S_SCP_EDG;
4205         cmd_len = 1;
4206         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
4207         break;
4208 
4209     case TOK_SCOPE_VBW:
4210         lvl_cn = C_CTL_SCP;
4211         lvl_sc = S_SCP_VBW;
4212         cmd_len = 1;
4213         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
4214         break;
4215 
4216     case TOK_SCOPE_RBW:
4217         lvl_cn = C_CTL_SCP;
4218         lvl_sc = S_SCP_RBW;
4219         cmd_len = 1;
4220         cmdbuf[0] = icom_get_spectrum_vfo(rig, vfo);
4221         break;
4222 
4223     default:
4224         cfp = (cfp == NULL) ? icom_ext_levels : cfp;
4225 
4226         for (i = 0; (cfp[i].token != RIG_CONF_END) || (cfp != icom_ext_levels);)
4227         {
4228             if (cfp[i].token == RIG_CONF_END)
4229             {
4230                 cfp = icom_ext_levels;
4231                 i = 0;
4232             }
4233             else if (cfp[i].token == token)
4234             {
4235                 RETURNFUNC(icom_get_ext_cmd(rig, vfo, token, val));
4236             }
4237             else { i++; }
4238         }
4239 
4240         rig_debug(RIG_DEBUG_ERR, "%s: unsupported get_ext_level token: %ld\n", __func__,
4241                   token);
4242         RETURNFUNC(-RIG_EINVAL);
4243     }
4244 
4245     /* use cmdbuf and cmd_len for 'set mode' subcommand */
4246     retval = icom_transaction(rig, lvl_cn, lvl_sc, cmdbuf, cmd_len, respbuf,
4247                               &resp_len);
4248 
4249     if (retval != RIG_OK)
4250     {
4251         RETURNFUNC(retval);
4252     }
4253 
4254     cmdhead = ((lvl_sc == -1) ? 1 : 2) + cmd_len;
4255     resp_len -= cmdhead;
4256 
4257     if (respbuf[0] != lvl_cn)
4258     {
4259         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
4260                   respbuf[0], resp_len);
4261         RETURNFUNC(-RIG_ERJCTED);
4262     }
4263 
4264     icom_val = from_bcd_be(respbuf + cmdhead, resp_len * 2);
4265 
4266     switch (token)
4267     {
4268     case TOK_SCOPE_EDG:
4269         val->i = icom_val - 1;
4270         break;
4271 
4272     default:
4273         val->i = icom_val;
4274         break;
4275     }
4276 
4277     rig_debug(RIG_DEBUG_TRACE, "%s: %d %d %d %f\n", __func__, resp_len,
4278               icom_val, val->i, val->f);
4279 
4280     RETURNFUNC(RIG_OK);
4281 }
4282 
icom_set_ext_func(RIG * rig,vfo_t vfo,token_t token,int status)4283 int icom_set_ext_func(RIG *rig, vfo_t vfo, token_t token, int status)
4284 {
4285     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4286 
4287     const struct confparams *cfp = rig->caps->extfuncs;
4288     cfp = (cfp == NULL) ? icom_ext_funcs : cfp;
4289     int i;
4290 
4291     for (i = 0; (cfp[i].token != RIG_CONF_END) || (cfp != icom_ext_funcs);)
4292     {
4293         if (cfp[i].token == RIG_CONF_END)
4294         {
4295             cfp = icom_ext_funcs;
4296             i = 0;
4297         }
4298         else if (cfp[i].token == token)
4299         {
4300             value_t value = { .i = status };
4301             RETURNFUNC(icom_set_ext_cmd(rig, vfo, token, value));
4302         }
4303         else { i++; }
4304     }
4305 
4306     RETURNFUNC(-RIG_EINVAL);
4307 }
4308 
icom_get_ext_func(RIG * rig,vfo_t vfo,token_t token,int * status)4309 int icom_get_ext_func(RIG *rig, vfo_t vfo, token_t token, int *status)
4310 {
4311     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4312 
4313     const struct confparams *cfp = rig->caps->extfuncs;
4314     cfp = (cfp == NULL) ? icom_ext_funcs : cfp;
4315     int i;
4316 
4317     for (i = 0; (cfp[i].token != RIG_CONF_END) || (cfp != icom_ext_funcs);)
4318     {
4319         if (cfp[i].token == RIG_CONF_END)
4320         {
4321             cfp = icom_ext_funcs;
4322             i = 0;
4323         }
4324         else if (cfp[i].token == token)
4325         {
4326             value_t value;
4327             int result = icom_get_ext_cmd(rig, vfo, token, &value);
4328 
4329             if (result == RIG_OK)
4330             {
4331                 *status = value.i;
4332             }
4333 
4334             RETURNFUNC(result);
4335         }
4336         else { i++; }
4337     }
4338 
4339     RETURNFUNC(-RIG_EINVAL);
4340 }
4341 
icom_set_ext_parm(RIG * rig,token_t token,value_t val)4342 int icom_set_ext_parm(RIG *rig, token_t token, value_t val)
4343 {
4344     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4345 
4346     const struct confparams *cfp = rig->caps->extparms;
4347     cfp = (cfp == NULL) ? icom_ext_parms : cfp;
4348     int i;
4349 
4350     for (i = 0; (cfp[i].token != RIG_CONF_END) || (cfp != icom_ext_parms);)
4351     {
4352         if (cfp[i].token == RIG_CONF_END)
4353         {
4354             cfp = icom_ext_parms;
4355             i = 0;
4356         }
4357         else if (cfp[i].token == token)
4358         {
4359             RETURNFUNC(icom_set_ext_cmd(rig, RIG_VFO_NONE, token, val));
4360         }
4361         else { i++; }
4362     }
4363 
4364     RETURNFUNC(-RIG_EINVAL);
4365 }
4366 
icom_get_ext_parm(RIG * rig,token_t token,value_t * val)4367 int icom_get_ext_parm(RIG *rig, token_t token, value_t *val)
4368 {
4369     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4370 
4371     const struct confparams *cfp = rig->caps->extparms;
4372     cfp = (cfp == NULL) ? icom_ext_parms : cfp;
4373     int i;
4374 
4375     for (i = 0; (cfp[i].token != RIG_CONF_END) || (cfp != icom_ext_parms);)
4376     {
4377         if (cfp[i].token == RIG_CONF_END)
4378         {
4379             cfp = icom_ext_parms;
4380             i = 0;
4381         }
4382         else if (cfp[i].token == token)
4383         {
4384             RETURNFUNC(icom_get_ext_cmd(rig, RIG_VFO_NONE, token, val));
4385         }
4386         else { i++; }
4387     }
4388 
4389     RETURNFUNC(-RIG_EINVAL);
4390 }
4391 
icom_get_ext_cmd(RIG * rig,vfo_t vfo,token_t token,value_t * val)4392 int icom_get_ext_cmd(RIG *rig, vfo_t vfo, token_t token, value_t *val)
4393 {
4394     int i;
4395 
4396     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4397 
4398     for (i = 0; rig->caps->ext_tokens
4399             && rig->caps->ext_tokens[i] != TOK_BACKEND_NONE; i++)
4400     {
4401         if (rig->caps->ext_tokens[i] == token)
4402         {
4403             const struct icom_priv_caps *priv = rig->caps->priv;
4404             const struct cmdparams *cmd = priv->extcmds ? priv->extcmds : icom_ext_cmd;
4405 
4406             for (i = 0; (cmd[i].id.t != 0) || (cmd != icom_ext_cmd);)
4407             {
4408                 if (cmd[i].id.t == 0)
4409                 {
4410                     cmd = icom_ext_cmd;
4411                     i = 0;
4412                 }
4413                 else if (cmd[i].cmdparamtype == CMD_PARAM_TYPE_TOKEN && cmd[i].id.t == token)
4414                 {
4415                     RETURNFUNC(icom_get_cmd(rig, vfo, (struct cmdparams *)&cmd[i], val));
4416                 }
4417                 else { i++; }
4418             }
4419 
4420             RETURNFUNC(-RIG_EINVAL);
4421         }
4422     }
4423 
4424     RETURNFUNC(-RIG_EINVAL);
4425 }
4426 
icom_set_ext_cmd(RIG * rig,vfo_t vfo,token_t token,value_t val)4427 int icom_set_ext_cmd(RIG *rig, vfo_t vfo, token_t token, value_t val)
4428 {
4429     int i;
4430 
4431     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4432 
4433     for (i = 0; rig->caps->ext_tokens
4434             && rig->caps->ext_tokens[i] != TOK_BACKEND_NONE; i++)
4435     {
4436         if (rig->caps->ext_tokens[i] == token)
4437         {
4438             const struct icom_priv_caps *priv = rig->caps->priv;
4439             const struct cmdparams *cmd = priv->extcmds ? priv->extcmds : icom_ext_cmd;
4440 
4441             for (i = 0; (cmd[i].id.t != 0) || (cmd != icom_ext_cmd);)
4442             {
4443                 if (cmd[i].id.t == 0)
4444                 {
4445                     cmd = icom_ext_cmd;
4446                     i = 0;
4447                 }
4448                 else if (cmd->cmdparamtype == CMD_PARAM_TYPE_TOKEN && cmd[i].id.t == token)
4449                 {
4450                     RETURNFUNC(icom_set_cmd(rig, vfo, (struct cmdparams *)&cmd[i], val));
4451                 }
4452                 else { i++; }
4453             }
4454 
4455             RETURNFUNC(-RIG_EINVAL);
4456         }
4457     }
4458 
4459     RETURNFUNC(-RIG_EINVAL);
4460 }
4461 
4462 /*
4463  * Assumes rig!=NULL, rig->state.priv!=NULL
4464  */
icom_set_conf(RIG * rig,token_t token,const char * val)4465 int icom_set_conf(RIG *rig, token_t token, const char *val)
4466 {
4467     struct icom_priv_data *priv;
4468     struct rig_state *rs;
4469 
4470     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4471     rs = &rig->state;
4472     priv = (struct icom_priv_data *) rs->priv;
4473 
4474     switch (token)
4475     {
4476     case TOK_CIVADDR:
4477         if (val[0] == '0' && val[1] == 'x')
4478         {
4479             priv->re_civ_addr = strtol(val, (char **) NULL, 16);
4480         }
4481         else
4482         {
4483             priv->re_civ_addr = atoi(val);
4484         }
4485 
4486         break;
4487 
4488     case TOK_MODE731:
4489         priv->civ_731_mode = atoi(val) ? 1 : 0;
4490         break;
4491 
4492     case TOK_NOXCHG:
4493         priv->no_xchg = atoi(val) ? 1 : 0;
4494         break;
4495 
4496     default:
4497         RETURNFUNC(-RIG_EINVAL);
4498     }
4499 
4500     RETURNFUNC(RIG_OK);
4501 }
4502 
4503 /*
4504  * assumes rig!=NULL,
4505  * Assumes rig!=NULL, rig->state.priv!=NULL
4506  *  and val points to a buffer big enough to hold the conf value.
4507  */
icom_get_conf(RIG * rig,token_t token,char * val)4508 int icom_get_conf(RIG *rig, token_t token, char *val)
4509 {
4510     struct icom_priv_data *priv;
4511     struct rig_state *rs;
4512 
4513     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4514     rs = &rig->state;
4515     priv = (struct icom_priv_data *) rs->priv;
4516 
4517     switch (token)
4518     {
4519     case TOK_CIVADDR:
4520         sprintf(val, "%d", priv->re_civ_addr);
4521         break;
4522 
4523     case TOK_MODE731: sprintf(val, "%d", priv->civ_731_mode);
4524         break;
4525 
4526     case TOK_NOXCHG: sprintf(val, "%d", priv->no_xchg);
4527         break;
4528 
4529     default: RETURNFUNC(-RIG_EINVAL);
4530     }
4531 
4532     RETURNFUNC(RIG_OK);
4533 }
4534 
4535 
4536 /*
4537  * icom_set_ptt
4538  * Assumes rig!=NULL, rig->state.priv!=NULL
4539  */
icom_set_ptt(RIG * rig,vfo_t vfo,ptt_t ptt)4540 int icom_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt)
4541 {
4542     unsigned char ackbuf[MAXFRAMELEN], pttbuf[1];
4543     int ack_len = sizeof(ackbuf), retval;
4544 
4545     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4546     pttbuf[0] = ptt == RIG_PTT_ON ? 1 : 0;
4547 
4548     retval = icom_transaction(rig, C_CTL_PTT, S_PTT, pttbuf, 1,
4549                               ackbuf, &ack_len);
4550 
4551     if (retval != RIG_OK)
4552     {
4553         RETURNFUNC(retval);
4554     }
4555 
4556     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
4557     {
4558         //  if we don't get ACK/NAK some serial corruption occurred
4559         // so we'll call it a timeout for retry purposes
4560         RETURNFUNC(-RIG_ETIMEOUT);
4561     }
4562 
4563     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
4564     {
4565         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
4566                   ackbuf[0], ack_len);
4567         RETURNFUNC(-RIG_ERJCTED);
4568     }
4569 
4570     RETURNFUNC(RIG_OK);
4571 }
4572 
4573 /*
4574  * icom_get_ptt
4575  * Assumes rig!=NULL, rig->state.priv!=NULL, ptt!=NULL
4576  */
icom_get_ptt(RIG * rig,vfo_t vfo,ptt_t * ptt)4577 int icom_get_ptt(RIG *rig, vfo_t vfo, ptt_t *ptt)
4578 {
4579     unsigned char pttbuf[MAXFRAMELEN];
4580     int ptt_len, retval;
4581 
4582     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4583     retval = icom_transaction(rig, C_CTL_PTT, S_PTT, NULL, 0,
4584                               pttbuf, &ptt_len);
4585 
4586     if (retval != RIG_OK)
4587     {
4588         RETURNFUNC(retval);
4589     }
4590 
4591     /*
4592      * pttbuf should contain Cn,Sc,Data area
4593      */
4594     ptt_len -= 2;
4595 
4596     if (ptt_len != 1)
4597     {
4598         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n",
4599                   __func__, ptt_len);
4600         RETURNFUNC(-RIG_ERJCTED);
4601     }
4602 
4603     *ptt = pttbuf[2] == 1 ? RIG_PTT_ON : RIG_PTT_OFF;
4604 
4605     RETURNFUNC(RIG_OK);
4606 }
4607 
4608 /*
4609  * icom_get_dcd
4610  * Assumes rig!=NULL, rig->state.priv!=NULL, ptt!=NULL
4611  */
icom_get_dcd(RIG * rig,vfo_t vfo,dcd_t * dcd)4612 int icom_get_dcd(RIG *rig, vfo_t vfo, dcd_t *dcd)
4613 {
4614     unsigned char dcdbuf[MAXFRAMELEN];
4615     int dcd_len, retval;
4616 
4617     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4618     retval = icom_transaction(rig, C_RD_SQSM, S_SQL, NULL, 0,
4619                               dcdbuf, &dcd_len);
4620 
4621     if (retval != RIG_OK)
4622     {
4623         RETURNFUNC(retval);
4624     }
4625 
4626     /*
4627      * dcdbuf should contain Cn,Data area
4628      */
4629     dcd_len -= 2;
4630 
4631     if (dcd_len != 1)
4632     {
4633         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n",
4634                   __func__, dcd_len);
4635         RETURNFUNC(-RIG_ERJCTED);
4636     }
4637 
4638     /*
4639      * 0x00=sql closed, 0x01=sql open
4640      */
4641 
4642     *dcd = dcdbuf[2] == 1 ? RIG_DCD_ON : RIG_DCD_OFF;
4643 
4644     RETURNFUNC(RIG_OK);
4645 }
4646 
4647 /*
4648  * icom_set_rptr_shift
4649  * Assumes rig!=NULL, rig->state.priv!=NULL
4650  */
icom_set_rptr_shift(RIG * rig,vfo_t vfo,rptr_shift_t rptr_shift)4651 int icom_set_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t rptr_shift)
4652 {
4653     unsigned char ackbuf[MAXFRAMELEN];
4654     int ack_len = sizeof(ackbuf), retval;
4655     int rptr_sc;
4656 
4657     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4658 
4659     switch (rptr_shift)
4660     {
4661     case RIG_RPT_SHIFT_NONE:
4662         rptr_sc = S_DUP_OFF;  /* Simplex mode */
4663         break;
4664 
4665     case RIG_RPT_SHIFT_MINUS:
4666         rptr_sc = S_DUP_M;    /* Duplex - mode */
4667         break;
4668 
4669     case RIG_RPT_SHIFT_PLUS:
4670         rptr_sc = S_DUP_P;    /* Duplex + mode */
4671         break;
4672 
4673     default:
4674         rig_debug(RIG_DEBUG_ERR, "%s: unsupported shift %d\n", __func__,
4675                   rptr_shift);
4676         RETURNFUNC(-RIG_EINVAL);
4677     }
4678 
4679     retval = icom_transaction(rig, C_CTL_SPLT, rptr_sc, NULL, 0,
4680                               ackbuf, &ack_len);
4681 
4682     if (retval != RIG_OK)
4683     {
4684         RETURNFUNC(retval);
4685     }
4686 
4687     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
4688     {
4689         //  if we don't get ACK/NAK some serial corruption occurred
4690         // so we'll call it a timeout for retry purposes
4691         RETURNFUNC(-RIG_ETIMEOUT);
4692     }
4693 
4694     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
4695     {
4696         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
4697                   ackbuf[0], ack_len);
4698         RETURNFUNC(-RIG_ERJCTED);
4699     }
4700 
4701     RETURNFUNC(RIG_OK);
4702 }
4703 
4704 
4705 /*
4706  * icom_get_rptr_shift
4707  * Assumes rig!=NULL, rig->state.priv!=NULL, rptr_shift!=NULL
4708  * will not work for IC-746 Pro
4709  * NOTE: seems not to work (tested on IC-706MkIIG), please report --SF
4710  */
icom_get_rptr_shift(RIG * rig,vfo_t vfo,rptr_shift_t * rptr_shift)4711 int icom_get_rptr_shift(RIG *rig, vfo_t vfo, rptr_shift_t *rptr_shift)
4712 {
4713     unsigned char rptrbuf[MAXFRAMELEN];
4714     int rptr_len, retval;
4715 
4716     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4717     retval = icom_transaction(rig, C_CTL_SPLT, -1, NULL, 0,
4718                               rptrbuf, &rptr_len);
4719 
4720     if (retval != RIG_OK)
4721     {
4722         RETURNFUNC(retval);
4723     }
4724 
4725     /*
4726      * rptrbuf should contain Cn,Sc
4727      */
4728     rptr_len--;
4729 
4730     if (rptr_len != 1)
4731     {
4732         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n",
4733                   __func__, rptr_len);
4734         RETURNFUNC(-RIG_ERJCTED);
4735     }
4736 
4737     switch (rptrbuf[1])
4738     {
4739     case S_DUP_OFF:
4740     case S_DUP_DD_RPS:
4741         *rptr_shift = RIG_RPT_SHIFT_NONE; /* Simplex mode */
4742         break;
4743 
4744     case S_DUP_M:
4745         *rptr_shift = RIG_RPT_SHIFT_MINUS;    /* Duplex - mode */
4746         break;
4747 
4748     case S_DUP_P:
4749         *rptr_shift = RIG_RPT_SHIFT_PLUS; /* Duplex + mode */
4750         break;
4751 
4752     // The same command indicates split state, which means simplex mode
4753     case S_SPLT_OFF:
4754     case S_SPLT_ON:
4755         *rptr_shift = RIG_RPT_SHIFT_NONE; /* Simplex mode */
4756         break;
4757 
4758     default:
4759         rig_debug(RIG_DEBUG_ERR, "%s: unsupported shift %d\n", __func__,
4760                   rptrbuf[1]);
4761         RETURNFUNC(-RIG_EPROTO);
4762     }
4763 
4764     RETURNFUNC(RIG_OK);
4765 }
4766 
4767 /*
4768  * icom_set_rptr_offs
4769  * Assumes rig!=NULL, rig->state.priv!=NULL
4770  */
icom_set_rptr_offs(RIG * rig,vfo_t vfo,shortfreq_t rptr_offs)4771 int icom_set_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t rptr_offs)
4772 {
4773     int offs_len;
4774     unsigned char offsbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
4775     int ack_len = sizeof(ackbuf), retval;
4776     const struct icom_priv_caps *priv_caps;
4777 
4778     priv_caps = (const struct icom_priv_caps *) rig->caps->priv;
4779     offs_len = (priv_caps->offs_len) ? priv_caps->offs_len : OFFS_LEN;
4780 
4781     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4782     /*
4783      * Icoms are using a 100Hz unit (at least on 706MKIIg) -- SF
4784      */
4785     to_bcd(offsbuf, rptr_offs / 100, offs_len * 2);
4786 
4787     retval = icom_transaction(rig, C_SET_OFFS, -1, offsbuf, offs_len,
4788                               ackbuf, &ack_len);
4789 
4790     if (retval != RIG_OK)
4791     {
4792         RETURNFUNC(retval);
4793     }
4794 
4795     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
4796     {
4797         //  if we don't get ACK/NAK some serial corruption occurred
4798         // so we'll call it a timeout for retry purposes
4799         RETURNFUNC(-RIG_ETIMEOUT);
4800     }
4801 
4802     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
4803     {
4804         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
4805                   ackbuf[0], ack_len);
4806         RETURNFUNC(-RIG_ERJCTED);
4807     }
4808 
4809     RETURNFUNC(RIG_OK);
4810 }
4811 
4812 
4813 /*
4814  * icom_get_rptr_offs
4815  * Assumes rig!=NULL, rig->state.priv!=NULL, rptr_offs!=NULL
4816  */
icom_get_rptr_offs(RIG * rig,vfo_t vfo,shortfreq_t * rptr_offs)4817 int icom_get_rptr_offs(RIG *rig, vfo_t vfo, shortfreq_t *rptr_offs)
4818 {
4819     int offs_len;
4820     unsigned char offsbuf[MAXFRAMELEN];
4821     int buf_len, retval;
4822     const struct icom_priv_caps *priv_caps;
4823 
4824     priv_caps = (const struct icom_priv_caps *) rig->caps->priv;
4825     offs_len = (priv_caps->offs_len) ? priv_caps->offs_len : OFFS_LEN;
4826 
4827     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4828     retval = icom_transaction(rig, C_RD_OFFS, -1, NULL, 0, offsbuf, &buf_len);
4829 
4830     if (retval != RIG_OK)
4831     {
4832         RETURNFUNC(retval);
4833     }
4834 
4835     /*
4836      * offsbuf should contain Cn
4837      */
4838     buf_len--;
4839 
4840     if (buf_len != offs_len)
4841     {
4842         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n", __func__,
4843                   buf_len);
4844         RETURNFUNC(-RIG_ERJCTED);
4845     }
4846 
4847     /*
4848      * Icoms are using a 100Hz unit (at least on 706MKIIg) -- SF
4849      */
4850     *rptr_offs = from_bcd(offsbuf + 1, buf_len * 2) * 100;
4851 
4852     RETURNFUNC(RIG_OK);
4853 }
4854 
4855 /*
4856  * Helper function to go back and forth split VFO
4857  */
icom_get_split_vfos(RIG * rig,vfo_t * rx_vfo,vfo_t * tx_vfo)4858 int icom_get_split_vfos(RIG *rig, vfo_t *rx_vfo, vfo_t *tx_vfo)
4859 {
4860     struct icom_priv_data *priv;
4861     struct rig_state *rs;
4862 
4863     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
4864 
4865     rs = (struct rig_state *) &rig->state;
4866     priv = (struct icom_priv_data *) rs->priv;
4867 
4868 
4869     if (VFO_HAS_A_B_ONLY)
4870     {
4871         *rx_vfo = *tx_vfo = RIG_VFO_A;
4872 
4873         if (priv->split_on)
4874         {
4875             *rx_vfo = RIG_VFO_A;
4876             *tx_vfo = RIG_VFO_B;  /* rig doesn't enforce this but
4877                    convention is needed here */
4878         }
4879 
4880         rig_debug(RIG_DEBUG_TRACE, "%s: VFO_HAS_A_B_ONLY, split=%d, rx=%s, tx=%s\n",
4881                   __func__,
4882                   priv->split_on, rig_strvfo(*rx_vfo), rig_strvfo(*tx_vfo));
4883     }
4884     else if (VFO_HAS_MAIN_SUB_ONLY)
4885     {
4886         *rx_vfo = *tx_vfo = RIG_VFO_MAIN;
4887 
4888         if (priv->split_on)
4889         {
4890             *rx_vfo = RIG_VFO_MAIN;
4891             *tx_vfo = RIG_VFO_SUB;
4892         }
4893 
4894         rig_debug(RIG_DEBUG_TRACE,
4895                   "%s: VFO_HAS_MAIN_SUB_ONLY, split=%d, rx=%s, tx=%s\n",
4896                   __func__, priv->split_on, rig_strvfo(*rx_vfo), rig_strvfo(*tx_vfo));
4897     }
4898     else if (VFO_HAS_MAIN_SUB_A_B_ONLY)
4899     {
4900         int satmode = 0;
4901 
4902         // e.g. IC9700 split on Main/Sub does not work
4903         // only Main VFOA/B and SubRx/MainTx split works
4904         if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
4905         {
4906             // satmode defaults to 0 -- only call if we need to
4907             rig_get_func((RIG *)rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode);
4908         }
4909 
4910         rig->state.cache.satmode = satmode;
4911 
4912         // don't care about retval here...only care about satmode=1
4913         if (satmode)
4914         {
4915             *rx_vfo = priv->rx_vfo = RIG_VFO_MAIN;
4916             *tx_vfo = priv->tx_vfo = RIG_VFO_SUB;
4917         }
4918         else if (priv->split_on)
4919         {
4920             *rx_vfo = priv->rx_vfo = RIG_VFO_A;
4921             *tx_vfo = priv->tx_vfo = RIG_VFO_B;
4922         }
4923         else
4924         {
4925             *rx_vfo = priv->rx_vfo = RIG_VFO_A;
4926             *tx_vfo = priv->tx_vfo = RIG_VFO_A;
4927         }
4928 
4929         rig_debug(RIG_DEBUG_TRACE,
4930                   "%s: VFO_HAS_MAIN_SUB_A_B_ONLY, split=%d, rx=%s, tx=%s\n",
4931                   __func__, priv->split_on, rig_strvfo(*rx_vfo), rig_strvfo(*tx_vfo));
4932     }
4933     else
4934     {
4935         rig_debug(RIG_DEBUG_ERR, "%s invalid vfo setup?\n", __func__);
4936         RETURNFUNC(-RIG_ENAVAIL);
4937     }
4938 
4939     RETURNFUNC(RIG_OK);
4940 }
4941 
4942 /*
4943  * icom_set_split_freq
4944  * Assumes rig!=NULL, rig->state.priv!=NULL,
4945  *  icom_set_vfo,icom_set_freq works for this rig
4946  *
4947  * Assumes also that the current VFO is the rx VFO.
4948  */
icom_set_split_freq(RIG * rig,vfo_t vfo,freq_t tx_freq)4949 int icom_set_split_freq(RIG *rig, vfo_t vfo, freq_t tx_freq)
4950 {
4951     int retval;
4952     vfo_t rx_vfo, tx_vfo;
4953     struct icom_priv_data *priv;
4954     struct rig_state *rs;
4955     unsigned char ackbuf[MAXFRAMELEN];
4956     int ack_len = sizeof(ackbuf);
4957 
4958     rig_debug(RIG_DEBUG_VERBOSE, "%s called for %s\n", __func__, rig_strvfo(vfo));
4959     rs = &rig->state;
4960     priv = (struct icom_priv_data *) rs->priv;
4961     rig_debug(RIG_DEBUG_VERBOSE, "%s: curr_vfo=%s\n", __func__,
4962               rig_strvfo(rig->state.current_vfo));
4963 
4964     rig_debug(RIG_DEBUG_VERBOSE, "%s: satmode=%d, subvfo=%s\n", __func__,
4965               rig->state.cache.satmode, rig_strvfo(priv->tx_vfo));
4966 
4967     if (vfo == RIG_VFO_TX)
4968     {
4969         if (rig->state.cache.satmode) { vfo = RIG_VFO_SUB; }
4970         else { vfo = priv->tx_vfo; }
4971     }
4972 
4973     rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo is now %s\n", __func__, rig_strvfo(vfo));
4974 
4975     if (rig->state.cache.satmode && vfo == RIG_VFO_TX) { vfo = RIG_VFO_SUB; }
4976 
4977     if (rig->state.current_vfo == RIG_VFO_NONE)
4978     {
4979         retval = icom_set_default_vfo(rig);
4980 
4981         if (retval != RIG_OK)
4982         {
4983             rig_debug(RIG_DEBUG_ERR, "%s: set_default_vfo failed: %s\n", __func__,
4984                       rigerror(retval));
4985             RETURNFUNC(retval);
4986         }
4987     }
4988 
4989 #if 0
4990     TRACE;
4991     retval = set_vfo_curr(rig, RIG_VFO_TX, RIG_VFO_TX);
4992 
4993     if (retval != RIG_OK)
4994     {
4995         rig_debug(RIG_DEBUG_ERR, "%s: set_default_vfo failed: %s\n", __func__,
4996                   rigerror(retval));
4997         RETURNFUNC(retval);
4998     }
4999 
5000 #endif
5001 
5002     // If the rigs supports the 0x25 command we'll use it
5003     // This eliminates VFO swapping and improves split operations
5004     if (priv->x25cmdfails == 0)
5005     {
5006         int satmode = 0;
5007 
5008         // retval not important here...only satmode=1 means anything
5009         if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
5010         {
5011             rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode);
5012         }
5013 
5014         rig->state.cache.satmode = satmode;
5015         rig_debug(RIG_DEBUG_VERBOSE, "%s: satmode=%d\n", __func__, satmode);
5016 
5017         if (satmode == 0) // only worth trying if not in satmode
5018         {
5019             int cmd, subcmd, freq_len;
5020             unsigned char freqbuf[32];
5021             freq_len = priv->civ_731_mode ? 4 : 5;
5022             /*
5023              * to_bcd requires nibble len
5024              */
5025             to_bcd(freqbuf, tx_freq, freq_len * 2);
5026 
5027             cmd = C_SEND_SEL_FREQ;
5028             subcmd = 0x01; // set the unselected vfo
5029 
5030             // if we're already on the tx_vfo don't need the "other" vfo
5031             if (rig->state.current_vfo == rig->state.tx_vfo)
5032             {
5033                 subcmd = 0x00;
5034             }
5035 
5036             retval = icom_transaction(rig, cmd, subcmd, freqbuf, freq_len, ackbuf,
5037                                       &ack_len);
5038 
5039             if (retval == RIG_OK) // then we're done!!
5040             {
5041                 RETURNFUNC(retval);
5042             }
5043         }
5044 
5045         priv->x25cmdfails = 1;
5046     }
5047 
5048 
5049     if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG))
5050     {
5051         rig_debug(RIG_DEBUG_TRACE, "%s: Using XCHG to swap/set/swap\n", __func__);
5052 
5053         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5054         {
5055             RETURNFUNC(retval);
5056         }
5057 
5058         if (RIG_OK != (retval = icom_set_freq(rig, RIG_VFO_CURR, tx_freq)))
5059         {
5060             RETURNFUNC(retval);
5061         }
5062 
5063         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5064         {
5065             RETURNFUNC(retval);
5066         }
5067 
5068         RETURNFUNC(retval);
5069     }
5070 
5071     /* In the case of rigs with an A/B VFO arrangement we assume the
5072        current VFO is VFO A and the split Tx VFO is always VFO B. These
5073        assumptions allow us to deal with the lack of VFO and split
5074        queries */
5075     if (VFO_HAS_A_B_ONLY
5076             && priv->split_on)   /* broken if user changes split on rig :( */
5077     {
5078         /* VFO A/B style rigs swap VFO on split Tx so we need to disable
5079            split for certainty */
5080         if (RIG_OK !=
5081                 (retval =
5082                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf,
5083                                       &ack_len)))
5084         {
5085             RETURNFUNC(retval);
5086         }
5087 
5088         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
5089         {
5090             //  if we don't get ACK/NAK some serial corruption occurred
5091             // so we'll call it a timeout for retry purposes
5092             RETURNFUNC(-RIG_ETIMEOUT);
5093         }
5094 
5095         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
5096         {
5097             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
5098                       ackbuf[0], ack_len);
5099             RETURNFUNC(-RIG_ERJCTED);
5100         }
5101     }
5102 
5103     if (RIG_OK != (retval = icom_get_split_vfos(rig, &rx_vfo, &tx_vfo)))
5104     {
5105         RETURNFUNC(retval);
5106     }
5107 
5108     rig_debug(RIG_DEBUG_TRACE, "%s: rx_vfo=%s, tx_vfo=%s\n", __func__,
5109               rig_strvfo(rx_vfo), rig_strvfo(tx_vfo));
5110 
5111     TRACE;
5112 
5113     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_FREQ)
5114             && RIG_OK != (retval = rig_set_vfo(rig, tx_vfo)))
5115     {
5116         RETURNFUNC(retval);
5117     }
5118 
5119     if (RIG_OK != (retval = rig_set_freq(rig, tx_vfo, tx_freq)))
5120     {
5121         RETURNFUNC(retval);
5122     }
5123 
5124     TRACE;
5125 
5126     if (VFO_HAS_MAIN_SUB_A_B_ONLY)
5127     {
5128         // Then we return the VFO to the rx_vfo
5129         rig_debug(RIG_DEBUG_TRACE, "%s: SATMODE split_on=%d rig so setting vfo to %s\n",
5130                   __func__,
5131                   priv->split_on, rig_strvfo(rx_vfo));
5132 
5133         TRACE;
5134 
5135         if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_FREQ)
5136                 && RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5137         {
5138             RETURNFUNC(retval);
5139         }
5140     }
5141     else if (RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5142     {
5143         TRACE;
5144         RETURNFUNC(retval);
5145     }
5146 
5147     if (VFO_HAS_A_B_ONLY && priv->split_on)
5148     {
5149         /* Re-enable split */
5150         if (RIG_OK !=
5151                 (retval =
5152                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf,
5153                                       &ack_len)))
5154         {
5155             RETURNFUNC(retval);
5156         }
5157     }
5158 
5159     // Update our internal freqs to match what we just did
5160     if (vfo == RIG_VFO_MAIN)
5161     {
5162         priv->main_freq = tx_freq;
5163     }
5164     else if (vfo == RIG_VFO_SUB)
5165     {
5166         priv->sub_freq = tx_freq;
5167     }
5168 
5169     RETURNFUNC(retval);
5170 }
5171 
5172 /*
5173  * icom_get_split_freq
5174  * Assumes rig!=NULL, rig->state.priv!=NULL, rx_freq!=NULL, tx_freq!=NULL
5175  *  icom_set_vfo,icom_get_freq works for this rig
5176  */
icom_get_split_freq(RIG * rig,vfo_t vfo,freq_t * tx_freq)5177 int icom_get_split_freq(RIG *rig, vfo_t vfo, freq_t *tx_freq)
5178 {
5179     int retval;
5180     vfo_t rx_vfo, tx_vfo;
5181     struct icom_priv_data *priv;
5182     struct rig_state *rs;
5183     unsigned char ackbuf[MAXFRAMELEN];
5184     int ack_len = sizeof(ackbuf);
5185 
5186     rig_debug(RIG_DEBUG_VERBOSE, "%s called %s\n", __func__, rig_strvfo(vfo));
5187 
5188     rs = &rig->state;
5189     priv = (struct icom_priv_data *) rs->priv;
5190     rig_debug(RIG_DEBUG_VERBOSE, "%s: curr_vfo=%s\n", __func__,
5191               rig_strvfo(rig->state.current_vfo));
5192 
5193 
5194     if (rig->caps->rig_model == RIG_MODEL_IC910)
5195     {
5196         ptt_t ptt;
5197         rig_debug(RIG_DEBUG_VERBOSE, "%s: ic910#2\n", __func__);
5198         retval = rig_get_ptt(rig, RIG_VFO_CURR, &ptt);
5199 
5200         if (retval != RIG_OK)
5201         {
5202             RETURNFUNC(retval);
5203         }
5204 
5205         if (ptt)
5206         {
5207             rig_debug(RIG_DEBUG_TRACE, "%s: ptt is on so returning last known freq\n",
5208                       __func__);
5209             *tx_freq = priv->vfob_freq;
5210             RETURNFUNC(RIG_OK);
5211         }
5212     }
5213 
5214     rig_debug(RIG_DEBUG_VERBOSE, "%s curr_vfo=%s\n", __func__,
5215               rig_strvfo(rig->state.current_vfo));
5216 
5217     if (rig->state.current_vfo == RIG_VFO_NONE)
5218     {
5219         icom_set_default_vfo(rig);
5220     }
5221 
5222     // If the rigs supports the 0x25 command we'll use it
5223     // This eliminates VFO swapping and improves split operations
5224     // This does not work in satellite mode for the 9700
5225     if (priv->x25cmdfails == 0)
5226     {
5227         int cmd, subcmd;
5228         int satmode = 0;
5229 
5230         // don't care about the retval here..only satmode=1 is important
5231         if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
5232         {
5233             rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode);
5234         }
5235 
5236         rig->state.cache.satmode = satmode;
5237         rig_debug(RIG_DEBUG_VERBOSE, "%s: satmode=%d\n", __func__, satmode);
5238 
5239         if (satmode == 0) // only worth trying if not in satmode
5240         {
5241             if (priv->x25cmdfails == 0)
5242             {
5243                 int retry_save = rs->rigport.retry;
5244                 rs->rigport.retry = 0;
5245                 cmd = C_SEND_SEL_FREQ;
5246                 subcmd = 0x01; // get the unselected vfo
5247                 retval = icom_transaction(rig, cmd, subcmd, NULL, 0, ackbuf,
5248                                           &ack_len);
5249 
5250                 rs->rigport.retry = retry_save;
5251 
5252                 if (retval == RIG_OK) // then we're done!!
5253                 {
5254                     *tx_freq = from_bcd(ackbuf + 2, (priv->civ_731_mode ? 4 : 5) * 2);
5255                     RETURNFUNC(retval);
5256                 }
5257 
5258                 priv->x25cmdfails = 1;
5259             }
5260         }
5261         else   // we're in satmode so we try another command
5262         {
5263             if (priv->x1cx03cmdfails == 0)
5264             {
5265                 cmd = 0x1c;
5266                 subcmd = 0x03;
5267                 retval = icom_transaction(rig, cmd, subcmd, NULL, 0, ackbuf,
5268                                           &ack_len);
5269 
5270                 if (retval == RIG_OK) // then we're done!!
5271                 {
5272                     *tx_freq = from_bcd(&ackbuf[2], (priv->civ_731_mode ? 4 : 5) * 2);
5273                     RETURNFUNC(retval);
5274                 }
5275 
5276                 priv->x1cx03cmdfails = 1;
5277             }
5278         }
5279 
5280     }
5281 
5282     /* This method works also in memory mode(RIG_VFO_MEM) */
5283     if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG))
5284     {
5285         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5286         {
5287             RETURNFUNC(retval);
5288         }
5289 
5290         if (RIG_OK != (retval = rig_get_freq(rig, RIG_VFO_CURR, tx_freq)))
5291         {
5292             RETURNFUNC(retval);
5293         }
5294 
5295         priv->vfob_freq = *tx_freq;
5296 
5297         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5298         {
5299             RETURNFUNC(retval);
5300         }
5301 
5302         RETURNFUNC(retval);
5303     }
5304 
5305     /* In the case of rigs with an A/B VFO arrangement we assume the
5306        current VFO is VFO A and the split Tx VFO is always VFO B. These
5307        assumptions allow us to deal with the lack of VFO and split
5308        queries */
5309     if (VFO_HAS_A_B_ONLY
5310             && priv->split_on)   /* broken if user changes split on rig :( */
5311     {
5312         /* VFO A/B style rigs swap VFO on split Tx so we need to disable
5313            split for certainty */
5314         if (RIG_OK !=
5315                 (retval =
5316                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf,
5317                                       &ack_len)))
5318         {
5319             RETURNFUNC(retval);
5320         }
5321 
5322         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
5323         {
5324             //  if we don't get ACK/NAK some serial corruption occurred
5325             // so we'll call it a timeout for retry purposes
5326             RETURNFUNC(-RIG_ETIMEOUT);
5327         }
5328 
5329         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
5330         {
5331             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
5332                       ackbuf[0], ack_len);
5333             RETURNFUNC(-RIG_ERJCTED);
5334         }
5335     }
5336 
5337     if (RIG_OK != (retval = icom_get_split_vfos(rig, &rx_vfo, &tx_vfo)))
5338     {
5339         RETURNFUNC(retval);
5340     }
5341 
5342     TRACE;
5343 
5344     if (RIG_OK != (retval = rig_set_vfo(rig, tx_vfo)))
5345     {
5346         RETURNFUNC(retval);
5347     }
5348 
5349     if (RIG_OK != (retval = rig_get_freq(rig, tx_vfo, tx_freq)))
5350     {
5351         RETURNFUNC(retval);
5352     }
5353 
5354     TRACE;
5355 
5356     if (VFO_HAS_MAIN_SUB_A_B_ONLY)
5357     {
5358         // Then we return the VFO to where it was
5359         rig_debug(RIG_DEBUG_TRACE, "%s: SATMODE rig so returning vfo to %s\n", __func__,
5360                   rig_strvfo(rx_vfo));
5361 
5362         TRACE;
5363 
5364         if (RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5365         {
5366             RETURNFUNC(retval);
5367         }
5368     }
5369     else if (RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5370     {
5371         TRACE;
5372         RETURNFUNC(retval);
5373     }
5374 
5375     if (VFO_HAS_A_B_ONLY && priv->split_on)
5376     {
5377         /* Re-enable split */
5378         if (RIG_OK !=
5379                 (retval =
5380                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf,
5381                                       &ack_len)))
5382         {
5383             RETURNFUNC(retval);
5384         }
5385     }
5386 
5387     priv->vfob_freq = *tx_freq;
5388     RETURNFUNC(retval);
5389 }
5390 
5391 /*
5392  * icom_set_split_mode
5393  * Assumes rig!=NULL, rig->state.priv!=NULL,
5394  *  icom_set_vfo,icom_set_mode works for this rig
5395  */
icom_set_split_mode(RIG * rig,vfo_t vfo,rmode_t tx_mode,pbwidth_t tx_width)5396 int icom_set_split_mode(RIG *rig, vfo_t vfo, rmode_t tx_mode,
5397                         pbwidth_t tx_width)
5398 {
5399     int retval;
5400     vfo_t rx_vfo, tx_vfo;
5401     struct icom_priv_data *priv;
5402     struct rig_state *rs;
5403     unsigned char ackbuf[MAXFRAMELEN];
5404     int ack_len = sizeof(ackbuf);
5405 
5406     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
5407     rs = &rig->state;
5408     priv = (struct icom_priv_data *) rs->priv;
5409 
5410     /* This method works also in memory mode(RIG_VFO_MEM) */
5411     if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG))
5412     {
5413         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5414         {
5415             RETURNFUNC(retval);
5416         }
5417 
5418         if (RIG_OK != (retval = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode,
5419                                 tx_width)))
5420         {
5421             RETURNFUNC(retval);
5422         }
5423 
5424         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5425         {
5426             RETURNFUNC(retval);
5427         }
5428 
5429         RETURNFUNC(retval);
5430     }
5431 
5432     /* In the case of rigs with an A/B VFO arrangement we assume the
5433        current VFO is VFO A and the split Tx VFO is always VFO B. These
5434        assumptions allow us to deal with the lack of VFO and split
5435        queries */
5436     if (VFO_HAS_A_B_ONLY
5437             && priv->split_on)   /* broken if user changes split on rig :( */
5438     {
5439         /* VFO A/B style rigs swap VFO on split Tx so we need to disable
5440            split for certainty */
5441         if (RIG_OK !=
5442                 (retval =
5443                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf,
5444                                       &ack_len)))
5445         {
5446             RETURNFUNC(retval);
5447         }
5448 
5449         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
5450         {
5451             //  if we don't get ACK/NAK some serial corruption occurred
5452             // so we'll call it a timeout for retry purposes
5453             RETURNFUNC(-RIG_ETIMEOUT);
5454         }
5455 
5456         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
5457         {
5458             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
5459                       ackbuf[0], ack_len);
5460             RETURNFUNC(-RIG_ERJCTED);
5461         }
5462     }
5463 
5464     if (RIG_OK != (retval = icom_get_split_vfos(rig, &rx_vfo, &tx_vfo)))
5465     {
5466         RETURNFUNC(retval);
5467     }
5468 
5469     TRACE;
5470 
5471     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
5472             && RIG_OK != (retval = rig_set_vfo(rig, tx_vfo)))
5473     {
5474         RETURNFUNC(retval);
5475     }
5476 
5477     if (RIG_OK != (retval = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode,
5478                             tx_width)))
5479     {
5480         RETURNFUNC(retval);
5481     }
5482 
5483     TRACE;
5484 
5485     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
5486             && RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5487     {
5488         RETURNFUNC(retval);
5489     }
5490 
5491     if (VFO_HAS_A_B_ONLY && priv->split_on)
5492     {
5493         /* Re-enable split */
5494         if (RIG_OK !=
5495                 (retval =
5496                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf,
5497                                       &ack_len)))
5498         {
5499             RETURNFUNC(retval);
5500         }
5501     }
5502 
5503     RETURNFUNC(retval);
5504 }
5505 
5506 /*
5507  * icom_get_split_mode
5508  * Assumes rig!=NULL, rig->state.priv!=NULL,
5509  *  rx_mode!=NULL, rx_width!=NULL, tx_mode!=NULL, tx_width!=NULL
5510  *  icom_set_vfo,icom_get_mode works for this rig
5511  */
icom_get_split_mode(RIG * rig,vfo_t vfo,rmode_t * tx_mode,pbwidth_t * tx_width)5512 int icom_get_split_mode(RIG *rig, vfo_t vfo, rmode_t *tx_mode,
5513                         pbwidth_t *tx_width)
5514 {
5515     int retval;
5516     vfo_t rx_vfo, tx_vfo;
5517     struct icom_priv_data *priv;
5518     struct rig_state *rs;
5519     unsigned char ackbuf[MAXFRAMELEN];
5520     int ack_len = sizeof(ackbuf);
5521 
5522     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
5523     rs = &rig->state;
5524     priv = (struct icom_priv_data *) rs->priv;
5525 
5526     /* This method works also in memory mode(RIG_VFO_MEM) */
5527     if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG))
5528     {
5529         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5530         {
5531             RETURNFUNC(retval);
5532         }
5533 
5534         if (RIG_OK != (retval = rig->caps->get_mode(rig, RIG_VFO_CURR, tx_mode,
5535                                 tx_width)))
5536         {
5537             RETURNFUNC(retval);
5538         }
5539 
5540         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5541         {
5542             RETURNFUNC(retval);
5543         }
5544 
5545         RETURNFUNC(retval);
5546     }
5547 
5548     /* In the case of rigs with an A/B VFO arrangement we assume the
5549        current VFO is VFO A and the split Tx VFO is always VFO B. These
5550        assumptions allow us to deal with the lack of VFO and split
5551        queries */
5552     if (VFO_HAS_A_B_ONLY
5553             && priv->split_on)   /* broken if user changes split on rig :( */
5554     {
5555         /* VFO A/B style rigs swap VFO on split Tx so we need to disable
5556            split for certainty */
5557         if (RIG_OK !=
5558                 (retval =
5559                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf,
5560                                       &ack_len)))
5561         {
5562             RETURNFUNC(retval);
5563         }
5564 
5565         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
5566         {
5567             //  if we don't get ACK/NAK some serial corruption occurred
5568             // so we'll call it a timeout for retry purposes
5569             RETURNFUNC(-RIG_ETIMEOUT);
5570         }
5571 
5572         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
5573         {
5574             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
5575                       ackbuf[0], ack_len);
5576             RETURNFUNC(-RIG_ERJCTED);
5577         }
5578     }
5579 
5580     if (RIG_OK != (retval = icom_get_split_vfos(rig, &rx_vfo, &tx_vfo)))
5581     {
5582         RETURNFUNC(retval);
5583     }
5584 
5585     TRACE;
5586 
5587     if (RIG_OK != (retval = rig_set_vfo(rig, tx_vfo)))
5588     {
5589         RETURNFUNC(retval);
5590     }
5591 
5592     if (RIG_OK != (retval = rig->caps->get_mode(rig, RIG_VFO_CURR, tx_mode,
5593                             tx_width)))
5594     {
5595         RETURNFUNC(retval);
5596     }
5597 
5598     TRACE;
5599 
5600     if (RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5601     {
5602         RETURNFUNC(retval);
5603     }
5604 
5605     if (VFO_HAS_A_B_ONLY && priv->split_on)
5606     {
5607         /* Re-enable split */
5608         if (RIG_OK !=
5609                 (retval =
5610                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf,
5611                                       &ack_len)))
5612         {
5613             RETURNFUNC(retval);
5614         }
5615     }
5616 
5617     RETURNFUNC(retval);
5618 }
5619 
5620 /*
5621  * icom_set_split_freq_mode
5622  * Assumes rig!=NULL, rig->state.priv!=NULL,
5623  *  icom_set_vfo,icom_set_mode works for this rig
5624  */
icom_set_split_freq_mode(RIG * rig,vfo_t vfo,freq_t tx_freq,rmode_t tx_mode,pbwidth_t tx_width)5625 int icom_set_split_freq_mode(RIG *rig, vfo_t vfo, freq_t tx_freq,
5626                              rmode_t tx_mode, pbwidth_t tx_width)
5627 {
5628     int retval;
5629     struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
5630     unsigned char ackbuf[MAXFRAMELEN];
5631     int ack_len = sizeof(ackbuf);
5632     vfo_t rx_vfo, tx_vfo;
5633     int split_assumed = 0;
5634 
5635     rig_debug(RIG_DEBUG_VERBOSE, "%s called vfo=%s\n", __func__,
5636               rig_strvfo(vfo));
5637     rig_debug(RIG_DEBUG_VERBOSE, "%s: curr_vfo=%s\n", __func__,
5638               rig_strvfo(rig->state.current_vfo));
5639 
5640     // If the user is asking to set split on VFO_CURR we'll assume split mode
5641     // WSJT-X calls this function before turning on split mode
5642     if (vfo == RIG_VFO_CURR) { split_assumed = 1; }
5643 
5644     if (rig->state.current_vfo == RIG_VFO_NONE)
5645     {
5646         icom_set_default_vfo(rig);
5647     }
5648 
5649     /* This method works also in memory mode(RIG_VFO_MEM) */
5650     if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG))
5651     {
5652         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5653         {
5654             RETURNFUNC(retval);
5655         }
5656 
5657         if (RIG_OK != (retval = rig_set_freq(rig, RIG_VFO_CURR, tx_freq)))
5658         {
5659             RETURNFUNC(retval);
5660         }
5661 
5662         if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
5663                 && RIG_OK != (retval = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode,
5664                                        tx_width)))
5665         {
5666             RETURNFUNC(retval);
5667         }
5668 
5669         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5670         {
5671             RETURNFUNC(retval);
5672         }
5673 
5674         RETURNFUNC(retval);
5675     }
5676 
5677     /* In the case of rigs with an A/B VFO arrangement we assume the
5678        current VFO is VFO A and the split Tx VFO is always VFO B. These
5679        assumptions allow us to deal with the lack of VFO and split
5680        queries */
5681     /* broken if user changes split on rig :( */
5682     if (VFO_HAS_A_B && (split_assumed || priv->split_on))
5683     {
5684         /* VFO A/B style rigs swap VFO on split Tx so we need to disable
5685            split for certainty */
5686         if (RIG_OK !=
5687                 (retval =
5688                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf,
5689                                       &ack_len)))
5690         {
5691             RETURNFUNC(retval);
5692         }
5693 
5694         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
5695         {
5696             //  if we don't get ACK/NAK some serial corruption occurred
5697             // so we'll call it a timeout for retry purposes
5698             RETURNFUNC(-RIG_ETIMEOUT);
5699         }
5700 
5701         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
5702         {
5703             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
5704                       ackbuf[0], ack_len);
5705             RETURNFUNC(-RIG_ERJCTED);
5706         }
5707     }
5708 
5709     rig_debug(RIG_DEBUG_VERBOSE,
5710               "%s: before get_split_vfos rx_vfo=%s tx_vfo=%s\n", __func__,
5711               rig_strvfo(priv->rx_vfo), rig_strvfo(priv->tx_vfo));
5712 
5713     if (RIG_OK != (retval = icom_get_split_vfos(rig, &rx_vfo, &tx_vfo)))
5714     {
5715         RETURNFUNC(retval);
5716     }
5717 
5718     // WSJT-X calls this function before setting split
5719     // So in this case we have to force the tx_vfo
5720     if (split_assumed && vfo == RIG_VFO_CURR)
5721     {
5722         rig_debug(RIG_DEBUG_TRACE, "%s: split_assumed so tx_vfo=%s\n", __func__,
5723                   rig_strvfo(vfo));
5724         tx_vfo = VFO_HAS_A_B_ONLY ? RIG_VFO_B : RIG_VFO_SUB;
5725     }
5726 
5727 
5728     rig_debug(RIG_DEBUG_VERBOSE,
5729               "%s: after get_split_vfos  rx_vfo=%s tx_vfo=%s\n", __func__,
5730               rig_strvfo(priv->rx_vfo), rig_strvfo(priv->tx_vfo));
5731 
5732     // if not asking for RIG_VFO_CURR we'll use the requested VFO in the function call as tx_vfo
5733     if (!priv->split_on && vfo != RIG_VFO_CURR)
5734     {
5735         tx_vfo = vfo;
5736         rig_debug(RIG_DEBUG_TRACE, "%s: split not on so using requested vfo=%s\n",
5737                   __func__, rig_strvfo(tx_vfo));
5738     }
5739 
5740     TRACE;
5741 
5742     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_FREQ)
5743             && RIG_OK != (retval = rig_set_vfo(rig, tx_vfo)))
5744     {
5745         RETURNFUNC(retval);
5746     }
5747 
5748     if (RIG_OK != (retval = rig_set_freq(rig, RIG_VFO_CURR, tx_freq)))
5749     {
5750         RETURNFUNC(retval);
5751     }
5752 
5753     TRACE;
5754 
5755     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
5756             && RIG_OK != (retval = rig_set_vfo(rig, tx_vfo)))
5757     {
5758         RETURNFUNC(retval);
5759     }
5760 
5761     if (RIG_OK != (retval = rig->caps->set_mode(rig, RIG_VFO_CURR, tx_mode,
5762                             tx_width)))
5763     {
5764         RETURNFUNC(retval);
5765     }
5766 
5767     TRACE;
5768 
5769     if (!(rig->caps->targetable_vfo & RIG_TARGETABLE_MODE)
5770             && RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5771     {
5772         RETURNFUNC(retval);
5773     }
5774 
5775     if (VFO_HAS_A_B && priv->split_on)
5776     {
5777         /* Re-enable split */
5778         if (RIG_OK !=
5779                 (retval =
5780                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf,
5781                                       &ack_len)))
5782         {
5783             RETURNFUNC(retval);
5784         }
5785     }
5786 
5787     RETURNFUNC(retval);
5788 }
5789 
5790 /*
5791  * icom_get_split_freq_mode
5792  * Assumes rig!=NULL, rig->state.priv!=NULL,
5793  *  rx_mode!=NULL, rx_width!=NULL, tx_mode!=NULL, tx_width!=NULL
5794  *  icom_set_vfo,icom_get_mode works for this rig
5795  */
icom_get_split_freq_mode(RIG * rig,vfo_t vfo,freq_t * tx_freq,rmode_t * tx_mode,pbwidth_t * tx_width)5796 int icom_get_split_freq_mode(RIG *rig, vfo_t vfo, freq_t *tx_freq,
5797                              rmode_t *tx_mode, pbwidth_t *tx_width)
5798 {
5799     int retval;
5800     vfo_t rx_vfo, tx_vfo;
5801     struct icom_priv_data *priv;
5802     struct rig_state *rs;
5803     unsigned char ackbuf[MAXFRAMELEN];
5804     int ack_len = sizeof(ackbuf);
5805 
5806     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
5807     rs = &rig->state;
5808     priv = (struct icom_priv_data *) rs->priv;
5809 
5810     /* This method works also in memory mode(RIG_VFO_MEM) */
5811     if (!priv->no_xchg && rig_has_vfo_op(rig, RIG_OP_XCHG))
5812     {
5813         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5814         {
5815             RETURNFUNC(retval);
5816         }
5817 
5818         if (RIG_OK != (retval = rig_get_freq(rig, RIG_VFO_CURR, tx_freq)))
5819         {
5820             RETURNFUNC(retval);
5821         }
5822 
5823         if (RIG_OK != (retval = rig->caps->get_mode(rig, RIG_VFO_CURR, tx_mode,
5824                                 tx_width)))
5825         {
5826             RETURNFUNC(retval);
5827         }
5828 
5829         if (RIG_OK != (retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG)))
5830         {
5831             RETURNFUNC(retval);
5832         }
5833 
5834         RETURNFUNC(retval);
5835     }
5836 
5837     /* In the case of rigs with an A/B VFO arrangement we assume the
5838        current VFO is VFO A and the split Tx VFO is always VFO B. These
5839        assumptions allow us to deal with the lack of VFO and split
5840        queries */
5841     if (VFO_HAS_A_B_ONLY
5842             && priv->split_on)   /* broken if user changes split on rig :( */
5843     {
5844         /* VFO A/B style rigs swap VFO on split Tx so we need to disable
5845            split for certainty */
5846         if (RIG_OK !=
5847                 (retval =
5848                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_OFF, NULL, 0, ackbuf,
5849                                       &ack_len)))
5850         {
5851             RETURNFUNC(retval);
5852         }
5853 
5854         if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
5855         {
5856             //  if we don't get ACK/NAK some serial corruption occurred
5857             // so we'll call it a timeout for retry purposes
5858             RETURNFUNC(-RIG_ETIMEOUT);
5859         }
5860 
5861         if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
5862         {
5863             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
5864                       ackbuf[0], ack_len);
5865             RETURNFUNC(-RIG_ERJCTED);
5866         }
5867     }
5868 
5869     if (RIG_OK != (retval = icom_get_split_vfos(rig, &rx_vfo, &tx_vfo)))
5870     {
5871         RETURNFUNC(retval);
5872     }
5873 
5874     TRACE;
5875 
5876     if (RIG_OK != (retval = rig_set_vfo(rig, tx_vfo)))
5877     {
5878         RETURNFUNC(retval);
5879     }
5880 
5881     if (RIG_OK != (retval = rig_get_freq(rig, RIG_VFO_CURR, tx_freq)))
5882     {
5883         RETURNFUNC(retval);
5884     }
5885 
5886     if (RIG_OK != (retval = rig->caps->get_mode(rig, RIG_VFO_CURR, tx_mode,
5887                             tx_width)))
5888     {
5889         RETURNFUNC(retval);
5890     }
5891 
5892     TRACE;
5893 
5894     if (RIG_OK != (retval = rig_set_vfo(rig, rx_vfo)))
5895     {
5896         RETURNFUNC(retval);
5897     }
5898 
5899     if (VFO_HAS_A_B_ONLY && priv->split_on)
5900     {
5901         /* Re-enable split */
5902         if (RIG_OK !=
5903                 (retval =
5904                      icom_transaction(rig, C_CTL_SPLT, S_SPLT_ON, NULL, 0, ackbuf,
5905                                       &ack_len)))
5906         {
5907             RETURNFUNC(retval);
5908         }
5909     }
5910 
5911     RETURNFUNC(retval);
5912 }
5913 
5914 
5915 /*
5916  * icom_set_split
5917  * Assumes rig!=NULL, rig->state.priv!=NULL
5918  */
icom_set_split_vfo(RIG * rig,vfo_t vfo,split_t split,vfo_t tx_vfo)5919 int icom_set_split_vfo(RIG *rig, vfo_t vfo, split_t split, vfo_t tx_vfo)
5920 {
5921     struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
5922     unsigned char ackbuf[MAXFRAMELEN];
5923     int ack_len = sizeof(ackbuf), retval;
5924     int split_sc;
5925     //vfo_t vfo_final = RIG_VFO_NONE;  // where does the VFO end up?
5926 
5927     /* For Icom which VFO is active for this call is not important
5928      * S VFOA 1 VFOB -- RX on VFOA, TX on VFOB
5929      * S VFOB 1 VFOA -- RX on VFOB, TX on VFOA
5930      * S Main 1 Sub -- RX on Main, TX on Sub
5931      * S Sub 1 Main -- RX on Sub, TX on Main
5932      */
5933     rig_debug(RIG_DEBUG_VERBOSE,
5934               "%s called vfo='%s', split=%d, tx_vfo=%s, curr_vfo=%s\n", __func__,
5935               rig_strvfo(vfo), split, rig_strvfo(tx_vfo), rig_strvfo(rig->state.current_vfo));
5936 
5937     // This should automatically switch between satmode on/off based on the requested split vfo
5938     if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
5939     {
5940         if ((tx_vfo == RIG_VFO_SUB || tx_vfo == RIG_VFO_MAIN)
5941                 && !rig->state.cache.satmode)
5942         {
5943             rig_debug(RIG_DEBUG_VERBOSE,
5944                       "%s: VFO_SUB and satmode is off so turning satmode on\n",
5945                       __func__);
5946             rig_set_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, 1);
5947             rig->state.cache.satmode = 1;
5948             priv->tx_vfo = RIG_VFO_SUB;
5949         }
5950         else if ((tx_vfo == RIG_VFO_A || tx_vfo == RIG_VFO_B)
5951                  && rig->state.cache.satmode)
5952         {
5953             rig_debug(RIG_DEBUG_VERBOSE,
5954                       "%s: VFO_B and satmode is on so turning satmode off\n",
5955                       __func__);
5956             rig_set_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, 0);
5957             rig->state.cache.satmode = 0;
5958             priv->tx_vfo = RIG_VFO_B;
5959         }
5960         else if (tx_vfo == RIG_VFO_SUB && rig->state.cache.satmode && split == 1)
5961         {
5962             rig_debug(RIG_DEBUG_VERBOSE,
5963                       "%s: rig in satmode so setting split on is redundant and will create error...returning OK\n",
5964                       __func__);
5965             // we'll return OK anyways as this is a split mode
5966             // and gpredict wants to see the OK response here
5967             RETURNFUNC(RIG_OK);  // we'll return OK anyways as this is a split mode
5968         }
5969     }
5970 
5971     switch (split)
5972     {
5973     case RIG_SPLIT_OFF:
5974 
5975         // if either VFOA or B is the vfo we set to VFOA when split is turned off
5976         if (tx_vfo == RIG_VFO_A || tx_vfo == RIG_VFO_B)
5977         {
5978             rig_debug(RIG_DEBUG_TRACE, "%s: tx_vfo=%s\n", __func__,
5979                       rig_strvfo(tx_vfo));
5980             priv->tx_vfo = RIG_VFO_A;
5981             //vfo_final = RIG_VFO_A; // do we need to switch back at all?
5982         }
5983         // otherwise if Main or Sub we set Main or VFOA as the current vfo
5984         else if (tx_vfo == RIG_VFO_MAIN || tx_vfo == RIG_VFO_SUB)
5985         {
5986             rig_debug(RIG_DEBUG_TRACE, "%s: vfo is VFO_MAIN/SUB tx_vfo=%s\n",
5987                       __func__, rig_strvfo(tx_vfo));
5988 
5989             //rig_set_vfo(rig, RIG_VFO_MAIN);
5990             //vfo_final = RIG_VFO_MAIN; // do we need to switch back at all?
5991 
5992             if (VFO_HAS_A_B_ONLY)
5993             {
5994                 priv->tx_vfo = RIG_VFO_A;
5995                 priv->rx_vfo = RIG_VFO_A;
5996             }
5997             else
5998             {
5999                 priv->tx_vfo = RIG_VFO_MAIN;
6000                 priv->rx_vfo = RIG_VFO_MAIN;
6001             }
6002         }
6003 
6004         split_sc = S_SPLT_OFF;
6005         break;
6006 
6007     case RIG_SPLIT_ON:
6008         split_sc = S_SPLT_ON;
6009         rig_debug(RIG_DEBUG_TRACE, "trace %s(%d)\n", __func__, __LINE__);
6010 
6011         // the VFO adjusting here could probably be done in rig.c for all rigs
6012         /* If asking for Sub or Main on rig that doesn't have it map it */
6013         if (VFO_HAS_A_B_ONLY && ((tx_vfo == RIG_VFO_MAIN || tx_vfo == RIG_VFO_SUB)
6014                                  || vfo == RIG_VFO_MAIN || vfo == RIG_VFO_SUB))
6015         {
6016             rig_debug(RIG_DEBUG_TRACE, "%s: vfo clause 1\n", __func__);
6017 
6018             if (tx_vfo == RIG_VFO_MAIN) { tx_vfo = RIG_VFO_A; vfo = RIG_VFO_B; }
6019             else if (tx_vfo == RIG_VFO_SUB) { tx_vfo = RIG_VFO_B; vfo = RIG_VFO_A; }
6020 
6021             priv->tx_vfo = tx_vfo;
6022             priv->rx_vfo = vfo;
6023         }
6024 
6025         /* ensure VFO A is Rx and VFO B is Tx as we assume that elsewhere */
6026         else if (VFO_HAS_A_B && (tx_vfo == RIG_VFO_A || tx_vfo == RIG_VFO_B))
6027         {
6028             rig_debug(RIG_DEBUG_TRACE, "%s: vfo clause 2\n", __func__);
6029             rig_debug(RIG_DEBUG_TRACE,
6030                       "%s: rx_vfo to VFO_A, tx_vfo to VFO_B because tx_vfo=%s\n", __func__,
6031                       rig_strvfo(tx_vfo));
6032 
6033             if (tx_vfo == RIG_VFO_B)
6034             {
6035                 priv->tx_vfo = RIG_VFO_B;
6036                 priv->rx_vfo = vfo = RIG_VFO_A;
6037             }
6038             else
6039             {
6040                 priv->tx_vfo = RIG_VFO_A;
6041                 priv->rx_vfo = vfo = RIG_VFO_B;
6042             }
6043         }
6044         else if (VFO_HAS_MAIN_SUB_A_B_ONLY && (tx_vfo == RIG_VFO_MAIN
6045                                                || tx_vfo == RIG_VFO_SUB))
6046         {
6047             // do we need another case for tx_vfo = A/B ?
6048             rig_debug(RIG_DEBUG_TRACE, "%s: vfo clause 3\n", __func__);
6049             // if we're asking for split in this case we split Main on A/B
6050             priv->tx_vfo = RIG_VFO_SUB;
6051             priv->rx_vfo = RIG_VFO_MAIN;
6052             rig_debug(RIG_DEBUG_TRACE,
6053                       "%s: tx=%s, rx=%s because tx_vfo=%s\n", __func__,
6054                       rig_strvfo(priv->tx_vfo), rig_strvfo(priv->rx_vfo), rig_strvfo(tx_vfo));
6055             tx_vfo = RIG_VFO_SUB;
6056 
6057 #if 0 // is this needed for satmode?
6058 
6059             // make sure we're on Main/VFOA
6060             TRACE;
6061 
6062             if (RIG_OK != (retval = icom_set_vfo(rig, RIG_VFO_MAIN)))
6063             {
6064                 RETURNFUNC(retval);
6065             }
6066 
6067             TRACE;
6068 
6069             if (RIG_OK != (retval = icom_set_vfo(rig, RIG_VFO_A)))
6070             {
6071                 RETURNFUNC(retval);
6072             }
6073 
6074 #endif
6075         }
6076         else if (VFO_HAS_MAIN_SUB && (tx_vfo == RIG_VFO_MAIN || tx_vfo == RIG_VFO_SUB))
6077         {
6078             rig_debug(RIG_DEBUG_TRACE, "%s: vfo clause 4\n", __func__);
6079             rig_debug(RIG_DEBUG_TRACE, "%s: set_vfo because tx_vfo=%s\n", __func__,
6080                       rig_strvfo(tx_vfo));
6081 
6082 #if 0 // do we need this for satmode?
6083 
6084             TRACE;
6085 
6086             if (RIG_OK != (retval = icom_set_vfo(rig, tx_vfo)))
6087             {
6088                 RETURNFUNC(retval);
6089             }
6090 
6091 #endif
6092 
6093             priv->rx_vfo = vfo;
6094             priv->tx_vfo = tx_vfo;
6095             //vfo_final = RIG_VFO_MAIN;
6096 
6097             split_sc = S_SPLT_ON;
6098         }
6099         else
6100         {
6101             rig_debug(RIG_DEBUG_ERR, "%s: split on vfo=%s not known\n", __func__,
6102                       rig_strvfo(vfo));
6103             RETURNFUNC(-RIG_EINVAL);
6104         }
6105 
6106         break;
6107 
6108     default:
6109         rig_debug(RIG_DEBUG_ERR, "%s: unsupported split %d", __func__, split);
6110         RETURNFUNC(-RIG_EINVAL);
6111     }
6112 
6113     if (RIG_OK != (retval = icom_transaction(rig, C_CTL_SPLT, split_sc, NULL, 0,
6114                             ackbuf, &ack_len)))
6115     {
6116         RETURNFUNC(retval);
6117     }
6118 
6119     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
6120     {
6121         //  if we don't get ACK/NAK some serial corruption occurred
6122         // so we'll call it a timeout for retry purposes
6123         RETURNFUNC(-RIG_ETIMEOUT);
6124     }
6125 
6126     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
6127     {
6128         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
6129                   ackbuf[0], ack_len);
6130         RETURNFUNC(-RIG_ERJCTED);
6131     }
6132 
6133     priv->split_on = RIG_SPLIT_ON == split;
6134 
6135 #if 0 // don't think we need this anymore -- 20210731
6136 
6137     if (vfo_final != RIG_VFO_NONE && vfo_final != rig->state.current_vfo)
6138     {
6139         rig_debug(RIG_DEBUG_TRACE, "%s: vfo_final set %s\n", __func__,
6140                   rig_strvfo(vfo_final));
6141         TRACE;
6142         retval = rig_set_vfo(rig, vfo_final);
6143 
6144         if (retval != RIG_OK)
6145         {
6146             rig_debug(RIG_DEBUG_TRACE, "%s: vfo_final set failed? err=%s\n", __func__,
6147                       rigerror(retval));
6148         }
6149     }
6150 
6151 #endif
6152 
6153     rig_debug(RIG_DEBUG_VERBOSE,
6154               "%s: vfo=%s curr_vfo=%s rx_vfo=%s tx_vfo=%s split=%d\n",
6155               __func__, rig_strvfo(vfo), rig_strvfo(rig->state.current_vfo),
6156               rig_strvfo(priv->rx_vfo),
6157               rig_strvfo(priv->tx_vfo), split);
6158     RETURNFUNC(RIG_OK);
6159 }
6160 
6161 /*
6162  * icom_get_split_vfo
6163  * Assumes rig!=NULL, rig->state.priv!=NULL, split!=NULL
6164  *
6165  * Does not appear to be supported by any mode?
6166  * \sa icom_mem_get_split_vfo()
6167  */
icom_get_split_vfo(RIG * rig,vfo_t vfo,split_t * split,vfo_t * tx_vfo)6168 int icom_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split, vfo_t *tx_vfo)
6169 {
6170     unsigned char splitbuf[MAXFRAMELEN];
6171     int split_len, retval, satmode = 0;
6172     struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
6173 
6174     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6175     retval = icom_transaction(rig, C_CTL_SPLT, -1, NULL, 0,
6176                               splitbuf, &split_len);
6177 
6178     if (retval != RIG_OK)
6179     {
6180         rig_debug(RIG_DEBUG_ERR, "%s: CTL_SPLT failed?\n", __func__);
6181         RETURNFUNC(retval);
6182     }
6183 
6184     /*
6185      * splitbuf should contain Cn,Sc
6186      */
6187     split_len--;
6188 
6189     if (split_len != 1)
6190     {
6191         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n",
6192                   __func__, split_len);
6193         RETURNFUNC(-RIG_ERJCTED);
6194     }
6195 
6196     switch (splitbuf[1])
6197     {
6198     case S_SPLT_OFF:
6199         *split = RIG_SPLIT_OFF;
6200         break;
6201 
6202     case S_SPLT_ON:
6203         *split = RIG_SPLIT_ON;
6204         break;
6205 
6206     // The same command indicates repeater shift state, which means that split is off
6207     case S_DUP_M:
6208     case S_DUP_P:
6209     case S_DUP_DD_RPS:
6210         *split = RIG_SPLIT_OFF;
6211         break;
6212 
6213     default:
6214         rig_debug(RIG_DEBUG_ERR, "%s: unsupported split %d", __func__,
6215                   splitbuf[1]);
6216         RETURNFUNC(-RIG_EPROTO);
6217     }
6218 
6219     if (rig->caps->has_get_func & RIG_FUNC_SATMODE)
6220     {
6221         rig_get_func(rig, RIG_VFO_CURR, RIG_FUNC_SATMODE, &satmode);
6222 
6223         if (satmode != rig->state.cache.satmode)
6224         {
6225             rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): satmode changed to reset x25cmdfails\n",
6226                       __func__, __LINE__);
6227             priv->x25cmdfails = satmode; // reset this so it tries again
6228         }
6229     }
6230 
6231     rig->state.cache.satmode = satmode;
6232 
6233     priv->split_on = RIG_SPLIT_ON == *split;
6234 
6235     icom_get_split_vfos(rig, &priv->rx_vfo, &priv->tx_vfo);
6236 
6237     *tx_vfo = priv->tx_vfo;
6238     rig_debug(RIG_DEBUG_VERBOSE, "%s: vfo=%s rx_vfo=%s tx_vfo=%s split=%d\n",
6239               __func__, rig_strvfo(vfo), rig_strvfo(priv->rx_vfo),
6240               rig_strvfo(priv->tx_vfo), *split);
6241     RETURNFUNC(RIG_OK);
6242 }
6243 
6244 
6245 /*
6246  * icom_mem_get_split_vfo
6247  * Assumes rig!=NULL, rig->state.priv!=NULL, split!=NULL
6248  */
icom_mem_get_split_vfo(RIG * rig,vfo_t vfo,split_t * split,vfo_t * tx_vfo)6249 int icom_mem_get_split_vfo(RIG *rig, vfo_t vfo, split_t *split,
6250                            vfo_t *tx_vfo)
6251 {
6252     int retval;
6253 
6254     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6255 
6256     /* this hacks works only when in memory mode
6257      * I have no clue how to detect split in regular VFO mode
6258      */
6259     if (rig->state.current_vfo != RIG_VFO_MEM ||
6260             !rig_has_vfo_op(rig, RIG_OP_XCHG))
6261     {
6262         *split = rig->state.cache.split; // we set this but still return ENAVAIL
6263         RETURNFUNC(-RIG_ENAVAIL);
6264     }
6265 
6266     retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
6267 
6268     if (retval == RIG_OK)
6269     {
6270         *split = RIG_SPLIT_ON;
6271         /* get it back to normal */
6272         retval = icom_vfo_op(rig, vfo, RIG_OP_XCHG);
6273 
6274         if (retval != RIG_OK) { RETURNFUNC(retval); }
6275     }
6276     else if (retval == -RIG_ERJCTED)
6277     {
6278         *split = RIG_SPLIT_OFF;
6279     }
6280     else
6281     {
6282         /* this is really an error! */
6283         RETURNFUNC(retval);
6284     }
6285 
6286     RETURNFUNC(RIG_OK);
6287 }
6288 
6289 /*
6290  * icom_set_ts
6291  * Assumes rig!=NULL, rig->caps->priv!=NULL
6292  */
icom_set_ts(RIG * rig,vfo_t vfo,shortfreq_t ts)6293 int icom_set_ts(RIG *rig, vfo_t vfo, shortfreq_t ts)
6294 {
6295     const struct icom_priv_caps *priv_caps;
6296     unsigned char ackbuf[MAXFRAMELEN];
6297     int i, ack_len = sizeof(ackbuf), retval;
6298     int ts_sc = 0;
6299 
6300     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6301     priv_caps = (const struct icom_priv_caps *) rig->caps->priv;
6302 
6303     for (i = 0; i < HAMLIB_TSLSTSIZ; i++)
6304     {
6305         if (priv_caps->ts_sc_list[i].ts == ts)
6306         {
6307             ts_sc = priv_caps->ts_sc_list[i].sc;
6308             break;
6309         }
6310     }
6311 
6312     if (i >= HAMLIB_TSLSTSIZ)
6313     {
6314         RETURNFUNC(-RIG_EINVAL);   /* not found, unsupported */
6315     }
6316 
6317     retval = icom_transaction(rig, C_SET_TS, ts_sc, NULL, 0, ackbuf, &ack_len);
6318 
6319     if (retval != RIG_OK)
6320     {
6321         RETURNFUNC(retval);
6322     }
6323 
6324     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
6325     {
6326         //  if we don't get ACK/NAK some serial corruption occurred
6327         // so we'll call it a timeout for retry purposes
6328         RETURNFUNC(-RIG_ETIMEOUT);
6329     }
6330 
6331     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
6332     {
6333         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
6334                   ackbuf[0], ack_len);
6335         RETURNFUNC(-RIG_ERJCTED);
6336     }
6337 
6338     RETURNFUNC(RIG_OK);
6339 }
6340 
6341 /*
6342  * icom_get_ts
6343  * Assumes rig!=NULL, rig->caps->priv!=NULL, ts!=NULL
6344  * NOTE: seems not to work (tested on IC-706MkIIG), please report --SF  Not available on 746pro
6345  */
icom_get_ts(RIG * rig,vfo_t vfo,shortfreq_t * ts)6346 int icom_get_ts(RIG *rig, vfo_t vfo, shortfreq_t *ts)
6347 {
6348     const struct icom_priv_caps *priv_caps;
6349     unsigned char tsbuf[MAXFRAMELEN];
6350     int ts_len, i, retval;
6351 
6352     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6353     priv_caps = (const struct icom_priv_caps *) rig->caps->priv;
6354 
6355     retval = icom_transaction(rig, C_SET_TS, -1, NULL, 0, tsbuf, &ts_len);
6356 
6357     if (retval != RIG_OK)
6358     {
6359         RETURNFUNC(retval);
6360     }
6361 
6362     /*
6363      * tsbuf should contain Cn,Sc
6364      */
6365     ts_len--;
6366 
6367     if (ts_len != 1)
6368     {
6369         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n", __func__, ts_len);
6370         RETURNFUNC(-RIG_ERJCTED);
6371     }
6372 
6373     for (i = 0; i < HAMLIB_TSLSTSIZ; i++)
6374     {
6375         if (priv_caps->ts_sc_list[i].sc == tsbuf[1])
6376         {
6377             *ts = priv_caps->ts_sc_list[i].ts;
6378             break;
6379         }
6380     }
6381 
6382     if (i >= HAMLIB_TSLSTSIZ)
6383     {
6384         RETURNFUNC(-RIG_EPROTO);   /* not found, unsupported */
6385     }
6386 
6387     RETURNFUNC(RIG_OK);
6388 }
6389 
6390 
6391 /*
6392  * icom_set_func
6393  * Assumes rig!=NULL, rig->state.priv!=NULL
6394  */
icom_set_func(RIG * rig,vfo_t vfo,setting_t func,int status)6395 int icom_set_func(RIG *rig, vfo_t vfo, setting_t func, int status)
6396 {
6397     unsigned char fctbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
6398     int fct_len, ack_len, retval;
6399     int fct_cn, fct_sc;       /* Command Number, Subcommand */
6400     struct rig_state *rs = &rig->state;
6401     struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
6402 
6403     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6404 
6405     const struct icom_priv_caps *priv_caps = rig->caps->priv;
6406     const struct cmdparams *extcmds = priv_caps->extcmds;
6407     int i;
6408 
6409     value_t value = { .i = status };
6410 
6411     for (i = 0; extcmds && extcmds[i].id.s != 0; i++)
6412     {
6413         if (extcmds[i].cmdparamtype == CMD_PARAM_TYPE_FUNC && extcmds[i].id.s == func)
6414         {
6415             RETURNFUNC(icom_set_cmd(rig, vfo, (struct cmdparams *)&extcmds[i], value));
6416         }
6417     }
6418 
6419     fctbuf[0] = status ? 0x01 : 0x00;
6420     fct_len = 1;
6421 
6422     switch (func)
6423     {
6424     case RIG_FUNC_NB:
6425         fct_cn = C_CTL_FUNC;
6426         fct_sc = S_FUNC_NB;
6427         break;
6428 
6429     case RIG_FUNC_COMP: fct_cn = C_CTL_FUNC;
6430         fct_sc = S_FUNC_COMP;
6431         break;
6432 
6433     case RIG_FUNC_VOX: fct_cn = C_CTL_FUNC;
6434         fct_sc = S_FUNC_VOX;
6435         break;
6436 
6437     case RIG_FUNC_TONE:   /* repeater tone */
6438         fct_cn = C_CTL_FUNC;
6439         fct_sc = S_FUNC_TONE;
6440         break;
6441 
6442     case RIG_FUNC_TSQL: fct_cn = C_CTL_FUNC;
6443         fct_sc = S_FUNC_TSQL;
6444         break;
6445 
6446     case RIG_FUNC_SBKIN: fct_cn = C_CTL_FUNC;
6447         fct_sc = S_FUNC_BKIN;
6448 
6449         if (status != 0)
6450         {
6451             fctbuf[0] = 0x01;
6452         }
6453         else
6454         {
6455             fctbuf[0] = 0x00;
6456         }
6457 
6458         break;
6459 
6460     case RIG_FUNC_FBKIN:
6461         fct_cn = C_CTL_FUNC;
6462         fct_sc = S_FUNC_BKIN;
6463 
6464         if (status != 0)
6465         {
6466             fctbuf[0] = 0x02;
6467         }
6468         else
6469         {
6470             fctbuf[0] = 0x00;
6471         }
6472 
6473         break;
6474 
6475     case RIG_FUNC_ANF:
6476         fct_cn = C_CTL_FUNC;
6477         fct_sc = S_FUNC_ANF;
6478         break;
6479 
6480     case RIG_FUNC_NR:
6481         fct_cn = C_CTL_FUNC;
6482         fct_sc = S_FUNC_NR;
6483         break;
6484 
6485     case RIG_FUNC_APF:
6486         fct_cn = C_CTL_FUNC;
6487         fct_sc = S_FUNC_APF;
6488         break;
6489 
6490     case RIG_FUNC_MON:
6491         fct_cn = C_CTL_FUNC;
6492         fct_sc = S_FUNC_MON;
6493         break;
6494 
6495     case RIG_FUNC_MN:
6496         fct_cn = C_CTL_FUNC;
6497         fct_sc = S_FUNC_MN;
6498         break;
6499 
6500     case RIG_FUNC_RF:
6501         fct_cn = C_CTL_FUNC;
6502         fct_sc = S_FUNC_RF;
6503         break;
6504 
6505     case RIG_FUNC_VSC:
6506         fct_cn = C_CTL_FUNC;
6507         fct_sc = S_FUNC_VSC;
6508         break;
6509 
6510     case RIG_FUNC_LOCK:
6511         fct_cn = C_CTL_FUNC;
6512         fct_sc = S_FUNC_DIAL_LK;
6513         break;
6514 
6515     case RIG_FUNC_AFC:      /* IC-910H */
6516         fct_cn = C_CTL_FUNC;
6517         fct_sc = S_FUNC_AFC;
6518         break;
6519 
6520     case RIG_FUNC_SCOPE:
6521         fct_cn = C_CTL_SCP;
6522         fct_sc = S_SCP_STS;
6523         fctbuf[0] = status;
6524         fct_len = 1;
6525         break;
6526 
6527     case RIG_FUNC_SPECTRUM:
6528         fct_cn = C_CTL_SCP;
6529         fct_sc = S_SCP_DOP;
6530         fctbuf[0] = status;
6531         fct_len = 1;
6532         break;
6533 
6534     case RIG_FUNC_SPECTRUM_HOLD:
6535         fct_cn = C_CTL_SCP;
6536         fct_sc = S_SCP_HLD;
6537 
6538         fct_len = 2;
6539         fctbuf[0] = icom_get_spectrum_vfo(rig, vfo);
6540         fctbuf[1] = status;
6541         break;
6542 
6543     case RIG_FUNC_RESUME:   /* IC-910H  & IC-746-Pro */
6544         fct_cn = C_CTL_SCAN;
6545         fct_sc = status ? S_SCAN_RSMON : S_SCAN_RSMOFF;
6546         fct_len = 0;
6547         break;
6548 
6549     case RIG_FUNC_CSQL:
6550         fct_cn = C_CTL_FUNC;
6551         fct_sc = S_FUNC_CSQL;
6552         break;
6553 
6554     case RIG_FUNC_DSQL:
6555         fct_cn = C_CTL_FUNC;
6556         fct_sc = S_FUNC_DSSQL;
6557 
6558         if (status <= 2)
6559         {
6560             fctbuf[0] = status;
6561         }
6562         else
6563         {
6564             fctbuf[0] = 0;
6565         }
6566 
6567         break;
6568 
6569     case RIG_FUNC_AFLT:
6570         fct_cn = C_CTL_MEM;
6571         fct_sc = S_MEM_AFLT;
6572         break;
6573 
6574     case RIG_FUNC_ANL:
6575         fct_cn = C_CTL_MEM;
6576         fct_sc = S_MEM_ANL;
6577         break;
6578 
6579     case RIG_FUNC_AIP:      /* IC-R8600 IP+ function, misusing AIP since RIG_FUNC_ word is full (32 bit) */
6580         fct_cn = C_CTL_MEM;
6581         fct_sc = S_FUNC_IPPLUS;
6582         break;
6583 
6584     case RIG_FUNC_RIT:
6585         fct_cn = C_CTL_RIT;
6586         fct_sc = S_RIT;
6587         break;
6588 
6589     case RIG_FUNC_XIT:
6590         fct_cn = C_CTL_RIT;
6591         fct_sc = S_XIT;
6592         break;
6593 
6594     case RIG_FUNC_TUNER:
6595         fct_cn = C_CTL_PTT;
6596         fct_sc = S_ANT_TUN;
6597         break;
6598 
6599     case RIG_FUNC_DUAL_WATCH:
6600         fct_cn = C_SET_VFO;
6601         fct_sc = S_DUAL;
6602         break;
6603 
6604     case RIG_FUNC_SATMODE:
6605         if (rig->caps->rig_model == RIG_MODEL_IC910)
6606         {
6607             // Is the 910 the only one that uses this command?
6608             fct_cn = C_CTL_MEM;
6609             fct_sc = S_MEM_SATMODE910;
6610         }
6611         else
6612         {
6613             fct_cn = C_CTL_FUNC;
6614             fct_sc = S_MEM_SATMODE;
6615         }
6616 
6617         priv->x25cmdfails =
6618             status; // we reset this to current status -- fails in SATMODE
6619         priv->x1cx03cmdfails = 0; // we reset this to try it again
6620         rig->state.cache.satmode = status;
6621 
6622         break;
6623 
6624 
6625     default:
6626         rig_debug(RIG_DEBUG_ERR, "%s: unsupported set_func %s", __func__,
6627                   rig_strfunc(func));
6628         RETURNFUNC(-RIG_EINVAL);
6629     }
6630 
6631     retval = icom_transaction(rig, fct_cn, fct_sc, fctbuf, fct_len, ackbuf,
6632                               &ack_len);
6633 
6634     if (retval != RIG_OK)
6635     {
6636         RETURNFUNC(retval);
6637     }
6638 
6639     if (ack_len != 1)
6640     {
6641         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n", __func__, ack_len);
6642         RETURNFUNC(-RIG_EPROTO);
6643     }
6644 
6645     // turning satmode on/off can change the tx/rx vfos
6646     // when in satmode split=off always
6647     if (VFO_HAS_MAIN_SUB_A_B_ONLY)
6648     {
6649         vfo_t tx_vfo;
6650         split_t split;
6651 
6652         // update split status
6653         retval = icom_get_split_vfo(rig, RIG_VFO_CURR, &split, &tx_vfo);
6654 
6655         if (retval != RIG_OK) { RETURNFUNC(retval); }
6656 
6657         priv->tx_vfo = RIG_VFO_A;
6658 
6659         if (priv->split_on)   // must have turned off satmode
6660         {
6661             priv->tx_vfo = RIG_VFO_B;
6662         }
6663         else if (status)   // turned on satmode so tx is always Sub
6664         {
6665             priv->tx_vfo = RIG_VFO_SUB;
6666         }
6667     }
6668 
6669     RETURNFUNC(RIG_OK);
6670 }
6671 
6672 /*
6673  * icom_get_func
6674  * Assumes rig!=NULL, rig->state.priv!=NULL
6675  * FIXME: IC8500 and no-sc, any support?
6676  */
icom_get_func(RIG * rig,vfo_t vfo,setting_t func,int * status)6677 int icom_get_func(RIG *rig, vfo_t vfo, setting_t func, int *status)
6678 {
6679     unsigned char ackbuf[MAXFRAMELEN];
6680     int ack_len = sizeof(ackbuf), retval;
6681     int fct_cn, fct_sc;       /* Command Number, Subcommand */
6682     unsigned char fctbuf[MAXFRAMELEN];
6683     int fct_len = 0;
6684 
6685     const struct icom_priv_caps *priv_caps = rig->caps->priv;
6686     const struct cmdparams *extcmds = priv_caps->extcmds;
6687     int i;
6688 
6689     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6690 
6691     value_t value;
6692 
6693     for (i = 0; extcmds && extcmds[i].id.s != 0; i++)
6694     {
6695         rig_debug(RIG_DEBUG_TRACE, "%s: i=%d\n", __func__, i);
6696 
6697         if (extcmds[i].cmdparamtype == CMD_PARAM_TYPE_FUNC && extcmds[i].id.s == func)
6698         {
6699             int result = icom_get_cmd(rig, vfo, (struct cmdparams *)&extcmds[i], &value);
6700 
6701             if (result == RIG_OK)
6702             {
6703                 *status = value.i;
6704             }
6705 
6706             RETURNFUNC(result);
6707         }
6708     }
6709 
6710     switch (func)
6711     {
6712     case RIG_FUNC_NB:
6713         fct_cn = C_CTL_FUNC;
6714         fct_sc = S_FUNC_NB;
6715         break;
6716 
6717     case RIG_FUNC_COMP: fct_cn = C_CTL_FUNC;
6718         fct_sc = S_FUNC_COMP;
6719         break;
6720 
6721     case RIG_FUNC_VOX: fct_cn = C_CTL_FUNC;
6722         fct_sc = S_FUNC_VOX;
6723         break;
6724 
6725     case RIG_FUNC_TONE:   /* repeater tone */
6726         fct_cn = C_CTL_FUNC;
6727         fct_sc = S_FUNC_TONE;
6728         break;
6729 
6730     case RIG_FUNC_TSQL: fct_cn = C_CTL_FUNC;
6731         fct_sc = S_FUNC_TSQL;
6732         break;
6733 
6734     case RIG_FUNC_SBKIN:  /* returns 1 for semi and 2 for full adjusted below */
6735     case RIG_FUNC_FBKIN: fct_cn = C_CTL_FUNC;
6736         fct_sc = S_FUNC_BKIN;
6737         break;
6738 
6739     case RIG_FUNC_ANF: fct_cn = C_CTL_FUNC;
6740         fct_sc = S_FUNC_ANF;
6741         break;
6742 
6743     case RIG_FUNC_NR: fct_cn = C_CTL_FUNC;
6744         fct_sc = S_FUNC_NR;
6745         break;
6746 
6747     case RIG_FUNC_APF: fct_cn = C_CTL_FUNC;
6748         fct_sc = S_FUNC_APF;
6749         break;
6750 
6751     case RIG_FUNC_MON: fct_cn = C_CTL_FUNC;
6752         fct_sc = S_FUNC_MON;
6753         break;
6754 
6755     case RIG_FUNC_MN: fct_cn = C_CTL_FUNC;
6756         fct_sc = S_FUNC_MN;
6757         break;
6758 
6759     case RIG_FUNC_RF: fct_cn = C_CTL_FUNC;
6760         fct_sc = S_FUNC_RF;
6761         break;
6762 
6763     case RIG_FUNC_VSC: fct_cn = C_CTL_FUNC;
6764         fct_sc = S_FUNC_VSC;
6765         break;
6766 
6767     case RIG_FUNC_LOCK: fct_cn = C_CTL_FUNC;
6768         fct_sc = S_FUNC_DIAL_LK;
6769         break;
6770 
6771     case RIG_FUNC_AFC:    /* IC-910H */
6772         fct_cn = C_CTL_FUNC;
6773         fct_sc = S_FUNC_AFC;
6774         break;
6775 
6776     case RIG_FUNC_SCOPE:
6777         fct_cn = C_CTL_SCP;
6778         fct_sc = S_SCP_STS;
6779         break;
6780 
6781     case RIG_FUNC_SPECTRUM:
6782         fct_cn = C_CTL_SCP;
6783         fct_sc = S_SCP_DOP;
6784         break;
6785 
6786     case RIG_FUNC_SPECTRUM_HOLD:
6787         fct_cn = C_CTL_SCP;
6788         fct_sc = S_SCP_HLD;
6789 
6790         fctbuf[0] = icom_get_spectrum_vfo(rig, vfo);
6791         fct_len = 1;
6792         break;
6793 
6794     case RIG_FUNC_AIP:    /* IC-R8600 IP+ function, misusing AIP since RIG_FUNC_ word is full (32 bit) */
6795         fct_cn = C_CTL_MEM;   /* 1a */
6796         fct_sc = S_FUNC_IPPLUS;
6797         break;
6798 
6799     case RIG_FUNC_CSQL: fct_cn = C_CTL_FUNC;
6800         fct_sc = S_FUNC_CSQL;
6801         break;
6802 
6803     case RIG_FUNC_DSQL: fct_cn = C_CTL_FUNC;
6804         fct_sc = S_FUNC_DSSQL;
6805         break;
6806 
6807     case RIG_FUNC_AFLT: fct_cn = C_CTL_MEM;
6808         fct_sc = S_MEM_AFLT;
6809         break;
6810 
6811     case RIG_FUNC_ANL: fct_cn = C_CTL_MEM;
6812         fct_sc = S_MEM_ANL;
6813         break;
6814 
6815     case RIG_FUNC_RIT: fct_cn = C_CTL_RIT;
6816         fct_sc = S_RIT;
6817         break;
6818 
6819     case RIG_FUNC_XIT: fct_cn = C_CTL_RIT;
6820         fct_sc = S_XIT;
6821         break;
6822 
6823     case RIG_FUNC_TUNER: fct_cn = C_CTL_PTT;
6824         fct_sc = S_ANT_TUN;
6825         break;
6826 
6827     case RIG_FUNC_DUAL_WATCH: fct_cn = C_SET_VFO;
6828         fct_sc = S_DUAL;
6829         break;
6830 
6831     case RIG_FUNC_SATMODE:
6832         if (rig->caps->rig_model == RIG_MODEL_IC910)
6833         {
6834             // Is the 910 the only one that uses this command?
6835             fct_cn = C_CTL_MEM;
6836             fct_sc = S_MEM_SATMODE910;
6837         }
6838         else
6839         {
6840             fct_cn = C_CTL_FUNC;
6841             fct_sc = S_MEM_SATMODE;
6842         }
6843 
6844         break;
6845 
6846     default:
6847         rig_debug(RIG_DEBUG_ERR, "%s: unsupported get_func %s\n", __func__,
6848                   rig_strfunc(func));
6849         RETURNFUNC(-RIG_EINVAL);
6850     }
6851 
6852     retval = icom_transaction(rig, fct_cn, fct_sc, fctbuf, fct_len, ackbuf,
6853                               &ack_len);
6854 
6855     if (retval != RIG_OK)
6856     {
6857         RETURNFUNC(retval);
6858     }
6859 
6860     if (ack_len != (3 + fct_len))
6861     {
6862         rig_debug(RIG_DEBUG_ERR, "%s: wrong frame len=%d\n", __func__,
6863                   ack_len);
6864         RETURNFUNC(-RIG_EPROTO);
6865     }
6866 
6867     if (func == RIG_FUNC_FBKIN)
6868     {
6869         *status = ackbuf[2] == 2 ? 1 : 0;
6870     }
6871     else if (func == RIG_FUNC_SATMODE)
6872     {
6873         struct rig_state *rs = &rig->state;
6874         struct icom_priv_data *priv = rs->priv;
6875 
6876         *status = ackbuf[2 + fct_len];
6877 
6878         // we'll reset this based on current status
6879         priv->x25cmdfails = *status;
6880     }
6881     else
6882     {
6883         *status = ackbuf[2 + fct_len];
6884     }
6885 
6886     RETURNFUNC(RIG_OK);
6887 }
6888 
6889 /*
6890  * icom_set_parm
6891  * Assumes rig!=NULL
6892  *
6893  * NOTE: Most of the parm commands are rig-specific.
6894  *
6895  * See the IC-7300 backend how to implement them for newer rigs that have 0x1A 0x05-based commands.
6896  *
6897  * For older rigs, see the IC-R75 backend where icom_set_raw()/icom_get_raw() are used.
6898  */
icom_set_parm(RIG * rig,setting_t parm,value_t val)6899 int icom_set_parm(RIG *rig, setting_t parm, value_t val)
6900 {
6901     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6902 
6903     int i;
6904     const struct icom_priv_caps *priv = rig->caps->priv;
6905     const struct cmdparams *extcmds = priv->extcmds;
6906 
6907     for (i = 0; extcmds && extcmds[i].id.s != 0; i++)
6908     {
6909         if (extcmds[i].cmdparamtype == CMD_PARAM_TYPE_PARM && extcmds[i].id.s == parm)
6910         {
6911             RETURNFUNC(icom_set_cmd(rig, RIG_VFO_NONE, (struct cmdparams *)&extcmds[i],
6912                                     val));
6913         }
6914     }
6915 
6916     switch (parm)
6917     {
6918     case RIG_PARM_ANN:
6919     {
6920         int ann_mode;
6921 
6922         switch (val.i)
6923         {
6924         case RIG_ANN_OFF:
6925             ann_mode = S_ANN_ALL;
6926             break;
6927 
6928         case RIG_ANN_FREQ:
6929             ann_mode = S_ANN_FREQ;
6930             break;
6931 
6932         case RIG_ANN_RXMODE:
6933             ann_mode = S_ANN_MODE;
6934             break;
6935 
6936         default:
6937             rig_debug(RIG_DEBUG_ERR, "%s: unsupported RIG_PARM_ANN %d\n",
6938                       __func__, val.i);
6939             RETURNFUNC(-RIG_EINVAL);
6940         }
6941 
6942         RETURNFUNC(icom_set_raw(rig, C_CTL_ANN, ann_mode, 0, NULL, 0, 0));
6943     }
6944 
6945     default:
6946         rig_debug(RIG_DEBUG_ERR, "%s: unsupported set_parm %s\n", __func__,
6947                   rig_strparm(parm));
6948         RETURNFUNC(-RIG_EINVAL);
6949     }
6950 }
6951 
6952 /*
6953  * icom_get_parm
6954  * Assumes rig!=NULL
6955  *
6956  * NOTE: Most of the parm commands are rig-specific.
6957  *
6958  * See the IC-7300 backend how to implement them for newer rigs that have 0x1A 0x05-based commands.
6959  *
6960  * For older rigs, see the IC-R75 backend where icom_set_raw()/icom_get_raw() are used.
6961  */
icom_get_parm(RIG * rig,setting_t parm,value_t * val)6962 int icom_get_parm(RIG *rig, setting_t parm, value_t *val)
6963 {
6964     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
6965 
6966     const struct icom_priv_caps *priv = rig->caps->priv;
6967     const struct cmdparams *cmd = priv->extcmds;
6968     int i;
6969 
6970     for (i = 0; cmd && cmd[i].id.s != 0; i++)
6971     {
6972         if (cmd[i].cmdparamtype == CMD_PARAM_TYPE_PARM && cmd[i].id.s == parm)
6973         {
6974             RETURNFUNC(icom_get_cmd(rig, RIG_VFO_NONE, (struct cmdparams *)&cmd[i], val));
6975         }
6976     }
6977 
6978     switch (parm)
6979     {
6980     default:
6981         rig_debug(RIG_DEBUG_ERR, "%s: unsupported get_parm %s", __func__,
6982                   rig_strparm(parm));
6983         RETURNFUNC(-RIG_EINVAL);
6984     }
6985 
6986     RETURNFUNC(RIG_OK);
6987 }
6988 
6989 /*
6990  * icom_set_ctcss_tone
6991  * Assumes rig!=NULL, rig->state.priv!=NULL
6992  *
6993  * Works for 746 pro and should work for 756 xx and 7800
6994  */
icom_set_ctcss_tone(RIG * rig,vfo_t vfo,tone_t tone)6995 int icom_set_ctcss_tone(RIG *rig, vfo_t vfo, tone_t tone)
6996 {
6997     const struct rig_caps *caps;
6998     unsigned char tonebuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
6999     int tone_len, ack_len = sizeof(ackbuf), retval;
7000 
7001     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7002     caps = rig->caps;
7003 
7004     if (caps->ctcss_list)
7005     {
7006         int i;
7007 
7008         for (i = 0; caps->ctcss_list[i] != 0; i++)
7009         {
7010             if (caps->ctcss_list[i] == tone)
7011             {
7012                 break;
7013             }
7014         }
7015 
7016         if (caps->ctcss_list[i] != tone)
7017         {
7018             RETURNFUNC(-RIG_EINVAL);
7019         }
7020     }
7021 
7022     /* Sent as frequency in tenth of Hz */
7023 
7024     tone_len = 3;
7025     to_bcd_be(tonebuf, tone, tone_len * 2);
7026 
7027     retval = icom_transaction(rig, C_SET_TONE, S_TONE_RPTR,
7028                               tonebuf, tone_len, ackbuf, &ack_len);
7029 
7030     if (retval != RIG_OK)
7031     {
7032         RETURNFUNC(retval);
7033     }
7034 
7035     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7036     {
7037         //  if we don't get ACK/NAK some serial corruption occurred
7038         // so we'll call it a timeout for retry purposes
7039         RETURNFUNC(-RIG_ETIMEOUT);
7040     }
7041 
7042     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7043     {
7044         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7045                   ackbuf[0], ack_len);
7046         RETURNFUNC(-RIG_ERJCTED);
7047     }
7048 
7049     RETURNFUNC(RIG_OK);
7050 }
7051 
7052 /*
7053  * icom_get_ctcss_tone
7054  * Assumes rig!=NULL, rig->state.priv!=NULL
7055  */
icom_get_ctcss_tone(RIG * rig,vfo_t vfo,tone_t * tone)7056 int icom_get_ctcss_tone(RIG *rig, vfo_t vfo, tone_t *tone)
7057 {
7058     const struct rig_caps *caps;
7059     unsigned char tonebuf[MAXFRAMELEN];
7060     int tone_len, retval;
7061     int i;
7062 
7063     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7064     caps = rig->caps;
7065 
7066     retval = icom_transaction(rig, C_SET_TONE, S_TONE_RPTR, NULL, 0,
7067                               tonebuf, &tone_len);
7068 
7069     if (retval != RIG_OK)
7070     {
7071         RETURNFUNC(retval);
7072     }
7073 
7074     /* cn,sc,data*3 */
7075     if (tone_len != 5)
7076     {
7077         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7078                   tonebuf[0], tone_len);
7079         RETURNFUNC(-RIG_ERJCTED);
7080     }
7081 
7082     tone_len -= 2;
7083     *tone = from_bcd_be(tonebuf + 2, tone_len * 2);
7084 
7085     if (!caps->ctcss_list)
7086     {
7087         RETURNFUNC(RIG_OK);
7088     }
7089 
7090     /* check this tone exists. That's better than nothing. */
7091     for (i = 0; caps->ctcss_list[i] != 0; i++)
7092     {
7093         if (caps->ctcss_list[i] == *tone)
7094         {
7095             RETURNFUNC(RIG_OK);
7096         }
7097     }
7098 
7099     rig_debug(RIG_DEBUG_ERR, "%s: CTCSS NG (%#.2x)\n", __func__, tonebuf[2]);
7100     RETURNFUNC(-RIG_EPROTO);
7101 }
7102 
7103 /*
7104  * icom_set_ctcss_sql
7105  * Assumes rig!=NULL, rig->state.priv!=NULL
7106  */
icom_set_ctcss_sql(RIG * rig,vfo_t vfo,tone_t tone)7107 int icom_set_ctcss_sql(RIG *rig, vfo_t vfo, tone_t tone)
7108 {
7109     const struct rig_caps *caps;
7110     unsigned char tonebuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
7111     int tone_len, ack_len = sizeof(ackbuf), retval;
7112     int i;
7113 
7114     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7115     caps = rig->caps;
7116 
7117     for (i = 0; caps->ctcss_list[i] != 0; i++)
7118     {
7119         if (caps->ctcss_list[i] == tone)
7120         {
7121             break;
7122         }
7123     }
7124 
7125     if (caps->ctcss_list[i] != tone)
7126     {
7127         RETURNFUNC(-RIG_EINVAL);
7128     }
7129 
7130     /* Sent as frequency in tenth of Hz */
7131 
7132     tone_len = 3;
7133     to_bcd_be(tonebuf, tone, tone_len * 2);
7134 
7135     retval = icom_transaction(rig, C_SET_TONE, S_TONE_SQL,
7136                               tonebuf, tone_len, ackbuf, &ack_len);
7137 
7138     if (retval != RIG_OK)
7139     {
7140         RETURNFUNC(retval);
7141     }
7142 
7143     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7144     {
7145         //  if we don't get ACK/NAK some serial corruption occurred
7146         // so we'll call it a timeout for retry purposes
7147         RETURNFUNC(-RIG_ETIMEOUT);
7148     }
7149 
7150     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7151     {
7152         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7153                   ackbuf[0], ack_len);
7154         RETURNFUNC(-RIG_ERJCTED);
7155     }
7156 
7157     RETURNFUNC(RIG_OK);
7158 }
7159 
7160 /*
7161  * icom_get_ctcss_sql
7162  * Assumes rig!=NULL, rig->state.priv!=NULL
7163  */
icom_get_ctcss_sql(RIG * rig,vfo_t vfo,tone_t * tone)7164 int icom_get_ctcss_sql(RIG *rig, vfo_t vfo, tone_t *tone)
7165 {
7166     const struct rig_caps *caps;
7167     unsigned char tonebuf[MAXFRAMELEN];
7168     int tone_len, retval;
7169     int i;
7170 
7171     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7172     caps = rig->caps;
7173 
7174     retval = icom_transaction(rig, C_SET_TONE, S_TONE_SQL, NULL, 0,
7175                               tonebuf, &tone_len);
7176 
7177     if (retval != RIG_OK)
7178     {
7179         RETURNFUNC(retval);
7180     }
7181 
7182     if (tone_len != 5)
7183     {
7184         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7185                   tonebuf[0], tone_len);
7186         RETURNFUNC(-RIG_ERJCTED);
7187     }
7188 
7189     tone_len -= 2;
7190     *tone = from_bcd_be(tonebuf + 2, tone_len * 2);
7191 
7192     /* check this tone exists. That's better than nothing. */
7193     for (i = 0; caps->ctcss_list[i] != 0; i++)
7194     {
7195         if (caps->ctcss_list[i] == *tone)
7196         {
7197             RETURNFUNC(RIG_OK);
7198         }
7199     }
7200 
7201     rig_debug(RIG_DEBUG_ERR, "%s: CTCSS NG (%#.2x)\n", __func__, tonebuf[2]);
7202     RETURNFUNC(-RIG_EPROTO);
7203 }
7204 
7205 /*
7206  * icom_set_dcs_code
7207  * Assumes rig!=NULL, rig->state.priv!=NULL
7208  */
icom_set_dcs_code(RIG * rig,vfo_t vfo,tone_t code)7209 int icom_set_dcs_code(RIG *rig, vfo_t vfo, tone_t code)
7210 {
7211     const struct rig_caps *caps;
7212     unsigned char codebuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
7213     int code_len, ack_len = sizeof(ackbuf), retval;
7214     int i;
7215 
7216     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7217     caps = rig->caps;
7218 
7219     for (i = 0; caps->dcs_list[i] != 0; i++)
7220     {
7221         if (caps->dcs_list[i] == code)
7222         {
7223             break;
7224         }
7225     }
7226 
7227     if (caps->dcs_list[i] != code)
7228     {
7229         RETURNFUNC(-RIG_EINVAL);
7230     }
7231 
7232     /* DCS Polarity ignored, by setting code_len to 3 it's foretval to 0 (= Tx:norm, Rx:norm). */
7233     code_len = 3;
7234     to_bcd_be(codebuf, code, code_len * 2);
7235 
7236     retval = icom_transaction(rig, C_SET_TONE, S_TONE_DTCS,
7237                               codebuf, code_len, ackbuf, &ack_len);
7238 
7239     if (retval != RIG_OK)
7240     {
7241         RETURNFUNC(retval);
7242     }
7243 
7244     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7245     {
7246         //  if we don't get ACK/NAK some serial corruption occurred
7247         // so we'll call it a timeout for retry purposes
7248         RETURNFUNC(-RIG_ETIMEOUT);
7249     }
7250 
7251     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7252     {
7253         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7254                   ackbuf[0], ack_len);
7255         RETURNFUNC(-RIG_ERJCTED);
7256     }
7257 
7258     RETURNFUNC(RIG_OK);
7259 }
7260 
7261 /*
7262  * icom_get_dcs_code
7263  * Assumes rig!=NULL, rig->state.priv!=NULL
7264  */
icom_get_dcs_code(RIG * rig,vfo_t vfo,tone_t * code)7265 int icom_get_dcs_code(RIG *rig, vfo_t vfo, tone_t *code)
7266 {
7267     const struct rig_caps *caps;
7268     unsigned char codebuf[MAXFRAMELEN];
7269     int code_len, retval;
7270     int i;
7271 
7272     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7273     caps = rig->caps;
7274 
7275     retval = icom_transaction(rig, C_SET_TONE, S_TONE_DTCS, NULL, 0,
7276                               codebuf, &code_len);
7277 
7278     if (retval != RIG_OK)
7279     {
7280         RETURNFUNC(retval);
7281     }
7282 
7283     /* cn,sc,data*3 */
7284     if (code_len != 5)
7285     {
7286         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7287                   codebuf[0], code_len);
7288         RETURNFUNC(-RIG_ERJCTED);
7289     }
7290 
7291     /* buf is cn,sc, polarity, code_lo, code_hi, so code bytes start at 3, len is 2
7292        polarity is not decoded yet, hard to do without breaking ABI
7293      */
7294 
7295     code_len -= 3;
7296     *code = from_bcd_be(codebuf + 3, code_len * 2);
7297 
7298     /* check this code exists. That's better than nothing. */
7299     for (i = 0; caps->dcs_list[i] != 0; i++)
7300     {
7301         if (caps->dcs_list[i] == *code)
7302         {
7303             RETURNFUNC(RIG_OK);
7304         }
7305     }
7306 
7307     rig_debug(RIG_DEBUG_ERR, "%s: DTCS NG (%#.2x)\n", __func__, codebuf[2]);
7308     RETURNFUNC(-RIG_EPROTO);
7309 }
7310 
7311 /*
7312  * icom_set_dcs_sql
7313  * Assumes rig!=NULL, rig->state.priv!=NULL
7314  */
icom_set_dcs_sql(RIG * rig,vfo_t vfo,tone_t code)7315 int icom_set_dcs_sql(RIG *rig, vfo_t vfo, tone_t code)
7316 {
7317     const struct rig_caps *caps;
7318     unsigned char codebuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
7319     int code_len, ack_len = sizeof(ackbuf), retval;
7320     int i;
7321 
7322     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7323     caps = rig->caps;
7324 
7325     for (i = 0; caps->dcs_list[i] != 0; i++)
7326     {
7327         if (caps->dcs_list[i] == code)
7328         {
7329             break;
7330         }
7331     }
7332 
7333     if (caps->dcs_list[i] != code)
7334     {
7335         RETURNFUNC(-RIG_EINVAL);
7336     }
7337 
7338     /* DCS Polarity ignored, by setting code_len to 3 it's forced to 0 (= Tx:norm, Rx:norm). */
7339     code_len = 3;
7340     to_bcd_be(codebuf, code, code_len * 2);
7341 
7342     retval = icom_transaction(rig, C_SET_TONE, S_TONE_DTCS,
7343                               codebuf, code_len, ackbuf, &ack_len);
7344 
7345     if (retval != RIG_OK)
7346     {
7347         RETURNFUNC(retval);
7348     }
7349 
7350     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7351     {
7352         //  if we don't get ACK/NAK some serial corruption occurred
7353         // so we'll call it a timeout for retry purposes
7354         RETURNFUNC(-RIG_ETIMEOUT);
7355     }
7356 
7357     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7358     {
7359         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7360                   ackbuf[0], ack_len);
7361         RETURNFUNC(-RIG_ERJCTED);
7362     }
7363 
7364     RETURNFUNC(RIG_OK);
7365 }
7366 
7367 /*
7368  * icom_get_dcs_sql
7369  * Assumes rig!=NULL, rig->state.priv!=NULL
7370  */
icom_get_dcs_sql(RIG * rig,vfo_t vfo,tone_t * code)7371 int icom_get_dcs_sql(RIG *rig, vfo_t vfo, tone_t *code)
7372 {
7373     const struct rig_caps *caps;
7374     unsigned char codebuf[MAXFRAMELEN];
7375     int code_len, retval;
7376     int i;
7377 
7378     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7379     caps = rig->caps;
7380 
7381     retval = icom_transaction(rig, C_SET_TONE, S_TONE_DTCS, NULL, 0,
7382                               codebuf, &code_len);
7383 
7384     if (retval != RIG_OK)
7385     {
7386         RETURNFUNC(retval);
7387     }
7388 
7389     /* cn,sc,data*3 */
7390     if (code_len != 5)
7391     {
7392         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7393                   codebuf[0], code_len);
7394         RETURNFUNC(-RIG_ERJCTED);
7395     }
7396 
7397     /* buf is cn,sc, polarity, code_lo, code_hi, so code bytes start at 3, len is 2
7398        polarity is not decoded yet, hard to do without breaking ABI
7399      */
7400 
7401     code_len -= 3;
7402     *code = from_bcd_be(codebuf + 3, code_len * 2);
7403 
7404     /* check this code exists. That's better than nothing. */
7405     for (i = 0; caps->dcs_list[i] != 0; i++)
7406     {
7407         if (caps->dcs_list[i] == *code)
7408         {
7409             RETURNFUNC(RIG_OK);
7410         }
7411     }
7412 
7413     rig_debug(RIG_DEBUG_ERR, "%s: DTCS NG (%#.2x)\n", __func__, codebuf[2]);
7414     RETURNFUNC(-RIG_EPROTO);
7415 }
7416 
7417 /*
7418  * icom_set_powerstat
7419  * Assumes rig!=NULL, rig->state.priv!=NULL
7420  */
icom_set_powerstat(RIG * rig,powerstat_t status)7421 int icom_set_powerstat(RIG *rig, powerstat_t status)
7422 {
7423     unsigned char ackbuf[200];
7424     int ack_len = sizeof(ackbuf), retval = RIG_OK;
7425     int pwr_sc;
7426     // so we'll do up to 175 for 115,200
7427     int fe_max = 175;
7428     unsigned char fe_buf[fe_max]; // for FE's to power up
7429     int i;
7430     int retry;
7431     struct rig_state *rs = &rig->state;
7432     struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
7433 
7434     rig_debug(RIG_DEBUG_VERBOSE, "%s called status=%d\n", __func__,
7435               (int) status);
7436 
7437     switch (status)
7438     {
7439     case RIG_POWER_ON:
7440 
7441         sleep(1);         // let serial bus idle for a while
7442         rig_debug(RIG_DEBUG_TRACE, "%s: PWR_ON failed, trying 0xfe's\n",
7443                   __func__);
7444         // ic7300 manual says ~150 for 115,200
7445         // we'll just send a few more to be sure for all speeds
7446         memset(fe_buf, 0xfe, fe_max);
7447         // sending more than enough 0xfe's to wake up the rs232
7448         write_block(&rs->rigport, (char *) fe_buf, fe_max);
7449 
7450         hl_usleep(100 * 1000);
7451         // we'll try 0x18 0x01 now -- should work on STBY rigs too
7452         pwr_sc = S_PWR_ON;
7453         fe_buf[0] = 0;
7454         retry = rs->rigport.retry;
7455         rs->rigport.retry = 0;
7456         priv->serial_USB_echo_off = 1;
7457         retval =
7458             icom_transaction(rig, C_SET_PWR, pwr_sc, NULL, 0, ackbuf, &ack_len);
7459         rs->rigport.retry = retry;
7460         // why was this sleep here?  We'll try without it
7461         //hl_usleep(3000 * 1000); // give it 3 seconds to wake up
7462 
7463         break;
7464 
7465     default:
7466         pwr_sc = S_PWR_OFF;
7467         fe_buf[0] = 0;
7468         retry = rs->rigport.retry;
7469         rs->rigport.retry = 0;
7470         retval =
7471             icom_transaction(rig, C_SET_PWR, pwr_sc, NULL, 0, ackbuf, &ack_len);
7472         rs->rigport.retry = retry;
7473     }
7474 
7475     i = 0;
7476     retry = 1;
7477 
7478     if (status == RIG_POWER_ON)   // wait for wakeup only
7479     {
7480 
7481         for (i = 0; i < retry; ++i)   // up to 10 attempts
7482         {
7483             freq_t freq;
7484             sleep(1);
7485             // need to see if echo is on or not first
7486             // until such time as rig is awake we don't know
7487             icom_get_usb_echo_off(rig);
7488 
7489             // Use get_freq as all rigs should repond to this
7490             retval = rig_get_freq(rig, RIG_VFO_CURR, &freq);
7491 
7492             if (retval == RIG_OK)
7493             {
7494                 RETURNFUNC(retval);
7495             }
7496             else
7497             {
7498                 rig_debug(RIG_DEBUG_TRACE, "%s: get_freq err=%s\n", __func__,
7499                           rigerror(retval));
7500             }
7501 
7502             rig_debug(RIG_DEBUG_TRACE, "%s: Wait %d of %d for get_powerstat\n",
7503                       __func__, i + 1, retry);
7504         }
7505     }
7506 
7507     if (i == retry)
7508     {
7509         rig_debug(RIG_DEBUG_TRACE, "%s: Wait failed for get_powerstat\n",
7510                   __func__);
7511         retval = -RIG_ETIMEOUT;
7512     }
7513 
7514     if (retval != RIG_OK)
7515     {
7516         rig_debug(RIG_DEBUG_TRACE, "%s: retval != RIG_OK, =%s\n", __func__,
7517                   rigerror(retval));
7518         RETURNFUNC(retval);
7519     }
7520 
7521     if (status == RIG_POWER_OFF && (ack_len != 1 || (ack_len >= 1
7522                                     && ackbuf[0] != ACK)))
7523     {
7524         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7525                   ackbuf[0], ack_len);
7526         RETURNFUNC(-RIG_ERJCTED);
7527     }
7528 
7529     RETURNFUNC(RIG_OK);
7530 }
7531 
7532 /*
7533  * icom_get_powerstat
7534  * Assumes rig!=NULL, rig->state.priv!=NULL
7535  */
icom_get_powerstat(RIG * rig,powerstat_t * status)7536 int icom_get_powerstat(RIG *rig, powerstat_t *status)
7537 {
7538     unsigned char ackbuf[MAXFRAMELEN];
7539     int ack_len = sizeof(ackbuf), retval;
7540 
7541     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7542 
7543     /* r75 has no way to get power status, so fake it */
7544     if (rig->caps->rig_model == RIG_MODEL_ICR75)
7545     {
7546         /* getting the mode doesn't work if a memory is blank */
7547         /* so use one of the more innculous 'set mode' commands instead */
7548         int cmd_len = 1;
7549         unsigned char cmdbuf[MAXFRAMELEN];
7550         cmdbuf[0] = S_PRM_TIME;
7551         retval = icom_transaction(rig, C_CTL_MEM, S_MEM_MODE_SLCT,
7552                                   cmdbuf, cmd_len, ackbuf, &ack_len);
7553 
7554         if (retval != RIG_OK)
7555         {
7556             RETURNFUNC(retval);
7557         }
7558 
7559         *status = ((ack_len == 6) && (ackbuf[0] == C_CTL_MEM)) ?
7560                   RIG_POWER_ON : RIG_POWER_OFF;
7561     }
7562     else
7563     {
7564         retval = icom_transaction(rig, C_SET_PWR, -1, NULL, 0,
7565                                   ackbuf, &ack_len);
7566 
7567         if (retval != RIG_OK)
7568         {
7569             RETURNFUNC(retval);
7570         }
7571 
7572         *status = ackbuf[1] == S_PWR_ON ? RIG_POWER_ON : RIG_POWER_OFF;
7573     }
7574 
7575     RETURNFUNC(RIG_OK);
7576 }
7577 
7578 
7579 /*
7580  * icom_set_mem
7581  * Assumes rig!=NULL, rig->state.priv!=NULL
7582  */
icom_set_mem(RIG * rig,vfo_t vfo,int ch)7583 int icom_set_mem(RIG *rig, vfo_t vfo, int ch)
7584 {
7585     unsigned char membuf[2];
7586     unsigned char ackbuf[MAXFRAMELEN];
7587     int ack_len = sizeof(ackbuf), retval;
7588     int chan_len;
7589 
7590     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7591     chan_len = ch < 100 ? 1 : 2;
7592 
7593     to_bcd_be(membuf, ch, chan_len * 2);
7594     retval = icom_transaction(rig, C_SET_MEM, -1, membuf, chan_len,
7595                               ackbuf, &ack_len);
7596 
7597     if (retval != RIG_OK)
7598     {
7599         RETURNFUNC(retval);
7600     }
7601 
7602     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7603     {
7604         //  if we don't get ACK/NAK some serial corruption occurred
7605         // so we'll call it a timeout for retry purposes
7606         RETURNFUNC(-RIG_ETIMEOUT);
7607     }
7608 
7609     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7610     {
7611         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7612                   ackbuf[0], ack_len);
7613         RETURNFUNC(-RIG_ERJCTED);
7614     }
7615 
7616     RETURNFUNC(RIG_OK);
7617 }
7618 
7619 /*
7620  * icom_set_bank
7621  * Assumes rig!=NULL, rig->state.priv!=NULL
7622  */
icom_set_bank(RIG * rig,vfo_t vfo,int bank)7623 int icom_set_bank(RIG *rig, vfo_t vfo, int bank)
7624 {
7625     unsigned char bankbuf[2];
7626     unsigned char ackbuf[MAXFRAMELEN];
7627     int ack_len = sizeof(ackbuf), retval;
7628 
7629     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7630     to_bcd_be(bankbuf, bank, BANK_NB_LEN * 2);
7631     retval = icom_transaction(rig, C_SET_MEM, S_BANK,
7632                               bankbuf, CHAN_NB_LEN, ackbuf, &ack_len);
7633 
7634     if (retval != RIG_OK)
7635     {
7636         RETURNFUNC(retval);
7637     }
7638 
7639     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7640     {
7641         //  if we don't get ACK/NAK some serial corruption occurred
7642         // so we'll call it a timeout for retry purposes
7643         RETURNFUNC(-RIG_ETIMEOUT);
7644     }
7645 
7646     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7647     {
7648         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7649                   ackbuf[0], ack_len);
7650         RETURNFUNC(-RIG_ERJCTED);
7651     }
7652 
7653     RETURNFUNC(RIG_OK);
7654 }
7655 
7656 /*
7657  * icom_set_ant
7658  * Assumes rig!=NULL, rig->state.priv!=NULL
7659  */
icom_set_ant(RIG * rig,vfo_t vfo,ant_t ant,value_t option)7660 int icom_set_ant(RIG *rig, vfo_t vfo, ant_t ant, value_t option)
7661 {
7662     unsigned char antopt[2];
7663     unsigned char ackbuf[MAXFRAMELEN];
7664     int ack_len = sizeof(ackbuf), retval, i_ant = 0;
7665     int antopt_len = 0;
7666     const struct icom_priv_caps *priv_caps = (const struct icom_priv_caps *)
7667             rig->caps->priv;
7668 
7669     rig_debug(RIG_DEBUG_VERBOSE,
7670               "%s called, ant=0x%02x, option=%d, antack_len=%d\n", __func__, ant, option.i,
7671               priv_caps->antack_len);
7672 
7673     // query the antennas once and find out how many we have
7674     if (ant >= rig_idx2setting(priv_caps->ant_count))
7675     {
7676         RETURNFUNC(-RIG_EINVAL);
7677     }
7678 
7679     if (ant > RIG_ANT_4)
7680     {
7681         RETURNFUNC(-RIG_EDOM);
7682     }
7683 
7684     switch (ant)
7685     {
7686     case RIG_ANT_1:
7687         i_ant = 0;
7688         break;
7689 
7690     case RIG_ANT_2:
7691         i_ant = 1;
7692         break;
7693 
7694     case RIG_ANT_3:
7695         i_ant = 2;
7696         break;
7697 
7698     case RIG_ANT_4:
7699         i_ant = 3;
7700         break;
7701 
7702     default:
7703         rig_debug(RIG_DEBUG_ERR, "%s: unsupported ant %#x", __func__, ant);
7704         RETURNFUNC(-RIG_EINVAL);
7705     }
7706 
7707 
7708     if (priv_caps->antack_len == 0)   // we need to find out the antack_len
7709     {
7710         ant_t tmp_ant, ant_tx, ant_rx;
7711         int ant0 = 0;
7712         value_t tmp_option;
7713         retval = rig_get_ant(rig, vfo, ant0, &tmp_option, &tmp_ant, &ant_tx, &ant_rx);
7714 
7715         if (retval != RIG_OK)
7716         {
7717             rig_debug(RIG_DEBUG_ERR, "%s: rig_get_ant error: %s \n", __func__,
7718                       rigerror(retval));
7719             RETURNFUNC(retval);
7720         }
7721     }
7722 
7723     // Some rigs have 3-byte ant cmd so there is an option to be set too
7724     if (priv_caps->antack_len == 3)
7725     {
7726         if (option.i != 0 && option.i != 1)
7727         {
7728             rig_debug(RIG_DEBUG_ERR, "%s: option.i != 0 or 1, ==%d?\n", __func__, option.i);
7729             RETURNFUNC(-RIG_EINVAL);
7730         }
7731 
7732         antopt_len = 1;
7733         antopt[0] = option.i;
7734         // we have to set the rx option by itself apparently
7735         rig_debug(RIG_DEBUG_TRACE, "%s: setting antopt=%d\n", __func__, antopt[0]);
7736         retval = icom_transaction(rig, C_CTL_ANT, i_ant,
7737                                   antopt, antopt_len, ackbuf, &ack_len);
7738 
7739         if (retval != RIG_OK)
7740         {
7741             RETURNFUNC(retval);
7742         }
7743 
7744         rig_debug(RIG_DEBUG_TRACE,
7745                   "%s: antack_len=%d so antopt_len=%d, antopt=0x%02x\n",
7746                   __func__, priv_caps->antack_len, antopt_len, antopt[0]);
7747     }
7748     else if (priv_caps->antack_len == 2)
7749     {
7750         antopt_len = 0;
7751         rig_debug(RIG_DEBUG_TRACE, "%s: antack_len=%d so antopt_len=%d\n", __func__,
7752                   priv_caps->antack_len, antopt_len);
7753     }
7754     else
7755     {
7756         rig_debug(RIG_DEBUG_TRACE, "%s: antack_len=%d so antopt_len=%d\n", __func__,
7757                   priv_caps->antack_len, antopt_len);
7758         antopt_len = 0;
7759         rig_debug(RIG_DEBUG_ERR,
7760                   "%s: rig does not have antenna select? antack_len=%d\n", __func__,
7761                   priv_caps->antack_len);
7762     }
7763 
7764     rig_debug(RIG_DEBUG_TRACE, "%s: i_ant=%d, antopt=0x%02x, antopt_len=%d\n",
7765               __func__, i_ant, antopt[0], antopt_len);
7766     retval = icom_transaction(rig, C_CTL_ANT, i_ant,
7767                               antopt, antopt_len, ackbuf, &ack_len);
7768 
7769     if (retval != RIG_OK)
7770     {
7771         RETURNFUNC(retval);
7772     }
7773 
7774     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7775     {
7776         //  if we don't get ACK/NAK some serial corruption occurred
7777         // so we'll call it a timeout for retry purposes
7778         RETURNFUNC(-RIG_ETIMEOUT);
7779     }
7780 
7781     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7782     {
7783         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7784                   ackbuf[0], ack_len);
7785         RETURNFUNC(-RIG_ERJCTED);
7786     }
7787 
7788     RETURNFUNC(RIG_OK);
7789 }
7790 
7791 /*
7792  * icom_get_ant
7793  * Assumes rig!=NULL, rig->state.priv!=NULL
7794  * only meaningful for HF
7795  */
icom_get_ant(RIG * rig,vfo_t vfo,ant_t ant,value_t * option,ant_t * ant_curr,ant_t * ant_tx,ant_t * ant_rx)7796 int icom_get_ant(RIG *rig, vfo_t vfo, ant_t ant, value_t *option,
7797                  ant_t *ant_curr, ant_t *ant_tx, ant_t *ant_rx)
7798 {
7799     unsigned char ackbuf[MAXFRAMELEN];
7800     int ack_len = sizeof(ackbuf), retval;
7801     struct icom_priv_caps *priv_caps = (struct icom_priv_caps *) rig->caps->priv;
7802 
7803 
7804     rig_debug(RIG_DEBUG_VERBOSE, "%s called, ant=0x%02x\n", __func__, ant);
7805 
7806     if (ant != RIG_ANT_CURR)
7807     {
7808         ant = rig_setting2idx(ant);
7809 
7810         if (ant >= priv_caps->ant_count)
7811         {
7812             rig_debug(RIG_DEBUG_ERR, "%s: ant index=%u > ant_count=%d\n", __func__, ant,
7813                       priv_caps->ant_count);
7814             RETURNFUNC(-RIG_EINVAL);
7815         }
7816     }
7817 
7818     // Should be able to use just C_CTL_ANT for 1 or 2 antennas hopefully
7819     if (ant == RIG_ANT_CURR || priv_caps->ant_count <= 2)
7820     {
7821         retval = icom_transaction(rig, C_CTL_ANT, -1, NULL, 0, ackbuf, &ack_len);
7822     }
7823     else if (rig->caps->rig_model == RIG_MODEL_IC785x)
7824     {
7825         unsigned char buf[2];
7826         buf[0] = 0x03;
7827         buf[1] = 0x05 + ant;
7828         *ant_curr = ant;
7829         retval = icom_transaction(rig, C_CTL_MEM, 0x05, buf, sizeof(buf), ackbuf,
7830                                   &ack_len);
7831 
7832         if (retval == RIG_OK)
7833         {
7834             option->i = ackbuf[4];
7835             RETURNFUNC(RIG_OK);
7836         }
7837     }
7838     else
7839     {
7840         rig_debug(RIG_DEBUG_ERR,
7841                   "%s: asking for non-current antenna and ant_count==0?\n", __func__);
7842         rig_debug(RIG_DEBUG_ERR, "%s: need to implement ant control for this rig?\n",
7843                   __func__);
7844         RETURNFUNC(-RIG_EINVAL);
7845     }
7846 
7847     if (retval != RIG_OK)
7848     {
7849         RETURNFUNC(retval);
7850     }
7851 
7852     // ack_len should be either 2 or 3
7853     // ant cmd format is one of
7854     // 0x12 0xaa
7855     // 0x12 0xaa 0xrr
7856     // Where aa is a zero-base antenna number and rr is a binary for rx only
7857 
7858     if ((ack_len != 2 && ack_len != 3) || ackbuf[0] != C_CTL_ANT ||
7859             ackbuf[1] > 3)
7860     {
7861         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d, ant=%d\n", __func__,
7862                   ackbuf[0], ack_len, ackbuf[1]);
7863         RETURNFUNC(-RIG_ERJCTED);
7864     }
7865 
7866     rig_debug(RIG_DEBUG_ERR, "%s: ackbuf= 0x%02x 0x%02x 0x%02x\n", __func__,
7867               ackbuf[0], ackbuf[1], ackbuf[2]);
7868 
7869     *ant_curr = *ant_tx = *ant_rx = rig_idx2setting(ackbuf[1]);
7870 
7871     // Note: with IC756/IC-756Pro/IC-7800 and more, ackbuf[2] deals with [RX ANT]
7872     // Hopefully any ack_len=3 can fit in the option field
7873     if (ack_len == 3)
7874     {
7875         option->i = ackbuf[2];
7876         *ant_rx = rig_idx2setting(ackbuf[2]);
7877     }
7878 
7879     RETURNFUNC(RIG_OK);
7880 }
7881 
7882 
7883 /*
7884  * icom_vfo_op, Mem/VFO operation
7885  * Assumes rig!=NULL, rig->state.priv!=NULL
7886  */
icom_vfo_op(RIG * rig,vfo_t vfo,vfo_op_t op)7887 int icom_vfo_op(RIG *rig, vfo_t vfo, vfo_op_t op)
7888 {
7889     unsigned char mvbuf[MAXFRAMELEN];
7890     unsigned char ackbuf[MAXFRAMELEN];
7891     int mv_len = 0, ack_len = sizeof(ackbuf), retval;
7892     int mv_cn, mv_sc;
7893     int vfo_list;
7894 
7895     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7896 
7897     switch (op)
7898     {
7899     case RIG_OP_CPY:
7900         mv_cn = C_SET_VFO;
7901         vfo_list = rig->state.vfo_list;
7902 
7903         if ((vfo_list & (RIG_VFO_A | RIG_VFO_B)) == (RIG_VFO_A | RIG_VFO_B))
7904         {
7905             mv_sc = S_BTOA;
7906         }
7907         else if ((vfo_list & (RIG_VFO_MAIN | RIG_VFO_SUB)) == (RIG_VFO_MAIN |
7908                  RIG_VFO_SUB))
7909         {
7910             mv_sc = S_SUBTOMAIN;
7911         }
7912         else
7913         {
7914             RETURNFUNC(-RIG_ENAVAIL);
7915         }
7916 
7917         break;
7918 
7919     case RIG_OP_XCHG:
7920         mv_cn = C_SET_VFO;
7921         mv_sc = S_XCHNG;
7922         break;
7923 
7924     case RIG_OP_FROM_VFO:
7925         mv_cn = C_WR_MEM;
7926         mv_sc = -1;
7927         break;
7928 
7929     case RIG_OP_TO_VFO:
7930         mv_cn = C_MEM2VFO;
7931         mv_sc = -1;
7932         break;
7933 
7934     case RIG_OP_MCL:
7935         mv_cn = C_CLR_MEM;
7936         mv_sc = -1;
7937         break;
7938 
7939     case RIG_OP_TUNE:
7940         mv_cn = C_CTL_PTT;
7941         mv_sc = S_ANT_TUN;
7942         mvbuf[0] = 2;
7943         mv_len = 1;
7944         break;
7945 
7946     default:
7947         rig_debug(RIG_DEBUG_ERR, "%s: unsupported mem/vfo op %#x", __func__,
7948                   op);
7949         RETURNFUNC(-RIG_EINVAL);
7950     }
7951 
7952     retval =
7953         icom_transaction(rig, mv_cn, mv_sc, mvbuf, mv_len, ackbuf, &ack_len);
7954 
7955     if (retval != RIG_OK)
7956     {
7957         RETURNFUNC(retval);
7958     }
7959 
7960     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
7961     {
7962         //  if we don't get ACK/NAK some serial corruption occurred
7963         // so we'll call it a timeout for retry purposes
7964         RETURNFUNC(-RIG_ETIMEOUT);
7965     }
7966 
7967     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
7968     {
7969         if (op != RIG_OP_XCHG)
7970         {
7971             rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
7972                       ackbuf[0], ack_len);
7973         }
7974 
7975         RETURNFUNC(-RIG_ERJCTED);
7976     }
7977 
7978     RETURNFUNC(RIG_OK);
7979 }
7980 
7981 /*
7982  * icom_scan, scan operation
7983  * Assumes rig!=NULL, rig->state.priv!=NULL
7984  */
icom_scan(RIG * rig,vfo_t vfo,scan_t scan,int ch)7985 int icom_scan(RIG *rig, vfo_t vfo, scan_t scan, int ch)
7986 {
7987     unsigned char scanbuf[MAXFRAMELEN];
7988     unsigned char ackbuf[MAXFRAMELEN];
7989     int scan_len, ack_len = sizeof(ackbuf), retval;
7990     int scan_cn, scan_sc;
7991 
7992     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
7993     scan_len = 0;
7994     scan_cn = C_CTL_SCAN;
7995 
7996     switch (scan)
7997     {
7998     case RIG_SCAN_STOP:
7999         scan_sc = S_SCAN_STOP;
8000         break;
8001 
8002     case RIG_SCAN_MEM:
8003         TRACE;
8004         retval = rig_set_vfo(rig, RIG_VFO_MEM);
8005 
8006         if (retval != RIG_OK)
8007         {
8008             RETURNFUNC(retval);
8009         }
8010 
8011         /* Looks like all the IC-R* have this command,
8012          * but some old models don't have it.
8013          * Should be put in icom_priv_caps ?
8014          */
8015         if (rig->caps->rig_type == RIG_TYPE_RECEIVER)
8016         {
8017             scan_sc = S_SCAN_MEM2;
8018         }
8019         else
8020         {
8021             scan_sc = S_SCAN_START;
8022         }
8023 
8024         break;
8025 
8026     case RIG_SCAN_SLCT:
8027         TRACE;
8028         retval = rig_set_vfo(rig, RIG_VFO_MEM);
8029 
8030         if (retval != RIG_OK)
8031         {
8032             RETURNFUNC(retval);
8033         }
8034 
8035         scan_sc = S_SCAN_START;
8036         break;
8037 
8038     case RIG_SCAN_PRIO:
8039     case RIG_SCAN_PROG:
8040         /* TODO: for SCAN_PROG, check this is an edge chan */
8041         /* BTW, I'm wondering if this is possible with CI-V */
8042         retval = icom_set_mem(rig, RIG_VFO_CURR, ch);
8043 
8044         if (retval != RIG_OK)
8045         {
8046             RETURNFUNC(retval);
8047         }
8048 
8049         TRACE;
8050         retval = rig_set_vfo(rig, RIG_VFO_VFO);
8051 
8052         if (retval != RIG_OK)
8053         {
8054             RETURNFUNC(retval);
8055         }
8056 
8057         scan_sc = S_SCAN_START;
8058         break;
8059 
8060     case RIG_SCAN_DELTA:
8061         scan_sc = S_SCAN_DELTA;   /* TODO: delta-f support */
8062         break;
8063 
8064     default:
8065         rig_debug(RIG_DEBUG_ERR, "%s: unsupported scan %#x", __func__, scan);
8066         RETURNFUNC(-RIG_EINVAL);
8067     }
8068 
8069     retval = icom_transaction(rig, scan_cn, scan_sc, scanbuf, scan_len,
8070                               ackbuf, &ack_len);
8071 
8072     if (retval != RIG_OK)
8073     {
8074         RETURNFUNC(retval);
8075     }
8076 
8077     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
8078     {
8079         //  if we don't get ACK/NAK some serial corruption occurred
8080         // so we'll call it a timeout for retry purposes
8081         RETURNFUNC(-RIG_ETIMEOUT);
8082     }
8083 
8084     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
8085     {
8086         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
8087                   ackbuf[0], ack_len);
8088         RETURNFUNC(-RIG_ERJCTED);
8089     }
8090 
8091     RETURNFUNC(RIG_OK);
8092 }
8093 
8094 /*
8095  * icom_send_morse
8096  * Assumes rig!=NULL, msg!=NULL
8097  */
icom_send_morse(RIG * rig,vfo_t vfo,const char * msg)8098 int icom_send_morse(RIG *rig, vfo_t vfo, const char *msg)
8099 {
8100     unsigned char ackbuf[MAXFRAMELEN];
8101     int ack_len = sizeof(ackbuf), retval;
8102     int len;
8103 
8104     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8105     len = strlen(msg);
8106 
8107     if (len > 30)
8108     {
8109         len = 30;
8110     }
8111 
8112     rig_debug(RIG_DEBUG_TRACE, "%s: %s\n", __func__, msg);
8113 
8114     retval = icom_transaction(rig, C_SND_CW, -1, (unsigned char *) msg, len,
8115                               ackbuf, &ack_len);
8116 
8117     if (retval != RIG_OK)
8118     {
8119         RETURNFUNC(retval);
8120     }
8121 
8122     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
8123     {
8124         //  if we don't get ACK/NAK some serial corruption occurred
8125         // so we'll call it a timeout for retry purposes
8126         RETURNFUNC(-RIG_ETIMEOUT);
8127     }
8128 
8129     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
8130     {
8131         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
8132                   ackbuf[0], ack_len);
8133         RETURNFUNC(-RIG_ERJCTED);
8134     }
8135 
8136     RETURNFUNC(RIG_OK);
8137 }
8138 
8139 /*
8140  * icom_stop_morse
8141  * Assumes rig!=NULL, msg!=NULL
8142  */
icom_stop_morse(RIG * rig,vfo_t vfo)8143 int icom_stop_morse(RIG *rig, vfo_t vfo)
8144 {
8145     unsigned char ackbuf[MAXFRAMELEN];
8146     unsigned char cmd[MAXFRAMELEN];
8147     int ack_len = sizeof(ackbuf), retval;
8148 
8149     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8150 
8151     cmd[0] = 0xff;
8152 
8153     retval = icom_transaction(rig, C_SND_CW, -1, (unsigned char *) cmd, 1,
8154                               ackbuf, &ack_len);
8155 
8156     if (retval != RIG_OK)
8157     {
8158         RETURNFUNC(retval);
8159     }
8160 
8161     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
8162     {
8163         //  if we don't get ACK/NAK some serial corruption occurred
8164         // so we'll call it a timeout for retry purposes
8165         RETURNFUNC(-RIG_ETIMEOUT);
8166     }
8167 
8168     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
8169     {
8170         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
8171                   ackbuf[0], ack_len);
8172         RETURNFUNC(-RIG_ERJCTED);
8173     }
8174 
8175     RETURNFUNC(RIG_OK);
8176 }
8177 
icom_power2mW(RIG * rig,unsigned int * mwpower,float power,freq_t freq,rmode_t mode)8178 int icom_power2mW(RIG *rig, unsigned int *mwpower, float power, freq_t freq,
8179                   rmode_t mode)
8180 {
8181     int rig_id;
8182 
8183     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8184     rig_id = rig->caps->rig_model;
8185 
8186     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8187 
8188     switch (rig_id)
8189     {
8190     default:
8191         /* Normal 100 Watts */
8192         *mwpower = power * 100000;
8193         break;
8194     }
8195 
8196     RETURNFUNC(RIG_OK);
8197 }
8198 
icom_mW2power(RIG * rig,float * power,unsigned int mwpower,freq_t freq,rmode_t mode)8199 int icom_mW2power(RIG *rig, float *power, unsigned int mwpower, freq_t freq,
8200                   rmode_t mode)
8201 {
8202     int rig_id;
8203 
8204     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8205     rig_id = rig->caps->rig_model;
8206 
8207     rig_debug(RIG_DEBUG_TRACE, "%s: passed mwpower = %u\n", __func__,
8208               mwpower);
8209     rig_debug(RIG_DEBUG_TRACE, "%s: passed freq = %" PRIfreq " Hz\n",
8210               __func__, freq);
8211     rig_debug(RIG_DEBUG_TRACE, "%s: passed mode = %s\n", __func__,
8212               rig_strrmode(mode));
8213 
8214     if (mwpower > 100000)
8215     {
8216         RETURNFUNC(-RIG_EINVAL);
8217     }
8218 
8219     switch (rig_id)
8220     {
8221     default:            /* Default to a 100W radio */
8222         *power = ((float) mwpower / 100000);
8223         break;
8224     }
8225 
8226     RETURNFUNC(RIG_OK);
8227 }
8228 
icom_parse_spectrum_frame(RIG * rig,int length,const unsigned char * frame_data)8229 static int icom_parse_spectrum_frame(RIG *rig, int length,
8230                                      const unsigned char *frame_data)
8231 {
8232     struct rig_caps *caps = rig->caps;
8233     struct icom_priv_caps *priv_caps = (struct icom_priv_caps *) caps->priv;
8234     struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
8235     struct icom_spectrum_scope_cache *cache;
8236 
8237     int division = (int) from_bcd(frame_data + 1, 1 * 2);
8238     int max_division = (int) from_bcd(frame_data + 2, 1 * 2);
8239 
8240     int spectrum_data_length_in_frame;
8241     const unsigned char *spectrum_data_start_in_frame;
8242 
8243     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8244 
8245     // The first byte indicates spectrum scope ID/VFO: 0 = Main, 1 = Sub
8246     int spectrum_id = frame_data[0];
8247 
8248     if (spectrum_id < 0 || spectrum_id >= priv->spectrum_scope_count)
8249     {
8250         rig_debug(RIG_DEBUG_ERR, "%s: invalid spectrum scope ID from CI-V frame: %d\n",
8251                   __func__, spectrum_id);
8252         RETURNFUNC(-RIG_EPROTO);
8253     }
8254 
8255     cache = &priv->spectrum_scope_cache[spectrum_id];
8256 
8257     if (division == 1)
8258     {
8259         int spectrum_scope_mode = frame_data[3];
8260         int out_of_range = frame_data[14];
8261 
8262         cache->spectrum_mode = RIG_SPECTRUM_MODE_NONE;
8263 
8264         switch (spectrum_scope_mode)
8265         {
8266         case SCOPE_MODE_CENTER:
8267             cache->spectrum_mode = RIG_SPECTRUM_MODE_CENTER;
8268             cache->spectrum_center_freq = (freq_t) from_bcd(frame_data + 4, 5 * 2);
8269             cache->spectrum_span_freq = (freq_t) from_bcd(frame_data + 9, 5 * 2) * 2;
8270             cache->spectrum_low_edge_freq = cache->spectrum_center_freq -
8271                                             cache->spectrum_span_freq / 2;
8272             cache->spectrum_high_edge_freq = cache->spectrum_center_freq +
8273                                              cache->spectrum_span_freq / 2;
8274             break;
8275 
8276         case SCOPE_MODE_FIXED:
8277             cache->spectrum_mode = RIG_SPECTRUM_MODE_FIXED;
8278 
8279         case SCOPE_MODE_SCROLL_C:
8280             if (cache->spectrum_mode == RIG_SPECTRUM_MODE_NONE)
8281             {
8282                 cache->spectrum_mode = RIG_SPECTRUM_MODE_CENTER_SCROLL;
8283             }
8284 
8285         case SCOPE_MODE_SCROLL_F:
8286             if (cache->spectrum_mode == RIG_SPECTRUM_MODE_NONE)
8287             {
8288                 cache->spectrum_mode = RIG_SPECTRUM_MODE_FIXED_SCROLL;
8289             }
8290 
8291             cache->spectrum_low_edge_freq = (freq_t) from_bcd(frame_data + 4, 5 * 2);
8292             cache->spectrum_high_edge_freq = (freq_t) from_bcd(frame_data + 9, 5 * 2);
8293             cache->spectrum_span_freq = (cache->spectrum_high_edge_freq -
8294                                          cache->spectrum_low_edge_freq);
8295             cache->spectrum_center_freq = cache->spectrum_high_edge_freq -
8296                                           cache->spectrum_span_freq / 2;
8297             break;
8298 
8299         default:
8300             rig_debug(RIG_DEBUG_ERR, "%s: unknown Icom spectrum scope mode: %d\n", __func__,
8301                       spectrum_scope_mode)
8302             RETURNFUNC(-RIG_EPROTO);
8303         }
8304 
8305         spectrum_data_length_in_frame = length - 15;
8306         spectrum_data_start_in_frame = frame_data + 15;
8307 
8308         memset(cache->spectrum_data, 0,
8309                priv_caps->spectrum_scope_caps.spectrum_line_length);
8310 
8311         cache->spectrum_data_length = 0;
8312         cache->spectrum_metadata_valid = 1;
8313 
8314         rig_debug(RIG_DEBUG_TRACE,
8315                   "%s: Spectrum line start: id=%d division=%d max_division=%d mode=%d center=%.0f span=%.0f low_edge=%.0f high_edge=%.0f oor=%d data_length=%d\n",
8316                   __func__, spectrum_id, division, max_division, spectrum_scope_mode,
8317                   cache->spectrum_center_freq, cache->spectrum_span_freq,
8318                   cache->spectrum_low_edge_freq, cache->spectrum_high_edge_freq, out_of_range,
8319                   spectrum_data_length_in_frame);
8320     }
8321     else
8322     {
8323         spectrum_data_length_in_frame = length - 3;
8324         spectrum_data_start_in_frame = frame_data + 3;
8325     }
8326 
8327     if (spectrum_data_length_in_frame > 0)
8328     {
8329         int frame_length = priv_caps->spectrum_scope_caps.single_frame_data_length;
8330         int data_frame_index = (max_division > 1) ? (division - 2) : (division - 1);
8331         int offset = data_frame_index * frame_length;
8332 
8333         if (offset + spectrum_data_length_in_frame >
8334                 priv_caps->spectrum_scope_caps.spectrum_line_length)
8335         {
8336             rig_debug(RIG_DEBUG_ERR,
8337                       "%s: too much spectrum scope data received: %d bytes > %d bytes expected\n",
8338                       __func__, offset + spectrum_data_length_in_frame,
8339                       priv_caps->spectrum_scope_caps.spectrum_line_length);
8340             RETURNFUNC(-RIG_EPROTO);
8341         }
8342 
8343         memcpy(cache->spectrum_data + offset, spectrum_data_start_in_frame,
8344                spectrum_data_length_in_frame);
8345         cache->spectrum_data_length = offset + spectrum_data_length_in_frame;
8346     }
8347 
8348     if (cache->spectrum_metadata_valid && division == max_division)
8349     {
8350         struct rig_spectrum_line spectrum_line =
8351         {
8352             .data_level_min = priv_caps->spectrum_scope_caps.data_level_min,
8353             .data_level_max = priv_caps->spectrum_scope_caps.data_level_max,
8354             .signal_strength_min = priv_caps->spectrum_scope_caps.signal_strength_min,
8355             .signal_strength_max = priv_caps->spectrum_scope_caps.signal_strength_max,
8356             .spectrum_mode = cache->spectrum_mode,
8357             .center_freq = cache->spectrum_center_freq,
8358             .span_freq = cache->spectrum_span_freq,
8359             .low_edge_freq = cache->spectrum_low_edge_freq,
8360             .high_edge_freq = cache->spectrum_high_edge_freq,
8361             .spectrum_data_length = cache->spectrum_data_length,
8362             .spectrum_data = cache->spectrum_data,
8363         };
8364 
8365         if (rig->callbacks.spectrum_event)
8366         {
8367             rig->callbacks.spectrum_event(rig, &spectrum_line, rig->callbacks.spectrum_arg);
8368         }
8369 
8370         cache->spectrum_metadata_valid = 0;
8371     }
8372 
8373     RETURNFUNC(RIG_OK);
8374 }
8375 
icom_is_async_frame(RIG * rig,int frame_len,const unsigned char * frame)8376 int icom_is_async_frame(RIG *rig, int frame_len, const unsigned char *frame)
8377 {
8378     if (frame_len < ACKFRMLEN)
8379     {
8380         return 0;
8381     }
8382 
8383     /* Spectrum scope data is not CI-V transceive data, but handled the same way as it is pushed by the rig */
8384     return frame[2] == BCASTID || (frame[2] == CTRLID && frame[4] == C_CTL_SCP
8385                                    && frame[5] == S_SCP_DAT);
8386 }
8387 
icom_process_async_frame(RIG * rig,int frame_len,const unsigned char * frame)8388 int icom_process_async_frame(RIG *rig, int frame_len,
8389                              const unsigned char *frame)
8390 {
8391     struct rig_state *rs = &rig->state;
8392     struct icom_priv_data *priv = (struct icom_priv_data *) rs->priv;
8393     rmode_t mode;
8394     pbwidth_t width;
8395 
8396     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8397 
8398     /*
8399      * the first 2 bytes must be 0xfe
8400      * the 3rd one 0x00 since this is transceive mode
8401      * the 4rd one the emitter
8402      * then the command number
8403      * the rest is data
8404      * and don't forget one byte at the end for the EOM
8405      */
8406     switch (frame[4])
8407     {
8408     case C_SND_FREQ:
8409 
8410         /*
8411          * TODO: the freq length might be less than 4 or 5 bytes
8412          *          on older rigs!
8413          */
8414         if (rig->callbacks.freq_event)
8415         {
8416             freq_t freq;
8417             freq = from_bcd(frame + 5, (priv->civ_731_mode ? 4 : 5) * 2);
8418             RETURNFUNC(rig->callbacks.freq_event(rig, RIG_VFO_CURR, freq,
8419                                                  rig->callbacks.freq_arg));
8420         }
8421         else
8422         {
8423             RETURNFUNC(-RIG_ENAVAIL);
8424         }
8425 
8426         break;
8427 
8428     case C_SND_MODE:
8429         if (rig->callbacks.mode_event)
8430         {
8431             icom2rig_mode(rig, frame[5], frame[6], &mode, &width);
8432             RETURNFUNC(rig->callbacks.mode_event(rig, RIG_VFO_CURR,
8433                                                  mode, width, rig->callbacks.mode_arg));
8434         }
8435         else
8436         {
8437             RETURNFUNC(-RIG_ENAVAIL);
8438         }
8439 
8440         break;
8441 
8442     case C_CTL_SCP:
8443         if (frame[5] == S_SCP_DAT)
8444         {
8445             icom_parse_spectrum_frame(rig, frame_len - (6 + 1), frame + 6);
8446         }
8447 
8448         break;
8449 
8450     default:
8451         rig_debug(RIG_DEBUG_VERBOSE, "%s: transceive cmd unsupported %#2.2x\n",
8452                   __func__, frame[4]);
8453         RETURNFUNC(-RIG_ENIMPL);
8454     }
8455 
8456     RETURNFUNC(RIG_OK);
8457 }
8458 
8459 /*
8460  * icom_decode is called by sa_sigio, when some asynchronous
8461  * data has been received from the rig
8462  */
icom_decode_event(RIG * rig)8463 int icom_decode_event(RIG *rig)
8464 {
8465     struct icom_priv_data *priv;
8466     struct rig_state *rs;
8467     unsigned char buf[MAXFRAMELEN];
8468     int retval, frm_len;
8469 
8470     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8471 
8472     rs = &rig->state;
8473     priv = (struct icom_priv_data *) rs->priv;
8474 
8475     frm_len = read_icom_frame(&rs->rigport, buf, sizeof(buf));
8476 
8477     if (frm_len == -RIG_ETIMEOUT)
8478     {
8479         rig_debug(RIG_DEBUG_VERBOSE,
8480                   "%s: got a timeout before the first character\n", __func__);
8481     }
8482 
8483     if (frm_len < 1)
8484     {
8485         RETURNFUNC(RIG_OK);
8486     }
8487 
8488     retval = icom_frame_fix_preamble(frm_len, buf);
8489 
8490     if (retval < 0)
8491     {
8492         RETURNFUNC(retval);
8493     }
8494 
8495     frm_len = retval;
8496 
8497     switch (buf[frm_len - 1])
8498     {
8499     case COL:
8500         rig_debug(RIG_DEBUG_VERBOSE, "%s: saw a collision\n", __func__);
8501         /* Collision */
8502         RETURNFUNC(-RIG_BUSBUSY);
8503 
8504     case FI:
8505         /* Ok, normal frame */
8506         break;
8507 
8508     default:
8509         /* Timeout after reading at least one character */
8510         /* Problem on ci-v bus? */
8511         RETURNFUNC(-RIG_EPROTO);
8512     }
8513 
8514     if (!icom_is_async_frame(rig, frm_len, buf))
8515     {
8516         rig_debug(RIG_DEBUG_WARN, "%s: CI-V %#x called for %#x!\n", __func__,
8517                   priv->re_civ_addr, buf[2]);
8518     }
8519 
8520     RETURNFUNC(icom_process_async_frame(rig, frm_len, buf));
8521 }
8522 
icom_set_raw(RIG * rig,int cmd,int subcmd,int subcmdbuflen,unsigned char * subcmdbuf,int val_bytes,int val)8523 int icom_set_raw(RIG *rig, int cmd, int subcmd, int subcmdbuflen,
8524                  unsigned char *subcmdbuf, int val_bytes, int val)
8525 {
8526     unsigned char cmdbuf[MAXFRAMELEN], ackbuf[MAXFRAMELEN];
8527     int ack_len = sizeof(ackbuf);
8528     int cmdbuflen = subcmdbuflen;
8529     int retval;
8530 
8531     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8532 
8533     if (subcmdbuflen > 0)
8534     {
8535         if (subcmdbuf == NULL)
8536         {
8537             RETURNFUNC(-RIG_EINTERNAL);
8538         }
8539 
8540         memcpy(cmdbuf, subcmdbuf, subcmdbuflen);
8541     }
8542 
8543     if (val_bytes > 0)
8544     {
8545         to_bcd_be(cmdbuf + subcmdbuflen, (long long) val, val_bytes * 2);
8546         cmdbuflen += val_bytes;
8547     }
8548 
8549     retval =
8550         icom_transaction(rig, cmd, subcmd, cmdbuf, cmdbuflen, ackbuf, &ack_len);
8551 
8552     if (retval != RIG_OK)
8553     {
8554         RETURNFUNC(retval);
8555     }
8556 
8557     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
8558     {
8559         //  if we don't get ACK/NAK some serial corruption occurred
8560         // so we'll call it a timeout for retry purposes
8561         RETURNFUNC(-RIG_ETIMEOUT);
8562     }
8563 
8564     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
8565     {
8566         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
8567                   ackbuf[0], ack_len);
8568         RETURNFUNC(-RIG_ERJCTED);
8569     }
8570 
8571     RETURNFUNC(RIG_OK);
8572 }
8573 
icom_get_raw_buf(RIG * rig,int cmd,int subcmd,int subcmdbuflen,unsigned char * subcmdbuf,int * reslen,unsigned char * res)8574 int icom_get_raw_buf(RIG *rig, int cmd, int subcmd, int subcmdbuflen,
8575                      unsigned char *subcmdbuf, int *reslen,
8576                      unsigned char *res)
8577 {
8578     unsigned char ackbuf[MAXFRAMELEN];
8579     int ack_len = sizeof(ackbuf);
8580     int cmdhead = subcmdbuflen;
8581     int retval;
8582 
8583     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8584 
8585     retval =
8586         icom_transaction(rig, cmd, subcmd, subcmdbuf, subcmdbuflen, ackbuf,
8587                          &ack_len);
8588 
8589     if (retval != RIG_OK)
8590     {
8591         RETURNFUNC(retval);
8592     }
8593 
8594     cmdhead += (subcmd == -1) ? 1 : 2;
8595     ack_len -= cmdhead;
8596 
8597     rig_debug(RIG_DEBUG_TRACE, "%s: %d\n", __func__, ack_len);
8598 
8599     if (*reslen < ack_len || res == NULL)
8600     {
8601         RETURNFUNC(-RIG_EINTERNAL);
8602     }
8603 
8604     memcpy(res, ackbuf + cmdhead, ack_len);
8605     *reslen = ack_len;
8606 
8607     RETURNFUNC(RIG_OK);
8608 }
8609 
icom_get_raw(RIG * rig,int cmd,int subcmd,int subcmdbuflen,unsigned char * subcmdbuf,int * val)8610 int icom_get_raw(RIG *rig, int cmd, int subcmd, int subcmdbuflen,
8611                  unsigned char *subcmdbuf, int *val)
8612 {
8613     unsigned char resbuf[MAXFRAMELEN];
8614     int reslen = sizeof(resbuf);
8615     int retval;
8616 
8617     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8618 
8619     retval =
8620         icom_get_raw_buf(rig, cmd, subcmd, subcmdbuflen, subcmdbuf, &reslen,
8621                          resbuf);
8622 
8623     if (retval != RIG_OK)
8624     {
8625         RETURNFUNC(retval);
8626     }
8627 
8628     * val = from_bcd_be(resbuf, reslen * 2);
8629 
8630     rig_debug(RIG_DEBUG_TRACE, "%s: %d %d\n", __func__, reslen, *val);
8631 
8632     RETURNFUNC(RIG_OK);
8633 }
8634 
icom_set_level_raw(RIG * rig,setting_t level,int cmd,int subcmd,int subcmdbuflen,unsigned char * subcmdbuf,int val_bytes,value_t val)8635 int icom_set_level_raw(RIG *rig, setting_t level, int cmd, int subcmd,
8636                        int subcmdbuflen, unsigned char *subcmdbuf,
8637                        int val_bytes, value_t val)
8638 {
8639     int icom_val;
8640 
8641     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8642 
8643     if (RIG_LEVEL_IS_FLOAT(level))
8644     {
8645         icom_val = (int)(val.f * 255.0f);
8646     }
8647     else
8648     {
8649         icom_val = val.i;
8650     }
8651 
8652     RETURNFUNC(icom_set_raw(rig, cmd, subcmd, subcmdbuflen, subcmdbuf, val_bytes,
8653                             icom_val));
8654 }
8655 
icom_get_level_raw(RIG * rig,setting_t level,int cmd,int subcmd,int subcmdbuflen,unsigned char * subcmdbuf,value_t * val)8656 int icom_get_level_raw(RIG *rig, setting_t level, int cmd, int subcmd,
8657                        int subcmdbuflen, unsigned char *subcmdbuf,
8658                        value_t *val)
8659 {
8660     int icom_val;
8661     int retval;
8662 
8663     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8664 
8665     retval =
8666         icom_get_raw(rig, cmd, subcmd, subcmdbuflen, subcmdbuf, &icom_val);
8667 
8668     if (retval != RIG_OK)
8669     {
8670         RETURNFUNC(retval);
8671     }
8672 
8673     if (RIG_LEVEL_IS_FLOAT(level))
8674     {
8675         val->f = (float) icom_val / 255.0f;
8676     }
8677     else
8678     {
8679         val->i = icom_val;
8680     }
8681 
8682     RETURNFUNC(RIG_OK);
8683 }
8684 
8685 /*
8686  * icom_send_voice_mem
8687  * Assumes rig!=NULL, rig->state.priv!=NULL
8688  */
icom_send_voice_mem(RIG * rig,vfo_t vfo,int ch)8689 int icom_send_voice_mem(RIG *rig, vfo_t vfo, int ch)
8690 {
8691     unsigned char chbuf[1];
8692     unsigned char ackbuf[MAXFRAMELEN];
8693     int ack_len = sizeof(ackbuf), retval;
8694 
8695     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8696 
8697     to_bcd_be(chbuf, ch, 2);
8698 
8699     retval = icom_transaction(rig, C_SND_VOICE, 0, chbuf, 1,
8700                               ackbuf, &ack_len);
8701 
8702     if (retval != RIG_OK)
8703     {
8704         RETURNFUNC(retval);
8705     }
8706 
8707     if ((ack_len >= 1 && ackbuf[0] != ACK) && (ack_len >= 2 && ackbuf[1] != NAK))
8708     {
8709         //  if we don't get ACK/NAK some serial corruption occurred
8710         // so we'll call it a timeout for retry purposes
8711         RETURNFUNC(-RIG_ETIMEOUT);
8712     }
8713 
8714     if (ack_len != 1 || (ack_len >= 1 && ackbuf[0] != ACK))
8715     {
8716         rig_debug(RIG_DEBUG_ERR, "%s: ack NG (%#.2x), len=%d\n", __func__,
8717                   ackbuf[0], ack_len);
8718         RETURNFUNC(-RIG_ERJCTED);
8719     }
8720 
8721     RETURNFUNC(RIG_OK);
8722 }
8723 
8724 /*
8725  * icom_get_freq_range
8726  * Assumes rig!=NULL, rig->state.priv!=NULL
8727  * Always returns RIG_OK
8728  */
icom_get_freq_range(RIG * rig)8729 int icom_get_freq_range(RIG *rig)
8730 {
8731     int nrange = 0;
8732     int i;
8733     int cmd, subcmd;
8734     int retval;
8735     unsigned char cmdbuf[MAXFRAMELEN];
8736     unsigned char ackbuf[MAXFRAMELEN];
8737     int ack_len = sizeof(ackbuf);
8738 //    struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
8739 //    int freq_len = priv->civ_731_mode ? 4 : 5;
8740     int freq_len = 5;
8741 
8742     cmd = C_CTL_EDGE;
8743     subcmd = 0;
8744     retval = icom_transaction(rig, cmd, subcmd, NULL, 0, ackbuf, &ack_len);
8745 
8746     if (retval != RIG_OK)
8747     {
8748         rig_debug(RIG_DEBUG_TRACE,
8749                   "%s: rig does not have 0x1e command so skipping this check\n", __func__);
8750         RETURNFUNC(RIG_OK);
8751     }
8752 
8753     rig_debug(RIG_DEBUG_TRACE, "%s: ackbuf[0]=%02x, ackbuf[1]=%02x\n", __func__,
8754               ackbuf[0], ackbuf[1]);
8755     nrange = from_bcd(&ackbuf[2], 2);
8756     rig_debug(RIG_DEBUG_TRACE, "%s: nrange=%d\n", __func__, nrange);
8757 
8758     for (i = 1; i <= nrange; ++i)
8759     {
8760         cmd = C_CTL_EDGE;
8761         subcmd = 1;
8762         to_bcd(cmdbuf, i, 2);
8763         retval = icom_transaction(rig, cmd, subcmd, cmdbuf, 1, ackbuf,
8764                                   &ack_len);
8765 
8766         if (retval == RIG_OK)
8767         {
8768             freq_t freqlo, freqhi;
8769             rig_debug(RIG_DEBUG_TRACE, "%s: ackbuf= %02x %02x %02x %02x...\n", __func__,
8770                       ackbuf[0], ackbuf[1], ackbuf[2], ackbuf[3]);
8771             freqlo = from_bcd(&ackbuf[3], freq_len * 2);
8772             freqhi = from_bcd(&ackbuf[3 + freq_len + 1], freq_len * 2);
8773             rig_debug(RIG_DEBUG_TRACE, "%s: rig chan %d, low=%.0f, high=%.0f\n", __func__,
8774                       i, freqlo, freqhi);
8775         }
8776         else
8777         {
8778             rig_debug(RIG_DEBUG_ERR, "%s: error from C_CTL_EDGE?  err=%s\n", __func__,
8779                       rigerror(retval));
8780         }
8781     }
8782 
8783     // To be implemented
8784     // Automatically fill in the freq range for this rig if available
8785     rig_debug(RIG_DEBUG_TRACE, "%s: Hamlib ranges\n", __func__);
8786 
8787     for (i = 0; i < HAMLIB_FRQRANGESIZ
8788             && !RIG_IS_FRNG_END(rig->caps->rx_range_list1[i]); i++)
8789     {
8790         rig_debug(RIG_DEBUG_TRACE, "%s: rig chan %d, low=%.0f, high=%.0f\n", __func__,
8791                   i, (double)rig->caps->rx_range_list1[i].startf,
8792                   (double)rig->caps->rx_range_list1[i].endf);
8793     }
8794 
8795     RETURNFUNC(RIG_OK);
8796 }
8797 
8798 // Sets rig vfo && rig->state.current_vfo to default VFOA, or current vfo, or the vfo requested
set_vfo_curr(RIG * rig,vfo_t vfo,vfo_t curr_vfo)8799 static int set_vfo_curr(RIG *rig, vfo_t vfo, vfo_t curr_vfo)
8800 {
8801     int retval;
8802     struct icom_priv_data *priv = (struct icom_priv_data *) rig->state.priv;
8803 
8804     rig_debug(RIG_DEBUG_TRACE, "%s: vfo=%s, curr_vfo=%s\n", __func__,
8805               rig_strvfo(vfo), rig_strvfo(curr_vfo));
8806 
8807     if (vfo == RIG_VFO_CURR)
8808     {
8809         rig_debug(RIG_DEBUG_TRACE, "%s: Asking for currVFO,  currVFO=%s\n", __func__,
8810                   rig_strvfo(rig->state.current_vfo));
8811         vfo = rig->state.current_vfo;
8812         RETURNFUNC(RIG_OK);
8813     }
8814 
8815     if (vfo == RIG_VFO_MAIN && VFO_HAS_A_B_ONLY)
8816     {
8817         vfo = RIG_VFO_A;
8818         rig_debug(RIG_DEBUG_TRACE, "%s: Rig does not have MAIN/SUB so Main=%s\n",
8819                   __func__, rig_strvfo(vfo));
8820     }
8821     else if (vfo == RIG_VFO_SUB && VFO_HAS_A_B_ONLY)
8822     {
8823         vfo = RIG_VFO_B;
8824         rig_debug(RIG_DEBUG_TRACE, "%s: Rig does not have MAIN/SUB so Sub=%s\n",
8825                   __func__, rig_strvfo(vfo));
8826     }
8827 
8828     /* This method works also in memory mode(RIG_VFO_MEM) */
8829     // first time we will set default to VFOA or Main as
8830     // So if you ask for frequency or such without setting VFO first you'll get Main/VFOA
8831     if (rig->state.current_vfo == RIG_VFO_NONE && vfo == RIG_VFO_CURR)
8832     {
8833         icom_set_default_vfo(rig);
8834     }
8835     // asking for vfo_curr so give it to them
8836     else if (rig->state.current_vfo != RIG_VFO_NONE && vfo == RIG_VFO_CURR)
8837     {
8838         rig_debug(RIG_DEBUG_TRACE, "%s: using curr_vfo=%s\n", __func__,
8839                   rig_strvfo(rig->state.current_vfo));
8840         vfo = rig->state.current_vfo;
8841     }
8842     // only need to set vfo if it's changed
8843     else if (rig->state.current_vfo != vfo)
8844     {
8845         if (!(VFO_HAS_MAIN_SUB_A_B_ONLY && !priv->split_on && !rig->state.cache.satmode
8846                 && vfo == RIG_VFO_SUB && rig->state.current_vfo == RIG_VFO_B))
8847         {
8848             rig_debug(RIG_DEBUG_TRACE, "%s: setting new vfo=%s\n", __func__,
8849                       rig_strvfo(vfo));
8850             TRACE;
8851             retval = rig_set_vfo(rig, vfo);
8852 
8853             if (retval != RIG_OK)
8854             {
8855                 RETURNFUNC(retval);
8856             }
8857         }
8858     }
8859 
8860     rig_debug(RIG_DEBUG_TRACE, "%s: curr_vfo now=%s\n", __func__,
8861               rig_strvfo(rig->state.current_vfo));
8862 
8863     rig->state.current_vfo = vfo;
8864 
8865     RETURNFUNC(RIG_OK);
8866 }
8867 
icom_get_spectrum_vfo(RIG * rig,vfo_t vfo)8868 static int icom_get_spectrum_vfo(RIG *rig, vfo_t vfo)
8869 {
8870     if (rig->caps->targetable_vfo & RIG_TARGETABLE_SPECTRUM)
8871     {
8872         RETURNFUNC(ICOM_GET_VFO_NUMBER(vfo));
8873     }
8874 
8875     RETURNFUNC(0);
8876 }
8877 
icom_get_spectrum_edge_frequency_range(RIG * rig,vfo_t vfo,int * range_id)8878 static int icom_get_spectrum_edge_frequency_range(RIG *rig, vfo_t vfo,
8879         int *range_id)
8880 {
8881     freq_t freq;
8882     rmode_t mode;
8883     pbwidth_t width;
8884     int cache_ms_freq, cache_ms_mode, cache_ms_width;
8885     int i, retval;
8886     struct icom_priv_caps *priv_caps = (struct icom_priv_caps *) rig->caps->priv;
8887 
8888     retval = rig_get_cache(rig, vfo, &freq, &cache_ms_freq, &mode, &cache_ms_mode,
8889                            &width, &cache_ms_width);
8890 
8891     if (retval != RIG_OK)
8892     {
8893         RETURNFUNC(retval);
8894     }
8895 
8896     // Get frequency if it is not cached or value is old
8897     if (freq == 0 || cache_ms_freq >= 1000)
8898     {
8899         retval = rig_get_freq(rig, vfo, &freq);
8900 
8901         if (retval != RIG_OK)
8902         {
8903             RETURNFUNC(retval);
8904         }
8905     }
8906 
8907     for (i = 0; i < ICOM_MAX_SPECTRUM_FREQ_RANGES; i++)
8908     {
8909         int id = priv_caps->spectrum_edge_frequency_ranges[i].range_id;
8910 
8911         if (id < 1)
8912         {
8913             break;
8914         }
8915 
8916         if (freq >= priv_caps->spectrum_edge_frequency_ranges[i].low_freq
8917                 && freq < priv_caps->spectrum_edge_frequency_ranges[i].high_freq)
8918         {
8919             *range_id = id;
8920             RETURNFUNC(RIG_OK);
8921         }
8922     }
8923 
8924     RETURNFUNC(-RIG_EINVAL);
8925 }
8926 
8927 /*
8928  * init_icom is called by rig_probe_all (register.c)
8929  *
8930  * probe_icom reports all the devices on the CI-V bus.
8931  *
8932  * rig_model_t probeallrigs_icom(port_t *port, rig_probe_func_t cfunc, rig_ptr_t data)
8933  */
DECLARE_PROBERIG_BACKEND(icom)8934 DECLARE_PROBERIG_BACKEND(icom)
8935 {
8936     unsigned char buf[MAXFRAMELEN], civ_addr, civ_id;
8937     int frm_len, i;
8938     rig_model_t model = RIG_MODEL_NONE;
8939     int rates[] = { 19200, 9600, 300, 0 };
8940     int rates_idx;
8941 
8942     rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
8943 
8944     if (!port)
8945     {
8946         RETURNFUNC(RIG_MODEL_NONE);
8947     }
8948 
8949     if (port->type.rig != RIG_PORT_SERIAL)
8950     {
8951         RETURNFUNC(RIG_MODEL_NONE);
8952     }
8953 
8954     port->write_delay = port->post_write_delay = 0;
8955     port->retry = 1;
8956 
8957     /*
8958      * try for all different baud rates
8959      */
8960     for (rates_idx = 0; rates[rates_idx]; rates_idx++)
8961     {
8962         int retval;
8963         port->parm.serial.rate = rates[rates_idx];
8964         port->timeout = 2 * 1000 / rates[rates_idx] + 40;
8965 
8966         retval = serial_open(port);
8967 
8968         if (retval != RIG_OK)
8969         {
8970             RETURNFUNC(RIG_MODEL_NONE);
8971         }
8972 
8973         /*
8974          * try all possible addresses on the CI-V bus
8975          * FIXME: actually, old rigs do not support C_RD_TRXID cmd!
8976          *      Try to be smart, and deduce model depending
8977          *      on freq range, return address, and
8978          *      available commands.
8979          */
8980         for (civ_addr = 0x01; civ_addr <= 0x7f; civ_addr++)
8981         {
8982 
8983             frm_len = make_cmd_frame((char *) buf, civ_addr, CTRLID,
8984                                      C_RD_TRXID, S_RD_TRXID, NULL, 0);
8985 
8986             rig_flush(port);
8987             write_block(port, (char *) buf, frm_len);
8988 
8989             /* read out the bytes we just sent
8990              * TODO: check this is what we expect
8991              */
8992             read_icom_frame(port, buf, sizeof(buf));
8993 
8994             /* this is the reply */
8995             frm_len = read_icom_frame(port, buf, sizeof(buf));
8996 
8997             /* timeout.. nobody's there */
8998             if (frm_len <= 0)
8999             {
9000                 continue;
9001             }
9002 
9003             if (buf[7] != FI && buf[5] != FI)
9004             {
9005                 /* protocol error, unexpected reply.
9006                  * is this a CI-V device?
9007                  */
9008                 close(port->fd);
9009                 RETURNFUNC(RIG_MODEL_NONE);
9010             }
9011             else if (buf[4] == NAK)
9012             {
9013                 /*
9014                  * this is an Icom, but it does not support transceiver ID
9015                  * try to guess from the return address
9016                  */
9017                 civ_id = buf[3];
9018             }
9019             else
9020             {
9021                 civ_id = buf[6];
9022             }
9023 
9024             for (i = 0; icom_addr_list[i].model != RIG_MODEL_NONE; i++)
9025             {
9026                 if (icom_addr_list[i].re_civ_addr == civ_id)
9027                 {
9028                     rig_debug(RIG_DEBUG_VERBOSE, "%s: found %#x at %#x\n",
9029                               __func__, civ_id, buf[3]);
9030                     model = icom_addr_list[i].model;
9031 
9032                     if (cfunc)
9033                     {
9034                         (*cfunc)(port, model, data);
9035                     }
9036 
9037                     break;
9038                 }
9039             }
9040 
9041             /*
9042              * not found in known table....
9043              * update icom_addr_list[]!
9044              */
9045             if (icom_addr_list[i].model == RIG_MODEL_NONE)
9046                 rig_debug(RIG_DEBUG_WARN, "%s: found unknown device "
9047                           "with CI-V ID %#x, please report to Hamlib "
9048                           "developers.\n", __func__, civ_id);
9049         }
9050 
9051         /*
9052          * Try to identify OptoScan
9053          */
9054         for (civ_addr = 0x80; civ_addr <= 0x8f; civ_addr++)
9055         {
9056 
9057             frm_len = make_cmd_frame((char *) buf, civ_addr, CTRLID,
9058                                      C_CTL_MISC, S_OPTO_RDID, NULL, 0);
9059 
9060             rig_flush(port);
9061             write_block(port, (char *) buf, frm_len);
9062 
9063             /* read out the bytes we just sent
9064              * TODO: check this is what we expect
9065              */
9066             read_icom_frame(port, buf, sizeof(buf));
9067 
9068             /* this is the reply */
9069             frm_len = read_icom_frame(port, buf, sizeof(buf));
9070 
9071             /* timeout.. nobody's there */
9072             if (frm_len <= 0)
9073             {
9074                 continue;
9075             }
9076 
9077             /* wrong protocol? */
9078             if (frm_len != 7 || buf[4] != C_CTL_MISC || buf[5] != S_OPTO_RDID)
9079             {
9080                 continue;
9081             }
9082 
9083             rig_debug(RIG_DEBUG_VERBOSE, "%s: "
9084                       "found OptoScan%c%c%c, software version %d.%d, "
9085                       "interface version %d.%d, at %#x\n",
9086                       __func__,
9087                       buf[2], buf[3], buf[4],
9088                       buf[5] >> 4, buf[5] & 0xf,
9089                       buf[6] >> 4, buf[6] & 0xf, civ_addr);
9090 
9091             if (buf[6] == '5' && buf[7] == '3' && buf[8] == '5')
9092             {
9093                 model = RIG_MODEL_OS535;
9094             }
9095             else if (buf[6] == '4' && buf[7] == '5' && buf[8] == '6')
9096             {
9097                 model = RIG_MODEL_OS456;
9098             }
9099             else
9100             {
9101                 continue;
9102             }
9103 
9104             if (cfunc)
9105             {
9106                 (*cfunc)(port, model, data);
9107             }
9108 
9109             break;
9110         }
9111 
9112         close(port->fd);
9113 
9114         /*
9115          * Assumes all the rigs on the bus are running at same speed.
9116          * So if one at least has been found, none will be at lower speed.
9117          */
9118         if (model != RIG_MODEL_NONE)
9119         {
9120             RETURNFUNC(model);
9121         }
9122     }
9123 
9124     RETURNFUNC(model);
9125 }
9126 
9127 /*
9128  * initrigs_icom is called by rig_backend_load
9129  */
DECLARE_INITRIG_BACKEND(icom)9130 DECLARE_INITRIG_BACKEND(icom)
9131 {
9132     rig_debug(RIG_DEBUG_VERBOSE, "%s: _init called\n", __func__);
9133 
9134     rig_register(&ic703_caps);
9135     rig_register(&ic705_caps);
9136     rig_register(&ic706_caps);
9137     rig_register(&ic706mkii_caps);
9138     rig_register(&ic706mkiig_caps);
9139     rig_register(&ic718_caps);
9140     rig_register(&ic725_caps);
9141     rig_register(&ic726_caps);
9142     rig_register(&ic735_caps);
9143     rig_register(&ic736_caps);
9144     rig_register(&ic737_caps);
9145     rig_register(&ic738_caps);
9146     rig_register(&ic7410_caps);
9147     rig_register(&ic746_caps);
9148     rig_register(&ic746pro_caps);
9149     rig_register(&ic751_caps);
9150     rig_register(&ic761_caps);
9151     rig_register(&ic775_caps);
9152     rig_register(&ic756_caps);
9153     rig_register(&ic756pro_caps);
9154     rig_register(&ic756pro2_caps);
9155     rig_register(&ic756pro3_caps);
9156     rig_register(&ic7600_caps);
9157     rig_register(&ic765_caps);
9158     rig_register(&ic7700_caps);
9159     rig_register(&ic78_caps);
9160     rig_register(&ic7800_caps);
9161     rig_register(&ic785x_caps);
9162     rig_register(&ic7000_caps);
9163     rig_register(&ic7100_caps);
9164     rig_register(&ic7200_caps);
9165     rig_register(&ic7300_caps);
9166     rig_register(&ic7610_caps);
9167     rig_register(&ic781_caps);
9168     rig_register(&ic707_caps);
9169     rig_register(&ic728_caps);
9170     rig_register(&ic729_caps);
9171 
9172     rig_register(&ic820h_caps);
9173     rig_register(&ic821h_caps);
9174     rig_register(&ic910_caps);
9175     rig_register(&ic9100_caps);
9176     rig_register(&ic970_caps);
9177     rig_register(&ic9700_caps);
9178 
9179     rig_register(&icrx7_caps);
9180     rig_register(&icr6_caps);
9181     rig_register(&icr10_caps);
9182     rig_register(&icr20_caps);
9183     rig_register(&icr30_caps);
9184     rig_register(&icr71_caps);
9185     rig_register(&icr72_caps);
9186     rig_register(&icr75_caps);
9187     rig_register(&icr7000_caps);
9188     rig_register(&icr7100_caps);
9189     rig_register(&icr8500_caps);
9190     rig_register(&icr8600_caps);
9191     rig_register(&icr9000_caps);
9192     rig_register(&icr9500_caps);
9193 
9194     rig_register(&ic271_caps);
9195     rig_register(&ic275_caps);
9196     rig_register(&ic471_caps);
9197     rig_register(&ic475_caps);
9198     rig_register(&ic575_caps);
9199     rig_register(&ic1275_caps);
9200 
9201     rig_register(&os535_caps);
9202     rig_register(&os456_caps);
9203 
9204     rig_register(&omnivip_caps);
9205     rig_register(&delta2_caps);
9206 
9207     rig_register(&ic92d_caps);
9208     rig_register(&id1_caps);
9209     rig_register(&id31_caps);
9210     rig_register(&id51_caps);
9211     rig_register(&id4100_caps);
9212     rig_register(&id5100_caps);
9213     rig_register(&ic2730_caps);
9214 
9215     rig_register(&perseus_caps);
9216 
9217     rig_register(&x108g_caps);
9218 
9219     RETURNFUNC(RIG_OK);
9220 }
9221