216 lines
4.8 KiB
C
216 lines
4.8 KiB
C
#pragma once
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
|
|
#include "dsp.h"
|
|
|
|
#define LM_VERSION "0.2.5"
|
|
|
|
/* bit fifo */
|
|
|
|
struct sm_fifo {
|
|
unsigned char *sptr, *wptr, *rptr, *eptr;
|
|
int size, max_size;
|
|
};
|
|
|
|
void sm_flush(struct sm_fifo *f);
|
|
int sm_size(struct sm_fifo *f);
|
|
void sm_put_bit(struct sm_fifo *f, int v);
|
|
void sm_put_bits(struct sm_fifo *f, int v, int n);
|
|
int sm_get_bit(struct sm_fifo *f);
|
|
int sm_get_bits(struct sm_fifo *f, int n);
|
|
void sm_init_fifo(struct sm_fifo *f, u8 *buf, int size);
|
|
|
|
/* bit I/O for data pumps */
|
|
typedef void (*put_bit_func)(void *opaque, int bit);
|
|
typedef int (*get_bit_func)(void *opaque);
|
|
|
|
/* timer */
|
|
struct sm_timer {
|
|
long timeout;
|
|
};
|
|
|
|
int sm_time(void);
|
|
void sm_set_timer(struct sm_timer *t, int delay);
|
|
int sm_check_timer(struct sm_timer *t);
|
|
|
|
/* debug */
|
|
extern int lm_debug;
|
|
extern char *sm_states_str[];
|
|
|
|
/* protocol description */
|
|
|
|
#include "dtmf.h"
|
|
#include "fsk.h"
|
|
#include "v21.h"
|
|
#include "v22.h"
|
|
#include "v23.h"
|
|
#include "v8.h"
|
|
#include "v34.h"
|
|
|
|
/* modem state */
|
|
#define SM_FIFO_SIZE 4096
|
|
|
|
struct sm_state {
|
|
/* pretty name of the modem (to debug) */
|
|
char name[16];
|
|
|
|
struct sm_hw_info *hw;
|
|
struct lm_interface_state *hw_state;
|
|
|
|
/* bytes to be transmitted */
|
|
struct sm_fifo tx_fifo;
|
|
u8 tx_fifo_buf[SM_FIFO_SIZE];
|
|
|
|
/* received chars */
|
|
struct sm_fifo rx_fifo;
|
|
u8 rx_fifo_buf[SM_FIFO_SIZE];
|
|
|
|
/* true if we are the caller */
|
|
int calling;
|
|
/* phone number to call */
|
|
char call_num[64];
|
|
int pulse_dial; /* TRUE if we must use pulse dialing */
|
|
|
|
/* dialing */
|
|
struct sm_timer dtmf_timer;
|
|
DTMF_mod_state dtmf_tx;
|
|
int dtmf_ptr, dtmf_len; /* pointer in call_num */
|
|
|
|
/* dtmf receive: for testing (or voice mode in the future) */
|
|
struct sm_timer ring_timer;
|
|
DTMF_demod_state dtmf_rx;
|
|
|
|
/* modulation state */
|
|
union {
|
|
V8State v8_state;
|
|
V21State v21_state;
|
|
V23State v23_state;
|
|
} u;
|
|
|
|
/* serial state */
|
|
int serial_data_bits; /* 5 to 8 */
|
|
int serial_parity, serial_use_parity;
|
|
int serial_wordsize;
|
|
|
|
unsigned int serial_buf;
|
|
int serial_cnt;
|
|
|
|
unsigned int serial_tx_buf;
|
|
int serial_tx_cnt;
|
|
|
|
/* main modem state */
|
|
int state;
|
|
int debug_laststate;
|
|
int hangup_request;
|
|
unsigned int time; /* current time (in samples) */
|
|
|
|
/* config */
|
|
struct LinModemConfig *lm_config;
|
|
};
|
|
|
|
/* linmodem configuration registers */
|
|
typedef struct LinModemConfig {
|
|
int pulse_dial; /* default dial type */
|
|
int dtmf_level; /* in dB */
|
|
int dtmf_digit_length; /* in ms */
|
|
int dtmf_pause_length; /* in ms */
|
|
int available_modulations; /* mask of available modulations */
|
|
} LinModemConfig;
|
|
|
|
/* abstract line interface driver */
|
|
struct lm_interface_state {
|
|
struct sm_state *sm;
|
|
int handle;
|
|
};
|
|
|
|
/* modem hardware interface abstraction */
|
|
/* XXX: must be slightly modified for kernel mode operation */
|
|
struct sm_hw_info {
|
|
int (*open)(struct lm_interface_state *s);
|
|
void (*close)(struct lm_interface_state *s);
|
|
|
|
/* off hook or on hook modem */
|
|
void (*set_offhook)(struct lm_interface_state *s, int v);
|
|
|
|
/* when the ring is enabled, an event E_RING is sent to the
|
|
process if a ring occured */
|
|
void (*set_ring)(struct lm_interface_state *s, int v);
|
|
|
|
/* the main modem loop is here */
|
|
void (*main_loop)(struct lm_interface_state *s);
|
|
};
|
|
|
|
/* general state of the modem */
|
|
|
|
enum {
|
|
#define TAG(s) s,
|
|
#include "lmstates.h"
|
|
};
|
|
|
|
void lm_init(struct sm_state *sm, struct sm_hw_info *hw, const char *name);
|
|
|
|
/* main modem process */
|
|
void sm_process(struct sm_state *sm, s16 *output, s16 *input, int nb_samples);
|
|
|
|
int lm_start_dial(struct sm_state *s, int pulse, const char *number);
|
|
int lm_start_receive(struct sm_state *s);
|
|
int lm_hangup(struct sm_state *s);
|
|
|
|
enum lm_get_state_val {
|
|
LM_STATE_IDLE,
|
|
LM_STATE_CONNECTING,
|
|
LM_STATE_CONNECTED,
|
|
};
|
|
|
|
enum lm_get_state_val lm_get_state(struct sm_state *s);
|
|
|
|
/* lmsim.c */
|
|
|
|
void line_simulate(void);
|
|
|
|
struct LineModelState;
|
|
|
|
struct LineModelState *line_model_init(void);
|
|
void line_model(struct LineModelState *s,
|
|
s16 *output1, const s16 *input1,
|
|
s16 *output2, const s16 *input2,
|
|
int nb_samples);
|
|
|
|
/* lmreal.c */
|
|
|
|
void real_test(int calling);
|
|
|
|
/* lmsoundcard.c */
|
|
void soundcard_modem(void);
|
|
|
|
/* serial.c */
|
|
|
|
void serial_init(struct sm_state *s, int data_bits, int parity);
|
|
int serial_get_bit(void *opaque);
|
|
void serial_put_bit(void *opaque, int bit);
|
|
|
|
/* atparser.c */
|
|
|
|
enum lm_at_state_type {
|
|
AT_MODE_COMMAND,
|
|
AT_MODE_DIALING,
|
|
AT_MODE_CONNECTED,
|
|
};
|
|
|
|
struct lm_at_state {
|
|
char at_line[256];
|
|
int at_line_ptr;
|
|
int at_state;
|
|
struct sm_state *sm; /* corresponding modem state */
|
|
};
|
|
|
|
void lm_at_parser_init(struct lm_at_state *s, struct sm_state *sm);
|
|
void lm_at_parser(struct lm_at_state *s);
|
|
|
|
#include "display.h"
|