summaryrefslogtreecommitdiffstats
path: root/src/linuxaldl.h
blob: 02c87b1f978ceaa514b3e33a8c97b64e164cf5da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#ifndef LINUXALDL_INCLUDED
#define LINUXALDL_INCLUDED

/*(C) copyright 2008, Steven Snyder, All Rights Reserved

Steven T. Snyder, <stsnyder@ucla.edu> http://www.steventsnyder.com

LICENSING INFORMATION:
 This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

// debug mode
//#define _LINUXALDL_DEBUG

#define MAX_CONNECT_ATTEMPTS 3

// macros

#define _ALDL_MESSAGE_MODE8 aldl_settings.definition->mode8_request,aldl_settings.definition->mode8_request_length
#define _ALDL_MESSAGE_MODE9 aldl_settings.definition->mode9_request,aldl_settings.definition->mode9_request_length

#define __MAX_REQUEST_SIZE 16 /* maximum size (bytes) of a request message to send to the ECM */

enum ALDL_OP { ALDL_OP_SCALAR=0,
	       ALDL_OP_MAP,
	       ALDL_OP_BIT,
	       ALDL_OP_SEPERATOR,
};

// ============================================================================
// ALDL DEFINITION STRUCTS
// ============================================================================

// See linuxaldl_definitions.h for instructions on how to make a new definition


// byte_def_t struct
typedef struct _linuxaldl_byte_definition{
	const char* label;
	unsigned char byte_offset; /* Offset from the 1st byte of the data part of the mode1 message */
	unsigned char bits; /* 8 or 16 are currently supported */
	enum ALDL_OP operation;

	float op_factor; // factor for the operation
	float op_offset; // offset for the operation
	const char* units; /* Text string */

	const float *map;

	unsigned char b_bit;
	const char *b_set;
	const char *b_unset;
} byte_def_t;

#define ALDL_DEF_SCALAR8(__label, __offset, __factor, __shift, __units ) \
	{ .label = __label, \
	  .byte_offset = __offset, \
	  .operation = ALDL_OP_SCALAR, \
	  .bits = 8, \
	  .op_factor = __factor, \
	  .op_offset = __shift,	\
	  .units = __units, \
       	}
#define ALDL_DEF_SCALAR16(__label, __offset, __factor, __shift, __units ) \
	{ .label = __label, \
	  .byte_offset = __offset, \
	  .operation = ALDL_OP_SCALAR, \
	  .bits = 16, \
	  .op_factor = __factor, \
	  .op_offset = __shift,	\
	  .units = __units, \
       	}
#define ALDL_DEF_MAP8(__label, __offset, __map, __units ) \
	{ .label = __label, \
	  .byte_offset = __offset, \
	  .operation = ALDL_OP_MAP, \
	  .bits = 8, \
	  .map = __map,	\
	  .units = __units, \
       	}
#define ALDL_DEF_BIT(__label, __offset, __bit, __set, __unset ) \
	{ .label = __label, \
	  .byte_offset = __offset, \
	  .operation = ALDL_OP_BIT, \
	  .bits = 8, \
	  .b_bit = __bit, \
	  .b_set = __set, \
	  .b_unset = __unset, \
       	}
#define ALDL_DEF_SEPERATOR(__label) \
	{ .label = __label, \
	  .operation = ALDL_OP_SEPERATOR, \
	}
#define ALDL_DEF_END { .label = NULL }


typedef struct _linuxaldl_definition {
	const char* mask;
	const char* name;
	char mode1_request[__MAX_REQUEST_SIZE];  // the mode 1 request message, including the checksum
	unsigned int mode1_request_length;  // the length of the mode 1 message including the checksum

	unsigned int mode1_response_length; // the total length of the response from the ecm

	unsigned int mode1_data_length; // the number of data bytes in the mode1 message response

	unsigned int mode1_data_offset; // the byte offest from the start of the mode1 message response
									// to the first byte of the data. e.g. if the data part of the
									// message is the 4th byte onward, this should be 3. (1+3 = 4)

	byte_def_t* mode1_def; // pointer to start of table of byte_def_t structs.
							// the last element must be LINUXALDL_MODE1_END_DEF

	char mode8_request[__MAX_REQUEST_SIZE];  // the mode 8 (silence) request message, incl checksum
	unsigned int mode8_request_length;  // the length of the mode 8 message incl checksum

	char mode9_request[__MAX_REQUEST_SIZE];  // the mode 9 (un-silence) request message, incl checksum
	unsigned int mode9_request_length;  // the length of the mode 9 message including the checksum

	unsigned int basic_baudrate;  /* Fallback datarate */
	unsigned int ideal_baudrate;  /* Desired datarate -- 8192 or 160 */
} aldl_definition;

