diff --git a/uniden/bcd396t.c b/uniden/bcd396t.c index 6e1e2f7eb..bb1b0b9ce 100644 --- a/uniden/bcd396t.c +++ b/uniden/bcd396t.c @@ -2,7 +2,7 @@ * Hamlib Uniden backend - BCD396T description * Copyright (c) 2001-2008 by Stephane Fillod * - * $Id: bcd396t.c,v 1.1 2008-10-07 18:58:08 fillods Exp $ + * $Id: bcd396t.c,v 1.2 2008-10-18 06:21:31 roger-linux Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -27,7 +27,7 @@ #include #include "hamlib/rig.h" -#include "uniden.h" +/*#include "uniden.h"*/ #include "uniden_digital.h" @@ -122,7 +122,7 @@ const struct rig_caps bcd396t_caps = { RIG_FLT_END, }, -.get_info = uniden_get_info, +.get_info = uniden_digital_get_info, .set_freq = uniden_digital_set_freq, .get_freq = uniden_digital_get_freq, diff --git a/uniden/bcd996t.c b/uniden/bcd996t.c index 47480128b..5f518d537 100644 --- a/uniden/bcd996t.c +++ b/uniden/bcd996t.c @@ -2,7 +2,7 @@ * Hamlib Uniden backend - BCD996T description * Copyright (c) 2001-2008 by Stephane Fillod * - * $Id: bcd996t.c,v 1.1 2008-10-07 18:58:08 fillods Exp $ + * $Id: bcd996t.c,v 1.2 2008-10-18 06:21:31 roger-linux Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -27,7 +27,7 @@ #include #include "hamlib/rig.h" -#include "uniden.h" +/*#include "uniden.h"*/ #include "uniden_digital.h" @@ -120,7 +120,7 @@ const struct rig_caps bcd996t_caps = { RIG_FLT_END, }, -.get_info = uniden_get_info, +.get_info = uniden_digital_get_info, .set_freq = uniden_digital_set_freq, .get_freq = uniden_digital_get_freq, diff --git a/uniden/uniden_digital.c b/uniden/uniden_digital.c index 9ef1d224f..6f452ce6a 100644 --- a/uniden/uniden_digital.c +++ b/uniden/uniden_digital.c @@ -2,7 +2,7 @@ * Hamlib Uniden backend - uniden_digital backend * Copyright (c) 2001-2008 by Stephane Fillod * - * $Id: uniden_digital.c,v 1.2 2008-10-17 11:52:04 roger-linux Exp $ + * $Id: uniden_digital.c,v 1.3 2008-10-18 06:21:31 roger-linux Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -66,6 +66,189 @@ uniden_id_string_list[] = { }; +#define EOM "\r" + +#define BUFSZ 64 + +/** + * uniden_transaction + * uniden_digital_transaction + * Assumes rig!=NULL rig->state!=NULL rig->caps!=NULL + * + * cmdstr - Command to be sent to the rig. Cmdstr can also be NULL, indicating + * that only a reply is needed (nothing will be send). + * replystr - Reply prefix to be expected. Replystr can also be NULL, indicating + * that the prefix is either the cmdstr prefix or OK. + * data - Buffer for reply string. Can be NULL, indicating that no reply is + * is needed and will return with RIG_OK after command was sent. + * datasize - in: Size of buffer. It is the caller's responsibily to provide + * a large enough buffer for all possible replies for a command. + * out: location where to store number of bytes read. + * + * returns: + * RIG_OK - if no error occured. + * RIG_EIO - if an I/O error occured while sending/receiving data. + * RIG_ETIMEOUT - if timeout expires without any characters received. + * RIG_REJECTED - if a negative acknowledge was received or command not + * recognized by rig. + */ +int +uniden_digital_transaction (RIG *rig, const char *cmdstr, int cmd_len, const char *replystr, + char *data, size_t *datasize) +{ + struct rig_state *rs; + int retval; + int retry_read = 0; + char replybuf[BUFSZ]; + size_t reply_len=BUFSZ; + + rs = &rig->state; + rs->hold_decode = 1; + +transaction_write: + + serial_flush(&rs->rigport); + + if (cmdstr) { + retval = write_block(&rs->rigport, cmdstr, strlen(cmdstr)); + if (retval != RIG_OK) + goto transaction_quit; + } + + /* Always read the reply to known if it went OK */ + if (!data) + data = replybuf; + if (!datasize) + datasize = &reply_len; + + memset(data,0,*datasize); + retval = read_string(&rs->rigport, data, *datasize, EOM, strlen(EOM)); + if (retval < 0) { + if (retry_read++ < rig->state.rigport.retry) + goto transaction_write; + goto transaction_quit; + } else + *datasize = retval; + + /* Check that command termination is correct */ + if (strchr(EOM, data[strlen(data)-1])==NULL) { + rig_debug(RIG_DEBUG_ERR, "%s: Command is not correctly terminated '%s'\n", __FUNCTION__, data); + if (retry_read++ < rig->state.rigport.retry) + goto transaction_write; + retval = -RIG_EPROTO; + goto transaction_quit; + } + + if (strcmp(data, "OK"EOM)) { + /* everything is fine */ + retval = RIG_OK; + goto transaction_quit; + } + + /* Any syntax returning NG indicates a VALID Command but not entered + * in the right mode or using the correct parameters. ERR indicates + * an INVALID Command. + */ + if (strcmp(data, "NG"EOM) || strcmp(data, "ORER"EOM)) { + /* Invalid command */ + rig_debug(RIG_DEBUG_VERBOSE, "%s: NG/Overflow for '%s'\n", __FUNCTION__, cmdstr); + retval = -RIG_EPROTO; + goto transaction_quit; + } + + if (strcmp(data, "ERR"EOM)) { + /* Command format error */ + rig_debug(RIG_DEBUG_VERBOSE, "%s: Error for '%s'\n", __FUNCTION__, cmdstr); + retval = -RIG_EINVAL; + goto transaction_quit; + } + +#define CONFIG_STRIP_CMDTRM 1 +#ifdef CONFIG_STRIP_CMDTRM + if (strlen(data) > 0) + data[strlen(data)-1] = '\0'; /* not very elegant, but should work. */ + else + data[0] = '\0'; +#endif + + /* Special case for SQuelch */ + if (!memcmp(cmdstr,"SQ",2) && (replystr[0] == '-' || replystr[0] == '+')) { + retval = RIG_OK; + goto transaction_quit; + } + + /* Command prefix if no replystr supplied */ + if (!replystr) + replystr = cmdstr; + /* + * Check that received the correct reply. The first two characters + * should be the same as command. + */ + if (replystr && replystr[0] && (data[0] != replystr[0] || + (replystr[1] && data[1] != replystr[1]))) { + /* + * TODO: When RIG_TRN is enabled, we can pass the string + * to the decoder for callback. That way we don't ignore + * any commands. + */ + rig_debug(RIG_DEBUG_ERR, "%s: Unexpected reply '%s'\n", __FUNCTION__, data); + if (retry_read++ < rig->state.rigport.retry) + goto transaction_write; + + retval = -RIG_EPROTO; + goto transaction_quit; + } + + retval = RIG_OK; +transaction_quit: + rs->hold_decode = 0; + return retval; +} + + +/* + * uniden_get_info + * Assumes rig!=NULL + */ +const char * uniden_digital_get_info(RIG *rig) +{ + static char infobuf[BUFSZ]; + size_t info_len=BUFSZ/2, vrinfo_len=BUFSZ/2; + int ret; + + ret = uniden_digital_transaction (rig, "STS" EOM, 3, NULL, infobuf, &info_len); + if (ret != RIG_OK) + return NULL; + + /* SI BC250D,0000000000,104 */ + + if (info_len < 4) + return NULL; + + if (info_len >= BUFSZ) + info_len = BUFSZ-1; + infobuf[info_len] = '\0'; + + /* VR not on every rig */ + /* VR1.00 */ + ret = uniden_digital_transaction (rig, "MDL" EOM, 3, NULL, infobuf+info_len, &vrinfo_len); + if (ret == RIG_OK) + { + /* overwrite "VR" */ + /* FIXME: need to filter \r or it screws w/ stdout */ + infobuf[info_len] = '\n'; + infobuf[info_len+1] = ' '; + } + else + { + infobuf[info_len] = '\0'; + } + + /* skip "SI " */ + return infobuf+3; +} + + /* * skeleton */ @@ -114,4 +297,3 @@ int uniden_digital_get_freq(RIG *rig, vfo_t vfo, freq_t *freq) #endif } - diff --git a/uniden/uniden_digital.h b/uniden/uniden_digital.h index 881e97277..614d9e59e 100644 --- a/uniden/uniden_digital.h +++ b/uniden/uniden_digital.h @@ -2,7 +2,7 @@ * Hamlib Uniden backend - uniden_digital header * Copyright (c) 2001-2008 by Stephane Fillod * - * $Id: uniden_digital.h,v 1.1 2008-10-07 18:58:08 fillods Exp $ + * $Id: uniden_digital.h,v 1.2 2008-10-18 06:21:31 roger-linux Exp $ * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as @@ -27,6 +27,11 @@ #define BACKEND_DIGITAL_VER "0.3" +int uniden_digital_transaction (RIG *rig, const char *cmdstr, int cmd_len, + const char *replystr, char *data, size_t *datasize); + +const char* uniden_digital_get_info(RIG *rig); + int uniden_digital_set_freq(RIG *rig, vfo_t vfo, freq_t freq); int uniden_digital_get_freq(RIG *rig, vfo_t vfo, freq_t *freq);