From b04c910d53884f0e9b3de46951588ce43cbde334 Mon Sep 17 00:00:00 2001 From: Malcolm Herring Date: Thu, 6 Apr 2017 23:37:33 -0700 Subject: [PATCH 1/5] Icom IC-R10 & 20 testing complete. Move to Beta --- icom/icr10.c | 50 +++++++++++++++++++--------------------- icom/icr20.c | 65 ++++++++++++++++++++++++++-------------------------- 2 files changed, 57 insertions(+), 58 deletions(-) diff --git a/icom/icr10.c b/icom/icr10.c index da33d4e9f..5d4a5fe93 100644 --- a/icom/icr10.c +++ b/icom/icr10.c @@ -46,13 +46,12 @@ { 0, -60 }, /* S0 */ \ { 160, 60 } /* +60 */ \ } } - - + static const struct icom_priv_caps icr10_priv_caps = { - 0x52, /* default address */ - 0, /* 731 mode */ - 0, /* no XCHG */ - r8500_ts_sc_list /* wrong, but don't have set_ts anyway */ + 0x52, /* default address */ + 0, /* 731 mode */ + 0, /* no XCHG */ + r8500_ts_sc_list /* wrong, but don't have set_ts anyway */ }; const struct rig_caps icr10_caps = { @@ -61,7 +60,7 @@ const struct rig_caps icr10_caps = { .mfg_name = "Icom", .version = BACKEND_VER, .copyright = "LGPL", -.status = RIG_STATUS_ALPHA, +.status = RIG_STATUS_BETA, .rig_type = RIG_TYPE_RECEIVER|RIG_FLAG_HANDHELD, .ptt_type = RIG_PTT_NONE, .dcd_type = RIG_DCD_RIG, @@ -78,8 +77,8 @@ const struct rig_caps icr10_caps = { .retry = 3, .has_get_func = ICR10_FUNC_ALL, .has_set_func = ICR10_FUNC_ALL, -.has_get_level = ICR10_LEVEL_ALL, -.has_set_level = RIG_LEVEL_SET(ICR10_LEVEL_ALL), +.has_get_level = ICR10_LEVEL_ALL, +.has_set_level = RIG_LEVEL_NONE, .has_get_parm = RIG_PARM_NONE, .has_set_parm = RIG_PARM_NONE, /* FIXME: parms */ .level_gran = { @@ -101,32 +100,32 @@ const struct rig_caps icr10_caps = { .chan_desc_sz = 0, .chan_list = { - RIG_CHAN_END, - }, + RIG_CHAN_END, +}, .rx_range_list1 = { - {kHz(500),GHz(1.3),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, - RIG_FRNG_END, }, + {kHz(500),GHz(1.3),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, + RIG_FRNG_END, }, .tx_range_list1 = { RIG_FRNG_END, }, .rx_range_list2 = { - {kHz(500),MHz(823.9999),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, - {MHz(849),MHz(868.9999),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, - {MHz(894),GHz(1.3),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, - RIG_FRNG_END, }, + {kHz(500),MHz(823.9999),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, + {MHz(849),MHz(868.9999),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, + {MHz(894),GHz(1.3),ICR10_MODES,-1,-1,ICR10_VFO_ALL}, + RIG_FRNG_END, }, .tx_range_list2 = { RIG_FRNG_END, }, .tuning_steps = { - {ICR10_MODES,Hz(100)}, - RIG_TS_END, - }, + {ICR10_MODES,Hz(100)}, + RIG_TS_END, +}, /* mode/filter list, remember: order matters! */ .filters = { - {RIG_MODE_SSB|RIG_MODE_CW, kHz(4)}, - {RIG_MODE_AM|RIG_MODE_FM, kHz(15)}, - {RIG_MODE_WFM, kHz(150)}, - RIG_FLT_END, - }, + {RIG_MODE_SSB|RIG_MODE_CW, kHz(4)}, + {RIG_MODE_AM|RIG_MODE_FM, kHz(15)}, + {RIG_MODE_WFM, kHz(150)}, + RIG_FLT_END, +}, .str_cal = ICR10_STR_CAL, .cfgparams = icom_cfg_params, @@ -143,7 +142,6 @@ const struct rig_caps icr10_caps = { .get_freq = icom_get_freq, .set_mode = icom_set_mode, /* TODO: do not pass bandwidth data */ .get_mode = icom_get_mode, -/* .set_vfo = icom_set_vfo, */ .decode_event = icom_decode_event, .get_level = icom_get_level, diff --git a/icom/icr20.c b/icom/icr20.c index f16eb957c..4610e7f89 100644 --- a/icom/icr20.c +++ b/icom/icr20.c @@ -42,16 +42,16 @@ #define ICR20_SCAN_OPS (RIG_SCAN_NONE) #define ICR20_STR_CAL { 2, \ - { \ - { 0, -60 }, /* S0 */ \ - { 255, 60 } /* +60 */ \ - } } + { \ + { 0, -60 }, /* S0 */ \ + { 255, 60 } /* +60 */ \ + } } static const struct icom_priv_caps icr20_priv_caps = { - 0x6c, /* default address */ - 0, /* 731 mode */ - 0, /* no XCHG */ - r8500_ts_sc_list /* wrong, but don't have set_ts anyway */ + 0x6c, /* default address */ + 0, /* 731 mode */ + 0, /* no XCHG */ + r8500_ts_sc_list /* wrong, but don't have set_ts anyway */ }; const struct rig_caps icr20_caps = { @@ -60,7 +60,7 @@ const struct rig_caps icr20_caps = { .mfg_name = "Icom", .version = BACKEND_VER, .copyright = "LGPL", -.status = RIG_STATUS_ALPHA, +.status = RIG_STATUS_BETA, .rig_type = RIG_TYPE_RECEIVER|RIG_FLAG_HANDHELD, .ptt_type = RIG_PTT_NONE, .dcd_type = RIG_DCD_RIG, @@ -77,12 +77,12 @@ const struct rig_caps icr20_caps = { .retry = 3, .has_get_func = ICR20_FUNC_ALL, .has_set_func = ICR20_FUNC_ALL, -.has_get_level = ICR20_LEVEL_ALL, -.has_set_level = RIG_LEVEL_SET(ICR20_LEVEL_ALL), +.has_get_level = ICR20_LEVEL_ALL, +.has_set_level = RIG_LEVEL_NONE, .has_get_parm = RIG_PARM_NONE, .has_set_parm = RIG_PARM_NONE, /* FIXME: parms */ .level_gran = { - [LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 255 } }, + [LVL_RAWSTR] = { .min = { .i = 0 }, .max = { .i = 255 } }, }, .parm_gran = {}, .ctcss_list = NULL, @@ -101,36 +101,37 @@ const struct rig_caps icr20_caps = { /* Only through cloning mode OPC-1382 */ .chan_list = { - { 1, 999, RIG_MTYPE_MEM }, /* TBC */ - { 1000, 1199, RIG_MTYPE_MEM }, /* auto-write */ - { 1200, 1249, RIG_MTYPE_EDGE }, /* two by two */ - RIG_CHAN_END, - }, + { 1, 999, RIG_MTYPE_MEM }, /* TBC */ + { 1000, 1199, RIG_MTYPE_MEM }, /* auto-write */ + { 1200, 1249, RIG_MTYPE_EDGE }, /* two by two */ + RIG_CHAN_END, +}, .rx_range_list1 = { /* Other countries but France */ - {kHz(150),GHz(3.304999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, - RIG_FRNG_END, }, + {kHz(150),GHz(3.304999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, + RIG_FRNG_END, }, .tx_range_list1 = { RIG_FRNG_END, }, .rx_range_list2 = { /* USA */ - {kHz(150),MHz(821.999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, - {MHz(851),MHz(866.999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, - {MHz(896),GHz(1.304999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, - {GHz(1.305),GHz(3.304999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, - RIG_FRNG_END, }, + {kHz(150),MHz(821.999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, + {MHz(851),MHz(866.999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, + {MHz(896),GHz(1.304999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, + {GHz(1.305),GHz(3.304999),ICR20_MODES,-1,-1,ICR20_VFO_ALL}, + RIG_FRNG_END, +}, .tx_range_list2 = { RIG_FRNG_END, }, .tuning_steps = { - {ICR20_MODES,Hz(100)}, - RIG_TS_END, - }, + {ICR20_MODES,Hz(100)}, + RIG_TS_END, +}, /* mode/filter list, remember: order matters! */ .filters = { - {RIG_MODE_SSB|RIG_MODE_CW, kHz(1.8)}, - {RIG_MODE_AM|RIG_MODE_FM, kHz(12)}, - {RIG_MODE_WFM, kHz(150)}, - RIG_FLT_END, - }, + {RIG_MODE_SSB|RIG_MODE_CW, kHz(1.8)}, + {RIG_MODE_AM|RIG_MODE_FM, kHz(12)}, + {RIG_MODE_WFM, kHz(150)}, + RIG_FLT_END, +}, .str_cal = ICR20_STR_CAL, .cfgparams = icom_cfg_params, From 42de040bcb9e7cd2842be97780c5ed48746a5f27 Mon Sep 17 00:00:00 2001 From: Tobias Wellnitz Date: Thu, 13 Apr 2017 17:13:15 +0200 Subject: [PATCH 2/5] fixed reading the rig's return value in newcat_get_tx_vfo --- yaesu/newcat.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/yaesu/newcat.c b/yaesu/newcat.c index 91481271d..e4b0479c1 100644 --- a/yaesu/newcat.c +++ b/yaesu/newcat.c @@ -3526,7 +3526,6 @@ int newcat_set_tx_vfo(RIG * rig, vfo_t tx_vfo) { int newcat_get_tx_vfo(RIG * rig, vfo_t * tx_vfo) { struct newcat_priv_data *priv = (struct newcat_priv_data *)rig->state.priv; int err; - char c; vfo_t vfo_mode; char const * command = "FT"; @@ -3543,8 +3542,7 @@ int newcat_get_tx_vfo(RIG * rig, vfo_t * tx_vfo) { return err; } - c = priv->ret_data[strlen (priv->cmd_str)]; - switch (c) { + switch (priv->ret_data[2]) { case '0': *tx_vfo = RIG_VFO_A; break; From fbef95f30fa4c9a0abaf2bfa7025ee690b3b759d Mon Sep 17 00:00:00 2001 From: "Norvald H. Ryeng" Date: Sat, 13 May 2017 15:14:13 +0200 Subject: [PATCH 3/5] New rotator model: SPID MD-01/02 in ROT2 mode Add driver for SPID MD-01 and MD-02 in ROT2 mode. The MD-01 and MD-02 extend the command set from the original ROT2PROG and deviate slightly from the original protocol on the set_position command. --- include/hamlib/rotlist.h | 7 +++ spid/spid.c | 118 ++++++++++++++++++++++++++++++++++++--- spid/spid.h | 1 + 3 files changed, 117 insertions(+), 9 deletions(-) diff --git a/include/hamlib/rotlist.h b/include/hamlib/rotlist.h index 3f342d071..709eac2b0 100644 --- a/include/hamlib/rotlist.h +++ b/include/hamlib/rotlist.h @@ -206,10 +206,17 @@ * The SPID backend can be used with rotators that support the SPID * protocol. */ +/*! \def ROT_MODEL_SPID_MD01_ROT2PROG \brief A macro that returns the + * model number of the MD-01/02 (ROT2PROG protocol) backend. + * + * The SPID backend can be used with rotators that support the SPID + * protocol. + */ #define ROT_SPID 9 #define ROT_BACKEND_SPID "spid" #define ROT_MODEL_SPID_ROT2PROG ROT_MAKE_MODEL(ROT_SPID, 1) #define ROT_MODEL_SPID_ROT1PROG ROT_MAKE_MODEL(ROT_SPID, 2) +#define ROT_MODEL_SPID_MD01_ROT2PROG ROT_MAKE_MODEL(ROT_SPID, 3) /*! \def ROT_MODEL_RC2800 * \brief A macro that returns the model number of the RC2800 backend. diff --git a/spid/spid.c b/spid/spid.c index 3e0dce0c3..06643dfea 100644 --- a/spid/spid.c +++ b/spid/spid.c @@ -53,8 +53,9 @@ static int spid_rot_init(ROT *rot) if (!rot || !rot->caps) return -RIG_EINVAL; - if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG) { - priv = (struct spid_rot2prog_priv_data*)malloc(sizeof(struct spid_rot2prog_priv_data)); + if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || + rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) { + priv = (struct spid_rot2prog_priv_data*)malloc(sizeof(struct spid_rot2prog_priv_data)); if (!priv) { return -RIG_ENOMEM; } @@ -75,7 +76,8 @@ static int spid_rot_cleanup(ROT *rot) if (!rot) return -RIG_EINVAL; - if (rot->state.priv && rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG) + if (rot->state.priv && (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || + rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG)) free(rot->state.priv); rot->state.priv = NULL; @@ -88,7 +90,8 @@ static int spid_get_conf(ROT *rot, token_t token, char *val) rig_debug(RIG_DEBUG_TRACE, "%s called %d\n", __FUNCTION__, token); - if (rot->caps->rot_model != ROT_MODEL_SPID_ROT2PROG) + if (rot->caps->rot_model != ROT_MODEL_SPID_ROT2PROG && + rot->caps->rot_model != ROT_MODEL_SPID_MD01_ROT2PROG) return -RIG_EINVAL; switch(token) { @@ -110,7 +113,8 @@ static int spid_set_conf(ROT *rot, token_t token, const char *val) rig_debug(RIG_DEBUG_TRACE, "%s called %d %s\n", __FUNCTION__, token, val); - if (rot->caps->rot_model != ROT_MODEL_SPID_ROT2PROG) + if (rot->caps->rot_model != ROT_MODEL_SPID_ROT2PROG && + rot->caps->rot_model != ROT_MODEL_SPID_MD01_ROT2PROG) return -RIG_EINVAL; switch(token) { @@ -209,6 +213,15 @@ static int spid_rot2prog_rot_set_position(ROT *rot, azimuth_t az, elevation_t el return retval; } + /* Unlike the original Rot2Prog, MD-01 and MD-02 return the position + after receiving the set position command. */ + if (rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) { + retry_read = 0; + do { + retval = read_block(&rs->rotport, cmdstr, 12); + } while ((retval < 0) && (retry_read++ < rot->state.rotport.retry)); + } + return RIG_OK; } @@ -230,7 +243,8 @@ static int spid_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el) memset(posbuf, 0, 12); if (rot->caps->rot_model == ROT_MODEL_SPID_ROT1PROG) retval = read_block(&rs->rotport, posbuf, 5); - else if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG) + else if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || + rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) retval = read_block(&rs->rotport, posbuf, 12); else retval = -RIG_EINVAL; @@ -241,12 +255,14 @@ static int spid_rot_get_position(ROT *rot, azimuth_t *az, elevation_t *el) *az = posbuf[1] * 100; *az += posbuf[2] * 10; *az += posbuf[3]; - if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG) + if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || + rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) *az += posbuf[4] / 10.0; *az -= 360; *el = 0.0; - if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG) { + if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || + rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) { *el = posbuf[6] * 100; *el += posbuf[7] * 10; *el += posbuf[8]; @@ -278,7 +294,8 @@ static int spid_rot_stop(ROT *rot) memset(posbuf, 0, 12); if (rot->caps->rot_model == ROT_MODEL_SPID_ROT1PROG) retval = read_block(&rs->rotport, posbuf, 5); - else if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG) + else if (rot->caps->rot_model == ROT_MODEL_SPID_ROT2PROG || + rot->caps->rot_model == ROT_MODEL_SPID_MD01_ROT2PROG) retval = read_block(&rs->rotport, posbuf, 12); } while (retval < 0 && retry_read++ < rot->state.rotport.retry); if (retval < 0) @@ -287,6 +304,51 @@ static int spid_rot_stop(ROT *rot) return RIG_OK; } +static int spid_md01_rot2prog_rot_move(ROT *rot, int direction, int speed) +{ + struct rot_state *rs = &rot->state; + char dir = 0x00; + int retval; + char cmdstr[13]; + + rig_debug(RIG_DEBUG_TRACE, "%s called\n", __FUNCTION__); + + switch (direction) { + case ROT_MOVE_UP: + dir = 0x04; + break; + case ROT_MOVE_DOWN: + dir = 0x08; + break; + case ROT_MOVE_LEFT: + dir = 0x01; + break; + case ROT_MOVE_RIGHT: + dir = 0x02; + break; + } + + cmdstr[0] = 0x57; /* S */ + cmdstr[1] = dir; /* H1 */ + cmdstr[2] = 0x00; /* H2 */ + cmdstr[3] = 0x00; /* H3 */ + cmdstr[4] = 0x00; /* H4 */ + cmdstr[6] = 0x00; /* V1 */ + cmdstr[7] = 0x00; /* V2 */ + cmdstr[8] = 0x00; /* V3 */ + cmdstr[9] = 0x00; /* V4 */ + cmdstr[11] = 0x14; /* K */ + cmdstr[12] = 0x20; /* END */ + + /* The rotator must be stopped before changing directions. Since + we don't know which direction we're already moving in (if + moving at all), always send the stop command first. */ + spid_rot_stop(rot); + + retval = write_block(&rs->rotport, cmdstr, 13); + return retval; +} + const struct confparams spid_cfg_params[] = { { TOK_AZRES, "az_resolution", "Azimuth resolution", "Number of pulses per degree, 0 = auto sense", "0", RIG_CONF_NUMERIC, { .n = { 0, 0xff, 1 } } @@ -369,12 +431,50 @@ const struct rot_caps spid_rot2prog_rot_caps = { .stop = spid_rot_stop, }; +const struct rot_caps spid_md01_rot2prog_rot_caps = { + .rot_model = ROT_MODEL_SPID_MD01_ROT2PROG, + .model_name = "MD-01/02 (ROT2 mode)", + .mfg_name = "SPID", + .version = "1.0", + .copyright = "LGPL", + .status = RIG_STATUS_STABLE, + .rot_type = ROT_TYPE_AZEL, + .port_type = RIG_PORT_SERIAL, + .serial_rate_min = 600, + .serial_rate_max = 460800, + .serial_data_bits = 8, + .serial_stop_bits = 1, + .serial_parity = RIG_PARITY_NONE, + .serial_handshake = RIG_HANDSHAKE_NONE, + .write_delay = 0, + .post_write_delay = 0, + .timeout = 400, + .retry = 3, + + .min_az = -180.0, + .max_az = 540.0, + .min_el = -20.0, + .max_el = 210.0, + + .cfgparams = spid_cfg_params, + .get_conf = spid_get_conf, + .set_conf = spid_set_conf, + + .rot_init = spid_rot_init, + .rot_cleanup = spid_rot_cleanup, + .get_position = spid_rot_get_position, + .set_position = spid_rot2prog_rot_set_position, + .move = spid_md01_rot2prog_rot_move, + .stop = spid_rot_stop, +}; + DECLARE_INITROT_BACKEND(spid) { rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __FUNCTION__); rot_register(&spid_rot1prog_rot_caps); rot_register(&spid_rot2prog_rot_caps); + rot_register(&spid_md01_rot2prog_rot_caps); return RIG_OK; } diff --git a/spid/spid.h b/spid/spid.h index e509d2f51..3814f9420 100644 --- a/spid/spid.h +++ b/spid/spid.h @@ -24,5 +24,6 @@ extern const struct rot_caps spid_rot1prog_rot_caps; extern const struct rot_caps spid_rot2prog_rot_caps; +extern const struct rot_caps spid_md01_rot2prog_rot_caps; #endif /* _ROT_SPID_H */ From e156ef65fbc1c74a2390c669d764efde1706559b Mon Sep 17 00:00:00 2001 From: c vw Date: Mon, 22 May 2017 19:09:47 +0200 Subject: [PATCH 4/5] fixes for kenwood backends --- kenwood/kenwood.c | 25 +++++++++++++++++++++---- kenwood/ts570.c | 2 +- kenwood/ts590.c | 2 +- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/kenwood/kenwood.c b/kenwood/kenwood.c index ebb3401fd..3d96db508 100644 --- a/kenwood/kenwood.c +++ b/kenwood/kenwood.c @@ -1658,7 +1658,11 @@ int kenwood_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) switch (level) { case RIG_LEVEL_RFPOWER: - /* XXX check level range */ + /* + * Best estimate: 1.0 corresponds to 100W + * Anything better must be done in rig-specific files. + */ + if (RIG_LEVEL_IS_FLOAT(level)) kenwood_val = val.f * 100; sprintf(levelbuf, "PC%03d", kenwood_val); break; @@ -2728,9 +2732,22 @@ int kenwood_send_morse(RIG *rig, vfo_t vfo, const char *msg) while(msg_len > 0) { /* - * TODO: check with "KY" if char buffer is available. - * if not, sleep. - * + * Check with "KY" if char buffer is available. + * if not, sleep. + */ + for (;;) { + retval = kenwood_transaction(rig, "KY;", m2, 4); + if (retval != RIG_OK) + return retval; + /* + * If answer is "KY0;", there is space in buffer and we can proceed. + * If answer is "KY1;", we have to wait a while + * If answer is something else, return with error to prevent infinite loops + */ + if (!strncmp(m2,"KY0", 3)) break; + if (!strncmp(m2,"KY1", 3)) usleep(500000); else return -RIG_EINVAL; + } + /* * Make the total message segments 28 characters * in length because Kenwood demands it. * Spaces fill in the message end. diff --git a/kenwood/ts570.c b/kenwood/ts570.c index 4c69ae69f..68edf743b 100644 --- a/kenwood/ts570.c +++ b/kenwood/ts570.c @@ -37,7 +37,7 @@ #define TS570_FUNC_ALL (RIG_FUNC_FAGC|RIG_FUNC_TSQL|RIG_FUNC_TONE|RIG_FUNC_NB|RIG_FUNC_COMP|RIG_FUNC_VOX|RIG_FUNC_NR|RIG_FUNC_LOCK|RIG_FUNC_BC|RIG_FUNC_TUNER) -#define TS570_LEVEL_ALL (RIG_LEVEL_PREAMP|RIG_LEVEL_ATT|RIG_LEVEL_AGC|RIG_LEVEL_SQL|RIG_LEVEL_STRENGTH|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_RFPOWER|RIG_LEVEL_MICGAIN|RIG_LEVEL_SLOPE_LOW|RIG_LEVEL_SLOPE_HIGH) +#define TS570_LEVEL_ALL (RIG_LEVEL_PREAMP|RIG_LEVEL_ATT|RIG_LEVEL_AGC|RIG_LEVEL_SQL|RIG_LEVEL_STRENGTH|RIG_LEVEL_AF|RIG_LEVEL_RF|RIG_LEVEL_RFPOWER|RIG_LEVEL_MICGAIN|RIG_LEVEL_SLOPE_LOW|RIG_LEVEL_SLOPE_HIGH|RIG_LEVEL_KEYSPD) #define TS570_VFO (RIG_VFO_A|RIG_VFO_B) #define TS570_VFO_OP (RIG_OP_UP|RIG_OP_DOWN) diff --git a/kenwood/ts590.c b/kenwood/ts590.c index 96f829bb8..207b81e8e 100644 --- a/kenwood/ts590.c +++ b/kenwood/ts590.c @@ -41,7 +41,7 @@ const char* ts590_get_info(RIG *rig); #define TS590_LEVEL_ALL (RIG_LEVEL_RFPOWER|RIG_LEVEL_AF|RIG_LEVEL_RF|\ RIG_LEVEL_CWPITCH|RIG_LEVEL_METER|RIG_LEVEL_SWR|RIG_LEVEL_ALC|\ - RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_STRENGTH) + RIG_LEVEL_SQL|RIG_LEVEL_AGC|RIG_LEVEL_STRENGTH|RIG_LEVEL_KEYSPD) #define TS590_FUNC_ALL (RIG_FUNC_LOCK|RIG_FUNC_AIP|RIG_FUNC_TONE|\ RIG_FUNC_NB|RIG_FUNC_COMP|RIG_FUNC_VOX|RIG_FUNC_NR|RIG_FUNC_NR|RIG_FUNC_BC) From 2828422e92afeec5d87f1dc45c57271688aefadd Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 22 May 2017 21:51:08 +0100 Subject: [PATCH 5/5] Stop rigctld and rotctld crashing when service threads cannot write to clients Although there is no reasonable recovery from SIGPIPE we do not want to terminate the server process, just the client servicing thread. We do this by setting the disposition for SIGPIPE to ignored, this causes an EPIPE to be returned from blocked write() and send() calls that end up trying to send to a broken pipe/socket. --- configure.ac | 2 +- tests/rigctld.c | 32 ++++++++++++++++++++++++++------ tests/rotctld.c | 32 ++++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 58aa4472d..8d588dc0f 100644 --- a/configure.ac +++ b/configure.ac @@ -234,7 +234,7 @@ AC_SUBST([NET_LIBS]) dnl Checks for library functions. AC_CHECK_FUNCS([cfmakeraw floor getpagesize getpagesize gettimeofday inet_ntoa \ -ioctl memchr memmove memset pow rint select setitimer setlocale sigaction \ +ioctl memchr memmove memset pow rint select setitimer setlocale sigaction signal \ snprintf socket sqrt strchr strdup strerror strncasecmp strrchr strstr strtol]) AC_FUNC_ALLOCA diff --git a/tests/rigctld.c b/tests/rigctld.c index a593da3a3..2197c1af0 100644 --- a/tests/rigctld.c +++ b/tests/rigctld.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -172,6 +173,12 @@ int main(int argc, char *argv[]) char host[NI_MAXHOST]; char serv[NI_MAXSERV]; +#ifdef HAVE_PTHREAD + pthread_t thread; + pthread_attr_t attr; +#endif + struct handle_data *arg; + while (1) { int c; int option_index = 0; @@ -523,16 +530,29 @@ int main(int argc, char *argv[]) exit(1); } +#ifdef SIGPIPE + /* Ignore SIGPIPE as we will handle it at the write()/send() calls + that will consequently fail with EPIPE. All child threads will + inherit this disposition which is what we want. */ +#if HAVE_SIGACTION + struct sigaction act; + memset (&act, 0, sizeof act); + act.sa_handler = SIG_IGN; + act.sa_flags = SA_RESTART; + if (sigaction (SIGPIPE, &act, NULL)) { + handle_error (RIG_DEBUG_ERR, "sigaction"); + } +#elif HAVE_SIGNAL + if (SIG_ERR == signal (SIGPIPE, SIG_IGN))) + handle_error (RIG_DEBUG_ERR, "signal"); + } +#endif +#endif + /* * main loop accepting connections */ do { -#ifdef HAVE_PTHREAD - pthread_t thread; - pthread_attr_t attr; -#endif - struct handle_data *arg; - arg = malloc(sizeof(struct handle_data)); if (!arg) { diff --git a/tests/rotctld.c b/tests/rotctld.c index 04c9747ca..3c94aa54d 100644 --- a/tests/rotctld.c +++ b/tests/rotctld.c @@ -34,6 +34,7 @@ #include #include +#include #include /* See NOTES */ @@ -160,6 +161,12 @@ int main(int argc, char *argv[]) char host[NI_MAXHOST]; char serv[NI_MAXSERV]; +#ifdef HAVE_PTHREAD + pthread_t thread; + pthread_attr_t attr; +#endif + struct handle_data *arg; + while (1) { int c; int option_index = 0; @@ -416,16 +423,29 @@ int main(int argc, char *argv[]) exit(1); } +#ifdef SIGPIPE + /* Ignore SIGPIPE as we will handle it at the write()/send() calls + that will consequently fail with EPIPE. All child threads will + inherit this disposition which is what we want. */ +#if HAVE_SIGACTION + struct sigaction act; + memset (&act, 0, sizeof act); + act.sa_handler = SIG_IGN; + act.sa_flags = SA_RESTART; + if (sigaction (SIGPIPE, &act, NULL)) { + handle_error (RIG_DEBUG_ERR, "sigaction"); + } +#elif HAVE_SIGNAL + if (SIG_ERR == signal (SIGPIPE, SIG_IGN))) + handle_error (RIG_DEBUG_ERR, "signal"); + } +#endif +#endif + /* * main loop accepting connections */ do { -#ifdef HAVE_PTHREAD - pthread_t thread; - pthread_attr_t attr; -#endif - struct handle_data *arg; - arg = malloc(sizeof(struct handle_data)); if (!arg) {