// looks up def_name in the aldl_definition_table until it finds the first 
// definition in the table with the name def_name or the mask defmask
// if the definition is not in the table, returns NULL
aldl_definition* aldl_get_definition(const char* defname, const char *defmask);

typedef struct _linuxaldl_settings
{
	/* Configuration fields */
	const char* aldlportname; // path to aldl interface port
	const char* logfilename; 	// filename for the log file
	const char* aldldefname; // name for the ALDL definition to be used

	unsigned int scan_interval; // msec between scan requests
	unsigned int scan_timeout; // msec to timeout on scan request.
				// note that read-sequence takes timeout in usec.				// usec = msec*1000

	/* Data definitions */
	aldl_definition** aldl_definition_table; // array of pointers to data definitions. (see linuxaldl_definitions.h)
	
	/* Runtime stuff */
	int faldl; 			// aldl serial interface file descriptor
	int flogfile; 		// file descriptor for log file
	int scanning; // 1 when the timer has been set for making scans, otherwise 0.
	aldl_definition* definition; // see linuxaldl_definitions.h

	char* data_set_raw;	// the current/most recent set of data from a mode1 message.
				// this is allocated when a definition is selected

	char** data_set_strings;	// pointer to array of data set in string format.
					// allocated when a definition is selected in the GUI

	float* data_set_floats;		// data set in float format
					// allocated when a definition is selected in the GUI

} linuxaldl_settings;

// function prototypes
// =================================================

int verifyaldl();
// wake up / verify the ALDL interface

int aldl_scan_and_log(int fd);
// listens for aldl data and writes it to the file descriptor fd 
// stops when terminate_scan = 1 in the global settings struct and
// returns number of bytes written to fd.

char get_checksum(char* buffer, unsigned int len);
// calculates the single-byte checksum, summing from the start of buffer
// through len bytes. the checksum is calculated by summing the bytes,
// dropping carried bits, then adding 1 and taking the two's complement
// (subtract from FF) 

int send_aldl_message(char* msg_buf, unsigned int size);
// sends an artibtrary aldl message contained in the buffer msg_buf.
// the checksum must be set in the buffer by the caller.
// the following macros can be used as arguments:
//		_ALDL_MESSAGE_MODE8
//		_ALDL_MESSAGE_MODE9
// which use the mode 8 and mode 9 message definitions from the
// current aldl definition.

int get_mode1_message(char* inbuffer, unsigned int size);
// requests a mode1 message from the ECM using the currently loaded
// aldl definition. 
// returns 0 if the message was received successfully, -1 no response
// or bad checksum. 

int aldl_listen_raw(char* inbuffer, unsigned int len, int timeout);
// reads up to len bytes into inbuffer from the interface.
// listens for a maximum of timeout seconds.
// returns -1 on failure, 0 on timeout with no bytes received,
// and otherwise returns the number of bytes received 

typedef enum _ALDL_UPDATE_FLAGS { ALDL_UPDATE_STRINGS=1, ALDL_UPDATE_FLOATS=2} ALDL_UPDATE_FLAGS_t;
void aldl_update_sets(int flags);
// updates data_set_floats and/or data_set_strings using the current data_set_raw bytes.
// if the flags argument is ALDL_UPDATE_STRINGS then both sets will be updated.
// if it is ALDL_UPDATE_FLOATS then only floats will be updated, and the data_set_strings
// array will not be modified in any way.

#endif