mirror of https://github.com/wb2osz/direwolf.git
KISS Set Hardware commands TNC, TXBUF.
This commit is contained in:
parent
cc84a610dd
commit
c23ab04338
|
@ -1,7 +1,7 @@
|
|||
|
||||
# Revision History #
|
||||
|
||||
## Version 1.5 -- Development snapshot C -- September 2017 ##
|
||||
## Version 1.5 -- Development snapshot C -- October 2017 ##
|
||||
|
||||
This is a snapshot of ongoing development towards version of 1.5. Some features might be incomplete or broken or not documented properly.
|
||||
|
||||
|
@ -9,6 +9,8 @@ This is a snapshot of ongoing development towards version of 1.5. Some features
|
|||
|
||||
- "kissutil" for troubleshooting a KISS TNC or interfacing to an application via files.
|
||||
|
||||
- KISS "Set Hardware" command to report transmit queue length.
|
||||
|
||||
|
||||
### Bugs Fixed: ###
|
||||
|
||||
|
|
29
ax25_pad.c
29
ax25_pad.c
|
@ -2000,7 +2000,7 @@ int ax25_pack (packet_t this_p, unsigned char result[AX25_MAX_PACKET_LEN])
|
|||
assert (this_p->magic1 == MAGIC);
|
||||
assert (this_p->magic2 == MAGIC);
|
||||
|
||||
assert (this_p->frame_len > 0 && this_p->frame_len <= AX25_MAX_PACKET_LEN);
|
||||
assert (this_p->frame_len >= 0 && this_p->frame_len <= AX25_MAX_PACKET_LEN);
|
||||
|
||||
memcpy (result, this_p->frame_data, this_p->frame_len);
|
||||
|
||||
|
@ -2503,6 +2503,33 @@ int ax25_get_pid (packet_t this_p)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
*
|
||||
* Function: ax25_get_frame_len
|
||||
*
|
||||
* Purpose: Get length of frame.
|
||||
*
|
||||
* Inputs: this_p - pointer to packet object.
|
||||
*
|
||||
* Returns: Number of octets in the frame buffer.
|
||||
* Does NOT include the extra 2 for FCS.
|
||||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
int ax25_get_frame_len (packet_t this_p)
|
||||
{
|
||||
assert (this_p->magic1 == MAGIC);
|
||||
assert (this_p->magic2 == MAGIC);
|
||||
|
||||
assert (this_p->frame_len >= 0 && this_p->frame_len <= AX25_MAX_PACKET_LEN);
|
||||
|
||||
return (this_p->frame_len);
|
||||
|
||||
} /* end ax25_get_frame_len */
|
||||
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*
|
||||
* Name: ax25_dedupe_crc
|
||||
|
|
|
@ -427,6 +427,8 @@ extern int ax25_get_c2 (packet_t this_p);
|
|||
|
||||
extern int ax25_get_pid (packet_t this_p);
|
||||
|
||||
extern int ax25_get_frame_len (packet_t this_p);
|
||||
|
||||
extern unsigned short ax25_dedupe_crc (packet_t pp);
|
||||
|
||||
extern unsigned short ax25_m_m_crc (packet_t pp);
|
||||
|
|
84
kiss_frame.c
84
kiss_frame.c
|
@ -25,7 +25,7 @@
|
|||
*
|
||||
* Purpose: Common code used by Serial port and network versions of KISS protocol.
|
||||
*
|
||||
* Description: The KISS TNS protocol is described in http://www.ka9q.net/papers/kiss.html
|
||||
* Description: The KISS TNC protocol is described in http://www.ka9q.net/papers/kiss.html
|
||||
*
|
||||
* ( An extended form, to handle multiple TNCs on a single serial port.
|
||||
* Not applicable for our situation. http://he.fi/pub/oh7lzb/bpq/multi-kiss.pdf )
|
||||
|
@ -40,11 +40,11 @@
|
|||
*
|
||||
* The first byte of the frame contains:
|
||||
*
|
||||
* * port number in upper nybble.
|
||||
* * port number (radio channel) in upper nybble.
|
||||
* * command in lower nybble.
|
||||
*
|
||||
*
|
||||
* Commands from application recognized:
|
||||
* Commands from application tp TNC:
|
||||
*
|
||||
* _0 Data Frame AX.25 frame in raw format.
|
||||
*
|
||||
|
@ -72,6 +72,9 @@
|
|||
*
|
||||
* _0 Data Frame Received AX.25 frame in raw format.
|
||||
*
|
||||
* _6 SetHardware TNC specific.
|
||||
* Usually a response to a query.
|
||||
*
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
#include "direwolf.h"
|
||||
|
@ -88,6 +91,8 @@
|
|||
#include "kiss_frame.h"
|
||||
#include "tq.h"
|
||||
#include "xmit.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
/* In server.c. Should probably move to some misc. function file. */
|
||||
void hex_dump (unsigned char *p, int len);
|
||||
|
@ -138,10 +143,10 @@ static void kiss_set_hardware (int chan, char *command, int debug, int client, v
|
|||
|
||||
#endif
|
||||
|
||||
#if KISSUTIL
|
||||
#define text_color_set(x) ;
|
||||
#define dw_printf printf
|
||||
#endif
|
||||
//#if KISSUTIL
|
||||
//#define text_color_set(x) ;
|
||||
//#define dw_printf printf
|
||||
//#endif
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
|
@ -171,6 +176,7 @@ void kiss_frame_init (struct audio_s *pa)
|
|||
* Inputs: in - Address of input block.
|
||||
* First byte is the "type indicator" with type and
|
||||
* channel but we don't care about that here.
|
||||
* If it happens to be FEND or FESC, it is escaped, like any other byte.
|
||||
*
|
||||
* This seems cumbersome and confusing to have this
|
||||
* one byte offset when encapsulating an AX.25 frame.
|
||||
|
@ -190,7 +196,7 @@ void kiss_frame_init (struct audio_s *pa)
|
|||
* FEND - Magic frame separator.
|
||||
*
|
||||
* Returns: Number of bytes in the output.
|
||||
* Absolute max length will be twice input plus 2.
|
||||
* Absolute max length (extremely unlikely) will be twice input plus 2.
|
||||
*
|
||||
*-----------------------------------------------------------------*/
|
||||
|
||||
|
@ -242,6 +248,8 @@ int kiss_encapsulate (unsigned char *in, int ilen, unsigned char *out)
|
|||
* the escapes or FEND.
|
||||
* First byte is the "type indicator" with type and
|
||||
* channel but we don't care about that here.
|
||||
* We treat it like any other byte with special handling
|
||||
* if it happens to be FESC.
|
||||
* Note that this is "binary" data and can contain
|
||||
* nul (0x00) values. Don't treat it like a text string!
|
||||
*
|
||||
|
@ -509,6 +517,8 @@ void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, int client, v
|
|||
// Some functions are only for the TNC end.
|
||||
// Other functions are suitble for both TNC and client app.
|
||||
|
||||
// This is used only by the TNC sided.
|
||||
|
||||
void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int client, void (*sendfun)(int,int,unsigned char*,int,int))
|
||||
{
|
||||
int port;
|
||||
|
@ -690,6 +700,7 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int cli
|
|||
* debug - debug level.
|
||||
*
|
||||
* client - Client app number for TCP KISS.
|
||||
* Needed so we can send any response to the right client app.
|
||||
* Ignored for pseudo terminal and serial port.
|
||||
*
|
||||
* sendfun - Function to send something to the client application.
|
||||
|
@ -713,13 +724,17 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int cli
|
|||
* be used for throttling of large transmissions and performing some action
|
||||
* after the last frame has been sent.
|
||||
*
|
||||
* The original KISS protocol spec offers no guidance on what this might look
|
||||
* The original KISS protocol spec offers no guidance on what "Set Hardware" might look
|
||||
* like. I'm aware of only two, drastically different, implementations:
|
||||
*
|
||||
* fldigi - http://www.w1hkj.com/FldigiHelp-3.22/kiss_command_page.html
|
||||
*
|
||||
* Everything is in human readable text in the form of:
|
||||
* COMMAND : [ parameter [ , parameter ... ] ]
|
||||
* Everything is in human readable in both directions:
|
||||
*
|
||||
* COMMAND: [ parameter [ , parameter ... ] ]
|
||||
*
|
||||
* Lack of a parameter, in the client to TNC direction, is a query
|
||||
* which should generate a response in the same format.
|
||||
*
|
||||
* Used by applications, http://www.w1hkj.com/FldigiHelp/kiss_host_prgs_page.html
|
||||
* - BPQ32
|
||||
|
@ -740,6 +755,19 @@ void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, int cli
|
|||
*
|
||||
* Let's start with the easy to understand human readable format.
|
||||
*
|
||||
* Commands: (Client to TNC, with parameter(s) to set something.)
|
||||
*
|
||||
* none yet
|
||||
*
|
||||
* Queries: (Client to TNC, no parameters, generate a response.)
|
||||
*
|
||||
* Query Response Comment
|
||||
* ----- -------- -------
|
||||
*
|
||||
* TNC: TNC:DIREWOLF 9.9 9.9 represents current version.
|
||||
*
|
||||
* TXBUF: TXBUF:999 Number of bytes (not frames) in transmit queue.
|
||||
*
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
#ifndef KISSUTIL
|
||||
|
@ -754,39 +782,37 @@ static void kiss_set_hardware (int chan, char *command, int debug, int client, v
|
|||
*param = '\0';
|
||||
param++;
|
||||
|
||||
if (strcmp(command, "TXBUF") == 0) { /* Number of frames in transmit queue. */
|
||||
if (strcmp(command, "TNC") == 0) { /* TNC - Identify software version. */
|
||||
|
||||
if (strlen(param) > 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("KISS Set Hardware TXBUF: did not expect a parameter.\n");
|
||||
dw_printf ("KISS Set Hardware TNC: Did not expect a parameter.\n");
|
||||
}
|
||||
|
||||
// See what we have in the transmit queue for specified channel.
|
||||
// fldigi uses bytes but frames seems to make more sense in this situation.
|
||||
// Do we add one if PTT is on? That information doesn't seem to be easily available.
|
||||
|
||||
// TODO: FIXME: not implemented yet.
|
||||
|
||||
// n = tq_count (chan, TQ_PRIO_0_HI) + tq_count (chan, TQ_PRIO_1_LO);
|
||||
|
||||
snprintf (response, sizeof(response), "TXBUF:whatever");
|
||||
|
||||
snprintf (response, sizeof(response), "DIREWOLF %d.%d", MAJOR_VERSION, MINOR_VERSION);
|
||||
(*sendfun) (chan, KISS_CMD_SET_HARDWARE, (unsigned char *)response, strlen(response), client);
|
||||
}
|
||||
else if (strcmp(command, "TNC") == 0) { /* Identify software version. */
|
||||
; // TODO...
|
||||
|
||||
else if (strcmp(command, "TXBUF") == 0) { /* TXBUF - Number of bytes in transmit queue. */
|
||||
|
||||
if (strlen(param) > 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("KISS Set Hardware TXBUF: Did not expect a parameter.\n");
|
||||
}
|
||||
else if (strcmp(command, "TRXS") == 0) {
|
||||
; // TODO... BUSY
|
||||
|
||||
int n = tq_count (chan, -1, "", "", 1);
|
||||
snprintf (response, sizeof(response), "TXBUF:%d", n);
|
||||
(*sendfun) (chan, KISS_CMD_SET_HARDWARE, (unsigned char *)response, strlen(response), client);
|
||||
}
|
||||
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("KISS Set Hardware invalid command.\n");
|
||||
dw_printf ("KISS Set Hardware unrecognized command: %s.\n", command);
|
||||
}
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("KISS Set Hardware expected the form COMMAND:[parameter[,parameter...]]\n");
|
||||
dw_printf ("KISS Set Hardware \"%s\" expected the form COMMAND:[parameter[,parameter...]]\n", command);
|
||||
}
|
||||
return;
|
||||
|
||||
|
|
16
server.c
16
server.c
|
@ -1705,7 +1705,17 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
struct via_info {
|
||||
unsigned char num_digi; /* Expect to be in range 1 to 7. Why not up to 8? */
|
||||
char dcall[7][10];
|
||||
} *v = (struct via_info *)cmd.data;
|
||||
}
|
||||
#if 1
|
||||
// October 2017. gcc ??? complained:
|
||||
// warning: dereferencing pointer 'v' does break strict-aliasing rules
|
||||
// Try adding this attribute to get rid of the warning.
|
||||
// If this upsets your compiler, take it out.
|
||||
// Let me know. Maybe we could put in a compiler version check here.
|
||||
|
||||
__attribute__((__may_alias__))
|
||||
#endif
|
||||
*v = (struct via_info *)cmd.data;
|
||||
|
||||
char callsigns[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN];
|
||||
int num_calls = 2; /* 2 plus any digipeaters. */
|
||||
|
@ -1866,7 +1876,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
|
||||
int n = 0;
|
||||
if (cmd.hdr.portx >= 0 && cmd.hdr.portx < MAX_CHANS) {
|
||||
n = tq_count (cmd.hdr.portx, -1, "", "");
|
||||
n = tq_count (cmd.hdr.portx, -1, "", "", 0);
|
||||
}
|
||||
reply.data_NETLE = host2netle(n);
|
||||
|
||||
|
@ -1899,7 +1909,7 @@ static THREAD_F cmd_listen_thread (void *arg)
|
|||
|
||||
int n = 0;
|
||||
if (cmd.hdr.portx >= 0 && cmd.hdr.portx < MAX_CHANS) {
|
||||
n = tq_count (cmd.hdr.portx, -1, source, dest);
|
||||
n = tq_count (cmd.hdr.portx, -1, source, dest, 0);
|
||||
}
|
||||
reply.data_NETLE = host2netle(n);
|
||||
|
||||
|
|
49
tq.c
49
tq.c
|
@ -281,7 +281,7 @@ void tq_append (int chan, int prio, packet_t pp)
|
|||
* Implementing the 6PACK protocol is probably the proper solution.
|
||||
*/
|
||||
|
||||
if (ax25_is_aprs(pp) && tq_count(chan,prio,"","") > 100) {
|
||||
if (ax25_is_aprs(pp) && tq_count(chan,prio,"","",0) > 100) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Transmit packet queue for channel %d is too long. Discarding packet.\n", chan);
|
||||
dw_printf ("Perhaps the channel is so busy there is no opportunity to send.\n");
|
||||
|
@ -458,7 +458,7 @@ void lm_data_request (int chan, int prio, packet_t pp)
|
|||
* Is transmit queue out of control?
|
||||
*/
|
||||
|
||||
if (tq_count(chan,prio,"","") > 250) {
|
||||
if (tq_count(chan,prio,"","",0) > 250) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Warning: Transmit packet queue for channel %d is extremely long.\n", chan);
|
||||
dw_printf ("Perhaps the channel is so busy there is no opportunity to send.\n");
|
||||
|
@ -912,7 +912,7 @@ static int tq_is_empty (int chan)
|
|||
*
|
||||
* Name: tq_count
|
||||
*
|
||||
* Purpose: Return count of the number of packets in the specified transmit queue.
|
||||
* Purpose: Return count of the number of packets (or bytes) in the specified transmit queue.
|
||||
* This is used only for queries from KISS or AWG client applications.
|
||||
*
|
||||
* Inputs: chan - Channel, 0 is first.
|
||||
|
@ -924,56 +924,71 @@ static int tq_is_empty (int chan)
|
|||
*
|
||||
* dest - If specified, count only those with this destination address.
|
||||
*
|
||||
* bytes - If true, return number of bytes rather than packets.
|
||||
*
|
||||
* Returns: Number of items in specified queue.
|
||||
*
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
int tq_count (int chan, int prio, char *source, char *dest)
|
||||
int tq_count (int chan, int prio, char *source, char *dest, int bytes)
|
||||
{
|
||||
|
||||
packet_t p;
|
||||
packet_t pp;
|
||||
int n;
|
||||
|
||||
if (prio == -1) {
|
||||
return (tq_count(chan, TQ_PRIO_0_HI, source, dest)
|
||||
+ tq_count(chan, TQ_PRIO_1_LO, source, dest));
|
||||
return (tq_count(chan, TQ_PRIO_0_HI, source, dest, bytes)
|
||||
+ tq_count(chan, TQ_PRIO_1_LO, source, dest, bytes));
|
||||
}
|
||||
|
||||
|
||||
// Array bounds check. FIXME: TODO: should have internal error instead of dying.
|
||||
|
||||
assert (chan >= 0 && chan < MAX_CHANS);
|
||||
assert (prio >= 0 && prio < TQ_NUM_PRIO);
|
||||
if (chan < 0 || chan >= MAX_CHANS || prio < 0 || prio >= TQ_NUM_PRIO) {
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("INTERNAL ERROR - tq_count(%d, %d, \"%s\", \"%s\", %d)\n", chan, prio, source, dest, bytes);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (queue_head[chan][prio] == 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Don't want lists being rearranged while we are traversing them.
|
||||
|
||||
dw_mutex_lock (&tq_mutex);
|
||||
|
||||
n = 0;
|
||||
p = queue_head[chan][prio];
|
||||
while (p != NULL) {
|
||||
pp = queue_head[chan][prio];
|
||||
while (pp != NULL) {
|
||||
int count_it = 1;
|
||||
|
||||
if (source != NULL && *source != '\0') {
|
||||
char frame_source[AX25_MAX_ADDR_LEN];
|
||||
ax25_get_addr_with_ssid (p, AX25_SOURCE, frame_source);
|
||||
ax25_get_addr_with_ssid (pp, AX25_SOURCE, frame_source);
|
||||
if (strcmp(source,frame_source) != 0) count_it = 0;
|
||||
}
|
||||
if (count_it && dest != NULL && *dest != '\0') {
|
||||
char frame_dest[AX25_MAX_ADDR_LEN];
|
||||
ax25_get_addr_with_ssid (p, AX25_DESTINATION, frame_dest);
|
||||
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, frame_dest);
|
||||
if (strcmp(dest,frame_dest) != 0) count_it = 0;
|
||||
}
|
||||
|
||||
if (count_it) n++;
|
||||
p = ax25_get_nextp(p);
|
||||
if (count_it) {
|
||||
if (bytes) {
|
||||
n += ax25_get_frame_len(pp);
|
||||
}
|
||||
else {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
pp = ax25_get_nextp(pp);
|
||||
}
|
||||
|
||||
dw_mutex_unlock (&tq_mutex);
|
||||
|
||||
#if DEBUG
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("tq_count(%d, %d, \"%s\", \"%s\") returns %d\n", chan, prio, source, dest, n);
|
||||
dw_printf ("tq_count(%d, %d, \"%s\", \"%s\", %d) returns %d\n", chan, prio, source, dest, bytes, n);
|
||||
#endif
|
||||
|
||||
return (n);
|
||||
|
|
Loading…
Reference in New Issue