diff options
Diffstat (limited to 'firmware')
96 files changed, 12114 insertions, 3383 deletions
diff --git a/firmware/README.md b/firmware/README.md index c8ad9df16..b549d993b 100644 --- a/firmware/README.md +++ b/firmware/README.md @@ -18,7 +18,7 @@ __Build Instructions:__  ## fx3/ -__Description:__ This is the firmware for the FX3 USB PHY, and the AD9361 RFIC. +__Description:__ This is the firmware for the FX3 USB PHY.  __Devices:__ USRP B200 and USRP B210 @@ -36,7 +36,12 @@ __Devices:__ Octoclock.  __Tools:__ avrtools, cmake -__Build Instructions:__ Run `make` from the Octoclock source directory. +__Build Instructions:__ + +1. mkdir `<build directory>` +2. cd `<build directory>` +3. cmake `<source directory>` +4. make  ## zpu/ diff --git a/firmware/fx3/.gitignore b/firmware/fx3/.gitignore new file mode 100644 index 000000000..f2c372d44 --- /dev/null +++ b/firmware/fx3/.gitignore @@ -0,0 +1,3 @@ +common +lpp_source +u3p_firmware diff --git a/firmware/fx3/README.md b/firmware/fx3/README.md index e2e8a13d4..7e94c247c 100644 --- a/firmware/fx3/README.md +++ b/firmware/fx3/README.md @@ -9,10 +9,8 @@ show you how to build our firmware source  **A brief "Theory of Operations":**  The host sends commands to the FX3, our USB3 PHY, which has an on-board ARM -which runs the FX3 firmware code (hex file). That code translates commands into -SPI commands to/from the AD9361. The SPI lines run through the FPGA (bin or bit -file), where they are level-translated, and then head to the AD9361. Note that -the FPGA takes no action on these SPI lines. They are passive pass-throughs. +which runs the FX3 firmware code (hex file). That code is responsible for +managing the transport from the host to the FPGA by configuring IO and DMA.  ## Setting up the Cypress SDK @@ -46,7 +44,6 @@ uhd.git/                   |                   --fx3/                        | -                      --ad9361/             # From UHD                        --b200/               # From UHD                        --common/             # From Cypress SDK                        --gpif2_designer/     # From UHD diff --git a/firmware/fx3/ad9361/include/ad9361_dispatch.h b/firmware/fx3/ad9361/include/ad9361_dispatch.h deleted file mode 100644 index e89a4e0b0..000000000 --- a/firmware/fx3/ad9361/include/ad9361_dispatch.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -#ifndef INCLUDED_AD9361_DISPATCH_H -#define INCLUDED_AD9361_DISPATCH_H - -#include <ad9361_transaction.h> - -extern void ad9361_dispatch(const char* request, char* response); - -typedef void (*msgfn)(const char*, ...); - -extern void ad9361_set_msgfn(msgfn pfn); - -#endif /* INCLUDED_AD9361_DISPATCH_H */ diff --git a/firmware/fx3/ad9361/include/ad9361_transaction.h b/firmware/fx3/ad9361/include/ad9361_transaction.h deleted file mode 100644 index 2349a5d3d..000000000 --- a/firmware/fx3/ad9361/include/ad9361_transaction.h +++ /dev/null @@ -1,90 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -#ifndef INCLUDED_AD9361_TRANSACTION_H -#define INCLUDED_AD9361_TRANSACTION_H - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -//various constants -#define AD9361_TRANSACTION_VERSION       0x4 -#define AD9361_DISPATCH_PACKET_SIZE      64 - -//action types -#define AD9361_ACTION_ECHO 0 -#define AD9361_ACTION_INIT 1 -#define AD9361_ACTION_SET_RX1_GAIN 2 -#define AD9361_ACTION_SET_TX1_GAIN 3 -#define AD9361_ACTION_SET_RX2_GAIN 4 -#define AD9361_ACTION_SET_TX2_GAIN 5 -#define AD9361_ACTION_SET_RX_FREQ 6 -#define AD9361_ACTION_SET_TX_FREQ 7 -#define AD9361_ACTION_SET_CODEC_LOOP 8 -#define AD9361_ACTION_SET_CLOCK_RATE 9 -#define AD9361_ACTION_SET_ACTIVE_CHAINS 10 - -static inline void ad9361_double_pack(const double input, uint32_t output[2]) -{ -    const uint32_t *p = (const uint32_t *)&input; -    output[0] = p[0]; -    output[1] = p[1]; -} - -static inline double ad9361_double_unpack(const uint32_t input[2]) -{ -    double output = 0.0; -    uint32_t *p = (uint32_t *)&output; -    p[0] = input[0]; -    p[1] = input[1]; -    return output; -} - -typedef struct -{ -    //version is expected to be AD9361_TRANSACTION_VERSION -    //check otherwise for compatibility -    uint32_t version; - -    //sequence number - increment every call for sanity -    uint32_t sequence; - -    //action tells us what to do, see AD9361_ACTION_* -    uint32_t action; - -    union -    { -        //enable mask for chains -        uint32_t enable_mask; - -        //true to enable codec internal loopback -        uint32_t codec_loop; - -        //freq holds request LO freq and result from tune -        uint32_t freq[2]; - -        //gain holds request gain and result from action -        uint32_t gain[2]; - -        //rate holds request clock rate and result from action -        uint32_t rate[2]; - -    } value; - -    //error message comes back as a reply - -    //set to null string for no error \0 -    char error_msg[]; - -} ad9361_transaction_t; - -#define AD9361_TRANSACTION_MAX_ERROR_MSG (AD9361_DISPATCH_PACKET_SIZE - (sizeof(ad9361_transaction_t)-4)-1)	// -4 for 'error_msg' alignment padding, -1 for terminating \0 - -#ifdef __cplusplus -} -#endif - -#endif /* INCLUDED_AD9361_TRANSACTION_H */ diff --git a/firmware/fx3/ad9361/lib/ad9361_filter_taps.h b/firmware/fx3/ad9361/lib/ad9361_filter_taps.h deleted file mode 100644 index afbe27630..000000000 --- a/firmware/fx3/ad9361/lib/ad9361_filter_taps.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -#ifndef INCLUDED_AD9361_FILTER_TAPS_HPP -#define INCLUDED_AD9361_FILTER_TAPS_HPP - -/* A default 128-tap filter that can be used for generic circumstances. */ -static uint16_t default_128tap_coeffs[] = { -    0x0001,0xfff1,0xffcf,0xffc0,0xffe8,0x0020,0x001a,0xffe3, -    0xffe1,0x001f,0x0028,0xffdf,0xffcc,0x0024,0x0043,0xffdb, -    0xffac,0x0026,0x0068,0xffdb,0xff80,0x0022,0x009a,0xffe2, -    0xff47,0x0017,0x00db,0xfff3,0xfeff,0xffff,0x012b,0x0013, -    0xfea5,0xffd7,0x0190,0x0046,0xfe35,0xff97,0x020e,0x0095, -    0xfda7,0xff36,0x02ae,0x010d,0xfcf0,0xfea1,0x0383,0x01c6, -    0xfbf3,0xfdb6,0x04b7,0x02f8,0xfa6d,0xfc1a,0x06be,0x0541, -    0xf787,0xf898,0x0b60,0x0b6d,0xee88,0xea40,0x2786,0x7209 -}; - - -/* The below pair of filters is optimized for a 10MHz LTE application. */ -/* -static uint16_t lte10mhz_rx_coeffs[] = { -    0xffe2,0x0042,0x0024,0x0095,0x0056,0x004d,0xffcf,0xffb7, -    0xffb1,0x0019,0x0059,0x006a,0x0004,0xff9d,0xff72,0xffd4, -    0x0063,0x00b7,0x0062,0xffac,0xff21,0xff59,0x0032,0x0101, -    0x00f8,0x0008,0xfeea,0xfeac,0xffa3,0x0117,0x01b5,0x00d0, -    0xff05,0xfdea,0xfe9e,0x00ba,0x026f,0x0215,0xffb5,0xfd4a, -    0xfd18,0xffa0,0x02de,0x03dc,0x0155,0xfd2a,0xfb0d,0xfd54, -    0x0287,0x062f,0x048a,0xfe37,0xf862,0xf8c1,0x004d,0x0963, -    0x0b88,0x02a4,0xf3e7,0xebdd,0xf5f8,0x1366,0x3830,0x518b -}; - -static uint16_t lte10mhz_tx_coeffs[] = { -    0xfffb,0x0000,0x0004,0x0017,0x0024,0x0028,0x0013,0xfff3, -    0xffdc,0xffe5,0x000b,0x0030,0x002e,0xfffe,0xffc4,0xffb8, -    0xfff0,0x0045,0x0068,0x002b,0xffb6,0xff72,0xffad,0x0047, -    0x00b8,0x0088,0xffc8,0xff1c,0xff33,0x001a,0x0110,0x0124, -    0x0019,0xfec8,0xfe74,0xff9a,0x0156,0x0208,0x00d3,0xfe9b, -    0xfd68,0xfe96,0x015d,0x033f,0x0236,0xfecd,0xfc00,0xfcb5, -    0x00d7,0x04e5,0x04cc,0xffd5,0xf9fe,0xf8fb,0xfef2,0x078c, -    0x0aae,0x036d,0xf5c0,0xed89,0xf685,0x12af,0x36a4,0x4faa -}; -*/ - - -#endif // INCLUDED_AD9361_FILTER_TAPS_HPP diff --git a/firmware/fx3/ad9361/lib/ad9361_gain_tables.h b/firmware/fx3/ad9361/lib/ad9361_gain_tables.h deleted file mode 100644 index 58dcbeb65..000000000 --- a/firmware/fx3/ad9361/lib/ad9361_gain_tables.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -#ifndef INCLUDED_AD9361_GAIN_TABLES_HPP -#define INCLUDED_AD9361_GAIN_TABLES_HPP - -uint8_t gain_table_sub_1300mhz[77][5] = { {0,0x00,0x00,0x20,1}, -    {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x01,0x00,0}, -    {4,0x00,0x02,0x00,0}, {5,0x00,0x03,0x00,0}, {6,0x00,0x04,0x00,0}, -    {7,0x00,0x05,0x00,0}, {8,0x01,0x03,0x20,1}, {9,0x01,0x04,0x00,0}, -    {10,0x01,0x05,0x00,0}, {11,0x01,0x06,0x00,0}, {12,0x01,0x07,0x00,0}, -    {13,0x01,0x08,0x00,0}, {14,0x01,0x09,0x00,0}, {15,0x01,0x0A,0x00,0}, -    {16,0x01,0x0B,0x00,0}, {17,0x01,0x0C,0x00,0}, {18,0x01,0x0D,0x00,0}, -    {19,0x01,0x0E,0x00,0}, {20,0x02,0x09,0x20,1}, {21,0x02,0x0A,0x00,0}, -    {22,0x02,0x0B,0x00,0}, {23,0x02,0x0C,0x00,0}, {24,0x02,0x0D,0x00,0}, -    {25,0x02,0x0E,0x00,0}, {26,0x02,0x0F,0x00,0}, {27,0x02,0x10,0x00,0}, -    {28,0x02,0x2B,0x20,1}, {29,0x02,0x2C,0x00,0}, {30,0x04,0x27,0x20,1}, -    {31,0x04,0x28,0x00,0}, {32,0x04,0x29,0x00,0}, {33,0x04,0x2A,0x00,0}, -    {34,0x04,0x2B,0x00,1}, {35,0x24,0x21,0x20,0}, {36,0x24,0x22,0x00,1}, -    {37,0x44,0x20,0x20,0}, {38,0x44,0x21,0x00,0}, {39,0x44,0x22,0x00,0}, -    {40,0x44,0x23,0x00,0}, {41,0x44,0x24,0x00,0}, {42,0x44,0x25,0x00,0}, -    {43,0x44,0x26,0x00,0}, {44,0x44,0x27,0x00,0}, {45,0x44,0x28,0x00,0}, -    {46,0x44,0x29,0x00,0}, {47,0x44,0x2A,0x00,0}, {48,0x44,0x2B,0x00,0}, -    {49,0x44,0x2C,0x00,0}, {50,0x44,0x2D,0x00,0}, {51,0x44,0x2E,0x00,0}, -    {52,0x44,0x2F,0x00,0}, {53,0x44,0x30,0x00,0}, {54,0x44,0x31,0x00,0}, -    {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0}, -    {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0}, -    {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0}, -    {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1}, -    {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1}, -    {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1}, -    {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1}, -    {76,0x6F,0x38,0x20,1}}; - - -uint8_t gain_table_1300mhz_to_4000mhz[77][5] = {   {0,0x00,0x00,0x20,1}, -    {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x01,0x00,0}, -    {4,0x00,0x02,0x00,0}, {5,0x00,0x03,0x00,0}, {6,0x00,0x04,0x00,0}, -    {7,0x00,0x05,0x00,0}, {8,0x01,0x03,0x20,1}, {9,0x01,0x04,0x00,0}, -    {10,0x01,0x05,0x00,0}, {11,0x01,0x06,0x00,0}, {12,0x01,0x07,0x00,0}, -    {13,0x01,0x08,0x00,0}, {14,0x01,0x09,0x00,0}, {15,0x01,0x0A,0x00,0}, -    {16,0x01,0x0B,0x00,0}, {17,0x01,0x0C,0x00,0}, {18,0x01,0x0D,0x00,0}, -    {19,0x01,0x0E,0x00,0}, {20,0x02,0x09,0x20,1}, {21,0x02,0x0A,0x00,0}, -    {22,0x02,0x0B,0x00,0}, {23,0x02,0x0C,0x00,0}, {24,0x02,0x0D,0x00,0}, -    {25,0x02,0x0E,0x00,0}, {26,0x02,0x0F,0x00,0}, {27,0x02,0x10,0x00,0}, -    {28,0x02,0x2B,0x20,1}, {29,0x02,0x2C,0x00,0}, {30,0x04,0x28,0x20,1}, -    {31,0x04,0x29,0x00,0}, {32,0x04,0x2A,0x00,0}, {33,0x04,0x2B,0x00,0}, -    {34,0x24,0x20,0x20,0}, {35,0x24,0x21,0x00,1}, {36,0x44,0x20,0x20,0}, -    {37,0x44,0x21,0x00,1}, {38,0x44,0x22,0x00,0}, {39,0x44,0x23,0x00,0}, -    {40,0x44,0x24,0x00,0}, {41,0x44,0x25,0x00,0}, {42,0x44,0x26,0x00,0}, -    {43,0x44,0x27,0x00,0}, {44,0x44,0x28,0x00,0}, {45,0x44,0x29,0x00,0}, -    {46,0x44,0x2A,0x00,0}, {47,0x44,0x2B,0x00,0}, {48,0x44,0x2C,0x00,0}, -    {49,0x44,0x2D,0x00,0}, {50,0x44,0x2E,0x00,0}, {51,0x44,0x2F,0x00,0}, -    {52,0x44,0x30,0x00,0}, {53,0x44,0x31,0x00,0}, {54,0x44,0x32,0x00,0}, -    {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0}, -    {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0}, -    {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0}, -    {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1}, -    {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1}, -    {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1}, -    {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1}, -    {76,0x6F,0x38,0x20,1}}; - - -uint8_t gain_table_4000mhz_to_6000mhz[77][5] = { {0,0x00,0x00,0x20,1}, -    {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x00,0x00,0}, -    {4,0x00,0x00,0x00,0}, {5,0x00,0x01,0x00,0}, {6,0x00,0x02,0x00,0}, -    {7,0x00,0x03,0x00,0}, {8,0x01,0x01,0x20,1}, {9,0x01,0x02,0x00,0}, -    {10,0x01,0x03,0x00,0}, {11,0x01,0x04,0x20,1}, {12,0x01,0x05,0x00,0}, -    {13,0x01,0x06,0x00,0}, {14,0x01,0x07,0x00,0}, {15,0x01,0x08,0x00,0}, -    {16,0x01,0x09,0x00,0}, {17,0x01,0x0A,0x00,0}, {18,0x01,0x0B,0x00,0}, -    {19,0x01,0x0C,0x00,0}, {20,0x02,0x08,0x20,1}, {21,0x02,0x09,0x00,0}, -    {22,0x02,0x0A,0x00,0}, {23,0x02,0x0B,0x20,1}, {24,0x02,0x0C,0x00,0}, -    {25,0x02,0x0D,0x00,0}, {26,0x02,0x0E,0x00,0}, {27,0x02,0x0F,0x00,0}, -    {28,0x02,0x2A,0x20,1}, {29,0x02,0x2B,0x00,0}, {30,0x04,0x27,0x20,1}, -    {31,0x04,0x28,0x00,0}, {32,0x04,0x29,0x00,0}, {33,0x04,0x2A,0x00,0}, -    {34,0x04,0x2B,0x00,0}, {35,0x04,0x2C,0x00,0}, {36,0x04,0x2D,0x00,0}, -    {37,0x24,0x20,0x20,1}, {38,0x24,0x21,0x00,0}, {39,0x24,0x22,0x00,0}, -    {40,0x44,0x20,0x20,1}, {41,0x44,0x21,0x00,0}, {42,0x44,0x22,0x00,0}, -    {43,0x44,0x23,0x00,0}, {44,0x44,0x24,0x00,0}, {45,0x44,0x25,0x00,0}, -    {46,0x44,0x26,0x00,0}, {47,0x44,0x27,0x00,0}, {48,0x44,0x28,0x00,0}, -    {49,0x44,0x29,0x00,0}, {50,0x44,0x2A,0x00,0}, {51,0x44,0x2B,0x00,0}, -    {52,0x44,0x2C,0x00,0}, {53,0x44,0x2D,0x00,0}, {54,0x44,0x2E,0x00,0}, -    {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0}, -    {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0}, -    {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0}, -    {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1}, -    {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1}, -    {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1}, -    {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1}, -    {76,0x6F,0x38,0x20,1}}; - - -#endif /* INCLUDED_AD9361_GAIN_TABLES_HPP */ diff --git a/firmware/fx3/ad9361/lib/ad9361_impl.c b/firmware/fx3/ad9361/lib/ad9361_impl.c deleted file mode 100644 index 61512d2c8..000000000 --- a/firmware/fx3/ad9361/lib/ad9361_impl.c +++ /dev/null @@ -1,1918 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -/* This file implements b200 vendor requests handler - * It handles ad9361 setup and configuration - */ - -#include <stdarg.h> -#include <stdio.h> -#include <math.h> - -#include <ad9361_transaction.h> -#include "ad9361_filter_taps.h" -#include "ad9361_gain_tables.h" -#include "ad9361_synth_lut.h" -#include "ad9361_dispatch.h" - -//////////////////////////////////////////////////////////// - -static void fake_msg(const char* str, ...) -{ -} - -static msgfn _msgfn = fake_msg; - -//extern void msg(const char* str, ...);    External object must provide this symbol -#define msg (_msgfn) - -void ad9361_set_msgfn(msgfn pfn) -{ -    _msgfn = pfn; -} - -//////////////////////////////////////////////////////////// -#define AD9361_MAX_GAIN 89.75 - -#define DOUBLE_PI 3.14159265359 -#define DOUBLE_LN_2 0.693147181 - -#define RX_TYPE 0 -#define TX_TYPE 1 - -#ifndef AD9361_CLOCKING_MODE -#error define a AD9361_CLOCKING_MODE -#endif - -#ifndef AD9361_RX_BAND_EDGE0 -#error define a AD9361_RX_BAND_EDGE0 -#endif - -#ifndef AD9361_RX_BAND_EDGE1 -#error define a AD9361_RX_BAND_EDGE1 -#endif - -#ifndef AD9361_TX_BAND_EDGE -#error define a AD9361_TX_BAND_EDGE -#endif - -//////////////////////////////////////////////////////////// -// the following macros evaluate to a compile time constant -// macros By Tom Torfs - donated to the public domain - -/* turn a numeric literal into a hex constant -(avoids problems with leading zeroes) -8-bit constants max value 0x11111111, always fits in unsigned long -*/ -#define HEX__(n) 0x##n##LU - -/* 8-bit conversion function */ -#define B8__(x) ((x&0x0000000FLU)?1:0) \ -+((x&0x000000F0LU)?2:0) \ -+((x&0x00000F00LU)?4:0) \ -+((x&0x0000F000LU)?8:0) \ -+((x&0x000F0000LU)?16:0) \ -+((x&0x00F00000LU)?32:0) \ -+((x&0x0F000000LU)?64:0) \ -+((x&0xF0000000LU)?128:0) - -/* *** user macros *** */ - -/* for upto 8-bit binary constants */ -#define B8(d) ((unsigned char)B8__(HEX__(d))) - -//////////////////////////////////////////////////////////// -// shadow registers -static uint8_t reg_vcodivs; -static uint8_t reg_inputsel; -static uint8_t reg_rxfilt; -static uint8_t reg_txfilt; -static uint8_t reg_bbpll; -static uint8_t reg_bbftune_config; -static uint8_t reg_bbftune_mode; - -//////////////////////////////////////////////////////////// -// other private data fields for VRQ handler -static double _rx_freq, _tx_freq, _req_rx_freq, _req_tx_freq; -static double _baseband_bw, _bbpll_freq, _adcclock_freq; -static double _req_clock_rate, _req_coreclk; -static uint16_t _rx_bbf_tunediv; -static uint8_t _curr_gain_table; -static uint32_t _rx1_gain, _rx2_gain, _tx1_gain, _tx2_gain; -static int _tfir_factor; - -double set_gain(int which, int n, const double value); -void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2); -/*********************************************************************** - * Placeholders, unused, or test functions - **********************************************************************/ -static char *tmp_req_buffer; - -void post_err_msg(const char* error) -{ -    msg("[AD9361 error] %s", error); -     -    if (!tmp_req_buffer) -        return; -     -    ad9361_transaction_t *request = (ad9361_transaction_t *)tmp_req_buffer; -    strncpy(request->error_msg, error, (AD9361_TRANSACTION_MAX_ERROR_MSG + 1)); // '+ 1' as length excludes terminating NUL -    request->error_msg[AD9361_TRANSACTION_MAX_ERROR_MSG] = '\0';  // If string was too long, NUL will not be copied, so force one just in case -} - -void write_ad9361_reg(uint32_t reg, uint8_t val) -{ -    ad9361_transact_spi((reg << 8) | val | (1 << 23)); -} - -uint8_t read_ad9361_reg(uint32_t reg) -{ -    return ad9361_transact_spi((reg << 8)) & 0xff; -} - -//shortcuts for double packer/unpacker function -#define double_pack ad9361_double_pack -#define double_unpack ad9361_double_unpack - -/* Make Catalina output its test tone. */ -void output_test_tone(void) { -    /* Output a 480 kHz tone at 800 MHz */ -    write_ad9361_reg(0x3F4, 0x0B); -    write_ad9361_reg(0x3FC, 0xFF); -    write_ad9361_reg(0x3FD, 0xFF); -    write_ad9361_reg(0x3FE, 0x3F); -} - -/* Turn on/off Catalina's TX port --> RX port loopback. */ -void data_port_loopback(const int on) { -    msg("[data_port_loopback] Enabled: %d", on); -    write_ad9361_reg(0x3F5, (on ? 0x01 : 0x00)); -} - -/* This is a simple comparison for very large double-precision floating - * point numbers. It is used to prevent re-tunes for frequencies that are - * the same but not 'exactly' because of data precision issues. */ -// TODO: see if we can avoid the need for this function -int freq_is_nearly_equal(double a, double b) { -    return AD9361_MAX(a,b) - AD9361_MIN(a,b) < 1; -} - -/*********************************************************************** - * Filter functions - **********************************************************************/ - -/* This function takes in the calculated maximum number of FIR taps, and - * returns a number of taps that makes Catalina happy. */ -int get_num_taps(int max_num_taps) { - -    int num_taps = 0; -    int num_taps_list[] = {16, 32, 48, 64, 80, 96, 112, 128}; -    int i; -    for(i = 1; i < 8; i++) { -        if(max_num_taps >= num_taps_list[i]) { -            continue; -        } else { -            num_taps = num_taps_list[i - 1]; -            break; -        } -    } if(num_taps == 0) { num_taps = 128; } - -    return num_taps; -} - -/* Program either the RX or TX FIR filter. - * - * The process is the same for both filters, but the function must be told - * how many taps are in the filter, and given a vector of the taps - * themselves. Note that the filters are symmetric, so value of 'num_taps' - * should actually be twice the length of the tap vector. */ -void program_fir_filter(int which, int num_taps, \ -        uint16_t *coeffs) { - -    uint16_t base; -    if(which == RX_TYPE) { -        base = 0x0f0; -        write_ad9361_reg(base+6, 0x02); //filter gain -    } else { -        base = 0x060; -    } - -    /* Write the filter configuration. */ -    uint8_t reg_numtaps = (((num_taps / 16) - 1) & 0x07) << 5; - -    /* Turn on the filter clock. */ -    write_ad9361_reg(base+5, reg_numtaps | 0x1a); -    ad9361_msleep(1); - -    int num_unique_coeffs = (num_taps / 2); - -    /* The filters are symmetric, so iterate over the tap vector, -     * programming each index, and then iterate backwards, repeating the -     * process. */ -    int addr; -    for(addr=0; addr < num_unique_coeffs; addr++) { -        write_ad9361_reg(base+0, addr); -        write_ad9361_reg(base+1, (coeffs[addr]) & 0xff); -        write_ad9361_reg(base+2, (coeffs[addr] >> 8) & 0xff); -        write_ad9361_reg(base+5, 0xfe); -        write_ad9361_reg(base+4, 0x00); -        write_ad9361_reg(base+4, 0x00); -    } - -    for(addr=0; addr < num_unique_coeffs; addr++) { -        write_ad9361_reg(base+0, addr+num_unique_coeffs); -        write_ad9361_reg(base+1, (coeffs[num_unique_coeffs-1-addr]) & 0xff); -        write_ad9361_reg(base+2, (coeffs[num_unique_coeffs-1-addr] >> 8) & 0xff); -        write_ad9361_reg(base+5, 0xfe); -        write_ad9361_reg(base+4, 0x00); -        write_ad9361_reg(base+4, 0x00); -    } - -    /* Disable the filter clock. */ -    write_ad9361_reg(base+5, 0xf8); -} - -/* Program the RX FIR Filter. */ -void setup_rx_fir(int total_num_taps) { -    int num_taps = total_num_taps / 2; -    uint16_t coeffs[num_taps]; -    int i; -    for(i = 0; i < num_taps; i++) { -        coeffs[num_taps - 1 - i] = default_128tap_coeffs[63 - i]; -    } - -    program_fir_filter(RX_TYPE, total_num_taps, coeffs); -} - -/* Program the TX FIR Filter. */ -void setup_tx_fir(int total_num_taps) { -    int num_taps = total_num_taps / 2; -    uint16_t coeffs[num_taps]; -    int i; -    for(i = 0; i < num_taps; i++) { -        coeffs[num_taps - 1 - i] = default_128tap_coeffs[63 - i]; -    } - -    program_fir_filter(TX_TYPE, total_num_taps, coeffs); -} - -/*********************************************************************** - * Calibration functions - ***********************************************************************/ - -/* Calibrate and lock the BBPLL. - * - * This function should be called anytime the BBPLL is tuned. */ -void calibrate_lock_bbpll() { -    write_ad9361_reg(0x03F, 0x05); // Start the BBPLL calibration -    write_ad9361_reg(0x03F, 0x01); // Clear the 'start' bit - -    /* Increase BBPLL KV and phase margin. */ -    write_ad9361_reg(0x04c, 0x86); -    write_ad9361_reg(0x04d, 0x01); -    write_ad9361_reg(0x04d, 0x05); - -    /* Wait for BBPLL lock. */ -    int count = 0; -    while(!(read_ad9361_reg(0x05e) & 0x80)) { -        if(count > 1000) { -            post_err_msg("BBPLL not locked"); -            break; -        } - -        count++; -        ad9361_msleep(2); -    } -} - -/* Calibrate the synthesizer charge pumps. - * - * Technically, this calibration only needs to be done once, at device - * initialization. */ -void calibrate_synth_charge_pumps() { -    /* If this function ever gets called, and the ENSM isn't already in the -     * ALERT state, then something has gone horribly wrong. */ -    if((read_ad9361_reg(0x017) & 0x0F) != 5) { -        post_err_msg("Catalina not in ALERT during cal"); -    } - -    /* Calibrate the RX synthesizer charge pump. */ -    int count = 0; -    write_ad9361_reg(0x23d, 0x04); -    while(!(read_ad9361_reg(0x244) & 0x80)) { -        if(count > 5) { -            post_err_msg("RX charge pump cal failure"); -            break; -        } - -        count++; -        ad9361_msleep(1); -    } -    write_ad9361_reg(0x23d, 0x00); - -    /* Calibrate the TX synthesizer charge pump. */ -    count = 0; -    write_ad9361_reg(0x27d, 0x04); -    while(!(read_ad9361_reg(0x284) & 0x80)) { -        if(count > 5) { -            post_err_msg("TX charge pump cal failure"); -            break; -        } - -        count++; -        ad9361_msleep(1); -    } -    write_ad9361_reg(0x27d, 0x00); -} - -/* Calibrate the analog BB RX filter. - * - * Note that the filter calibration depends heavily on the baseband - * bandwidth, so this must be re-done after any change to the RX sample - * rate. */ -double calibrate_baseband_rx_analog_filter() { -    /* For filter tuning, baseband BW is half the complex BW, and must be -     * between 28e6 and 0.2e6. */ -    double bbbw = _baseband_bw / 2.0; -    if(bbbw > 28e6) { -        bbbw = 28e6; -    } else if (bbbw < 0.20e6) { -        bbbw = 0.20e6; -    } - -    double rxtune_clk = ((1.4 * bbbw * 2 * -            DOUBLE_PI) / DOUBLE_LN_2); - -    _rx_bbf_tunediv = AD9361_MIN(511, AD9361_CEIL_INT(_bbpll_freq / rxtune_clk)); - -    reg_bbftune_config = (reg_bbftune_config & 0xFE) \ -                         | ((_rx_bbf_tunediv >> 8) & 0x0001); - -    double bbbw_mhz = bbbw / 1e6; - -    double temp = ((bbbw_mhz - AD9361_FLOOR_INT(bbbw_mhz)) * 1000) / 7.8125; -    uint8_t bbbw_khz = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT(temp + 0.5))); - -    /* Set corner frequencies and dividers. */ -    write_ad9361_reg(0x1fb, (uint8_t)(bbbw_mhz)); -    write_ad9361_reg(0x1fc, bbbw_khz); -    write_ad9361_reg(0x1f8, (_rx_bbf_tunediv & 0x00FF)); -    write_ad9361_reg(0x1f9, reg_bbftune_config); - -    /* RX Mix Voltage settings - only change with apps engineer help. */ -    write_ad9361_reg(0x1d5, 0x3f); -    write_ad9361_reg(0x1c0, 0x03); - -    /* Enable RX1 & RX2 filter tuners. */ -    write_ad9361_reg(0x1e2, 0x02); -    write_ad9361_reg(0x1e3, 0x02); - -    /* Run the calibration! */ -    int count = 0; -    write_ad9361_reg(0x016, 0x80); -    while(read_ad9361_reg(0x016) & 0x80) { -        if(count > 100) { -            post_err_msg("RX baseband filter cal FAILURE"); -            break; -        } - -        count++; -        ad9361_msleep(1); -    } - -    /* Disable RX1 & RX2 filter tuners. */ -    write_ad9361_reg(0x1e2, 0x03); -    write_ad9361_reg(0x1e3, 0x03); - -    return bbbw; -} - -/* Calibrate the analog BB TX filter. - * - * Note that the filter calibration depends heavily on the baseband - * bandwidth, so this must be re-done after any change to the TX sample - * rate. */ -double calibrate_baseband_tx_analog_filter() { -    /* For filter tuning, baseband BW is half the complex BW, and must be -     * between 28e6 and 0.2e6. */ -    double bbbw = _baseband_bw / 2.0; -    if(bbbw > 20e6) { -        bbbw = 20e6; -    } else if (bbbw < 0.625e6) { -        bbbw = 0.625e6; -    } - -    double txtune_clk = ((1.6 * bbbw * 2 * -            DOUBLE_PI) / DOUBLE_LN_2); - -    uint16_t txbbfdiv = AD9361_MIN(511, (AD9361_CEIL_INT(_bbpll_freq / txtune_clk))); - -    reg_bbftune_mode = (reg_bbftune_mode & 0xFE) \ -                         | ((txbbfdiv >> 8) & 0x0001); - -    /* Program the divider values. */ -    write_ad9361_reg(0x0d6, (txbbfdiv & 0x00FF)); -    write_ad9361_reg(0x0d7, reg_bbftune_mode); - -    /* Enable the filter tuner. */ -    write_ad9361_reg(0x0ca, 0x22); - -    /* Calibrate! */ -    int count = 0; -    write_ad9361_reg(0x016, 0x40); -    while(read_ad9361_reg(0x016) & 0x40) { -        if(count > 100) { -            post_err_msg("TX baseband filter cal FAILURE"); -            break; -        } - -        count++; -        ad9361_msleep(1); -    } - -    /* Disable the filter tuner. */ -    write_ad9361_reg(0x0ca, 0x26); - -    return bbbw; -} - -/* Calibrate the secondary TX filter. - * - * This filter also depends on the TX sample rate, so if a rate change is - * made, the previous calibration will no longer be valid. */ -void calibrate_secondary_tx_filter() { -    /* For filter tuning, baseband BW is half the complex BW, and must be -     * between 20e6 and 0.53e6. */ -    double bbbw = _baseband_bw / 2.0; -    if(bbbw > 20e6) { -        bbbw = 20e6; -    } else if (bbbw < 0.53e6) { -        bbbw = 0.53e6; -    } - -    double bbbw_mhz = bbbw / 1e6; - -    /* Start with a resistor value of 100 Ohms. */ -    int res = 100; - -    /* Calculate target corner frequency. */ -    double corner_freq = 5 * bbbw_mhz * 2 * DOUBLE_PI; - -    /* Iterate through RC values to determine correct combination. */ -    int cap = 0; -    int i; -    for(i = 0; i <= 3; i++) { -        cap = (AD9361_FLOOR_INT(0.5 + (( 1 / ((corner_freq * res) * 1e6)) * 1e12))) - 12; - -        if(cap <= 63) { -            break; -        } - -        res = res * 2; -    } -    if(cap > 63) { -        cap = 63; -    } - -    uint8_t reg0d0, reg0d1, reg0d2; - -    /* Translate baseband bandwidths to register settings. */ -    if((bbbw_mhz * 2) <= 9) { -        reg0d0 = 0x59; -    } else if(((bbbw_mhz * 2) > 9) && ((bbbw_mhz * 2) <= 24)) { -        reg0d0 = 0x56; -    } else if((bbbw_mhz * 2) > 24) { -        reg0d0 = 0x57; -    } else { -        post_err_msg("Cal2ndTxFil: INVALID_CODE_PATH bad bbbw_mhz"); -        reg0d0 = 0x00; -    } - -    /* Translate resistor values to register settings. */ -    if(res == 100) { -        reg0d1 = 0x0c; -    } else if(res == 200) { -        reg0d1 = 0x04; -    } else if(res == 400) { -        reg0d1 = 0x03; -    } else if(res == 800) { -        reg0d1 = 0x01; -    } else { -        reg0d1 = 0x0c; -    } - -    reg0d2 = cap; - -    /* Program the above-calculated values. Sweet. */ -    write_ad9361_reg(0x0d2, reg0d2); -    write_ad9361_reg(0x0d1, reg0d1); -    write_ad9361_reg(0x0d0, reg0d0); -} - -/* Calibrate the RX TIAs. - * - * Note that the values in the TIA register, after calibration, vary with - * the RX gain settings. */ -void calibrate_rx_TIAs() { - -    uint8_t reg1eb = read_ad9361_reg(0x1eb) & 0x3F; -    uint8_t reg1ec = read_ad9361_reg(0x1ec) & 0x7F; -    uint8_t reg1e6 = read_ad9361_reg(0x1e6) & 0x07; -    uint8_t reg1db = 0x00; -    uint8_t reg1dc = 0x00; -    uint8_t reg1dd = 0x00; -    uint8_t reg1de = 0x00; -    uint8_t reg1df = 0x00; - -    /* For calibration, baseband BW is half the complex BW, and must be -     * between 28e6 and 0.2e6. */ -    double bbbw = _baseband_bw / 2.0; -    if(bbbw > 20e6) { -        bbbw = 20e6; -    } else if (bbbw < 0.20e6) { -        bbbw = 0.20e6; -    } -    double ceil_bbbw_mhz = AD9361_CEIL_INT(bbbw / 1e6); - -    /* Do some crazy resistor and capacitor math. */ -    int Cbbf = (reg1eb * 160) + (reg1ec * 10) + 140; -    int R2346 = 18300 * (reg1e6 & 0x07); -    double CTIA_fF = (Cbbf * R2346 * 0.56) / 3500; - -    /* Translate baseband BW to register settings. */ -    if(ceil_bbbw_mhz <= 3) { -        reg1db = 0xe0; -    } else if((ceil_bbbw_mhz > 3) && (ceil_bbbw_mhz <= 10)) { -        reg1db = 0x60; -    } else if(ceil_bbbw_mhz > 10) { -        reg1db = 0x20; -    } else { -        post_err_msg("CalRxTias: INVALID_CODE_PATH bad bbbw_mhz"); -    } - -    if(CTIA_fF > 2920) { -        reg1dc = 0x40; -        reg1de = 0x40; - -        uint8_t temp = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT(0.5 + ((CTIA_fF - 400.0) / 320.0)))); -        reg1dd = temp; -        reg1df = temp; -    } else { -        uint8_t temp = (uint8_t) AD9361_FLOOR_INT(0.5 + ((CTIA_fF - 400.0) / 40.0)) + 0x40; -        reg1dc = temp; -        reg1de = temp; -        reg1dd = 0; -        reg1df = 0; -    } - -    /* w00t. Settings calculated. Program them and roll out. */ -    write_ad9361_reg(0x1db, reg1db); -    write_ad9361_reg(0x1dd, reg1dd); -    write_ad9361_reg(0x1df, reg1df); -    write_ad9361_reg(0x1dc, reg1dc); -    write_ad9361_reg(0x1de, reg1de); -} - -/* Setup the Catalina ADC. - * - * There are 40 registers that control the ADC's operation, most of the - * values of which must be derived mathematically, dependent on the current - * setting of the BBPLL. Note that the order of calculation is critical, as - * some of the 40 registers depend on the values in others. */ -void setup_adc() { -    double bbbw_mhz = (((_bbpll_freq / 1e6) / _rx_bbf_tunediv) * DOUBLE_LN_2) \ -                  / (1.4 * 2 * DOUBLE_PI); - -    /* For calibration, baseband BW is half the complex BW, and must be -     * between 28e6 and 0.2e6. */ -    if(bbbw_mhz > 28) { -        bbbw_mhz = 28; -    } else if (bbbw_mhz < 0.20) { -        bbbw_mhz = 0.20; -    } - -    uint8_t rxbbf_c3_msb = read_ad9361_reg(0x1eb) & 0x3F; -    uint8_t rxbbf_c3_lsb = read_ad9361_reg(0x1ec) & 0x7F; -    uint8_t rxbbf_r2346 = read_ad9361_reg(0x1e6) & 0x07; - -    double fsadc = _adcclock_freq / 1e6; - -    /* Sort out the RC time constant for our baseband bandwidth... */ -    double rc_timeconst = 0.0; -    if(bbbw_mhz < 18) { -        rc_timeconst = (1 / ((1.4 * 2 * DOUBLE_PI) \ -                            * (18300 * rxbbf_r2346) -                            * ((160e-15 * rxbbf_c3_msb) -                                + (10e-15 * rxbbf_c3_lsb) + 140e-15) -                            * (bbbw_mhz * 1e6))); -    } else { -        rc_timeconst = (1 / ((1.4 * 2 * DOUBLE_PI) \ -                            * (18300 * rxbbf_r2346) -                            * ((160e-15 * rxbbf_c3_msb) -                                + (10e-15 * rxbbf_c3_lsb) + 140e-15) -                            * (bbbw_mhz * 1e6) * (1 + (0.01 * (bbbw_mhz - 18))))); -    } - -    double scale_res = ad9361_sqrt(1 / rc_timeconst); -    double scale_cap = ad9361_sqrt(1 / rc_timeconst); - -    double scale_snr = (_adcclock_freq < 80e6) ? 1.0 : 1.584893192; -    double maxsnr = 640 / 160; - -    /* Calculate the values for all 40 settings registers. -     * -     * DO NOT TOUCH THIS UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING. kthx.*/ -    uint8_t data[40]; -    data[0] = 0;    data[1] = 0; data[2] = 0; data[3] = 0x24; -    data[4] = 0x24; data[5] = 0; data[6] = 0; -    data[7] = (uint8_t) AD9361_MIN(124, (AD9361_FLOOR_INT(-0.5 -                    + (80.0 * scale_snr * scale_res -                    * AD9361_MIN(1.0, ad9361_sqrt(maxsnr * fsadc / 640.0)))))); -    double data007 = data[7]; -    data[8] = (uint8_t) AD9361_MIN(255, (AD9361_FLOOR_INT(0.5 -                    + ((20.0 * (640.0 / fsadc) * ((data007 / 80.0)) -                    / (scale_res * scale_cap)))))); -    data[10] = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT(-0.5 + (77.0 * scale_res -                    * AD9361_MIN(1.0, ad9361_sqrt(maxsnr * fsadc / 640.0)))))); -    double data010 = data[10]; -    data[9] = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT(0.8 * data010))); -    data[11] = (uint8_t) AD9361_MIN(255, (AD9361_FLOOR_INT(0.5 -                    + (20.0 * (640.0 / fsadc) * ((data010 / 77.0) -                    / (scale_res * scale_cap)))))); -    data[12] = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT(-0.5 -                    + (80.0 * scale_res * AD9361_MIN(1.0, -                    ad9361_sqrt(maxsnr * fsadc / 640.0)))))); -    double data012 = data[12]; -    data[13] = (uint8_t) AD9361_MIN(255, (AD9361_FLOOR_INT(-1.5 -                    + (20.0 * (640.0 / fsadc) * ((data012 / 80.0) -                    / (scale_res * scale_cap)))))); -    data[14] = 21 * (uint8_t)(AD9361_FLOOR_INT(0.1 * 640.0 / fsadc)); -    data[15] = (uint8_t) AD9361_MIN(127, (1.025 * data007)); -    double data015 = data[15]; -    data[16] = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT((data015 -                    * (0.98 + (0.02 * AD9361_MAX(1.0, -                    (640.0 / fsadc) / maxsnr))))))); -    data[17] = data[15]; -    data[18] = (uint8_t) AD9361_MIN(127, (0.975 * (data010))); -    double data018 = data[18]; -    data[19] = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT((data018 -                    * (0.98 + (0.02 * AD9361_MAX(1.0, -                    (640.0 / fsadc) / maxsnr))))))); -    data[20] = data[18]; -    data[21] = (uint8_t) AD9361_MIN(127, (0.975 * data012)); -    double data021 = data[21]; -    data[22] = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT((data021 -                    * (0.98 + (0.02 * AD9361_MAX(1.0, -                    (640.0 / fsadc) / maxsnr))))))); -    data[23] = data[21]; -    data[24] = 0x2e; -    data[25] = (uint8_t)(AD9361_FLOOR_INT(128.0 + AD9361_MIN(63.0, -                    63.0 * (fsadc / 640.0)))); -    data[26] = (uint8_t)(AD9361_FLOOR_INT(AD9361_MIN(63.0, 63.0 * (fsadc / 640.0) -                    * (0.92 + (0.08 * (640.0 / fsadc)))))); -    data[27] = (uint8_t)(AD9361_FLOOR_INT(AD9361_MIN(63.0, -                    32.0 * ad9361_sqrt(fsadc / 640.0)))); -    data[28] = (uint8_t)(AD9361_FLOOR_INT(128.0 + AD9361_MIN(63.0, -                    63.0 * (fsadc / 640.0)))); -    data[29] = (uint8_t)(AD9361_FLOOR_INT(AD9361_MIN(63.0, -                    63.0 * (fsadc / 640.0) -                    * (0.92 + (0.08 * (640.0 / fsadc)))))); -    data[30] = (uint8_t)(AD9361_FLOOR_INT(AD9361_MIN(63.0, -                    32.0 * ad9361_sqrt(fsadc / 640.0)))); -    data[31] = (uint8_t)(AD9361_FLOOR_INT(128.0 + AD9361_MIN(63.0, -                    63.0 * (fsadc / 640.0)))); -    data[32] = (uint8_t)(AD9361_FLOOR_INT(AD9361_MIN(63.0, -                    63.0 * (fsadc / 640.0) * (0.92 -                    + (0.08 * (640.0 / fsadc)))))); -    data[33] = (uint8_t)(AD9361_FLOOR_INT(AD9361_MIN(63.0, -                    63.0 * ad9361_sqrt(fsadc / 640.0)))); -    data[34] = (uint8_t) AD9361_MIN(127, (AD9361_FLOOR_INT(64.0 -                    * ad9361_sqrt(fsadc / 640.0)))); -    data[35] = 0x40; -    data[36] = 0x40; -    data[37] = 0x2c; -    data[38] = 0x00; -    data[39] = 0x00; - -    /* Program the registers! */ -    int i; -    for(i=0; i<40; i++) { -        write_ad9361_reg(0x200+i, data[i]); -    } - -} - -/* Calibrate the baseband DC offset. - * - * Note that this function is called from within the TX quadrature - * calibration function! */ -void calibrate_baseband_dc_offset() { -    write_ad9361_reg(0x193, 0x3f); // Calibration settings -    write_ad9361_reg(0x190, 0x0f); // Set tracking coefficient -    //write_ad9361_reg(0x190, /*0x0f*//*0xDF*/0x80*1 | 0x40*1 | (16+8/*+4*/)); // Set tracking coefficient: don't *4 counter, do decim /4, increased gain shift -    write_ad9361_reg(0x194, 0x01); // More calibration settings - -    /* Start that calibration, baby. */ -    int count = 0; -    write_ad9361_reg(0x016, 0x01); -    while(read_ad9361_reg(0x016) & 0x01) { -        if(count > 100) { -            post_err_msg("Baseband DC Offset Calibration Failure"); -            break; -        } - -        count++; -        ad9361_msleep(5); -    } -} - -/* Calibrate the RF DC offset. - * - * Note that this function is called from within the TX quadrature - * calibration function. */ -void calibrate_rf_dc_offset() { -    /* Some settings are frequency-dependent. */ -    if(_rx_freq < 4e9) { -        write_ad9361_reg(0x186, 0x32); // RF DC Offset count -        write_ad9361_reg(0x187, 0x24); -        write_ad9361_reg(0x188, 0x05); -    } else { -        write_ad9361_reg(0x186, 0x28); // RF DC Offset count -        write_ad9361_reg(0x187, 0x34); -        write_ad9361_reg(0x188, 0x06); -    } - -    write_ad9361_reg(0x185, 0x20); // RF DC Offset wait count -    write_ad9361_reg(0x18b, 0x83); -    write_ad9361_reg(0x189, 0x30); - -    /* Run the calibration! */ -    int count = 0; -    write_ad9361_reg(0x016, 0x02); -    while(read_ad9361_reg(0x016) & 0x02) { -        if(count > 100) { -            post_err_msg("RF DC Offset Calibration Failure"); -            break; -        } - -        count++; -        ad9361_msleep(50); -    } -} - -/* Start the RX quadrature calibration. - * - * Note that we are using Catalina's 'tracking' feature for RX quadrature - * calibration, so once it starts it continues to free-run during operation. - * It should be re-run for large frequency changes. */ -void calibrate_rx_quadrature(void) { -    /* Configure RX Quadrature calibration settings. */ -    write_ad9361_reg(0x168, 0x03); // Set tone level for cal -    write_ad9361_reg(0x16e, 0x25); // RX Gain index to use for cal -    write_ad9361_reg(0x16a, 0x75); // Set Kexp phase -    write_ad9361_reg(0x16b, 0x15); // Set Kexp amplitude -    write_ad9361_reg(0x169, 0xcf); // Continuous tracking mode -    write_ad9361_reg(0x18b, 0xad); -} - -/* TX quadtrature calibration routine. - * - * The TX quadrature needs to be done twice, once for each TX chain, with - * only one register change in between. Thus, this function enacts the - * calibrations, and it is called from calibrate_tx_quadrature. */ -void tx_quadrature_cal_routine(void) { - -    /* This is a weird process, but here is how it works: -     * 1) Read the calibrated NCO frequency bits out of 0A3. -     * 2) Write the two bits to the RX NCO freq part of 0A0. -     * 3) Re-read 0A3 to get bits [5:0] because maybe they changed? -     * 4) Update only the TX NCO freq bits in 0A3. -     * 5) Profit (I hope). */ -    uint8_t reg0a3 = read_ad9361_reg(0x0a3); -    uint8_t nco_freq = (reg0a3 & 0xC0); -    write_ad9361_reg(0x0a0, 0x15 | (nco_freq >> 1)); -    reg0a3 = read_ad9361_reg(0x0a3); -    write_ad9361_reg(0x0a3, (reg0a3 & 0x3F) | nco_freq); - -    /* It is possible to reach a configuration that won't operate correctly, -     * where the two test tones used for quadrature calibration are outside -     * of the RX BBF, and therefore don't make it to the ADC. We will check -     * for that scenario here. */ -    double max_cal_freq = (((_baseband_bw * _tfir_factor) * ((nco_freq >> 6) + 1)) / 32) * 2; -    double bbbw = _baseband_bw / 2.0; // bbbw represents the one-sided BW -    if(bbbw > 28e6) { -        bbbw = 28e6; -    } else if (bbbw < 0.20e6) { -        bbbw = 0.20e6; -    } -    if (max_cal_freq > bbbw ) -        post_err_msg("max_cal_freq > bbbw"); -  -    write_ad9361_reg(0x0a1, 0x7B); // Set tracking coefficient -    write_ad9361_reg(0x0a9, 0xff); // Cal count -    write_ad9361_reg(0x0a2, 0x7f); // Cal Kexp -    write_ad9361_reg(0x0a5, 0x01); // Cal magnitude threshold VVVV -    write_ad9361_reg(0x0a6, 0x01); - -    /* The gain table index used for calibration must be adjusted for the -     * mid-table to get a TIA index = 1 and LPF index = 0. */ -    if((_rx_freq >= 1300e6) && (_rx_freq < 4000e6)) { -        write_ad9361_reg(0x0aa, 0x22); // Cal gain table index -    } else { -        write_ad9361_reg(0x0aa, 0x25); // Cal gain table index -    } - -    write_ad9361_reg(0x0a4, 0xf0); // Cal setting conut -    write_ad9361_reg(0x0ae, 0x00); // Cal LPF gain index (split mode) - -    /* First, calibrate the baseband DC offset. */ -    calibrate_baseband_dc_offset(); - -    /* Second, calibrate the RF DC offset. */ -    calibrate_rf_dc_offset(); - -    /* Now, calibrate the TX quadrature! */ -    int count = 0; -    write_ad9361_reg(0x016, 0x10); -    while(read_ad9361_reg(0x016) & 0x10) { -        if(count > 100) { -            post_err_msg("TX Quadrature Calibration Failure"); -            break; -        } - -        count++; -        ad9361_msleep(10); -    } -} - -/* Run the TX quadrature calibration. - * - * Note that from within this function we are also triggering the baseband - * and RF DC calibrations. */ -void calibrate_tx_quadrature(void) { -    /* Make sure we are, in fact, in the ALERT state. If not, something is -     * terribly wrong in the driver execution flow. */ -    if((read_ad9361_reg(0x017) & 0x0F) != 5) { -        post_err_msg("TX Quad Cal started, but not in ALERT"); -    } - -    /* Turn off free-running and continuous calibrations. Note that this -     * will get turned back on at the end of the RX calibration routine. */ -    write_ad9361_reg(0x169, 0xc0); - -    /* This calibration must be done in a certain order, and for both TX_A -     * and TX_B, separately. Store the original setting so that we can -     * restore it later. */ -    uint8_t orig_reg_inputsel = reg_inputsel; - -    /*********************************************************************** -     * TX1/2-A Calibration -     **********************************************************************/ -    reg_inputsel = reg_inputsel & 0xBF; -    write_ad9361_reg(0x004, reg_inputsel); - -    tx_quadrature_cal_routine(); - -    /*********************************************************************** -     * TX1/2-B Calibration -     **********************************************************************/ -    reg_inputsel = reg_inputsel | 0x40; -    write_ad9361_reg(0x004, reg_inputsel); - -    tx_quadrature_cal_routine(); - -    /*********************************************************************** -     * fin -     **********************************************************************/ -    reg_inputsel = orig_reg_inputsel; -    write_ad9361_reg(0x004, orig_reg_inputsel); -} - - -/*********************************************************************** - * Other Misc Setup Functions - ***********************************************************************/ - -/* Program the mixer gain table. - * - * Note that this table is fixed for all frequency settings. */ -void program_mixer_gm_subtable() { -    uint8_t gain[] = {0x78, 0x74, 0x70, 0x6C, 0x68, 0x64, 0x60, 0x5C, 0x58, -                      0x54, 0x50, 0x4C, 0x48, 0x30, 0x18, 0x00}; -    uint8_t gm[] = {0x00, 0x0D, 0x15, 0x1B, 0x21, 0x25, 0x29, 0x2C, 0x2F, -                    0x31, 0x33, 0x34, 0x35, 0x3A, 0x3D, 0x3E}; - -    /* Start the clock. */ -    write_ad9361_reg(0x13f, 0x02); - -    /* Program the GM Sub-table. */ -    int i; -    for(i = 15; i >= 0; i--) { -        write_ad9361_reg(0x138, i); -        write_ad9361_reg(0x139, gain[(15 - i)]); -        write_ad9361_reg(0x13A, 0x00); -        write_ad9361_reg(0x13B, gm[(15 - i)]); -        write_ad9361_reg(0x13F, 0x06); -        write_ad9361_reg(0x13C, 0x00); -        write_ad9361_reg(0x13C, 0x00); -    } - -    /* Clear write bit and stop clock. */ -    write_ad9361_reg(0x13f, 0x02); -    write_ad9361_reg(0x13C, 0x00); -    write_ad9361_reg(0x13C, 0x00); -    write_ad9361_reg(0x13f, 0x00); -} - -/* Program the gain table. - * - * There are three different gain tables for different frequency ranges! */ -void program_gain_table() { - -    /* Figure out which gain table we should be using for our current -     * frequency band. */ -    uint8_t (*gain_table)[5] = NULL; -    uint8_t new_gain_table; -    if(_rx_freq  < 1300e6) { -        gain_table = gain_table_sub_1300mhz; -        new_gain_table = 1; -    } else if(_rx_freq < 4e9) { -        gain_table = gain_table_1300mhz_to_4000mhz; -        new_gain_table = 2; -    } else if(_rx_freq <= 6e9) { -        gain_table = gain_table_4000mhz_to_6000mhz; -        new_gain_table = 3; -    } else { -        post_err_msg("Wrong _rx_freq value"); -        new_gain_table = 1; -    } - -    /* Only re-program the gain table if there has been a band change. */ -    if(_curr_gain_table == new_gain_table) { -        return; -    } else { -        _curr_gain_table = new_gain_table; -    } - -    /* Okay, we have to program a new gain table. Sucks, brah. Start the -     * gain table clock. */ -    write_ad9361_reg(0x137, 0x1A); - -    /* IT'S PROGRAMMING TIME. */ -    uint8_t index = 0; -    for(; index < 77; index++) { -        write_ad9361_reg(0x130, index); -        write_ad9361_reg(0x131, gain_table[index][1]); -        write_ad9361_reg(0x132, gain_table[index][2]); -        write_ad9361_reg(0x133, gain_table[index][3]); -        write_ad9361_reg(0x137, 0x1E); -        write_ad9361_reg(0x134, 0x00); -        write_ad9361_reg(0x134, 0x00); -    } - -    /* Everything above the 77th index is zero. */ -    for(; index < 91; index++) { -        write_ad9361_reg(0x130, index); -        write_ad9361_reg(0x131, 0x00); -        write_ad9361_reg(0x132, 0x00); -        write_ad9361_reg(0x133, 0x00); -        write_ad9361_reg(0x137, 0x1E); -        write_ad9361_reg(0x134, 0x00); -        write_ad9361_reg(0x134, 0x00); -    } - -    /* Clear the write bit and stop the gain clock. */ -    write_ad9361_reg(0x137, 0x1A); -    write_ad9361_reg(0x134, 0x00); -    write_ad9361_reg(0x134, 0x00); -    write_ad9361_reg(0x137, 0x00); -} - -/* Setup gain control registers. - * - * This really only needs to be done once, at initialization. */ -void setup_gain_control() { -    write_ad9361_reg(0x0FA, 0xE0); // Gain Control Mode Select -    write_ad9361_reg(0x0FB, 0x08); // Table, Digital Gain, Man Gain Ctrl -    write_ad9361_reg(0x0FC, 0x23); // Incr Step Size, ADC Overrange Size -    write_ad9361_reg(0x0FD, 0x4C); // Max Full/LMT Gain Table Index -    write_ad9361_reg(0x0FE, 0x44); // Decr Step Size, Peak Overload Time -    write_ad9361_reg(0x100, 0x6F); // Max Digital Gain -    write_ad9361_reg(0x104, 0x2F); // ADC Small Overload Threshold -    write_ad9361_reg(0x105, 0x3A); // ADC Large Overload Threshold -    write_ad9361_reg(0x107, 0x31); // Large LMT Overload Threshold -    write_ad9361_reg(0x108, 0x39); // Small LMT Overload Threshold -    write_ad9361_reg(0x109, 0x23); // Rx1 Full/LMT Gain Index -    write_ad9361_reg(0x10A, 0x58); // Rx1 LPF Gain Index -    write_ad9361_reg(0x10B, 0x00); // Rx1 Digital Gain Index -    write_ad9361_reg(0x10C, 0x23); // Rx2 Full/LMT Gain Index -    write_ad9361_reg(0x10D, 0x18); // Rx2 LPF Gain Index -    write_ad9361_reg(0x10E, 0x00); // Rx2 Digital Gain Index -    write_ad9361_reg(0x114, 0x30); // Low Power Threshold -    write_ad9361_reg(0x11A, 0x27); // Initial LMT Gain Limit -    write_ad9361_reg(0x081, 0x00); // Tx Symbol Gain Control -} - -/* Setup the RX or TX synthesizers. - * - * This setup depends on a fixed look-up table, which is stored in an - * included header file. The table is indexed based on the passed VCO rate. - */ -void setup_synth(int which, double vcorate) { -    /* The vcorates in the vco_index array represent lower boundaries for -     * rates. Once we find a match, we use that index to look-up the rest of -     * the register values in the LUT. */ -    int vcoindex = 0; -    int i; -    for(i = 0; i < 53; i++) { -        vcoindex = i; -        if(vcorate > vco_index[i]) { -            break; -        } -    } - -    if (vcoindex > 53) -        post_err_msg("vcoindex > 53"); - -    /* Parse the values out of the LUT based on our calculated index... */ -    uint8_t vco_output_level = synth_cal_lut[vcoindex][0]; -    uint8_t vco_varactor = synth_cal_lut[vcoindex][1]; -    uint8_t vco_bias_ref = synth_cal_lut[vcoindex][2]; -    uint8_t vco_bias_tcf = synth_cal_lut[vcoindex][3]; -    uint8_t vco_cal_offset = synth_cal_lut[vcoindex][4]; -    uint8_t vco_varactor_ref = synth_cal_lut[vcoindex][5]; -    uint8_t charge_pump_curr = synth_cal_lut[vcoindex][6]; -    uint8_t loop_filter_c2 = synth_cal_lut[vcoindex][7]; -    uint8_t loop_filter_c1 = synth_cal_lut[vcoindex][8]; -    uint8_t loop_filter_r1 = synth_cal_lut[vcoindex][9]; -    uint8_t loop_filter_c3 = synth_cal_lut[vcoindex][10]; -    uint8_t loop_filter_r3 = synth_cal_lut[vcoindex][11]; - -    /* ... annnd program! */ -    if(which == RX_TYPE) { -        write_ad9361_reg(0x23a, 0x40 | vco_output_level); -        write_ad9361_reg(0x239, 0xC0 | vco_varactor); -        write_ad9361_reg(0x242, vco_bias_ref | (vco_bias_tcf << 3)); -        write_ad9361_reg(0x238, (vco_cal_offset << 3)); -        write_ad9361_reg(0x245, 0x00); -        write_ad9361_reg(0x251, vco_varactor_ref); -        write_ad9361_reg(0x250, 0x70); -        write_ad9361_reg(0x23b, 0x80 | charge_pump_curr); -        write_ad9361_reg(0x23e, loop_filter_c1 | (loop_filter_c2 << 4)); -        write_ad9361_reg(0x23f, loop_filter_c3 | (loop_filter_r1 << 4)); -        write_ad9361_reg(0x240, loop_filter_r3); -    } else if(which == TX_TYPE) { -        write_ad9361_reg(0x27a, 0x40 | vco_output_level); -        write_ad9361_reg(0x279, 0xC0 | vco_varactor); -        write_ad9361_reg(0x282, vco_bias_ref | (vco_bias_tcf << 3)); -        write_ad9361_reg(0x278, (vco_cal_offset << 3)); -        write_ad9361_reg(0x285, 0x00); -        write_ad9361_reg(0x291, vco_varactor_ref); -        write_ad9361_reg(0x290, 0x70); -        write_ad9361_reg(0x27b, 0x80 | charge_pump_curr); -        write_ad9361_reg(0x27e, loop_filter_c1 | (loop_filter_c2 << 4)); -        write_ad9361_reg(0x27f, loop_filter_c3 | (loop_filter_r1 << 4)); -        write_ad9361_reg(0x280, loop_filter_r3); -    } else { -        post_err_msg("[setup_synth] INVALID_CODE_PATH"); -    } -} - - -/* Tune the baseband VCO. - * - * This clock signal is what gets fed to the ADCs and DACs. This function is - * not exported outside of this file, and is invoked based on the rate - * fed to the public set_clock_rate function. */ -double tune_bbvco(const double rate) { -    msg("[tune_bbvco] rate=%.10f", rate); -     -    /* Let's not re-tune to the same frequency over and over... */ -    if(freq_is_nearly_equal(rate, _req_coreclk)) { -        return _adcclock_freq; -    } - -    _req_coreclk = rate; - -    const double fref = 40e6; -    const int modulus = 2088960; -    const double vcomax = 1430e6; -    const double vcomin = 672e6; -    double vcorate; -    int vcodiv; -     -    /* Iterate over VCO dividers until appropriate divider is found. */ -    int i = 1; -    for(; i <= 6; i++) { -        vcodiv = 1 << i; -        vcorate = rate * vcodiv; -         -        if(vcorate >= vcomin && vcorate <= vcomax) break; -    } -    if(i == 7)  -        post_err_msg("[tune_bbvco] wrong vcorate"); -     -    msg("[tune_bbvco] vcodiv=%d vcorate=%.10f", vcodiv, vcorate); -     -    /* Fo = Fref * (Nint + Nfrac / mod) */ -    int nint = vcorate / fref; -    msg("[tune_bbvco] (nint)=%.10f", (vcorate / fref)); -    int nfrac = lround(((vcorate / fref) - (double)nint) * (double)modulus); -    msg("[tune_bbvco] (nfrac)=%.10f", (((vcorate / fref) - (double)nint) * (double)modulus)); -    msg("[tune_bbvco] nint=%d nfrac=%d", nint, nfrac); -    double actual_vcorate = fref * ((double)nint + ((double)nfrac / (double)modulus)); -     -    /* Scale CP current according to VCO rate */ -    const double icp_baseline = 150e-6; -    const double freq_baseline = 1280e6; -    double icp = icp_baseline * (actual_vcorate / freq_baseline); -    int icp_reg = (icp / 25e-6) - 1; - -    write_ad9361_reg(0x045, 0x00);            // REFCLK / 1 to BBPLL -    write_ad9361_reg(0x046, icp_reg & 0x3F);  // CP current -    write_ad9361_reg(0x048, 0xe8);            // BBPLL loop filters -    write_ad9361_reg(0x049, 0x5b);            // BBPLL loop filters -    write_ad9361_reg(0x04a, 0x35);            // BBPLL loop filters - -    write_ad9361_reg(0x04b, 0xe0); -    write_ad9361_reg(0x04e, 0x10);            // Max accuracy - -    write_ad9361_reg(0x043, nfrac & 0xFF);         // Nfrac[7:0] -    write_ad9361_reg(0x042, (nfrac >> 8) & 0xFF);  // Nfrac[15:8] -    write_ad9361_reg(0x041, (nfrac >> 16) & 0xFF); // Nfrac[23:16] -    write_ad9361_reg(0x044, nint);                 // Nint - -    calibrate_lock_bbpll(); - -    reg_bbpll = (reg_bbpll & 0xF8) | i; - -    _bbpll_freq = actual_vcorate; -    _adcclock_freq = (actual_vcorate / vcodiv); - -    return _adcclock_freq; -} - -/* This function re-programs all of the gains in the system. - * - * Because the gain values match to different gain indices based on the - * current operating band, this function can be called to update all gain - * settings to the appropriate index after a re-tune. */ -void program_gains() { -    set_gain(RX_TYPE,1, _rx1_gain); -    set_gain(RX_TYPE,2, _rx2_gain); -    set_gain(TX_TYPE,1, _tx1_gain); -    set_gain(TX_TYPE,2, _tx2_gain); -} - -/* This is the internal tune function, not available for a host call. - * - * Calculate the VCO settings for the requested frquency, and then either - * tune the RX or TX VCO. */ -double tune_helper(int which, const double value) { - -    /* The RFPLL runs from 6 GHz - 12 GHz */ -    const double fref = 80e6; -    const int modulus = 8388593; -    const double vcomax = 12e9; -    const double vcomin = 6e9; -    double vcorate; -    int vcodiv; - -    /* Iterate over VCO dividers until appropriate divider is found. */ -    int i; -    for(i = 0; i <= 6; i++) { -        vcodiv = 2 << i; -        vcorate = value * vcodiv; -        if(vcorate >= vcomin && vcorate <= vcomax) break; -    } -    if(i == 7)  -        post_err_msg("RFVCO can't find valid VCO rate!"); - -    int nint = vcorate / fref; -    int nfrac = ((vcorate / fref) - nint) * modulus; - -    double actual_vcorate = fref * (nint + (double)(nfrac)/modulus); -    double actual_lo = actual_vcorate / vcodiv; - -    // UHD_VAR(actual_lo); // TODO:  - -    if(which == RX_TYPE) { - -        _req_rx_freq = value; - -        /* Set band-specific settings. */ -        if(value < AD9361_RX_BAND_EDGE0) { -            reg_inputsel = (reg_inputsel & 0xC0) | 0x30; -        } else if((value >= AD9361_RX_BAND_EDGE0) && (value < AD9361_RX_BAND_EDGE1)) { -            reg_inputsel = (reg_inputsel & 0xC0) | 0x0C; -        } else if((value >= AD9361_RX_BAND_EDGE1) && (value <= 6e9)) { -            reg_inputsel = (reg_inputsel & 0xC0) | 0x03; -        } else { -            post_err_msg("[tune_helper] INVALID_CODE_PATH"); -        } - -        write_ad9361_reg(0x004, reg_inputsel); - -        /* Store vcodiv setting. */ -        reg_vcodivs = (reg_vcodivs & 0xF0) | (i & 0x0F); - -        /* Setup the synthesizer. */ -        setup_synth(RX_TYPE, actual_vcorate); - -        /* Tune!!!! */ -        write_ad9361_reg(0x233, nfrac & 0xFF); -        write_ad9361_reg(0x234, (nfrac >> 8) & 0xFF); -        write_ad9361_reg(0x235, (nfrac >> 16) & 0xFF); -        write_ad9361_reg(0x232, (nint >> 8) & 0xFF); -        write_ad9361_reg(0x231, nint & 0xFF); -        write_ad9361_reg(0x005, reg_vcodivs); - -        /* Lock the PLL! */ -        ad9361_msleep(2); -        if((read_ad9361_reg(0x247) & 0x02) == 0) { -            post_err_msg("RX PLL NOT LOCKED"); -        } - -        _rx_freq = actual_lo; - -        return actual_lo; - -    } else { - -        _req_tx_freq = value; - -        /* Set band-specific settings. */ -        if(value < AD9361_TX_BAND_EDGE) { -            reg_inputsel = reg_inputsel | 0x40; -        } else if((value >= AD9361_TX_BAND_EDGE) && (value <= 6e9)) { -            reg_inputsel = reg_inputsel & 0xBF; -        } else { -            post_err_msg("[tune_helper] INVALID_CODE_PATH"); -        } - -        write_ad9361_reg(0x004, reg_inputsel); - -        /* Store vcodiv setting. */ -        reg_vcodivs = (reg_vcodivs & 0x0F) | ((i & 0x0F) << 4); - -        /* Setup the synthesizer. */ -        setup_synth(TX_TYPE, actual_vcorate); - -        /* Tune it, homey. */ -        write_ad9361_reg(0x273, nfrac & 0xFF); -        write_ad9361_reg(0x274, (nfrac >> 8) & 0xFF); -        write_ad9361_reg(0x275, (nfrac >> 16) & 0xFF); -        write_ad9361_reg(0x272, (nint >> 8) & 0xFF); -        write_ad9361_reg(0x271, nint & 0xFF); -        write_ad9361_reg(0x005, reg_vcodivs); - -        /* Lock the PLL! */ -        ad9361_msleep(2); -        if((read_ad9361_reg(0x287) & 0x02) == 0) { -            post_err_msg("TX PLL NOT LOCKED"); -        } - -        _tx_freq = actual_lo; - -        return actual_lo; -    } -} - -/* Configure the various clock / sample rates in the RX and TX chains. - * - * Functionally, this function configures Catalina's RX and TX rates. For - * a requested TX & RX rate, it sets the interpolation & decimation filters, - * and tunes the VCO that feeds the ADCs and DACs.  - */ -double setup_rates(const double rate) { - -    /* If we make it into this function, then we are tuning to a new rate. -     * Store the new rate. */ -    _req_clock_rate = rate; - -    /* Set the decimation and interpolation values in the RX and TX chains. -     * This also switches filters in / out. Note that all transmitters and -     * receivers have to be turned on for the calibration portion of -     * bring-up, and then they will be switched out to reflect the actual -     * user-requested antenna selections. */ -    int divfactor = 0; -    _tfir_factor = 0; -    if(rate < 0.33e6) { -        // RX1 + RX2 enabled, 3, 2, 2, 4 -        reg_rxfilt = B8( 11101111 ) ; - -        // TX1 + TX2 enabled, 3, 2, 2, 4 -        reg_txfilt = B8( 11101111 ) ; - -        divfactor = 48; -        _tfir_factor = 2; -    } else if(rate < 0.66e6) { -        // RX1 + RX2 enabled, 2, 2, 2, 4 -        reg_rxfilt = B8( 11011111 ) ; - -        // TX1 + TX2 enabled, 2, 2, 2, 4 -        reg_txfilt = B8( 11011111 ) ; - -        divfactor = 32; -        _tfir_factor = 2; -    } else if(rate <= 20e6) { -        // RX1 + RX2 enabled, 2, 2, 2, 2 -        reg_rxfilt = B8( 11011110 ) ; - -        // TX1 + TX2 enabled, 2, 2, 2, 2 -        reg_txfilt = B8( 11011110 ) ; - -        divfactor = 16; -        _tfir_factor = 2; -    } else if((rate > 20e6) && (rate < 23e6)) { -        // RX1 + RX2 enabled, 3, 2, 2, 2 -        reg_rxfilt = B8( 11101110 ) ; - -        // TX1 + TX2 enabled, 3, 1, 2, 2 -        reg_txfilt = B8( 11100110 ) ; - -        divfactor = 24; -        _tfir_factor = 2; -    } else if((rate >= 23e6) && (rate < 41e6)) { -        // RX1 + RX2 enabled, 2, 2, 2, 2 -        reg_rxfilt = B8( 11011110 ) ; - -        // TX1 + TX2 enabled, 1, 2, 2, 2 -        reg_txfilt = B8( 11001110 ) ; - -        divfactor = 16; -        _tfir_factor = 2; -    } else if((rate >= 41e6) && (rate <= 56e6)) { -        // RX1 + RX2 enabled, 3, 1, 2, 2 -        reg_rxfilt = B8( 11100110 ) ; - -        // TX1 + TX2 enabled, 3, 1, 1, 2 -        reg_txfilt = B8( 11100010 ) ; - -        divfactor = 12; -        _tfir_factor = 2; -    } else if((rate > 56e6) && (rate <= 61.44e6)) { -        // RX1 + RX2 enabled, 3, 1, 1, 2 -        reg_rxfilt = B8( 11100010 ) ; - -        // TX1 + TX2 enabled, 3, 1, 1, 1 -        reg_txfilt = B8( 11100001 ) ; - -        divfactor = 6; -        _tfir_factor = 1; -    } else { -        // should never get in here -        post_err_msg("[setup_rates] INVALID_CODE_PATH"); -    } -     -    msg("[setup_rates] divfactor=%d", divfactor); - -    /* Tune the BBPLL to get the ADC and DAC clocks. */ -    const double adcclk = tune_bbvco(rate * divfactor); -    double dacclk = adcclk; - -    /* The DAC clock must be <= 336e6, and is either the ADC clock or 1/2 the -     * ADC clock.*/ -    if(adcclk > 336e6) { -        /* Make the DAC clock = ADC/2, and bypass the TXFIR. */ -        reg_bbpll = reg_bbpll | 0x08; -        dacclk = adcclk / 2.0; -    } else { -        reg_bbpll = reg_bbpll & 0xF7; -    } - -    /* Set the dividers / interpolators in Catalina. */ -    write_ad9361_reg(0x002, reg_txfilt); -    write_ad9361_reg(0x003, reg_rxfilt); -    write_ad9361_reg(0x004, reg_inputsel); -    write_ad9361_reg(0x00A, reg_bbpll); -     -    msg("[setup_rates] adcclk=%f", adcclk); -    _baseband_bw = (adcclk / divfactor); -     -    /* Setup the RX and TX FIR filters. Scale the number of taps based on -     * the clock speed. */ -    const int max_tx_taps = 16 * AD9361_MIN((int)((dacclk / rate) + 0.5), \ -            AD9361_MIN(4 * (1 << _tfir_factor), 8)); -    const int max_rx_taps = AD9361_MIN((16 * (int)(adcclk / rate)), 128); - -    const int num_tx_taps = get_num_taps(max_tx_taps); -    const int num_rx_taps = get_num_taps(max_rx_taps); - -    setup_tx_fir(num_tx_taps); -    setup_rx_fir(num_rx_taps); - -    return _baseband_bw; -} - -/*********************************************************************** - * Publicly exported functions to host calls - **********************************************************************/ -void init_ad9361(void) { - -    /* Initialize shadow registers. */ -    reg_vcodivs = 0x00; -    reg_inputsel = 0x30; -    reg_rxfilt = 0x00; -    reg_txfilt = 0x00; -    reg_bbpll = 0x02; -    reg_bbftune_config = 0x1e; -    reg_bbftune_mode = 0x1e; - -    /* Initialize private VRQ fields. */ -    _rx_freq = 0.0; -    _tx_freq = 0.0; -    _req_rx_freq = 0.0; -    _req_tx_freq = 0.0; -    _baseband_bw = 0.0; -    _req_clock_rate = 0.0; -    _req_coreclk = 0.0; -    _bbpll_freq = 0.0; -    _adcclock_freq = 0.0; -    _rx_bbf_tunediv = 0; -    _curr_gain_table = 0; -    _rx1_gain = 0; -    _rx2_gain = 0; -    _tx1_gain = 0; -    _tx2_gain = 0; - -    /* Reset the device. */ -    write_ad9361_reg(0x000,0x01); -    write_ad9361_reg(0x000,0x00); -    ad9361_msleep(20); - -    /* There is not a WAT big enough for this. */ -    write_ad9361_reg(0x3df, 0x01); - -    write_ad9361_reg(0x2a6, 0x0e); // Enable master bias -    write_ad9361_reg(0x2a8, 0x0e); // Set bandgap trim - -    /* Set RFPLL ref clock scale to REFCLK * 2 */ -    write_ad9361_reg(0x2ab, 0x07); -    write_ad9361_reg(0x2ac, 0xff); - -    /* Enable clocks. */ -    if (AD9361_CLOCKING_MODE == 0) -    { -        write_ad9361_reg(0x009, 0x17); -    } -    if (AD9361_CLOCKING_MODE == 1) -    { -        write_ad9361_reg(0x009, 0x07); -        write_ad9361_reg(0x292, 0x08); -        write_ad9361_reg(0x293, 0x80); -        write_ad9361_reg(0x294, 0x00); -        write_ad9361_reg(0x295, 0x14); -    } -    ad9361_msleep(20); - -    /* Tune the BBPLL, write TX and RX FIRS. */ -    setup_rates(50e6); - -    /* Setup data ports (FDD dual port DDR CMOS): -     *      FDD dual port DDR CMOS no swap. -     *      Force TX on one port, RX on the other. */ -    write_ad9361_reg(0x010, 0xc8); -    write_ad9361_reg(0x011, 0x00); -    write_ad9361_reg(0x012, 0x02); - -    /* Data delay for TX and RX data clocks */ -    write_ad9361_reg(0x006, 0x0F); -    write_ad9361_reg(0x007, 0x0F); - -    /* Setup AuxDAC */ -    write_ad9361_reg(0x018, 0x00); // AuxDAC1 Word[9:2] -    write_ad9361_reg(0x019, 0x00); // AuxDAC2 Word[9:2] -    write_ad9361_reg(0x01A, 0x00); // AuxDAC1 Config and Word[1:0] -    write_ad9361_reg(0x01B, 0x00); // AuxDAC2 Config and Word[1:0] -    write_ad9361_reg(0x023, 0xFF); // AuxDAC Manaul/Auto Control -    write_ad9361_reg(0x026, 0x00); // AuxDAC Manual Select Bit/GPO Manual Select -    write_ad9361_reg(0x030, 0x00); // AuxDAC1 Rx Delay -    write_ad9361_reg(0x031, 0x00); // AuxDAC1 Tx Delay -    write_ad9361_reg(0x032, 0x00); // AuxDAC2 Rx Delay -    write_ad9361_reg(0x033, 0x00); // AuxDAC2 Tx Delay - -    /* Setup AuxADC */ -    write_ad9361_reg(0x00B, 0x00); // Temp Sensor Setup (Offset) -    write_ad9361_reg(0x00C, 0x00); // Temp Sensor Setup (Temp Window) -    write_ad9361_reg(0x00D, 0x03); // Temp Sensor Setup (Periodic Measure) -    write_ad9361_reg(0x00F, 0x04); // Temp Sensor Setup (Decimation) -    write_ad9361_reg(0x01C, 0x10); // AuxADC Setup (Clock Div) -    write_ad9361_reg(0x01D, 0x01); // AuxADC Setup (Decimation/Enable) - -    /* Setup control outputs. */ -    write_ad9361_reg(0x035, 0x07); -    write_ad9361_reg(0x036, 0xFF); - -    /* Setup GPO */ -    write_ad9361_reg(0x03a, 0x27); //set delay register -    write_ad9361_reg(0x020, 0x00); // GPO Auto Enable Setup in RX and TX -    write_ad9361_reg(0x027, 0x03); // GPO Manual and GPO auto value in ALERT -    write_ad9361_reg(0x028, 0x00); // GPO_0 RX Delay -    write_ad9361_reg(0x029, 0x00); // GPO_1 RX Delay -    write_ad9361_reg(0x02A, 0x00); // GPO_2 RX Delay -    write_ad9361_reg(0x02B, 0x00); // GPO_3 RX Delay -    write_ad9361_reg(0x02C, 0x00); // GPO_0 TX Delay -    write_ad9361_reg(0x02D, 0x00); // GPO_1 TX Delay -    write_ad9361_reg(0x02E, 0x00); // GPO_2 TX Delay -    write_ad9361_reg(0x02F, 0x00); // GPO_3 TX Delay - -    write_ad9361_reg(0x261, 0x00); // RX LO power -    write_ad9361_reg(0x2a1, 0x00); // TX LO power -    write_ad9361_reg(0x248, 0x0b); // en RX VCO LDO -    write_ad9361_reg(0x288, 0x0b); // en TX VCO LDO -    write_ad9361_reg(0x246, 0x02); // pd RX cal Tcf -    write_ad9361_reg(0x286, 0x02); // pd TX cal Tcf -    write_ad9361_reg(0x249, 0x8e); // rx vco cal length -    write_ad9361_reg(0x289, 0x8e); // rx vco cal length -    write_ad9361_reg(0x23b, 0x80); // set RX MSB?, FIXME 0x89 magic cp -    write_ad9361_reg(0x27b, 0x80); // "" TX //FIXME 0x88 see above -    write_ad9361_reg(0x243, 0x0d); // set rx prescaler bias -    write_ad9361_reg(0x283, 0x0d); // "" TX - -    write_ad9361_reg(0x23d, 0x00); // Clear half VCO cal clock setting -    write_ad9361_reg(0x27d, 0x00); // Clear half VCO cal clock setting - -    /* The order of the following process is EXTREMELY important. If the -     * below functions are modified at all, device initialization and -     * calibration might be broken in the process! */ - -    write_ad9361_reg(0x015, 0x04); // dual synth mode, synth en ctrl en -    write_ad9361_reg(0x014, 0x05); // use SPI for TXNRX ctrl, to ALERT, TX on -    write_ad9361_reg(0x013, 0x01); // enable ENSM -    ad9361_msleep(1); - -    calibrate_synth_charge_pumps(); - -    tune_helper(RX_TYPE, 800e6); -    tune_helper(TX_TYPE, 850e6); - -    program_mixer_gm_subtable(); -    program_gain_table(); -    setup_gain_control(); - -    calibrate_baseband_rx_analog_filter(); -    calibrate_baseband_tx_analog_filter(); -    calibrate_rx_TIAs(); -    calibrate_secondary_tx_filter(); - -    setup_adc();  - -    calibrate_tx_quadrature(); -    calibrate_rx_quadrature(); - -    write_ad9361_reg(0x012, 0x02); // cals done, set PPORT config -    write_ad9361_reg(0x013, 0x01); // Set ENSM FDD bit -    write_ad9361_reg(0x015, 0x04); // dual synth mode, synth en ctrl en - -    /* Default TX attentuation to 10dB on both TX1 and TX2 */ -    write_ad9361_reg(0x073, 0x00); -    write_ad9361_reg(0x074, 0x00); -    write_ad9361_reg(0x075, 0x00); -    write_ad9361_reg(0x076, 0x00); - -    /* Setup RSSI Measurements */ -    write_ad9361_reg(0x150, 0x0E); // RSSI Measurement Duration 0, 1 -    write_ad9361_reg(0x151, 0x00); // RSSI Measurement Duration 2, 3 -    write_ad9361_reg(0x152, 0xFF); // RSSI Weighted Multiplier 0 -    write_ad9361_reg(0x153, 0x00); // RSSI Weighted Multiplier 1 -    write_ad9361_reg(0x154, 0x00); // RSSI Weighted Multiplier 2 -    write_ad9361_reg(0x155, 0x00); // RSSI Weighted Multiplier 3 -    write_ad9361_reg(0x156, 0x00); // RSSI Delay -    write_ad9361_reg(0x157, 0x00); // RSSI Wait -    write_ad9361_reg(0x158, 0x0D); // RSSI Mode Select -    write_ad9361_reg(0x15C, 0x67); // Power Measurement Duration - -    /* Turn on the default RX & TX chains. */ -    set_active_chains(true, false, false, false); - -    /* Set TXers & RXers on (only works in FDD mode) */ -    write_ad9361_reg(0x014, 0x21); -} - - -/* This function sets the RX / TX rate between Catalina and the FPGA, and - * thus determines the interpolation / decimation required in the FPGA to - * achieve the user's requested rate. - * - * This is the only clock setting function that is exposed to the outside. */ -double set_clock_rate(const double req_rate) { -    if(req_rate > 61.44e6) { -        post_err_msg("Requested master clock rate outside range"); -    } -     -    msg("[set_clock_rate] req_rate=%.10f", req_rate); -     -    /* UHD has a habit of requesting the same rate like four times when it -     * starts up. This prevents that, and any bugs in user code that request -     * the same rate over and over. */ -    if(freq_is_nearly_equal(req_rate, _req_clock_rate)) { -        return _baseband_bw; -    } -     -    /* We must be in the SLEEP / WAIT state to do this. If we aren't already -     * there, transition the ENSM to State 0. */ -    uint8_t current_state = read_ad9361_reg(0x017) & 0x0F; -    switch(current_state) { -        case 0x05: -            /* We are in the ALERT state. */ -            write_ad9361_reg(0x014, 0x21); -            ad9361_msleep(5); -            write_ad9361_reg(0x014, 0x00); -            break; - -        case 0x0A: -            /* We are in the FDD state. */ -            write_ad9361_reg(0x014, 0x00); -            break; - -        default: -            post_err_msg("[set_clock_rate:1] AD9361 in unknown state"); -            break; -    }; - -    /* Store the current chain / antenna selections so that we can restore -     * them at the end of this routine; all chains will be enabled from -     * within setup_rates for calibration purposes. */ -    uint8_t orig_tx_chains = reg_txfilt & 0xC0; -    uint8_t orig_rx_chains = reg_rxfilt & 0xC0; - -    /* Call into the clock configuration / settings function. This is where -     * all the hard work gets done. */ -    double rate = setup_rates(req_rate); -     -    msg("[set_clock_rate] rate=%.10f", rate); - -    /* Transition to the ALERT state and calibrate everything. */ -    write_ad9361_reg(0x015, 0x04); //dual synth mode, synth en ctrl en -    write_ad9361_reg(0x014, 0x05); //use SPI for TXNRX ctrl, to ALERT, TX on -    write_ad9361_reg(0x013, 0x01); //enable ENSM -    ad9361_msleep(1); - -    calibrate_synth_charge_pumps(); - -    tune_helper(RX_TYPE, _rx_freq); -    tune_helper(TX_TYPE, _tx_freq); - -    program_mixer_gm_subtable(); -    program_gain_table(); -    setup_gain_control(); -    program_gains(); - -    calibrate_baseband_rx_analog_filter(); -    calibrate_baseband_tx_analog_filter(); -    calibrate_rx_TIAs(); -    calibrate_secondary_tx_filter(); - -    setup_adc(); - -    calibrate_tx_quadrature(); -    calibrate_rx_quadrature(); - -    write_ad9361_reg(0x012, 0x02); // cals done, set PPORT config -    write_ad9361_reg(0x013, 0x01); // Set ENSM FDD bit -    write_ad9361_reg(0x015, 0x04); // dual synth mode, synth en ctrl en - -    /* End the function in the same state as the entry state. */ -    switch(current_state) { -        case 0x05: -            /* We are already in ALERT. */ -            break; - -        case 0x0A: -            /* Transition back to FDD, and restore the original antenna -             * / chain selections. */ -            reg_txfilt = (reg_txfilt & 0x3F) | orig_tx_chains; -            reg_rxfilt = (reg_rxfilt & 0x3F) | orig_rx_chains; - -            write_ad9361_reg(0x002, reg_txfilt); -            write_ad9361_reg(0x003, reg_rxfilt); -            write_ad9361_reg(0x014, 0x21); -            break; - -        default: -            post_err_msg("[set_clock_rate:2] AD9361 in unknown state"); -            break; -    }; - -    return rate; -} - - -/* Set which of the four TX / RX chains provided by Catalina are active. - * - * Catalina provides two sets of chains, Side A and Side B. Each side - * provides one TX antenna, and one RX antenna. The B200 maintains the USRP - * standard of providing one antenna connection that is both TX & RX, and - * one that is RX-only - for each chain. Thus, the possible antenna and - * chain selections are: - * - *  B200 Antenna    Catalina Side       Catalina Chain - *  ------------------------------------------------------------------- - *  TX / RX1        Side A              TX1 (when switched to TX) - *  TX / RX1        Side A              RX1 (when switched to RX) - *  RX1             Side A              RX1 - * - *  TX / RX2        Side B              TX2 (when switched to TX) - *  TX / RX2        Side B              RX2 (when switched to RX) - *  RX2             Side B              RX2 - */ -void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2) { -    /* Clear out the current active chain settings. */ -    reg_txfilt = reg_txfilt & 0x3F; -    reg_rxfilt = reg_rxfilt & 0x3F; - -    /* Turn on the different chains based on the passed parameters. */ -    if(tx1) { reg_txfilt = reg_txfilt | 0x40; } -    if(tx2) { reg_txfilt = reg_txfilt | 0x80; } -    if(rx1) { reg_rxfilt = reg_rxfilt | 0x40; } -    if(rx2) { reg_rxfilt = reg_rxfilt | 0x80; } - -    /* Turn on / off the chains. */ -    write_ad9361_reg(0x002, reg_txfilt); -    write_ad9361_reg(0x003, reg_rxfilt); -} - -/* Tune the RX or TX frequency. - * - * This is the publicly-accessible tune function. It makes sure the tune - * isn't a redundant request, and if not, passes it on to the class's - * internal tune function. - * - * After tuning, it runs any appropriate calibrations. */ -double tune(int which, const double value) { - -    if(which == RX_TYPE) { -        if(freq_is_nearly_equal(value, _req_rx_freq)) { -            return _rx_freq; -        } - -    } else if(which == TX_TYPE) { -        if(freq_is_nearly_equal(value, _req_tx_freq)) { -            return _tx_freq; -        } - -    } else { -        post_err_msg("[tune] INVALID_CODE_PATH"); -    } -     -    /* If we aren't already in the ALERT state, we will need to return to -     * the FDD state after tuning. */ -    int not_in_alert = 0; -    if((read_ad9361_reg(0x017) & 0x0F) != 5) { -        /* Force the device into the ALERT state. */ -        not_in_alert = 1; -        write_ad9361_reg(0x014, 0x01); -    } - -    /* Tune the RF VCO! */ -    double tune_freq = tune_helper(which, value); - -    /* Run any necessary calibrations / setups */ -    if(which == RX_TYPE) { -        program_gain_table(); -    } - -    /* Update the gain settings. */ -    program_gains(); - -    /* Run the calibration algorithms. */ -    calibrate_tx_quadrature(); -    calibrate_rx_quadrature(); - -    /* If we were in the FDD state, return it now. */ -    if(not_in_alert) { -        write_ad9361_reg(0x014, 0x21); -    } - -    return tune_freq; -} - -/* Set the gain of RX1, RX2, TX1, or TX2. - * - * Note that the 'value' passed to this function is the actual gain value, - * _not_ the gain index. This is the opposite of the eval software's GUI! - * Also note that the RX chains are done in terms of gain, and the TX chains - * are done in terms of attenuation. */ -double set_gain(int which, int n, const double value) { - -    if(which == RX_TYPE) { -        /* Indexing the gain tables requires an offset from the requested -         * amount of total gain in dB: -         *      < 1300MHz: dB + 5 -         *      >= 1300MHz and < 4000MHz: dB + 3 -         *      >= 4000MHz and <= 6000MHz: dB + 14 -         */ -        int gain_offset = 0; -        if(_rx_freq < 1300e6) { -            gain_offset = 5; -        } else if(_rx_freq < 4000e6) { -            gain_offset = 3; -        } else { -            gain_offset = 14; -        } - -        int gain_index = value + gain_offset; - -        /* Clip the gain values to the proper min/max gain values. */ -        if(gain_index > 76) gain_index = 76; -        if(gain_index < 0) gain_index = 0; - -        if(n == 1) { -            _rx1_gain = value; -            write_ad9361_reg(0x109, gain_index); -        } else { -            _rx2_gain = value; -            write_ad9361_reg(0x10c, gain_index); -        } - -        return gain_index - gain_offset; -    } else { -        /* Setting the below bits causes a change in the TX attenuation word -         * to immediately take effect. */ -        write_ad9361_reg(0x077, 0x40); -        write_ad9361_reg(0x07c, 0x40); - -        /* Each gain step is -0.25dB. Calculate the attenuation necessary -         * for the requested gain, convert it into gain steps, then write -         * the attenuation word. Max gain (so zero attenuation) is 89.75. */ -        double atten = AD9361_MAX_GAIN - value; -        int attenreg = atten * 4; -        if(n == 1) { -            _tx1_gain = value; -            write_ad9361_reg(0x073, attenreg & 0xFF); -            write_ad9361_reg(0x074, (attenreg >> 8) & 0x01); -        } else { -            _tx2_gain = value; -            write_ad9361_reg(0x075, attenreg & 0xFF); -            write_ad9361_reg(0x076, (attenreg >> 8) & 0x01); -        } -        return AD9361_MAX_GAIN - ((double)(attenreg)/ 4); -    } -} - -/* This function is responsible to dispatch the vendor request call - * to the proper handler - */ -void ad9361_dispatch(const char* vrb, char* vrb_out) { -    memcpy(vrb_out, vrb, AD9361_DISPATCH_PACKET_SIZE);  // Copy request to response memory -    tmp_req_buffer = vrb_out;                           // Set this to enable 'post_err_msg' -     -    ////////////////////////////////////////////// -     -    double ret_val = 0.0; -    int mask = 0; -     -    const ad9361_transaction_t *request = (const ad9361_transaction_t *)vrb; -    ad9361_transaction_t *response = (ad9361_transaction_t *)vrb_out; -    response->error_msg[0] = '\0';  // Ensure error is cleared -     -    //msg("[ad9361_dispatch] action=%d", request->action); -     -    switch (request->action) { -        case AD9361_ACTION_ECHO: -            break; // nothing to do -        case AD9361_ACTION_INIT: -            init_ad9361(); -            break; -        case AD9361_ACTION_SET_RX1_GAIN: -            ret_val = set_gain(RX_TYPE,1,double_unpack(request->value.gain)); -            double_pack(ret_val, response->value.gain); -            break; -        case AD9361_ACTION_SET_TX1_GAIN: -            ret_val = set_gain(TX_TYPE,1,double_unpack(request->value.gain)); -            double_pack(ret_val, response->value.gain); -            break; -        case AD9361_ACTION_SET_RX2_GAIN: -            ret_val = set_gain(RX_TYPE,2,double_unpack(request->value.gain)); -            double_pack(ret_val, response->value.gain); -            break; -        case AD9361_ACTION_SET_TX2_GAIN: -            ret_val = set_gain(TX_TYPE,2,double_unpack(request->value.gain)); -            double_pack(ret_val, response->value.gain); -            break; -        case AD9361_ACTION_SET_RX_FREQ: -            ret_val = tune(RX_TYPE, double_unpack(request->value.freq)); -            double_pack(ret_val, response->value.freq); -            break; -        case AD9361_ACTION_SET_TX_FREQ: -            ret_val = tune(TX_TYPE, double_unpack(request->value.freq)); -            double_pack(ret_val, response->value.freq); -            break; -        case AD9361_ACTION_SET_CODEC_LOOP: -            data_port_loopback(request->value.codec_loop != 0); -            break; -        case AD9361_ACTION_SET_CLOCK_RATE: -            ret_val = set_clock_rate(double_unpack(request->value.rate)); -            double_pack(ret_val, response->value.rate); -            break; -        case AD9361_ACTION_SET_ACTIVE_CHAINS: -            mask = request->value.enable_mask; -            set_active_chains(mask & 1, mask & 2, mask & 4, mask & 8); -            break; -        default: -            post_err_msg("[ad9361_dispatch] NOT IMPLEMENTED"); -            break; -    } -} diff --git a/firmware/fx3/ad9361/lib/ad9361_synth_lut.h b/firmware/fx3/ad9361/lib/ad9361_synth_lut.h deleted file mode 100644 index 79214526d..000000000 --- a/firmware/fx3/ad9361/lib/ad9361_synth_lut.h +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -#ifndef INCLUDED_AD9361_SYNTH_LUT_HPP -#define INCLUDED_AD9361_SYNTH_LUT_HPP - - -double vco_index[53] = {12605000000, 12245000000, 11906000000, 11588000000, -                        11288000000, 11007000000, 10742000000, 10492000000, -                        10258000000, 10036000000, 9827800000, 9631100000, -                        9445300000, 9269800000, 9103600000, 8946300000, -                        8797000000, 8655300000, 8520600000, 8392300000, -                        8269900000, 8153100000, 8041400000, 7934400000, -                        7831800000, 7733200000, 7638400000, 7547100000, -                        7459000000, 7374000000, 7291900000, 7212400000, -                        7135500000, 7061000000, 6988700000, 6918600000, -                        6850600000, 6784600000, 6720500000, 6658200000, -                        6597800000, 6539200000, 6482300000, 6427000000, -                        6373400000, 6321400000, 6270900000, 6222000000, -                        6174500000, 6128400000, 6083600000, 6040100000, -                        5997700000}; - -int synth_cal_lut[53][12] = {   {10, 0, 4, 0, 15, 8, 8, 13, 4, 13, 15, 9}, -                                {10, 0, 4, 0, 15, 8, 9, 13, 4, 13, 15, 9}, -                                {10, 0, 4, 0, 15, 8, 10, 13, 4, 13, 15, 9}, -                                {10, 0, 4, 0, 15, 8, 11, 13, 4, 13, 15, 9}, -                                {10, 0, 4, 0, 15, 8, 11, 13, 4, 13, 15, 9}, -                                {10, 0, 4, 0, 14, 8, 12, 13, 4, 13, 15, 9}, -                                {10, 0, 4, 0, 14, 8, 13, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 14, 9, 13, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 14, 9, 14, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 14, 9, 15, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 14, 9, 15, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 13, 9, 16, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 13, 9, 17, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 13, 9, 18, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 13, 9, 18, 13, 4, 13, 15, 9}, -                                {10, 0, 5, 1, 13, 9, 19, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 14, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 14, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 15, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 15, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 16, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 16, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 17, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 17, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 18, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 18, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 19, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 19, 13, 4, 13, 15, 9}, -                                {10, 1, 6, 1, 15, 11, 20, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 12, 20, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 12, 21, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 12, 21, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 22, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 22, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 23, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 23, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 24, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 24, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 25, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 25, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 26, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 26, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 27, 13, 4, 13, 15, 9}, -                                {10, 1, 7, 2, 15, 14, 27, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 18, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 18, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 18, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 20, 13, 4, 13, 15, 9}, -                                {10, 3, 7, 3, 15, 12, 20, 13, 4, 13, 15, 9}}; - - -#if 0 /* This is the table for a 40MHz RFPLL Reference */ -int synth_cal_lut[53][12] = {   {10, 0, 4, 0, 15, 8, 8, 12, 3, 14, 15, 11}, -                                {10, 0, 4, 0, 15, 8, 9, 12, 3, 14, 15, 11}, -                                {10, 0, 4, 0, 15, 8, 9, 12, 3, 14, 15, 11}, -                                {10, 0, 4, 0, 15, 8, 10, 12, 3, 14, 15, 11}, -                                {10, 0, 4, 0, 15, 8, 11, 12, 3, 14, 15, 11}, -                                {10, 0, 4, 0, 15, 8, 11, 12, 3, 14, 15, 11}, -                                {10, 0, 4, 0, 14, 8, 12, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 13, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 13, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 14, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 15, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 15, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 16, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 17, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 17, 12, 3, 14, 15, 11}, -                                {10, 0, 5, 1, 14, 9, 18, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 13, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 14, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 14, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 15, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 15, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 16, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 16, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 17, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 17, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 17, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 18, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 18, 12, 3, 14, 15, 11}, -                                {10, 1, 6, 1, 15, 11, 19, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 12, 19, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 12, 20, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 12, 20, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 21, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 21, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 22, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 22, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 23, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 23, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 24, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 24, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 25, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 25, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 26, 12, 3, 14, 15, 11}, -                                {10, 1, 7, 2, 15, 14, 26, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 17, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 17, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 17, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 19, 12, 3, 14, 15, 11}, -                                {10, 3, 7, 3, 15, 12, 19, 12, 3, 14, 15, 11} }; -#endif - -#endif /* INCLUDED_AD9361_SYNTH_LUT_HPP */ diff --git a/firmware/fx3/b200/b200_ad9361.c b/firmware/fx3/b200/b200_ad9361.c deleted file mode 100644 index ebb0dda70..000000000 --- a/firmware/fx3/b200/b200_ad9361.c +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -#include "cyu3error.h" -#include "cyu3i2c.h" -#include "cyu3spi.h" -#include "cyu3os.h" -#include "cyu3pib.h" -#include "cyu3system.h" -#include "cyu3usb.h" -#include "cyu3utils.h" -#include "pib_regs.h" -#include "b200_vrq.h" -#include <stdint.h> - -#define true CyTrue -#define false CyFalse - -typedef CyBool_t bool; - -/* Fast sqrt() - precision can be improved by increasing  - * the number of iterations  - */ -float ad9361_sqrt(const float number) -{ -    uint32_t i; -    float x2, y; - -    x2 = number * 0.5F; -    y = number; -    i = *(uint32_t *) &y; -    i = 0x5f3759df - ( i >> 1 ); -    y = *(float *) &i; -    y = y * (1.5F - (x2 * y * y)); - -    return number * y; -} - -void ad9361_msleep(const unsigned millis) -{ -    CyU3PThreadSleep(millis); -} - -#define AD9361_MIN(a, b) CY_U3P_MIN(a, b) -#define AD9361_MAX(a, b) CY_U3P_MAX(a, b) - -#define AD9361_CEIL_INT(a)  ((int)(a+1))  -#define AD9361_FLOOR_INT(a) ((int)(a)) - -#define AD9361_CLOCKING_MODE 0 - -#define AD9361_RX_BAND_EDGE0 2.2e9 -#define AD9361_RX_BAND_EDGE1 4e9 -#define AD9361_TX_BAND_EDGE 2.5e9 - -#include "../ad9361/lib/ad9361_impl.c" diff --git a/firmware/fx3/b200/b200_main.c b/firmware/fx3/b200/b200_main.c index 38af9ed4e..077ee251b 100644 --- a/firmware/fx3/b200/b200_main.c +++ b/firmware/fx3/b200/b200_main.c @@ -12,7 +12,6 @@  #include "b200_main.h"  #include "b200_gpifconfig.h" -#include "b200_vrq.h"  #include "b200_i2c.h"  #include "cyu3dma.h" @@ -28,9 +27,6 @@  #include "cyfxversion.h"  #include "pib_regs.h" -#include <ad9361_transaction.h> -#include <ad9361_dispatch.h> -  #define STATIC_SAVER static // Save stack space for variables in a non-re-entrant function (e.g. USB setup callback)  /* @@ -40,7 +36,6 @@  //#define HAS_HEAP                    // This requires memory to be set aside for the heap (e.g. required for printing floating-point numbers). You can apply the accompanying patch ('fx3_mem_map.patch') to fx3.ld & cyfxtx.c to create one.  //#define ENABLE_MSG                  // This will cause the compiled code to exceed the default text memory area (SYS_MEM). You can apply the accompanying patch ('fx3_mem_map.patch') to fx3.ld & cyfxtx.c to resize the memory map so it will fit. -//#define   ENABLE_AD9361_LOGGING     // When enabling this, you *must* enable the heap with HAS_HEAP (and apply the accompanying memory map patch 'fx3_mem_map.patch') otherwise the FW will crash when printing a floating-point number (as there is no heap for _sbrk by default)  //#define ENABLE_MANUAL_DMA_XFER  //#define   ENABLE_MANUAL_DMA_XFER_FROM_HOST  //#define   ENABLE_MANUAL_DMA_XFER_TO_HOST @@ -69,13 +64,6 @@  #ifdef ENABLE_MSG  #pragma message "msg enabled" - -#ifdef ENABLE_AD9361_LOGGING -#pragma message "   AD9361 logging enabled" -#else -#pragma message "   AD9361 logging disabled" -#endif // ENABLE_AD9361_LOGGING -  #else  #pragma message "msg disabled"  #endif // ENABLE_MSG @@ -156,21 +144,15 @@ static CyU3PThread thread_fpga_config;  #ifdef ENABLE_RE_ENUM_THREAD  static CyU3PThread thread_re_enum;  #endif // ENABLE_RE_ENUM_THREAD -static CyU3PThread thread_ad9361;  static CyBool_t g_app_running = CyFalse;  static uint8_t g_fx3_state = STATE_UNDEFINED; -//#define AD9361_DISPATCH_PACKET_SIZE 64  // Must fit into smallest VREQ  #define USB2_VREQ_BUF_SIZE          64  #define USB3_VREQ_BUF_SIZE          512  #define MIN_VREQ_BUF_SIZE           USB2_VREQ_BUF_SIZE  #define MAX_VREQ_BUF_SIZE           USB3_VREQ_BUF_SIZE -#if AD9361_DISPATCH_PACKET_SIZE > MIN_VREQ_BUF_SIZE -#error "AD9361_DISPATCH_PACKET_SIZE must be less than MIN_VREQ_BUF_SIZE" -#endif -  static uint16_t g_vendor_req_buff_size = MIN_VREQ_BUF_SIZE;  static uint8_t g_vendor_req_buffer[MAX_VREQ_BUF_SIZE] __attribute__ ((aligned (32)));  static uint16_t g_vendor_req_read_count = 0; @@ -180,8 +162,6 @@ static uint8_t fw_hash[4] __attribute__ ((aligned (32)));  static uint8_t compat_num[2];  static uint32_t g_fpga_programming_write_count = 0; -static char g_ad9361_response[AD9361_DISPATCH_PACKET_SIZE]; -  #define COUNTER_MAGIC       0x10024001  #define LOG_BUFFER_SIZE     /*MAX_VREQ_BUF_SIZE*/1024	// [Max vreq @ USB3 (64 @ USB2)] Can be larger  static char log_buffer[LOG_BUFFER_SIZE]; @@ -685,214 +665,6 @@ void gpio_interrupt_callback(uint8_t gpio_id) {  } -// The following two functions are intended to replace write_spi_to_ad9361 -// and read_spi_from_ad9361 after the code porting is complete -/*! Perform a register write to the ad9361 chip. - * A pointer to the register address followed by data will be provided as  - * parameter - */ -static void write_ad9361_reg(uint16_t reg, uint8_t val) { - -    CyBool_t gpio_value; -    uint8_t write_buff[3]; -    MAKE_AD9361_WRITE(write_buff, reg, val) - -    // Number of bytes we are writing. -    uint8_t num_bytes = 3;  //register address = 2 bytes, data = 1 byte - -    CyU3PGpioSetValue(GPIO_FX3_CE, 0); - -    // Clock the data out to AD9361 over SPI. -    int8_t bit_count, byte_count; -    for(byte_count = 0; byte_count < num_bytes; byte_count++) { - -        uint8_t miso = 0x00; -        uint8_t data = write_buff[byte_count]; - -        for(bit_count = 7; bit_count >= 0; bit_count--) { -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 1); -            CyU3PGpioSetValue(GPIO_FX3_MOSI, ((data >> bit_count) & 0x01)); -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 0); - -            CyU3PGpioGetValue(GPIO_FX3_MISO, &gpio_value); -            if(gpio_value) { -                miso |= (1 << bit_count); -            } -        } -        // FIXME: Determine what to do with miso value; -    } - -    CyU3PGpioSetValue(GPIO_FX3_MOSI, 0); -    CyU3PGpioSetValue(GPIO_FX3_CE, 1); -} - -/*! Perform a register read from to the ad9361 chip. - * A pointer to register address will be provided as parameter - * The function returns the value read from the register - */ -static uint8_t read_ad9361_reg(uint16_t reg) { - -    CyBool_t gpio_value; -    uint8_t write_buff[2]; -    MAKE_AD9361_READ(write_buff, reg) - -    // Each 9361 register read returns 1 byte - -    CyU3PGpioSetValue(GPIO_FX3_CE, 0); - -    // Write the two register address bytes. -    int8_t bit_count, byte_count; -    for(byte_count = 0; byte_count < 2; byte_count++) { - -        uint8_t miso = 0x00; -        uint8_t data = write_buff[byte_count]; - -        for(bit_count = 7; bit_count >= 0; bit_count--) { -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 1); -            CyU3PGpioSetValue(GPIO_FX3_MOSI, ((data >> bit_count) & 0x01)); -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 0); - -            CyU3PGpioGetValue(GPIO_FX3_MISO, &gpio_value); -            if(gpio_value) { -                miso |= (1 << bit_count); -            } -        } -        // FIXME: Determine what to do with miso value; -    } - -    CyU3PGpioSetValue(GPIO_FX3_MOSI, 0); - -    // Read the response data from the chip. -    uint8_t data = 0x00; - -    for(bit_count = 7; bit_count >= 0; bit_count--) { -        CyU3PGpioSetValue(GPIO_FX3_SCLK, 1); - -        CyU3PGpioGetValue(GPIO_FX3_MISO, &gpio_value); -        if(gpio_value) { -            data |= (1 << bit_count); -        } - -        CyU3PGpioSetValue(GPIO_FX3_SCLK, 0); -    } -    CyU3PGpioSetValue(GPIO_FX3_CE, 1); -    return data; -} - -/*! Perform a register write to the ad9361 chip. - * - * This function will take data received over EP0, as a vendor request, and - * perform a SPI write to ad9361. This requires that the FPGA be passing these - * SPI lines through to the ad9361 chip. */ -void write_spi_to_ad9361(void) { - -    CyBool_t gpio_value; - -    /* Pull out the number of bytes we are writing. */ -    uint8_t num_bytes = ((g_vendor_req_buffer[0] & 0x70) >> 4) + 1; - -    CyU3PGpioSetValue(GPIO_FX3_CE, 0); - -    /* Clock the data out to AD9361 over SPI. */ -    int8_t bit_count, byte_count; -    for(byte_count = 0; byte_count < (num_bytes + 2); byte_count++) { - -        uint8_t miso = 0x00; -        uint8_t data = g_vendor_req_buffer[byte_count]; - -        for(bit_count = 7; bit_count >= 0; bit_count--) { -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 1); -            CyU3PGpioSetValue(GPIO_FX3_MOSI, ((data >> bit_count) & 0x01)); -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 0); - -            CyU3PGpioGetValue(GPIO_FX3_MISO, &gpio_value); -            if(gpio_value) { -                miso |= (1 << bit_count); -            } -        } - -        g_vendor_req_buffer[byte_count] = miso; -    } - -    CyU3PGpioSetValue(GPIO_FX3_MOSI, 0); -    CyU3PGpioSetValue(GPIO_FX3_CE, 1); -} - - -/*! Perform a register read from the ad9361 chip. - * - * This function will write a command to the ad9361 chip, performing a register - * read, and store the returned data in the vendor request buffer. This data can - * then be retrieved with another vendor request from the host. - * - * This requires that the FPGA be passing these SPI lines through to the - * ad9361 chip. */ -void read_spi_from_ad9361(void) { - -    CyBool_t gpio_value; - -    /* Pull out the number of bytes we are reading. */ -    uint8_t num_bytes = ((g_vendor_req_buffer[0] & 0x70) >> 4) + 1; - -    CyU3PGpioSetValue(GPIO_FX3_CE, 0); - -    /* Write the two instruction bytes. */ -    int8_t bit_count, byte_count; -    for(byte_count = 0; byte_count < 2; byte_count++) { - -        uint8_t miso = 0x00; -        uint8_t data = g_vendor_req_buffer[byte_count]; - -        for(bit_count = 7; bit_count >= 0; bit_count--) { -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 1); -            CyU3PGpioSetValue(GPIO_FX3_MOSI, ((data >> bit_count) & 0x01)); -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 0); - -            CyU3PGpioGetValue(GPIO_FX3_MISO, &gpio_value); -            if(gpio_value) { -                miso |= (1 << bit_count); -            } -        } - -        g_vendor_req_buffer[byte_count] = miso; -    } - -    CyU3PGpioSetValue(GPIO_FX3_MOSI, 0); - -    /* Read the response data from the chip. */ -    for(byte_count = 0; byte_count < num_bytes; byte_count++) { - -        uint8_t data = 0x00; - -        for(bit_count = 7; bit_count >= 0; bit_count--) { -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 1); - -            CyU3PGpioGetValue(GPIO_FX3_MISO, &gpio_value); -            if(gpio_value) { -                data |= (1 << bit_count); -            } - -            CyU3PGpioSetValue(GPIO_FX3_SCLK, 0); -        } - -        g_vendor_req_buffer[byte_count + 2] = data; -    } - -    CyU3PGpioSetValue(GPIO_FX3_CE, 1); -} - - -uint32_t ad9361_transact_spi(const uint32_t bits) { -    // FIXME: Could make this more sane -    if ((bits >> 23) & 0x1) -    { -        write_ad9361_reg(bits >> 8, bits & 0xff); -        return 0; -    } -    return read_ad9361_reg(bits >> 8); -} - -  /*! Stops the application, and destroys transport data structures.   *   * This function is essentially a destructor for all transport configurations. @@ -1891,22 +1663,6 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {                  break;              } -            case B200_VREQ_SPI_WRITE_AD9361: { -                CyU3PUsbGetEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer, \ -                        &read_count); - -                write_spi_to_ad9361();  // FIXME: Should have g_vendor_req_buffer & read_count passed in as args -                break; -            } - -            case B200_VREQ_SPI_READ_AD9361: { -                CyU3PUsbGetEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer, \ -                        &read_count); - -                read_spi_from_ad9361(); // FIXME: Should have g_vendor_req_buffer & read_count passed in as args -                break; -            } -              case B200_VREQ_LOOP_CODE: {                  CyU3PUsbSendEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer);                  break; @@ -2152,55 +1908,6 @@ CyBool_t usb_setup_callback(uint32_t data0, uint32_t data1) {                  break;              } -            case B200_VREQ_AD9361_CTRL_READ: { -                CyU3PUsbSendEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer); -                /* -                 * This is where vrb gets sent back to the host -                 */ -                break; -            } - -            case B200_VREQ_AD9361_CTRL_WRITE: { -                CyU3PUsbGetEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer, &read_count); -                CyU3PEventSet(&g_event_usb_config, EVENT_AD9361_XACT_INIT, CYU3P_EVENT_OR); -                 -                uint32_t event_flag; -                CyU3PEventGet(&g_event_usb_config, EVENT_AD9361_XACT_DONE, CYU3P_EVENT_AND_CLEAR, &event_flag, CYU3P_WAIT_FOREVER); -                 -                memcpy(g_vendor_req_buffer, g_ad9361_response, AD9361_DISPATCH_PACKET_SIZE); -                break; -            } -             -            case B200_VREQ_AD9361_LOOPBACK: { -                CyU3PUsbGetEP0Data(g_vendor_req_buff_size, g_vendor_req_buffer, &read_count); -                 -                if (read_count > 0) { -                    ad9361_transaction_t xact; -                    memset(&xact, 0x00, sizeof(xact)); -                     -                    xact.version = AD9361_TRANSACTION_VERSION; -                    xact.action = AD9361_ACTION_SET_CODEC_LOOP; -                    xact.sequence = 0; -                    xact.value.codec_loop = g_vendor_req_buffer[0]; -                     -                    memcpy(g_vendor_req_buffer, &xact, sizeof(xact)); -                     -                    CyU3PEventSet(&g_event_usb_config, EVENT_AD9361_XACT_INIT, CYU3P_EVENT_OR); -                     -                    uint32_t event_flag; -                    CyU3PEventGet(&g_event_usb_config, EVENT_AD9361_XACT_DONE, CYU3P_EVENT_AND_CLEAR, &event_flag, CYU3P_WAIT_FOREVER); -                     -                    memcpy(g_vendor_req_buffer, g_ad9361_response, AD9361_DISPATCH_PACKET_SIZE); -                     -                    if (xact.value.codec_loop) -                        msg("Codec loopback ON"); -                    else -                        msg("Codec loopback OFF"); -                } -                 -                break; -            } -              default:                  msg("! Unknown VREQ %02X", (uint32_t)bRequest);                  handled = CyFalse; @@ -2684,23 +2391,6 @@ void thread_main_app_entry(uint32_t input) {      }  } - -void thread_ad9361_entry(uint32_t input) { -    uint32_t event_flag; -     -    //msg("thread_ad9361_entry"); -     -    while (1) { -        if (CyU3PEventGet(&g_event_usb_config, \ -            EVENT_AD9361_XACT_INIT, CYU3P_EVENT_AND_CLEAR, \ -            &event_flag, CYU3P_WAIT_FOREVER) == CY_U3P_SUCCESS) { -            ad9361_dispatch((const char*)g_vendor_req_buffer, g_ad9361_response); -             -            CyU3PEventSet(&g_event_usb_config, EVENT_AD9361_XACT_DONE, CYU3P_EVENT_OR); -        } -    } -} -  static uint16_t g_poll_last_phy_error_count = 0, g_poll_last_link_error_count = 0;  static uint32_t g_poll_last_phy_error_status = 0; @@ -2966,7 +2656,7 @@ void thread_fpga_sb_poll_entry(uint32_t input) {   * If thread creation fails, lock the system and force a power reset.   */  void CyFxApplicationDefine(void) { -    void *app_thread_ptr, *fpga_thread_ptr, *ad9361_thread_ptr; +    void *app_thread_ptr, *fpga_thread_ptr;  #ifdef ENABLE_RE_ENUM_THREAD      void *re_enum_thread_ptr;  #endif // ENABLE_RE_ENUM_THREAD @@ -2975,9 +2665,6 @@ void CyFxApplicationDefine(void) {  #endif // ENABLE_FPGA_SB      g_counters.magic = COUNTER_MAGIC; -#ifdef ENABLE_AD9361_LOGGING -    ad9361_set_msgfn(msg); -#endif // ENABLE_AD9361_LOGGING      memset(&g_config, 0xFF, sizeof(g_config));  // Initialise to -1      CyU3PMutexCreate(&g_log_lock, CYU3P_NO_INHERIT); @@ -3032,7 +2719,6 @@ void CyFxApplicationDefine(void) {  #ifdef ENABLE_RE_ENUM_THREAD      re_enum_thread_ptr = CyU3PMemAlloc(APP_THREAD_STACK_SIZE);  #endif // ENABLE_RE_ENUM_THREAD -    ad9361_thread_ptr = CyU3PMemAlloc(APP_THREAD_STACK_SIZE);  #ifdef ENABLE_FPGA_SB      fpga_sb_poll_thread_ptr = CyU3PMemAlloc(APP_THREAD_STACK_SIZE);  #endif // ENABLE_FPGA_SB @@ -3077,18 +2763,6 @@ void CyFxApplicationDefine(void) {                                CYU3P_NO_TIME_SLICE,                                CYU3P_AUTO_START);  #endif // ENABLE_RE_ENUM_THREAD -    /* Create thread to handle AD9361 transactions */ -    if (ad9361_thread_ptr != NULL) -        CyU3PThreadCreate(&thread_ad9361, -                              "500:B200 AD9361", -                              thread_ad9361_entry, -                              0, -                              ad9361_thread_ptr, -                              APP_THREAD_STACK_SIZE, -                              THREAD_PRIORITY, -                              THREAD_PRIORITY, -                              CYU3P_NO_TIME_SLICE, -                              CYU3P_AUTO_START);  #ifdef ENABLE_FPGA_SB      /* Create thread to handling Settings Bus logging/transactions */      if (fpga_sb_poll_thread_ptr != NULL) diff --git a/firmware/fx3/b200/b200_main.h b/firmware/fx3/b200/b200_main.h index 7971c1625..1fdb74801 100644 --- a/firmware/fx3/b200/b200_main.h +++ b/firmware/fx3/b200/b200_main.h @@ -10,7 +10,7 @@  #include "cyu3types.h"  #include "cyu3usbconst.h" -#define FX3_COMPAT_MAJOR            (uint8_t)(4) +#define FX3_COMPAT_MAJOR            (uint8_t)(6)  #define FX3_COMPAT_MINOR            (uint8_t)(0)  /* GPIO Pins */ @@ -67,16 +67,11 @@  #define B200_VREQ_WRITE_SB              (uint8_t)(0x29)  #define B200_VREQ_SET_SB_BAUD_DIV       (uint8_t)(0x30)  #define B200_VREQ_FLUSH_DATA_EPS        (uint8_t)(0x31) -#define B200_VREQ_SPI_WRITE_AD9361      (uint8_t)(0x32) -#define B200_VREQ_SPI_READ_AD9361       (uint8_t)(0x42)  #define B200_VREQ_FPGA_CONFIG           (uint8_t)(0x55)  #define B200_VREQ_TOGGLE_FPGA_RESET     (uint8_t)(0x62)  #define B200_VREQ_TOGGLE_GPIF_RESET     (uint8_t)(0x72)  #define B200_VREQ_GET_USB_SPEED         (uint8_t)(0x80)  #define B200_VREQ_GET_STATUS            (uint8_t)(0x83) -#define B200_VREQ_AD9361_CTRL_WRITE     (uint8_t)(0x90) -#define B200_VREQ_AD9361_CTRL_READ      (uint8_t)(0x91) -#define B200_VREQ_AD9361_LOOPBACK       (uint8_t)(0x92)  #define B200_VREQ_RESET_DEVICE          (uint8_t)(0x99)  #define B200_VREQ_EEPROM_WRITE          (uint8_t)(0xBA)  #define B200_VREQ_EEPROM_READ           (uint8_t)(0xBB) @@ -86,8 +81,6 @@  #define EVENT_GPIO_INITB_RISE           (1 << 3)  #define EVENT_FPGA_CONFIG               (1 << 4)  #define EVENT_RE_ENUM                   (1 << 5) -#define EVENT_AD9361_XACT_INIT          (1 << 6) -#define EVENT_AD9361_XACT_DONE          (1 << 7)  /* FX3 States */ diff --git a/firmware/fx3/b200/b200_vrq.h b/firmware/fx3/b200/b200_vrq.h deleted file mode 100644 index d1f79f0ad..000000000 --- a/firmware/fx3/b200/b200_vrq.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// - -/* This file defines b200 vendor requests handlers, version 1 - */ -#ifndef B200_VRQ_H -#define B200_VRQ_H - -uint32_t ad9361_transact_spi(const uint32_t bits); - -// note: for a write instruction bit 7 from byte 0 is set to 1 -#define MAKE_AD9361_WRITE(dest, reg, val) {dest[0] = 0x80 | ((reg >> 8) & 0x3F); \ -                                           dest[1] = reg & 0xFF; \ -                                           dest[2] = val;} -#define MAKE_AD9361_READ(dest, reg) {dest[0] = (reg >> 8) & 0x3F; \ -                                                dest[1] = reg & 0xFF;} - -#endif //B200_VRQ_H - - diff --git a/firmware/fx3/b200/makefile b/firmware/fx3/b200/makefile index d693db076..22eb1bbcc 100644 --- a/firmware/fx3/b200/makefile +++ b/firmware/fx3/b200/makefile @@ -19,13 +19,9 @@ MODULE = b200_main  SOURCE += $(MODULE).c  SOURCE += b200_usb_descriptors.c -SOURCE += b200_ad9361.c  SOURCE += b200_i2c.c -INCLUDES = b200_main.h b200_vrq.h b200_gpifconfig.h b200_i2c.h -INCLUDES += ../ad9361/include/ad9361_transaction.h - -INCFLAGS = -I ../ad9361/include +INCLUDES = b200_main.h b200_gpifconfig.h b200_i2c.h  LDLIBS  += \  	"$$ARMGCC_INSTALL_PATH"/arm-none-eabi/lib/libm.a diff --git a/firmware/octoclock/.gitignore b/firmware/octoclock/.gitignore new file mode 100644 index 000000000..d6e09dedb --- /dev/null +++ b/firmware/octoclock/.gitignore @@ -0,0 +1,4 @@ +build +*.o +*.elf +*.hex diff --git a/firmware/octoclock/CMakeLists.txt b/firmware/octoclock/CMakeLists.txt new file mode 100644 index 000000000..80df0e9eb --- /dev/null +++ b/firmware/octoclock/CMakeLists.txt @@ -0,0 +1,45 @@ +# +# Copyright 2014 Ettus Research LLC +# +# 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/>. +# + +cmake_minimum_required(VERSION 2.6) +set(CMAKE_SYSTEM_NAME Generic) + +find_program(AVR_CC avr-gcc REQUIRED) +find_program(AVR_OBJCOPY avr-objcopy REQUIRED) +find_program(AVRDUDE avrdude REQUIRED) +set(CMAKE_C_COMPILER ${AVR_CC}) + +project(OCTOCLOCK C) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmcu=atmega128 -std=gnu99") + +if(NOT DEFINED PROGRAMMER) +    SET(PROGRAMMER "avrisp2") +endif(NOT DEFINED PROGRAMMER) + +if(OCTOCLOCK_DEBUG) +    message(STATUS "Debug enabled. Interrupts will be disabled.") +    add_definitions(-DDEBUG) +endif(OCTOCLOCK_DEBUG) + +include_directories( +    ${CMAKE_SOURCE_DIR}/include +    ${CMAKE_SOURCE_DIR}/../../host/lib/usrp_clock +) + +add_subdirectory(bootloader) +add_subdirectory(lib) +add_subdirectory(octoclock_r4) diff --git a/firmware/octoclock/Makefile b/firmware/octoclock/Makefile deleted file mode 100644 index acf26f617..000000000 --- a/firmware/octoclock/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright 2009 Ettus Research LLC -# -# 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/>. -# - -################################################## -# Compiler -################################################## -CC = avr-gcc -OBJCOPY = avr-objcopy -STRIP = avr-strip -OBJDUMP = avr-objdump -SREC = srec_cat -#CFLAGS = -O2 -std=gnu99 -fshort-enums -pedantic-errors -Wall -Werror \ -#	-Wstrict-prototypes -Wmissing-prototypes -Wcast-align -Wshadow -CFLAGS = -std=gnu99 -O2 - -#-D IO_DEBUG - -################################################## -# Files -################################################## -SRCS = OctoClock.c -TARGET = octoclock_fw - -################################################## -# Device -################################################## -MMCU = atmega128 -PROGRAMMER = avrisp2 -PORT = usb -AVRDUDE = avrdude -p $(MMCU) -c $(PROGRAMMER) -P $(PORT) - -################################################## -# Global Targets -################################################## -all: $(TARGET).hex - -clean: -	$(RM) *.o *.elf *.hex - -install: all -	$(AVRDUDE) -U efuse:w:0xFF:m -U hfuse:w:0x89:m -U lfuse:w:0xFF:m -U flash:w:$(TARGET).hex:i - -################################################## -# Dependency Targets -################################################## - -$(TARGET).hex: $(TARGET).elf -	$(OBJCOPY) -O ihex $< $@ - -$(TARGET).elf: $(SRCS:.c=.o) -	$(CC) -mmcu=$(MMCU) $^ -o $@ - -%.o: %.c Makefile -	$(CC) -mmcu=$(MMCU) -c $< -o $@ $(CFLAGS) diff --git a/firmware/octoclock/OctoClock.c b/firmware/octoclock/OctoClock.c deleted file mode 100644 index f73c30885..000000000 --- a/firmware/octoclock/OctoClock.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright 2013 Ettus Research LLC - * - * 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/>. - */ - -/* - * Welcome to the firmware code for the USRP Octoclock accessory product! - * - * Notes regarding this firmware: - *      NOT in M103 compatibility mode - *      no WDT - *      CKOPT full rail-to-rail - *      xtal osc - *      16K CK (16K clock cycles) - *      additional delay 65ms for Crystal Oscillator - *      slowly rising power - * - * These settings are very conservative. If a lower power oscillator is - * required, change CKOPT to '1' (UNPROGRAMMED). - * - * M103C     = [ ] - * WDTON     = [ ] - * OCDEN     = [ ] - * JTAGEN    = [X] - * SPIEN     = [X] - * EESAVE    = [ ] - * BOOTSZ    = 4096W_F000 - * BOOTRST   = [ ] - * CKOPT     = [X] - * BODLEVEL  = 2V7 - * BODEN     = [ ] - * SUT_CKSEL = EXTHIFXTALRES_16KCK_64MS - * - * EXTENDED  = 0xFF (valid) - * HIGH      = 0x89 (valid) - * LOW       = 0xFF (valid) - * - */ - -#include <stdint.h> -#include <stdbool.h> -#include <avr/io.h> -#include <avr/interrupt.h> - -#ifdef On -#undef On -#endif - -#ifdef Off -#undef Off -#endif - -#define Off     (0) -#define On      (!Off) - -#ifdef FALSE -#undef FALSE -#endif - -#ifdef TRUE -#undef TRUE -#endif - -#define FALSE   (0) -#define TRUE    (!FALSE) - - -// Important for the Serial Port, not used at the moment -#define FOSC    (7372800) -#define BAUD    (115200) - -#define MYUBRR FOSC/16/BAUD-1 - -#define wait() for(uint16_t u=14000; u; u--) asm("nop"); - -#define CLK   (PA0) // Shift by 0 bits -#define CE_   (PA1) // Is really the "Chip Disable" signal, as Hi disables SPI -#define MOSI  (PA2) -#define MISO  (PA3) -#define PD_   (PA4) -#define SYNC_ (PA5) - -// Top is 0, Mid is 1, and Bottom is 2 -enum LEDs {Top, Middle, Bottom}; - -enum TI_Input_10_MHz {Primary_GPS, Secondary_Ext}; - -enum Levels {Lo, Hi}; - -void led(enum LEDs which, int turn_it_on) { - -    // selects the proper bit -    uint8_t LED = 0x20 << which; - -    if(turn_it_on) -        PORTC |= LED; -    else -        PORTC &= ~LED; -} - -/******************************************************************************* -*   SPI routines -*******************************************************************************/ - -/* All macros evaluate to compile-time constants */ - - -/* turn a numeric literal into a hex constant - * (avoids problems with leading zeros) - * 8-bit constants max value 0x11111111, always fits in unsigned long - */ -#define HEX__(n) 0x##n##LU - -/* 8-bit conversion function */ -#define B8__(x) ((x&0x0000000FLU)?1:0) \ -    +((x&0x000000F0LU)?2:0) \ -    +((x&0x00000F00LU)?4:0) \ -    +((x&0x0000F000LU)?8:0) \ -    +((x&0x000F0000LU)?16:0) \ -    +((x&0x00F00000LU)?32:0) \ -    +((x&0x0F000000LU)?64:0) \ -    +((x&0xF0000000LU)?128:0) - -/* for up to 8-bit binary constants */ -#define Bits_8(d) ((unsigned char)B8__(HEX__(d))) - -/* for up to 16-bit binary constants, MSB first */ -#define Bits_16(dmsb,dlsb) (((unsigned short)Bits_8(dmsb)<<8) \ -    + Bits_8(dlsb)) - -/* for up to 32-bit binary constants, MSB first */ -#define Bits_32(dmsb,db2,db3,dlsb) (((unsigned long)Bits_8(dmsb)<<24) \ -    + ((unsigned long)Bits_8(db2)<<16) \ -    + ((unsigned long)Bits_8(db3)<<8) \ -    + Bits_8(dlsb)) - -/* Sample usage: - * Bits_8(01010101) = 85 - * Bits_16(10101010,01010101) = 43605 - * Bits_32(10000000,11111111,10101010,01010101) = 2164238933 - */ - -enum CDCE18005 { -        Reg0, Reg1, Reg2, Reg3, Reg4, Reg5, Reg6, Reg7, -        Reg8_Status_Control, -        Read_Command=0xE, -        RAM_EEPROM_Unlock=0x1F, -        RAM_EEPROM_Lock=0x3f -} TI_CDCE18005; - -// Table of 32-bit constants to be written to the TI chip's registers. These are -// from the "Special Settings" on Page 35 of the datasheet. -// For the GPS's 10 MHz output -uint32_t table_Pri_Ref[] = { -    Bits_32(1,01010100,0,0),    // Reg 0 -    Bits_32(1,01010100,0,0),    // Outputs LVCMOS Positive&Negative Active - Non-inverted -    Bits_32(1,01010100,0,0), -    Bits_32(1,01010100,0,0), -    Bits_32(1,01010100,0,0),    // All have output divide ratio to be 1; Aux Output is OFF -    Bits_32(0,0,1001,11010100), // Reg 5  LVCMOS in; p31 of TI datasheet -    Bits_32(1,0,0010000,0),     // Reg 6	// SCAS863A – NOVEMBER 2008 – REVISED JUNE 2011 -    Bits_32(1,01000000,0,0),    // Reg 7 -    Bits_32(0,0,1,10000000)     // Reg8  Status/Control -}; - -// For the External 10 MHz input LVDS with external termination,  -// Effectively DC coupled -uint32_t table_Sec_Ref[] = { -    Bits_32(0001,01010100,0,100000),    // Reg 0 -- use Secondary Reference for all channels -    Bits_32(0001,01010100,0,100000),    // Outputs LVCMOS Positive&Negative Active - Non-inverted -    Bits_32(0001,01010100,0,100000), -    Bits_32(0001,01010100,0,100000), -    Bits_32(0001,01010100,0,100000), -    Bits_32(0,0,1,10011011),            // Reg 5, Failsafe OFF   b5.11 = 0 -    Bits_32(1,0,10000,0),               // Reg 6; try again -    Bits_32(1,01000000,0,0), -    Bits_32(0,0,1,10000000)             // Reg8  Status/Control -}; - -// Table 19 conflicts with Tables 5 thru 9 - in how LVCMOS outputs are defined -// extra error in Table 9, for bits 24 and 25 -int table_size = sizeof (table_Pri_Ref) / sizeof(uint32_t); - -void set_bit(uint8_t  bit_number, enum Levels bit_value) { - -    if(bit_value == Hi) -        PORTA |= 1<<bit_number; -    else -        PORTA &= ~ (1<<bit_number); -} - -bool get_bit(uint8_t  bit_number) { -    asm("nop"); - -    uint8_t portA = PINA; -    return (portA &  1<< bit_number) > 0 ? TRUE : FALSE; -} - -// Send 32 bits to TI chip, LSB first. -// Don't worry about reading any bits back at this time -void send_SPI(uint32_t bits) { - -    // Basically, when the clock is low, one can set MOSI to anything, as it's -    // ignored. -    set_bit(CE_, Lo);    // Start SPI transaction with TI chip - -    // Send each bit, LSB first, add a bit of delay before the clock, and then -    // toggle the clock line. -    for (uint8_t i=0; i<32; i++) { -        set_bit(MOSI, ((bits & (1UL<<i)) ? Hi : Lo) ); -        asm("nop"); -        set_bit(CLK, Hi); -        set_bit(CLK, Lo); -    } - -    // OK, transaction is over -    set_bit(CE_, Hi); -} - -void reset_TI_CDCE18005() { -    // First, reset the chip.  Or, if you will, pull /SYNC low then high -    set_bit(CE_, Hi); -    set_bit(PD_, Lo); -    wait(); - -    // Out of Power Down state -    set_bit(PD_, Hi); -    wait(); - -    set_bit(SYNC_, Lo); -    wait(); -    set_bit(SYNC_, Hi); - -    wait(); -} - -void setup_TI_CDCE18005(enum TI_Input_10_MHz which_input) { -    // Send the table of data to init the clock distribution chip.  Uses SPI. -    uint32_t temp; - -    if(which_input == Primary_GPS) { -        for(uint8_t i=0; i<table_size; i++){ -            temp = table_Pri_Ref[i]<<4; -            temp |= i; -            send_SPI(temp); // Make sure the register's address is in the LSBs -        } -    } else { -        // is Secondary_Ext -- External 10 MHz input from SMA connector -        for(uint8_t i=0; i<table_size; i++){ -            temp = table_Sec_Ref[i]<<4; -            temp |= i; -            // Make sure the register's address is in the LSBs -            send_SPI(temp); -         } -    } -} - -uint32_t receive_SPI() { -    uint32_t bits = 0; - -    set_bit(CE_, Hi); // Make sure we're inactive -    set_bit(CLK, Lo); // and clk line is inactive, too -    set_bit(MOSI,Lo); // Make our bit output zero, for good measure -    set_bit(CE_, Lo); // Start SPI transaction with TI chip; MOSI is don't care - -    // For each bit we are receiving, prep, clock in the bit LSB first -    for (uint8_t i=0; i<32; i++){ -        bits >>= 1; -        set_bit(CLK, Hi); -        if( get_bit(MISO) ) bits |= 0x80000000; -        set_bit(CLK, Lo); -    } - -    // OK, transaction is over -    set_bit(CE_, Hi); - -    // Ditch the lower 4 bits, which only contain the address -    return (uint32_t)(bits >> 4); -} - -uint32_t get_TI_CDCE18005(enum CDCE18005 which_register){ -    uint32_t get_reg_value = 0; -    get_reg_value = (0xf0 & which_register << 4) | Read_Command; - -    // This tells the TI chip to send us the reg. value requested -    send_SPI(get_reg_value); -    return receive_SPI(); -} - -bool check_TI_CDCE18005(enum TI_Input_10_MHz which_input, -        enum CDCE18005 which_register) { - -    if(which_input == Primary_GPS){ -        uint32_t read_value = get_TI_CDCE18005(which_register); -        return read_value == table_Pri_Ref[which_register]; -    } else { -        uint32_t read_value = get_TI_CDCE18005(which_register); -        return read_value == table_Sec_Ref[which_register]; -    } -} - -void Setup_Atmel_IO_Ports() { -/* - * PORT A - * - * pin# Sig   Our Functional Name - * - * p51 PA0    CLK_CDCE    to U205 pin 24 --   L-->H edge latches MOSI and MISO in CDCE18005 - * p50 PA1    CE_CDCE    	Low = Chip Enabled for SPI comm  to U205 pin 25 - * p49 PA2    MOSI_CDCE    Goes to CDCE18005 - U205 pin 23 - * p48 PA3    MISO_CDCE    Input	Comes from U205 pin 22 - * p47 PA4    PD_CDCE    	Low = Chip is in Power-Down state; is Hi for normal operation U205 pin 12 - * p46 PA5    SYNC_CDCE    Low = Chip is sync'd with interal dividers; Hi for normal operation U205 pin 14 - * p45 PA6    PPS_SEL    	Low --> PPS_EXT selected; Hi -> PPS_GPS selected;    to U203 pin 1 - * p44 PA7    gps_lock    Input	Comes from M9107 - U206 pin 3 - * - */ - -// /pd_cdcd, /sync_code, /ce need to be 1 (disabled) to start -// all bits are outputs, except PA7 (gps_lock) and PA3 (MISO_CDCE) are inputs -PORTA = Bits_8(00110010); -DDRA =   1<<DDA6 | 1<<DDA5 | 1<<DDA4 | 1<<DDA2 | 1<<DDA1 | 1<<DDA0; - -/* - * Port B - * - * pin# Sig   Our Functional Name - * - * p10 PB0    Ethernet /SEN - * p11 PB1    Ethernet SCLK - * p12 PB2    Ethernet MOSI - * p13 PB3    Ethernet MISO - * p14 PB4    Not connected, set as output with value 0 - * p15 PB5    Ethernet /RESET  -- Set to HI for normal use, weak input - * p16 PB6    Ethernet /WOL  --- Wake on LAN -- set, weak input - * p17 PB7    Not connected, set as output with value 0 - * - */ - -PORTB = Bits_8(01100001);        // Initial Value is all zeros -DDRB = 1<<DDB2 | 1<<DDB4 | 1<<DDB7;  // MOSI is an output; the Not Connected pins are also outputs - -/* - * Port C - * - * pin# Sig   Our Functional Name - * - * p34 PC0    Not connected, set as output with value 0 - * p35 PC1    Reference Select Switch INPUT - * p36 PC2    Not connected, set as output with value 0 - * p37 PC3    Not connected, set as output with value 0 - * p38 PC4    Not connected, set as output with value 0 - * p40 PC5    "Top LED" of D103 3-stack of green LEDs - * p41 PC6    "Middle LED" - * p43 PC7    "Bottom LED" - * - */ - -PORTC = 0;        // Initial Value is all zeros -DDRC =  ~( 1<<DDC1 );     // All bits are outputs, except PC1. including the 5 Not Connected bits - -/* - * Port D - * - * pin# Sig   Our Functional Name - * - * p25 PD0    Ethernet /INT input - * p26 PD1    GPS NMEA bit, output - * p27 PD2    GPS Serial Out  (RXD; INT1)  INPUT - * p28 PD3    GPS Serial In   (TXD)        OUTPUT - * p29 PD4    GPS Present, INPUT  hi = Present - * p30 PD5    Not connected, set as output with value 0 - * p31 PD6    Not connected, set as output with value 0 - * p32 PD7    Not connected, set as output with value 0 - * - */ - -PORTD = 0;        // Initial Value is all zeros -DDRD =  1<<DDD3; - -/* - * Port E - * - * pin# Sig Dir Our Functional Name - * - * p2 PE0 In    avr_rxd (Also MOSI [PDI] when used for SPI programming of the chip) - * p3 PE1 Out   avr_txd (Also MISO [PDO] when used for SPI programming of the chip) - * p4 PE2 In    avr_cts - * p5 PE3 Out   avr_rts - * p6 PE4 In    PPS_GPS - * p7 PE5 In    PPS_EXT_n - * p8 PE6 In    Not Connected - * p9 PE7 In    Not Connected - * - */ - -PORTE = 0; -DDRE =  1<<DDE1; // make outputs, set to zero.  PE1 is usart0 TXD - -/* - * Port F - * - * Split into 2 nibbles; goes to Amp/Filter board to select ENABLE and two bits - * to select band one bit per nibble is not connected. - * - * pin Sig Dir        Our Functional Name - * - * p61 PF0 Out        J117 pin 3  (J117 pins 1 and 2 are GND) - * p60 PF1 Out        J117 pin 4 - * p59 PF2 Out        J117 pin 5 - * p58 PF3 Out        J117 pin 6 - * p57 PF4 Out        J118 pin 3  (J118 pins 1 and 2 are GND) - * p56 PF5 Out        J118 pin 4 - * p55 PF6 Out        J118 pin 5 - * p54 PF7 Out        J118 pin 6 - * - */ - -PORTF = 0;        // Initial Value is all zeros; be sure ENABLE bits are active high!!!! -DDRF =  0xff;    // All bits are outputs - -led(Middle,On); -setup_TI_CDCE18005(Primary_GPS);    // 10 MHz from Internal Source - -led(Top,On); -PORTA |= (1<<PA6);    // PPS from Internal source -} - -// NOT PRESENT unless proven so... -bool Global_GPS_Present = (bool)FALSE; -bool Global_Ext_Ref_Is_Present = (bool)FALSE; - -void LEDs_Off(){ -    led(Top,Off); -    led(Middle,Off); -    led(Bottom,Off); -} - -void Force_Internal(){ -    led(Top,On); -    led(Middle,Off); -    led(Bottom,On); - -    setup_TI_CDCE18005(Primary_GPS); - -    // Set PPS to Primary (1) n.b.:  "1" in general means "Internal" for all -    // such signals -    PORTA |= (1<<PA6); -} - -void Force_External(){ -    led(Top, Off); -    led(Middle, On); -    led(Bottom, On); - -    setup_TI_CDCE18005(Secondary_Ext); - -    // Set PPS to External -    PORTA &= ~(1<<PA6); -} - -void Prefer_Internal(){ - -    if(Global_GPS_Present) -        Force_Internal(); -    else if(Global_Ext_Ref_Is_Present) -        Force_External(); -    else -        LEDs_Off(); -} - -void Prefer_External(){ -    // if external is NOT OK, then force Internal -    if(Global_Ext_Ref_Is_Present) -        Force_External(); -    else if(Global_GPS_Present) -        Force_Internal(); -    else -        LEDs_Off(); -} - -bool Check_What_Is_Present(){ - -    // See if +5 scaled to 3.3 from GPSDO is there -    Global_GPS_Present = (PIND & (1<<DDD4)) != 0; - -    volatile uint8_t portE = PINE; -    volatile uint8_t prev, now; - -    // Get PREVIOUS state of the input -    prev = ( portE & (1 << DDE7) ?  1 : 0); - -    for(uint16_t c=1; c; c++){ -        portE = PINE; -        now = ( portE & (1 << DDE7) ?  1 : 0); - -        if(prev != now){ -            Global_Ext_Ref_Is_Present = (bool)TRUE; - -        return (bool)TRUE; -        } -    } - -  // Else, if it didn't wiggle in that time, then it didn't wiggle -  // So ext. is NOT present -  Global_Ext_Ref_Is_Present = (bool)FALSE; -  return (bool)FALSE; -} - - -bool get_Switch_State(){ -    uint8_t  portC = PINC; - -    // UP is prefer internal, -    // DOWN is prefer external -    return (bool)(portC &  (1<<DDC1) ? Off : On); -} - -/******************************************************************************* -*   Main Routine -*******************************************************************************/ - -int main(void){ - -    bool Old_Switch_State, Current_Switch_State, Old_Global_Ext_Ref_Is_Present = FALSE; - -    // Global Interrupt Disable --- enable with SEI if desired later -    asm("cli"); - -    Setup_Atmel_IO_Ports(); - -    /* -     * DO THIS FOREVER: -     * -     * get_switch_state -     * -     * if SWITCH_CHANGED: -     * -     *   if PREFER_INTERNAL: -     *     if INTERNAL_PRESENT do_internal -     *     else if EXTERNAL_PRESENT do_external -     *     else LEDs OFF -     * -     *   if PREFER_EXTERNAL: -     *     if EXTERNAL_PRESENT do_external -     *     else if INTERNAL_PRESENT do_internal -     *     else LEDs OFF -     * -     */ - -    Old_Switch_State = ! get_Switch_State(); - -    // Because down below, we use this to get state swap So we arbitrarily set -    // the PREVIOUS state to be the "other" state so that, below, we trigger -    // what happens when the switch changes This first "change" is therefore -    // artificial to keep the logic, below, cleaner -    while(TRUE) { -        // Set "Global_Ext_Ref_Is_Present" and "Global_GPS_Present" -        Check_What_Is_Present(); - -        // Off means "Prefer External" -- DOWN -        // On  means "Prefer Internal" -- UP -        Current_Switch_State = get_Switch_State(); - -        if( (Current_Switch_State != Old_Switch_State)  ||  -            (Global_Ext_Ref_Is_Present != Old_Global_Ext_Ref_Is_Present) ) { - -            Old_Switch_State = Current_Switch_State; -            Old_Global_Ext_Ref_Is_Present = Global_Ext_Ref_Is_Present; - -            if(Current_Switch_State == On) -                Prefer_Internal(); -            else -                Prefer_External(); -        } -    } -} diff --git a/firmware/octoclock/bootloader/CMakeLists.txt b/firmware/octoclock/bootloader/CMakeLists.txt new file mode 100644 index 000000000..04bcfc492 --- /dev/null +++ b/firmware/octoclock/bootloader/CMakeLists.txt @@ -0,0 +1,56 @@ +# +# Copyright 2014 Ettus Research LLC +# +# 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/>. +# +set(bootloader_sources +    ../lib/init.c +    ../lib/enc28j60.c +    ../lib/network.c +    ../lib/arp_cache.c +    main.c +) + +add_executable(octoclock_bootloader.elf ${bootloader_sources}) + +# +# The __AVR_LIBC_DEPRECATED_ENABLE__ flag is necessary because of a bug in some versions of avr-libc +# where including <avr/boot.h> when using an atmega128 will cause a compiler error. +# +# Details: http://savannah.nongnu.org/bugs/?36410 +# +set_target_properties(octoclock_bootloader.elf PROPERTIES +    COMPILE_FLAGS "${CMAKE_C_FLAGS} -Os -D__AVR_LIBC_DEPRECATED_ENABLE__ -D__BOOTLOADER__ -Wall" +    LINK_FLAGS "-Os -Wl,--relax,--section-start=.text=0x1E000,-Map=octoclock_bootloader.map,--cref" +) + + +add_custom_command( +    OUTPUT ${CMAKE_BINARY_DIR}/octoclock_bootloader.hex +    DEPENDS octoclock_bootloader.elf +    COMMENT "Generating octoclock_bootloader.hex" +    COMMAND ${AVR_OBJCOPY} -O ihex ${CMAKE_CURRENT_BINARY_DIR}/octoclock_bootloader.elf ${CMAKE_BINARY_DIR}/octoclock_bootloader.hex +) +add_custom_target( +    octoclock_bootloader_hex ALL +    DEPENDS ${CMAKE_BINARY_DIR}/octoclock_bootloader.hex +) + +add_custom_target( +    upload_bootloader +    ${AVRDUDE} -p atmega128 -c ${PROGRAMMER} -P usb -U efuse:w:0xFF:m -U hfuse:w:0x80:m -U lfuse:w:0xFF:m -U flash:w:octoclock_bootloader.hex:i +    WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +    DEPENDS octoclock_bootloader_hex +    COMMENT "Uploading OctoClock bootloader to device with ${PROGRAMMER}" +) diff --git a/firmware/octoclock/bootloader/main.c b/firmware/octoclock/bootloader/main.c new file mode 100644 index 000000000..5e2e6f17e --- /dev/null +++ b/firmware/octoclock/bootloader/main.c @@ -0,0 +1,235 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#include <avr/boot.h> +#include <avr/eeprom.h> +#include <avr/io.h> +#include <avr/pgmspace.h> + +#include <octoclock.h> +#include <debug.h> +#include <network.h> + +#include <util/delay.h> + +#include <net/enc28j60.h> + +#include "octoclock/common.h" + +/* + * The number for 5 seconds is close enough to 65535 that the + * timer may have overflowed before the main loop queries it. + */ +#define TIME_PASSED (TCNT1 > (TIMER1_ONE_SECOND*5) || (TIFR & _BV(TOV1))) + +//States +static bool received_cmd = false; +static bool done_burning = false; + +typedef struct { +    uint16_t fw_len; +    uint16_t fw_crc; +} crc_info_t; + +static crc_info_t crc_info; + +static void boot_program_page(uint8_t *buf, uint16_t page){ +    uint16_t i; + +    eeprom_busy_wait(); + +    boot_page_erase(page); +    boot_spm_busy_wait(); // Wait until the memory is erased. + +    for(i = 0; i < SPM_PAGESIZE; i += 2){ +        // Set up little-endian word. +        uint16_t w = *buf++; +        w += ((*buf++) << 8); + +        boot_page_fill(page + i, w); +    } + +    boot_page_write(page); // Store buffer in flash page. +    boot_spm_busy_wait(); // Wait until the memory is written. + +    // Reenable RWW-section again. We need this if we want to jump back +    // to the application after bootloading. +    boot_rww_enable(); +} + +static void read_firmware(uint16_t addr, octoclock_packet_t *pkt_out){ +    for(size_t i = 0; i < SPM_PAGESIZE; i++){ +        pkt_out->data[i] = pgm_read_byte(addr+i); +    } +} + +void handle_udp_query_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +){ +    const octoclock_packet_t *pkt_in = (octoclock_packet_t*)payload; + +    //Respond to query packets +    if(pkt_in->code == OCTOCLOCK_QUERY_CMD){ +        octoclock_packet_t pkt_out; +        pkt_out.proto_ver = OCTOCLOCK_BOOTLOADER_PROTO_VER; +        pkt_out.sequence = pkt_in->sequence; +        pkt_out.code = OCTOCLOCK_QUERY_ACK; +        pkt_out.len = 0; +        send_udp_pkt(OCTOCLOCK_UDP_CTRL_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t)); +    } +} + +static void calculate_crc(uint16_t *crc, uint16_t len){ +    *crc = 0xFFFF; + +    for(size_t i = 0; i < len; i++){ +        *crc ^= pgm_read_byte(i); +        for(uint8_t j = 0; j < 8; ++j){ +            if(*crc & 1) *crc = (*crc >> 1) ^ 0xA001; +            else *crc = (*crc >> 1); +        } +    } +} + +static bool valid_app(){ +    crc_info_t crc_eeprom_info; +    eeprom_read_block(&crc_eeprom_info, (void*)OCTOCLOCK_EEPROM_APP_LEN, 4); + +    calculate_crc(&(crc_info.fw_crc), crc_eeprom_info.fw_len); +    return (crc_info.fw_crc == crc_eeprom_info.fw_crc); +} + +void handle_udp_fw_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +){ +    octoclock_packet_t *pkt_in = (octoclock_packet_t*)payload; +    octoclock_packet_t pkt_out; +    pkt_out.proto_ver = OCTOCLOCK_BOOTLOADER_PROTO_VER; +    pkt_out.sequence = pkt_in->sequence; +    pkt_out.len = 0; + +    switch(pkt_in->code){ +        case PREPARE_FW_BURN_CMD: +            received_cmd = true; +            done_burning = false; +            crc_info.fw_len = pkt_in->len; +            pkt_out.code = FW_BURN_READY_ACK; +            break; + +        case FILE_TRANSFER_CMD: +            boot_program_page(pkt_in->data, pkt_in->addr); +            pkt_out.code = FILE_TRANSFER_ACK; +            break; + +        case READ_FW_CMD: +            pkt_out.code = READ_FW_ACK; +            read_firmware(pkt_in->addr, &pkt_out); +            break; + +        case FINALIZE_BURNING_CMD: +            //With stuff verified, burn CRC info into EEPROM +            done_burning = true; +            calculate_crc(&(crc_info.fw_crc), crc_info.fw_len); +            eeprom_write_block(&crc_info, (void*)OCTOCLOCK_EEPROM_APP_LEN, 4); +            pkt_out.code = FINALIZE_BURNING_ACK; +            break; + +        default: +            break; +    } +    send_udp_pkt(OCTOCLOCK_UDP_FW_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t)); +} + +void handle_udp_eeprom_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +){ +    octoclock_packet_t *pkt_in = (octoclock_packet_t*)payload; +    octoclock_packet_t pkt_out; +    pkt_out.proto_ver = OCTOCLOCK_BOOTLOADER_PROTO_VER; +    pkt_out.sequence = pkt_in->sequence; +    pkt_out.len = 0; + +    if(pkt_in->proto_ver == OCTOCLOCK_FW_COMPAT_NUM){ +        switch(pkt_in->code){ +            case CLEAR_EEPROM_CMD: +                received_cmd = true; +                uint8_t blank_eeprom[103]; +                memset(blank_eeprom, 0xFF, 103); +                eeprom_write_block(blank_eeprom, 0, 103); +                pkt_out.code = CLEAR_EEPROM_ACK; +                send_udp_pkt(OCTOCLOCK_UDP_EEPROM_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t)); +                break; + +            default: +                break; +        } +    } +} + +int main(void){ + +    asm("cli"); + +    //Initialization +    setup_atmel_io_ports(); +    network_init(); +    init_udp_listeners(); +    register_udp_listener(OCTOCLOCK_UDP_CTRL_PORT, handle_udp_query_packet); +    register_udp_listener(OCTOCLOCK_UDP_FW_PORT, handle_udp_fw_packet); +    register_udp_listener(OCTOCLOCK_UDP_EEPROM_PORT, handle_udp_eeprom_packet); + +    //Turn LED's on to show we're in the bootloader +    PORTC |= 0x20; +    PORTC |= (0x20<<1); +    PORTC |= (0x20<<2); + +    TIMER1_INIT(); +    bool app_checked = false; + +    while(true){ +        if(done_burning){ +            if(valid_app()) break; +            else done_burning = false; //Burning somehow failed and wasn't caught +        } +        if(!app_checked && !received_cmd && TIME_PASSED){ +            app_checked = true; +            if(valid_app()) break; +        } + +        network_check(); +    } + +    //Turn LED's off before moving to application +    PORTC &= ~0x20; +    PORTC &= ~(0x20<<1); +    PORTC &= ~(0x20<<2); + +    /* +     * Whether the bootloader reaches here through five seconds of inactivity +     * or after a firmware burn just finished, it can be assumed that the application +     * is valid. +     */ +    asm("jmp 0000"); +    return 0; //Will never get here, but AVR-GCC needs it +} diff --git a/firmware/octoclock/include/arch/cc.h b/firmware/octoclock/include/arch/cc.h new file mode 100644 index 000000000..d8d53ecf8 --- /dev/null +++ b/firmware/octoclock/include/arch/cc.h @@ -0,0 +1,65 @@ +#ifndef INCLUDED_ARCH_CC_H +#define INCLUDED_ARCH_CC_H + +#define BYTE_ORDER BIG_ENDIAN + + +#if 1 +#include <stdint.h> + +typedef uint8_t    u8_t; +typedef int8_t     s8_t; +typedef uint16_t   u16_t; +typedef int16_t    s16_t; +typedef uint32_t   u32_t; +typedef int32_t    s32_t; + +#else + +typedef unsigned   char    u8_t; +typedef signed     char    s8_t; +typedef unsigned   short   u16_t; +typedef signed     short   s16_t; +typedef unsigned   long    u32_t; +typedef signed     long    s32_t; +#endif + +typedef u32_t mem_ptr_t; + +#if 1   /* minimal printf */ +#define U16_F "u" +#define S16_F "d" +#define X16_F "x" +#define U32_F "u" +#define S32_F "d" +#define X32_F "x" + +#else + +#define U16_F "hu" +#define S16_F "hd" +#define X16_F "hx" +#define U32_F "lu" +#define S32_F "ld" +#define X32_F "lx" +#endif + +#if 1	// gcc: don't pack +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#else	// gcc: do pack +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#endif + +//#define LWIP_PLATFORM_ASSERT(msg) ((void)0) +void abort(void); +#define LWIP_PLATFORM_ASSERT(msg) abort() + + +#endif /* INCLUDED_ARCH_CC_H */ + diff --git a/firmware/octoclock/include/arch/perf.h b/firmware/octoclock/include/arch/perf.h new file mode 100644 index 000000000..f0906d03f --- /dev/null +++ b/firmware/octoclock/include/arch/perf.h @@ -0,0 +1,2 @@ +#define PERF_START     ((void) 0) +#define PERF_STOP(msg) ((void) 0) diff --git a/firmware/octoclock/include/avrlibdefs.h b/firmware/octoclock/include/avrlibdefs.h new file mode 100644 index 000000000..7f0cc0adc --- /dev/null +++ b/firmware/octoclock/include/avrlibdefs.h @@ -0,0 +1,72 @@ +/*! \file avrlibdefs.h \brief AVRlib global defines and macros. */ +//***************************************************************************** +// +// File Name	: 'avrlibdefs.h' +// Title		: AVRlib global defines and macros include file +// Author		: Pascal Stang +// Created		: 7/12/2001 +// Revised		: 9/30/2002 +// Version		: 1.1 +// Target MCU	: Atmel AVR series +// Editor Tabs	: 4 +// +//	Description : This include file is designed to contain items useful to all +//					code files and projects, regardless of specific implementation. +// +// This code is distributed under the GNU Public License +//		which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + + +#ifndef AVRLIBDEFS_H +#define AVRLIBDEFS_H + +// Code compatibility to new AVR-libc +// outb(), inb(), inw(), outw(), BV(), sbi(), cbi(), sei(), cli() +#ifndef outb +	#define	outb(addr, data)	addr = (data) +#endif +#ifndef inb +	#define	inb(addr)			(addr) +#endif +#ifndef outw +	#define	outw(addr, data)	addr = (data) +#endif +#ifndef inw +	#define	inw(addr)			(addr) +#endif +#ifndef BV +	#define BV(bit)			(1<<(bit)) +#endif +#ifndef cbi +	#define cbi(reg,bit)	reg &= ~(BV(bit)) +#endif +#ifndef sbi +	#define sbi(reg,bit)	reg |= (BV(bit)) +#endif +#ifndef cli +	#define cli()			__asm__ __volatile__ ("cli" ::) +#endif +#ifndef sei +	#define sei()			__asm__ __volatile__ ("sei" ::) +#endif + +// use this for packed structures +// (this is seldom necessary on an 8-bit architecture like AVR, +//  but can assist in code portability to AVR) +#define GNUC_PACKED __attribute__((packed))  + +// port address helpers +#define DDR(x) ((x)-1)    // address of data direction register of port x +#define PIN(x) ((x)-2)    // address of input register of port x + +// MIN/MAX/ABS macros +#define MIN(a,b)			((a<b)?(a):(b)) +#define MAX(a,b)			((a>b)?(a):(b)) +#define ABS(x)				((x>0)?(x):(-x)) + +// constants +#define PI		3.14159265359 + +#endif diff --git a/firmware/octoclock/include/avrlibtypes.h b/firmware/octoclock/include/avrlibtypes.h new file mode 100644 index 000000000..4351c8ea8 --- /dev/null +++ b/firmware/octoclock/include/avrlibtypes.h @@ -0,0 +1,73 @@ +/*! \file avrlibtypes.h \brief AVRlib global types and typedefines. */ +//***************************************************************************** +// +// File Name	: 'avrlibtypes.h' +// Title		: AVRlib global types and typedefines include file +// Author		: Pascal Stang +// Created		: 7/12/2001 +// Revised		: 9/30/2002 +// Version		: 1.0 +// Target MCU	: Atmel AVR series +// Editor Tabs	: 4 +// +//	Description : Type-defines required and used by AVRlib.  Most types are also +//						generally useful. +// +// This code is distributed under the GNU Public License +//		which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + + +#ifndef AVRLIBTYPES_H +#define AVRLIBTYPES_H + +#ifndef WIN32 +	// true/false defines +	#define FALSE	0 +	#define TRUE	-1 +#endif + +// datatype definitions macros +typedef unsigned char  u08; +typedef   signed char  s08; +typedef unsigned short u16; +typedef   signed short s16; +typedef unsigned long  u32; +typedef   signed long  s32; +typedef unsigned long long u64; +typedef   signed long long s64; + +// maximum value that can be held +// by unsigned data types (8,16,32bits) +#define MAX_U08	255 +#define MAX_U16	65535 +#define MAX_U32	4294967295 + +// maximum values that can be held +// by signed data types (8,16,32bits) +#define MIN_S08	-128 +#define MAX_S08	127 +#define MIN_S16	-32768 +#define MAX_S16	32767 +#define MIN_S32	-2147483648 +#define MAX_S32	2147483647 + +#ifndef WIN32 +	// more type redefinitions +	typedef unsigned char   BOOL; +	typedef unsigned char	BYTE; +	typedef unsigned int	WORD; +	typedef unsigned long	DWORD; + +	typedef unsigned char	UCHAR; +	typedef unsigned int	UINT; +	typedef unsigned short  USHORT; +	typedef unsigned long	ULONG; + +	typedef char			CHAR; +	typedef int				INT; +	typedef long			LONG; +#endif + +#endif diff --git a/firmware/octoclock/include/clkdist.h b/firmware/octoclock/include/clkdist.h new file mode 100644 index 000000000..633df9ddf --- /dev/null +++ b/firmware/octoclock/include/clkdist.h @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _CLKDIST_H_ +#define _CLKDIST_H_ + +#include <stdbool.h> + +#include <octoclock.h> + +typedef enum { +    Reg0, Reg1, Reg2, Reg3, Reg4, Reg5, Reg6, Reg7, +    Reg8_Status_Control, +    Read_Command=0xE, +    RAM_EEPROM_Unlock=0x1F, +    RAM_EEPROM_Lock=0x3f +} CDCE18005; + +typedef enum { +    Primary_GPS, +    Secondary_Ext +} TI_Input_10_MHz; + +typedef enum { +    Lo, +    Hi +} Levels; + +void setup_TI_CDCE18005(TI_Input_10_MHz which_input); + +void reset_TI_CDCE18005(void); + +uint32_t get_TI_CDCE18005(CDCE18005 which_register); + +bool check_TI_CDCE18005(TI_Input_10_MHz which_input, CDCE18005 which_register); + +#endif /* _CLKDIST_H_ */ diff --git a/firmware/octoclock/include/compiler.h b/firmware/octoclock/include/compiler.h new file mode 100644 index 000000000..542c83568 --- /dev/null +++ b/firmware/octoclock/include/compiler.h @@ -0,0 +1,24 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009, 2010, 2014 Ettus Research LLC + * + * 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/>. + */ +#ifndef INCLUDED_COMPILER_H +#define INCLUDED_COMPILER_H + +#define _AL2   __attribute__((aligned (2))) +#define _AL4   __attribute__((aligned (4))) + +#endif /* INCLUDED_COMPILER_H */ diff --git a/firmware/octoclock/include/debug.h b/firmware/octoclock/include/debug.h new file mode 100644 index 000000000..ee0618bc6 --- /dev/null +++ b/firmware/octoclock/include/debug.h @@ -0,0 +1,94 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +//Only expose these macros to the firmware, and only if specified +#if defined(DEBUG) && !defined(__BOOTLOADER__) + +#include <avr/pgmspace.h> +#include <stdbool.h> +#include <stdint.h> + +#include <serial.h> + +#define DEBUG_INIT() serial_init(&PORTF, 0) +#define DEBUG_LOG(msg) serial_tx_P(PSTR(msg), &PORTF, 0, true) +#define DEBUG_LOG_NNL(msg) serial_tx_P(PSTR(msg), &PORTF, 0, false) +#define DEBUG_LOG_BYTE(byte) serial_tx_byte(byte, &PORTF, 0, true) +#define DEBUG_LOG_BYTE_NNL(byte) serial_tx_byte(byte, &PORTF, 0, false) +#define DEBUG_LOG_HEX(byte) serial_tx_hex(byte, &PORTF, 0, true) +#define DEBUG_LOG_HEX_NNL(byte) serial_tx_hex(byte, &PORTF, 0, false) + +#define DEBUG_LOG_CHAR_ARR_NNL(arr,len) for(uint8_t i = 0; i < len; i++){ \ +                                            DEBUG_LOG_BYTE_NNL(arr[i]); \ +                                            DEBUG_LOG_NNL(" "); \ +                                        } +#define DEBUG_LOG_CHAR_ARR(arr,len) DEBUG_LOG_CHAR_ARR_NNL(arr,len); \ +                                    DEBUG_LOG(" ") + +#define DEBUG_LOG_MAC(mac_addr) DEBUG_LOG_HEX_NNL(mac_addr[0]); \ +                                DEBUG_LOG_NNL(":"); \ +                                DEBUG_LOG_HEX_NNL(mac_addr[1]); \ +                                DEBUG_LOG_NNL(":"); \ +                                DEBUG_LOG_HEX_NNL(mac_addr[2]); \ +                                DEBUG_LOG_NNL(":"); \ +                                DEBUG_LOG_HEX_NNL(mac_addr[3]); \ +                                DEBUG_LOG_NNL(":"); \ +                                DEBUG_LOG_HEX_NNL(mac_addr[4]); \ +                                DEBUG_LOG_NNL(":"); \ +                                DEBUG_LOG_HEX(mac_addr[5]); + +#define DEBUG_LOG_IP(ip_addr) DEBUG_LOG_BYTE_NNL(ip4_addr1(&ip_addr)); \ +                              DEBUG_LOG_NNL("."); \ +                              DEBUG_LOG_BYTE_NNL(ip4_addr2(&ip_addr)); \ +                              DEBUG_LOG_NNL("."); \ +                              DEBUG_LOG_BYTE_NNL(ip4_addr3(&ip_addr)); \ +                              DEBUG_LOG_NNL("."); \ +                              DEBUG_LOG_BYTE(ip4_addr4(&ip_addr)); + +#define DEBUG_LOG_SHORT(num) DEBUG_LOG_HEX_NNL(((uint8_t*)&num)[1]); \ +                             DEBUG_LOG_HEX(((uint8_t*)&num)[0]); + +#define DEBUG_LOG_INT(num) DEBUG_LOG_HEX_NNL(((uint8_t*)&num)[3]); \ +                           DEBUG_LOG_HEX(((uint8_t*)&num)[2]); \ +                           DEBUG_LOG_HEX(((uint8_t*)&num)[1]); \ +                           DEBUG_LOG_HEX(((uint8_t*)&num)[0]); + +#else + +#define DEBUG_INIT() +#define DEBUG_LOG(msg) +#define DEBUG_LOG_NNL(msg) +#define DEBUG_LOG_CHAR(byte) +#define DEBUG_LOG_CHAR_NNL(byte) +#define DEBUG_LOG_BYTE(byte) +#define DEBUG_LOG_BYTE_NNL(byte) +#define DEBUG_LOG_HEX(byte) +#define DEBUG_LOG_HEX_NNL(byte) +#define DEBUG_LOG_CHAR_ARR(arr,len) +#define DEBUG_LOG_CHAR_ARR_NNL(arr,len) + +#define DEBUG_LOG_MAC(mac_addr) +#define DEBUG_LOG_IP(ip_addr) +#define DEBUG_LOG_SHORT(num) +#define DEBUG_LOG_INT(num) + +#endif + +#endif /* _DEBUG_H_ */ diff --git a/firmware/octoclock/include/gpsdo.h b/firmware/octoclock/include/gpsdo.h new file mode 100644 index 000000000..fc7d87324 --- /dev/null +++ b/firmware/octoclock/include/gpsdo.h @@ -0,0 +1,32 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _GPSDO_H_ +#define _GPSDO_H_ + +#include <stdint.h> + +#define POOLSIZE 256 + +char gpsdo_buf[POOLSIZE]; +gpsdo_cache_state_t gpsdo_state; + +void send_gpsdo_cmd(char* buf, uint8_t size); + +void process_gpsdo_output(void); + +#endif /* _GPSDO_H_ */ diff --git a/firmware/octoclock/include/lwip/COPYING b/firmware/octoclock/include/lwip/COPYING new file mode 100644 index 000000000..e23898b5e --- /dev/null +++ b/firmware/octoclock/include/lwip/COPYING @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ + + diff --git a/firmware/octoclock/include/lwip/api.h b/firmware/octoclock/include/lwip/api.h new file mode 100644 index 000000000..f6b1f7434 --- /dev/null +++ b/firmware/octoclock/include/lwip/api.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_API_H__ +#define __LWIP_API_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include <stddef.h> /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY   0x01 +#define NETCONN_MORE   0x02 + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t)    (t&0xF0) +#define NETCONNTYPE_DATAGRAM(t) (t&0xE0) + +enum netconn_type { +  NETCONN_INVALID    = 0, +  /* NETCONN_TCP Group */ +  NETCONN_TCP        = 0x10, +  /* NETCONN_UDP Group */ +  NETCONN_UDP        = 0x20, +  NETCONN_UDPLITE    = 0x21, +  NETCONN_UDPNOCHKSUM= 0x22, +  /* NETCONN_RAW Group */ +  NETCONN_RAW        = 0x40 +}; + +enum netconn_state { +  NETCONN_NONE, +  NETCONN_WRITE, +  NETCONN_LISTEN, +  NETCONN_CONNECT, +  NETCONN_CLOSE +}; + +enum netconn_evt { +  NETCONN_EVT_RCVPLUS, +  NETCONN_EVT_RCVMINUS, +  NETCONN_EVT_SENDPLUS, +  NETCONN_EVT_SENDMINUS +}; + +#if LWIP_IGMP +enum netconn_igmp { +  NETCONN_JOIN, +  NETCONN_LEAVE +}; +#endif /* LWIP_IGMP */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { +  /** type of the netconn (TCP, UDP or RAW) */ +  enum netconn_type type; +  /** current state of the netconn */ +  enum netconn_state state; +  /** the lwIP internal protocol control block */ +  union { +    struct ip_pcb  *ip; +    struct tcp_pcb *tcp; +    struct udp_pcb *udp; +    struct raw_pcb *raw; +  } pcb; +  /** the last error this netconn had */ +  err_t err; +  /** sem that is used to synchroneously execute functions in the core context */ +  sys_sem_t op_completed; +  /** mbox where received packets are stored until they are fetched +      by the netconn application thread (can grow quite big) */ +  sys_mbox_t recvmbox; +  /** mbox where new connections are stored until processed +      by the application thread */ +  sys_mbox_t acceptmbox; +  /** only used for socket layer */ +  int socket; +#if LWIP_SO_RCVTIMEO +  /** timeout to wait for new data to be received +      (or connections to arrive for listening netconns) */ +  int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +  /** maximum amount of bytes queued in recvmbox */ +  int recv_bufsize; +#endif /* LWIP_SO_RCVBUF */ +  s16_t recv_avail; +#if LWIP_TCP +  /** TCP: when data passed to netconn_write doesn't fit into the send buffer, +      this temporarily stores the message. */ +  struct api_msg_msg *write_msg; +  /** TCP: when data passed to netconn_write doesn't fit into the send buffer, +      this temporarily stores how much is already sent. */ +  size_t write_offset; +#if LWIP_TCPIP_CORE_LOCKING +  /** TCP: when data passed to netconn_write doesn't fit into the send buffer, +      this temporarily stores whether to wake up the original application task +      if data couldn't be sent in the first try. */ +  u8_t write_delayed; +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_TCP */ +  /** A callback function that is informed about events for this netconn */ +  netconn_callback callback; +}; + +/* Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) {         \ +                           (*c->callback)(c, e, l); \ +                         } + +/* Network connection functions: */ +#define netconn_new(t)                  netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct +netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, +                                   netconn_callback callback); +err_t             netconn_delete  (struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t             netconn_getaddr (struct netconn *conn, +                                   struct ip_addr *addr, +                                   u16_t *port, +                                   u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t             netconn_bind    (struct netconn *conn, +                                   struct ip_addr *addr, +                                   u16_t port); +err_t             netconn_connect (struct netconn *conn, +                                   struct ip_addr *addr, +                                   u16_t port); +err_t             netconn_disconnect (struct netconn *conn); +err_t             netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +struct netconn *  netconn_accept  (struct netconn *conn); +struct netbuf *   netconn_recv    (struct netconn *conn); +err_t             netconn_sendto  (struct netconn *conn, +                                   struct netbuf *buf, struct ip_addr *addr, u16_t port); +err_t             netconn_send    (struct netconn *conn, +                                   struct netbuf *buf); +err_t             netconn_write   (struct netconn *conn, +                                   const void *dataptr, size_t size, +                                   u8_t apiflags); +err_t             netconn_close   (struct netconn *conn); + +#if LWIP_IGMP +err_t             netconn_join_leave_group (struct netconn *conn, +                                            struct ip_addr *multiaddr, +                                            struct ip_addr *interface, +                                            enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP */ +#if LWIP_DNS +err_t             netconn_gethostbyname(const char *name, struct ip_addr *addr); +#endif /* LWIP_DNS */ + +#define netconn_err(conn)          ((conn)->err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_H__ */ diff --git a/firmware/octoclock/include/lwip/api_msg.h b/firmware/octoclock/include/lwip/api_msg.h new file mode 100644 index 000000000..4272d77cc --- /dev/null +++ b/firmware/octoclock/include/lwip/api_msg.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include <stddef.h> /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function +    for a netconn in another thread context (mainly used to process netconns +    in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { +  /** The netconn which to process - always needed: it includes the semaphore +      which is used to block the application thread until the function finished. */ +  struct netconn *conn; +  /** Depending on the executed function, one of these union members is used */ +  union { +    /** used for do_send */ +    struct netbuf *b; +    /** used for do_newconn */ +    struct { +      u8_t proto; +    } n; +    /** used for do_bind and do_connect */ +    struct { +      struct ip_addr *ipaddr; +      u16_t port; +    } bc; +    /** used for do_getaddr */ +    struct { +      struct ip_addr *ipaddr; +      u16_t *port; +      u8_t local; +    } ad; +    /** used for do_write */ +    struct { +      const void *dataptr; +      size_t len; +      u8_t apiflags; +    } w; +    /** used ofr do_recv */ +    struct { +      u16_t len; +    } r; +#if LWIP_IGMP +    /** used for do_join_leave_group */ +    struct { +      struct ip_addr *multiaddr; +      struct ip_addr *interface; +      enum netconn_igmp join_or_leave; +    } jl; +#endif /* LWIP_IGMP */ +#if TCP_LISTEN_BACKLOG +    struct { +      u8_t backlog; +    } lb; +#endif /* TCP_LISTEN_BACKLOG */ +  } msg; +}; + +/** This struct contains a function to execute in another thread context and +    a struct api_msg_msg that serves as an argument for this function. +    This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { +  /** function to execute in tcpip_thread context */ +  void (* function)(struct api_msg_msg *msg); +  /** arguments for this function */ +  struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As do_gethostbyname requires more arguments but doesn't require a netconn, +    it has its own struct (to avoid struct api_msg getting bigger than necessary). +    do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg +    (see netconn_gethostbyname). */ +struct dns_api_msg { +  /** Hostname to query or dotted IP address string */ +  const char *name; +  /** Rhe resolved address is stored here */ +  struct ip_addr *addr; +  /** This semaphore is posted when the name is resolved, the application thread +      should wait on it. */ +  sys_sem_t sem; +  /** Errors are given back here */ +  err_t *err; +}; +#endif /* LWIP_DNS */ + +void do_newconn         ( struct api_msg_msg *msg); +void do_delconn         ( struct api_msg_msg *msg); +void do_bind            ( struct api_msg_msg *msg); +void do_connect         ( struct api_msg_msg *msg); +void do_disconnect      ( struct api_msg_msg *msg); +void do_listen          ( struct api_msg_msg *msg); +void do_send            ( struct api_msg_msg *msg); +void do_recv            ( struct api_msg_msg *msg); +void do_write           ( struct api_msg_msg *msg); +void do_getaddr         ( struct api_msg_msg *msg); +void do_close           ( struct api_msg_msg *msg); +#if LWIP_IGMP +void do_join_leave_group( struct api_msg_msg *msg); +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +void do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/firmware/octoclock/include/lwip/arch.h b/firmware/octoclock/include/lwip/arch.h new file mode 100644 index 000000000..3a5a0e4f2 --- /dev/null +++ b/firmware/octoclock/include/lwip/arch.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_ARCH_H__ +#define __LWIP_ARCH_H__ + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */  + + +#ifdef LWIP_PROVIDE_ERRNO + +#define  EPERM     1  /* Operation not permitted */ +#define  ENOENT     2  /* No such file or directory */ +#define  ESRCH     3  /* No such process */ +#define  EINTR     4  /* Interrupted system call */ +#define  EIO     5  /* I/O error */ +#define  ENXIO     6  /* No such device or address */ +#define  E2BIG     7  /* Arg list too long */ +#define  ENOEXEC     8  /* Exec format error */ +#define  EBADF     9  /* Bad file number */ +#define  ECHILD    10  /* No child processes */ +#define  EAGAIN    11  /* Try again */ +#define  ENOMEM    12  /* Out of memory */ +#define  EACCES    13  /* Permission denied */ +#define  EFAULT    14  /* Bad address */ +#define  ENOTBLK    15  /* Block device required */ +#define  EBUSY    16  /* Device or resource busy */ +#define  EEXIST    17  /* File exists */ +#define  EXDEV    18  /* Cross-device link */ +#define  ENODEV    19  /* No such device */ +#define  ENOTDIR    20  /* Not a directory */ +#define  EISDIR    21  /* Is a directory */ +#define  EINVAL    22  /* Invalid argument */ +#define  ENFILE    23  /* File table overflow */ +#define  EMFILE    24  /* Too many open files */ +#define  ENOTTY    25  /* Not a typewriter */ +#define  ETXTBSY    26  /* Text file busy */ +#define  EFBIG    27  /* File too large */ +#define  ENOSPC    28  /* No space left on device */ +#define  ESPIPE    29  /* Illegal seek */ +#define  EROFS    30  /* Read-only file system */ +#define  EMLINK    31  /* Too many links */ +#define  EPIPE    32  /* Broken pipe */ +#define  EDOM    33  /* Math argument out of domain of func */ +#define  ERANGE    34  /* Math result not representable */ +#define  EDEADLK    35  /* Resource deadlock would occur */ +#define  ENAMETOOLONG  36  /* File name too long */ +#define  ENOLCK    37  /* No record locks available */ +#define  ENOSYS    38  /* Function not implemented */ +#define  ENOTEMPTY  39  /* Directory not empty */ +#define  ELOOP    40  /* Too many symbolic links encountered */ +#define  EWOULDBLOCK  EAGAIN  /* Operation would block */ +#define  ENOMSG    42  /* No message of desired type */ +#define  EIDRM    43  /* Identifier removed */ +#define  ECHRNG    44  /* Channel number out of range */ +#define  EL2NSYNC  45  /* Level 2 not synchronized */ +#define  EL3HLT    46  /* Level 3 halted */ +#define  EL3RST    47  /* Level 3 reset */ +#define  ELNRNG    48  /* Link number out of range */ +#define  EUNATCH    49  /* Protocol driver not attached */ +#define  ENOCSI    50  /* No CSI structure available */ +#define  EL2HLT    51  /* Level 2 halted */ +#define  EBADE    52  /* Invalid exchange */ +#define  EBADR    53  /* Invalid request descriptor */ +#define  EXFULL    54  /* Exchange full */ +#define  ENOANO    55  /* No anode */ +#define  EBADRQC    56  /* Invalid request code */ +#define  EBADSLT    57  /* Invalid slot */ + +#define  EDEADLOCK  EDEADLK + +#define  EBFONT    59  /* Bad font file format */ +#define  ENOSTR    60  /* Device not a stream */ +#define  ENODATA    61  /* No data available */ +#define  ETIME    62  /* Timer expired */ +#define  ENOSR    63  /* Out of streams resources */ +#define  ENONET    64  /* Machine is not on the network */ +#define  ENOPKG    65  /* Package not installed */ +#define  EREMOTE    66  /* Object is remote */ +#define  ENOLINK    67  /* Link has been severed */ +#define  EADV    68  /* Advertise error */ +#define  ESRMNT    69  /* Srmount error */ +#define  ECOMM    70  /* Communication error on send */ +#define  EPROTO    71  /* Protocol error */ +#define  EMULTIHOP  72  /* Multihop attempted */ +#define  EDOTDOT    73  /* RFS specific error */ +#define  EBADMSG    74  /* Not a data message */ +#define  EOVERFLOW  75  /* Value too large for defined data type */ +#define  ENOTUNIQ  76  /* Name not unique on network */ +#define  EBADFD    77  /* File descriptor in bad state */ +#define  EREMCHG    78  /* Remote address changed */ +#define  ELIBACC    79  /* Can not access a needed shared library */ +#define  ELIBBAD    80  /* Accessing a corrupted shared library */ +#define  ELIBSCN    81  /* .lib section in a.out corrupted */ +#define  ELIBMAX    82  /* Attempting to link in too many shared libraries */ +#define  ELIBEXEC  83  /* Cannot exec a shared library directly */ +#define  EILSEQ    84  /* Illegal byte sequence */ +#define  ERESTART  85  /* Interrupted system call should be restarted */ +#define  ESTRPIPE  86  /* Streams pipe error */ +#define  EUSERS    87  /* Too many users */ +#define  ENOTSOCK  88  /* Socket operation on non-socket */ +#define  EDESTADDRREQ  89  /* Destination address required */ +#define  EMSGSIZE  90  /* Message too long */ +#define  EPROTOTYPE  91  /* Protocol wrong type for socket */ +#define  ENOPROTOOPT  92  /* Protocol not available */ +#define  EPROTONOSUPPORT  93  /* Protocol not supported */ +#define  ESOCKTNOSUPPORT  94  /* Socket type not supported */ +#define  EOPNOTSUPP  95  /* Operation not supported on transport endpoint */ +#define  EPFNOSUPPORT  96  /* Protocol family not supported */ +#define  EAFNOSUPPORT  97  /* Address family not supported by protocol */ +#define  EADDRINUSE  98  /* Address already in use */ +#define  EADDRNOTAVAIL  99  /* Cannot assign requested address */ +#define  ENETDOWN  100  /* Network is down */ +#define  ENETUNREACH  101  /* Network is unreachable */ +#define  ENETRESET  102  /* Network dropped connection because of reset */ +#define  ECONNABORTED  103  /* Software caused connection abort */ +#define  ECONNRESET  104  /* Connection reset by peer */ +#define  ENOBUFS    105  /* No buffer space available */ +#define  EISCONN    106  /* Transport endpoint is already connected */ +#define  ENOTCONN  107  /* Transport endpoint is not connected */ +#define  ESHUTDOWN  108  /* Cannot send after transport endpoint shutdown */ +#define  ETOOMANYREFS  109  /* Too many references: cannot splice */ +#define  ETIMEDOUT  110  /* Connection timed out */ +#define  ECONNREFUSED  111  /* Connection refused */ +#define  EHOSTDOWN  112  /* Host is down */ +#define  EHOSTUNREACH  113  /* No route to host */ +#define  EALREADY  114  /* Operation already in progress */ +#define  EINPROGRESS  115  /* Operation now in progress */ +#define  ESTALE    116  /* Stale NFS file handle */ +#define  EUCLEAN    117  /* Structure needs cleaning */ +#define  ENOTNAM    118  /* Not a XENIX named type file */ +#define  ENAVAIL    119  /* No XENIX semaphores available */ +#define  EISNAM    120  /* Is a named type file */ +#define  EREMOTEIO  121  /* Remote I/O error */ +#define  EDQUOT    122  /* Quota exceeded */ + +#define  ENOMEDIUM  123  /* No medium found */ +#define  EMEDIUMTYPE  124  /* Wrong medium type */ + + +#define ENSROK    0 /* DNS server returned answer with no data */ +#define ENSRNODATA  160 /* DNS server returned answer with no data */ +#define ENSRFORMERR 161 /* DNS server claims query was misformatted */ +#define ENSRSERVFAIL 162  /* DNS server returned general failure */ +#define ENSRNOTFOUND 163  /* Domain name not found */ +#define ENSRNOTIMP  164 /* DNS server does not implement requested operation */ +#define ENSRREFUSED 165 /* DNS server refused query */ +#define ENSRBADQUERY 166  /* Misformatted DNS query */ +#define ENSRBADNAME 167 /* Misformatted domain name */ +#define ENSRBADFAMILY 168 /* Unsupported address family */ +#define ENSRBADRESP 169 /* Misformatted DNS reply */ +#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */ +#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */ +#define ENSROF    172 /* End of file */ +#define ENSRFILE  173 /* Error reading file */ +#define ENSRNOMEM 174 /* Out of memory */ +#define ENSRDESTRUCTION 175 /* Application terminated lookup */ +#define ENSRQUERYDOMAINTOOLONG  176 /* Domain name is too long */ +#define ENSRCNAMELOOP 177 /* Domain name is too long */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ARCH_H__ */ diff --git a/firmware/octoclock/include/lwip/autoip.h b/firmware/octoclock/include/lwip/autoip.h new file mode 100644 index 000000000..076a2ed23 --- /dev/null +++ b/firmware/octoclock/include/lwip/autoip.h @@ -0,0 +1,105 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies <kontakt@dspies.de> + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * <kontakt@dspies.de> + */ +  +#ifndef __LWIP_AUTOIP_H__ +#define __LWIP_AUTOIP_H__ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL      100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT               1   /* second   (initial random delay)                 */ +#define PROBE_MIN                1   /* second   (minimum delay till repeated probe)    */ +#define PROBE_MAX                2   /* seconds  (maximum delay till repeated probe)    */ +#define PROBE_NUM                3   /*          (number of probe packets)              */ +#define ANNOUNCE_NUM             2   /*          (number of announcement packets)       */ +#define ANNOUNCE_INTERVAL        2   /* seconds  (time between announcement packets)    */ +#define ANNOUNCE_WAIT            2   /* seconds  (delay before announcing)              */ +#define MAX_CONFLICTS            10  /*          (max conflicts before rate limiting)   */ +#define RATE_LIMIT_INTERVAL      60  /* seconds  (delay between successive attempts)    */ +#define DEFEND_INTERVAL          10  /* seconds  (min. wait between defensive ARPs)     */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF         0 +#define AUTOIP_STATE_PROBING     1 +#define AUTOIP_STATE_ANNOUNCING  2 +#define AUTOIP_STATE_BOUND       3 + +struct autoip +{ +  struct ip_addr llipaddr;  /* the currently selected, probed, announced or used LL IP-Address */ +  u8_t state;               /* current AutoIP state machine state */ +  u8_t sent_num;            /* sent number of probes or announces, dependent on state */ +  u16_t ttw;                /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ +  u8_t lastconflict;        /* ticks until a conflict can be solved by defending */ +  u8_t tried_llipaddr;      /* total number of probed/used Link Local IP-Addresses */ +}; + + +/** Init srand, has to be called before entering mainloop */ +void autoip_init(void); + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +#endif /* LWIP_AUTOIP */ + +#endif /* __LWIP_AUTOIP_H__ */ diff --git a/firmware/octoclock/include/lwip/debug.h b/firmware/octoclock/include/lwip/debug.h new file mode 100644 index 000000000..d5c4e4747 --- /dev/null +++ b/firmware/octoclock/include/lwip/debug.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_DEBUG_H__ +#define __LWIP_DEBUG_H__ + +#include "lwip/arch.h" + +/** lower two bits indicate debug level + * - 0 off + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_OFF     0x00 +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE  0x03 +#define LWIP_DBG_MASK_LEVEL    0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON            0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF           0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE         0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE         0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH         0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT          0x08U + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ +  LWIP_PLATFORM_ASSERT(message); } while(0) +#else  /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion)  +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ +  LWIP_PLATFORM_ASSERT(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +/** print debug message only if debug message type is enabled... + *  AND is of correct type AND is at least LWIP_DBG_LEVEL + */ +#define LWIP_DEBUGF(debug, message) do { \ +                               if ( \ +                                   ((debug) & LWIP_DBG_ON) && \ +                                   ((debug) & LWIP_DBG_TYPES_ON) && \ +                                   ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ +                                 LWIP_PLATFORM_DIAG(message); \ +                                 if ((debug) & LWIP_DBG_HALT) { \ +                                   while(1); \ +                                 } \ +                               } \ +                             } while(0) + +#else  /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message)  +#endif /* LWIP_DEBUG */ + +#endif /* __LWIP_DEBUG_H__ */ + diff --git a/firmware/octoclock/include/lwip/def.h b/firmware/octoclock/include/lwip/def.h new file mode 100644 index 000000000..d2ed251df --- /dev/null +++ b/firmware/octoclock/include/lwip/def.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_DEF_H__ +#define __LWIP_DEF_H__ + +/* this might define NULL already */ +#include "lwip/arch.h" + +#define LWIP_MAX(x , y)  (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y)  (((x) < (y)) ? (x) : (y)) + +#ifndef NULL +#define NULL ((void *)0) +#endif + + +#endif /* __LWIP_DEF_H__ */ + diff --git a/firmware/octoclock/include/lwip/dhcp.h b/firmware/octoclock/include/lwip/dhcp.h new file mode 100644 index 000000000..825dba6ec --- /dev/null +++ b/firmware/octoclock/include/lwip/dhcp.h @@ -0,0 +1,246 @@ +/** @file + */ + +#ifndef __LWIP_DHCP_H__ +#define __LWIP_DHCP_H__ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60  +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500  + +struct dhcp +{ +  /** current DHCP state machine state */ +  u8_t state; +  /** retries of current request */ +  u8_t tries; +  /** transaction identifier of last sent request */  +  u32_t xid; +  /** our connection to the DHCP server */  +  struct udp_pcb *pcb; +  /** (first) pbuf of incoming msg */ +  struct pbuf *p; +  /** incoming msg */ +  struct dhcp_msg *msg_in; +  /** incoming msg options */ +  struct dhcp_msg *options_in;  +  /** ingoing msg options length */ +  u16_t options_in_len; + +  struct pbuf *p_out; /* pbuf of outcoming msg */ +  struct dhcp_msg *msg_out; /* outgoing msg */ +  u16_t options_out_len; /* outgoing msg options length */ +  u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ +  u16_t t1_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ +  u16_t t2_timeout;  /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ +  struct ip_addr server_ip_addr; /* dhcp server address that offered this lease */ +  struct ip_addr offered_ip_addr; +  struct ip_addr offered_sn_mask; +  struct ip_addr offered_gw_addr; +  struct ip_addr offered_bc_addr; +#define DHCP_MAX_DNS 2 +  u32_t dns_count; /* actual number of DNS servers obtained */ +  struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */ +  +  u32_t offered_t0_lease; /* lease period (in seconds) */ +  u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ +  u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period)  */ +#if LWIP_DHCP_AUTOIP_COOP +  u8_t autoip_coop_state; +#endif +/** Patch #1308 + *  TODO: See dhcp.c "TODO"s + */ +#if 0 +  struct ip_addr offered_si_addr; +  u8_t *boot_file_name; +#endif +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ +  PACK_STRUCT_FIELD(u8_t op); +  PACK_STRUCT_FIELD(u8_t htype); +  PACK_STRUCT_FIELD(u8_t hlen); +  PACK_STRUCT_FIELD(u8_t hops); +  PACK_STRUCT_FIELD(u32_t xid); +  PACK_STRUCT_FIELD(u16_t secs); +  PACK_STRUCT_FIELD(u16_t flags); +  PACK_STRUCT_FIELD(struct ip_addr ciaddr); +  PACK_STRUCT_FIELD(struct ip_addr yiaddr); +  PACK_STRUCT_FIELD(struct ip_addr siaddr); +  PACK_STRUCT_FIELD(struct ip_addr giaddr); +#define DHCP_CHADDR_LEN 16U +  PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]); +#define DHCP_SNAME_LEN 64U +  PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]); +#define DHCP_FILE_LEN 128U +  PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]); +  PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +#  undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +#  define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif +  PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr); +#endif + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); +  +/** DHCP message item offsets and length */ +#define DHCP_MSG_OFS (UDP_DATA_OFS)   +  #define DHCP_OP_OFS (DHCP_MSG_OFS + 0) +  #define DHCP_HTYPE_OFS (DHCP_MSG_OFS + 1) +  #define DHCP_HLEN_OFS (DHCP_MSG_OFS + 2) +  #define DHCP_HOPS_OFS (DHCP_MSG_OFS + 3) +  #define DHCP_XID_OFS (DHCP_MSG_OFS + 4) +  #define DHCP_SECS_OFS (DHCP_MSG_OFS + 8) +  #define DHCP_FLAGS_OFS (DHCP_MSG_OFS + 10) +  #define DHCP_CIADDR_OFS (DHCP_MSG_OFS + 12) +  #define DHCP_YIADDR_OFS (DHCP_MSG_OFS + 16) +  #define DHCP_SIADDR_OFS (DHCP_MSG_OFS + 20) +  #define DHCP_GIADDR_OFS (DHCP_MSG_OFS + 24) +  #define DHCP_CHADDR_OFS (DHCP_MSG_OFS + 28) +  #define DHCP_SNAME_OFS (DHCP_MSG_OFS + 44) +  #define DHCP_FILE_OFS (DHCP_MSG_OFS + 108) +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN) +#define DHCP_OPTIONS_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68   +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_REQUESTING 1 +#define DHCP_INIT 2 +#define DHCP_REBOOTING 3 +#define DHCP_REBINDING 4 +#define DHCP_RENEWING 5 +#define DHCP_SELECTING 6 +#define DHCP_INFORMING 7 +#define DHCP_CHECKING 8 +#define DHCP_PERMANENT 9 +#define DHCP_BOUND 10 +/** not yet implemented #define DHCP_RELEASING 11 */ +#define DHCP_BACKING_OFF 12 +#define DHCP_OFF 13 + +/** AUTOIP cooperatation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 +  +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_HTYPE_ETH 1 + +#define DHCP_HLEN_ETH 6 + +#define DHCP_BROADCAST_FLAG 15 +#define DHCP_BROADCAST_MASK (1 << DHCP_FLAG_BROADCAST) + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6  +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_END 255 + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME  2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*__LWIP_DHCP_H__*/ diff --git a/firmware/octoclock/include/lwip/dns.h b/firmware/octoclock/include/lwip/dns.h new file mode 100644 index 000000000..e5f4b7a3d --- /dev/null +++ b/firmware/octoclock/include/lwip/dns.h @@ -0,0 +1,97 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato  + *   April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + *    products derived from this software without specific prior + *    written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LWIP_DNS_H__ +#define __LWIP_DNS_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +/** DNS timer period */ +#define DNS_TMR_INTERVAL          1000 + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A              1     /* a host address */ +#define DNS_RRTYPE_NS             2     /* an authoritative name server */ +#define DNS_RRTYPE_MD             3     /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF             4     /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME          5     /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA            6     /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB             7     /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG             8     /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR             9     /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL           10    /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS            11    /* a well known service description */ +#define DNS_RRTYPE_PTR            12    /* a domain name pointer */ +#define DNS_RRTYPE_HINFO          13    /* host information */ +#define DNS_RRTYPE_MINFO          14    /* mailbox or mail list information */ +#define DNS_RRTYPE_MX             15    /* mail exchange */ +#define DNS_RRTYPE_TXT            16    /* text strings */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN            1     /* the Internet */ +#define DNS_RRCLASS_CS            2     /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH            3     /* the CHAOS class */ +#define DNS_RRCLASS_HS            4     /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH         0x800 /* Flush bit */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to a struct ip_addr containing the IP address of the hostname, + *        or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, struct ip_addr *ipaddr, void *callback_arg); + + +void           dns_init(void); + +void           dns_tmr(void); + +void           dns_setserver(u8_t numdns, struct ip_addr *dnsserver); + +struct ip_addr dns_getserver(u8_t numdns); + +err_t          dns_gethostbyname(const char *hostname, struct ip_addr *addr, +                                 dns_found_callback found, void *callback_arg); + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int            dns_local_removehost(const char *hostname, const struct ip_addr *addr); +err_t          dns_local_addhost(const char *hostname, const struct ip_addr *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#endif /* LWIP_DNS */ + +#endif /* __LWIP_DNS_H__ */ diff --git a/firmware/octoclock/include/lwip/err.h b/firmware/octoclock/include/lwip/err.h new file mode 100644 index 000000000..696764454 --- /dev/null +++ b/firmware/octoclock/include/lwip/err.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_ERR_H__ +#define __LWIP_ERR_H__ + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + *  a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ + typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK          0    /* No error, everything OK. */ +#define ERR_MEM        -1    /* Out of memory error.     */ +#define ERR_BUF        -2    /* Buffer error.            */ +#define ERR_TIMEOUT    -3    /* Timeout.                 */ +#define ERR_RTE        -4    /* Routing problem.         */ + +#define ERR_IS_FATAL(e) ((e) < ERR_RTE) + +#define ERR_ABRT       -5    /* Connection aborted.      */ +#define ERR_RST        -6    /* Connection reset.        */ +#define ERR_CLSD       -7    /* Connection closed.       */ +#define ERR_CONN       -8    /* Not connected.           */ + +#define ERR_VAL        -9    /* Illegal value.           */ + +#define ERR_ARG        -10   /* Illegal argument.        */ + +#define ERR_USE        -11   /* Address in use.          */ + +#define ERR_IF         -12   /* Low-level netif error    */ +#define ERR_ISCONN     -13   /* Already connected.       */ + +#define ERR_INPROGRESS -14   /* Operation in progress    */ + + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err); +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/firmware/octoclock/include/lwip/icmp.h b/firmware/octoclock/include/lwip/icmp.h new file mode 100644 index 000000000..ff838f43a --- /dev/null +++ b/firmware/octoclock/include/lwip/icmp.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0      /* echo reply */ +#define ICMP_DUR 3     /* destination unreachable */ +#define ICMP_SQ 4      /* source quench */ +#define ICMP_RD 5      /* redirect */ +#define ICMP_ECHO 8    /* echo */ +#define ICMP_TE 11     /* time exceeded */ +#define ICMP_PP 12     /* parameter problem */ +#define ICMP_TS 13     /* timestamp */ +#define ICMP_TSR 14    /* timestamp reply */ +#define ICMP_IRQ 15    /* information request */ +#define ICMP_IR 16     /* information reply */ + +enum icmp_dur_type { +  ICMP_DUR_NET = 0,    /* net unreachable */ +  ICMP_DUR_HOST = 1,   /* host unreachable */ +  ICMP_DUR_PROTO = 2,  /* protocol unreachable */ +  ICMP_DUR_PORT = 3,   /* port unreachable */ +  ICMP_DUR_FRAG = 4,   /* fragmentation needed and DF set */ +  ICMP_DUR_SR = 5      /* source route failed */ +}; + +enum icmp_te_type { +  ICMP_TE_TTL = 0,     /* time to live exceeded in transit */ +  ICMP_TE_FRAG = 1     /* fragment reassembly time exceeded */ +}; + +void icmp_input(struct pbuf *p, struct netif *inp); + +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t); +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t); + +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + *  is splitted to two u16_t like ICMP echo needs it. + *  This header is also used for other ICMP types that do not + *  use the data part. + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { +  PACK_STRUCT_FIELD(u8_t type); +  PACK_STRUCT_FIELD(u8_t code); +  PACK_STRUCT_FIELD(u16_t chksum); +  PACK_STRUCT_FIELD(u16_t id); +  PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t */ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_ICMP */ + +#endif /* __LWIP_ICMP_H__ */ diff --git a/firmware/octoclock/include/lwip/igmp.h b/firmware/octoclock/include/lwip/igmp.h new file mode 100644 index 000000000..59c933f35 --- /dev/null +++ b/firmware/octoclock/include/lwip/igmp.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without  + * modification, are permitted provided that the following conditions  + * are met:  + * 1. Redistributions of source code must retain the above copyright  + *    notice, this list of conditions and the following disclaimer.  + * 2. Redistributions in binary form must reproduce the above copyright  + *    notice, this list of conditions and the following disclaimer in the  + *    documentation and/or other materials provided with the distribution.  + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors  + *    may be used to endorse or promote products derived from this software  + *    without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  + * ARE DISCLAIMED.  IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE  + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  + * SUCH DAMAGE.  + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef __LWIP_IGMP_H__ +#define __LWIP_IGMP_H__ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*  + * IGMP constants + */ +#define IP_PROTO_IGMP                  2 +#define IGMP_TTL                       1 +#define IGMP_MINLEN                    8 +#define ROUTER_ALERT                   0x9404 +#define ROUTER_ALERTLEN                4 + +/* + * IGMP message types, including version number. + */ +#define IGMP_MEMB_QUERY                0x11 /* Membership query         */ +#define IGMP_V1_MEMB_REPORT            0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMB_REPORT            0x16 /* Ver. 2 membership report */ +#define IGMP_LEAVE_GROUP               0x17 /* Leave-group message      */ + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL              100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR   (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions */ +#define IGMP_DEL_MAC_FILTER            0 +#define IGMP_ADD_MAC_FILTER            1 + +/* Group  membership states */ +#define IGMP_GROUP_NON_MEMBER          0 +#define IGMP_GROUP_DELAYING_MEMBER     1 +#define IGMP_GROUP_IDLE_MEMBER         2 + +/* + * IGMP packet format. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct igmp_msg { + PACK_STRUCT_FIELD(u8_t           igmp_msgtype); + PACK_STRUCT_FIELD(u8_t           igmp_maxresp); + PACK_STRUCT_FIELD(u16_t          igmp_checksum); + PACK_STRUCT_FIELD(struct ip_addr igmp_group_address); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +/*  + * now a group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + *  + * There will be a group for the all systems group address but this  + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ + +struct igmp_group { +  struct igmp_group *next; +  struct netif      *interface; +  struct ip_addr     group_address; +  u8_t               last_reporter_flag; /* signifies we were the last person to report */ +  u8_t               group_state; +  u16_t              timer; +  u8_t               use; /* counter of simultaneous uses */ +}; + + +/*  Prototypes */ +void   igmp_init(void); + +err_t  igmp_start( struct netif *netif); + +err_t  igmp_stop( struct netif *netif); + +void   igmp_report_groups( struct netif *netif); + +struct igmp_group *igmp_lookfor_group( struct netif *ifp, struct ip_addr *addr); + +struct igmp_group *igmp_lookup_group( struct netif *ifp, struct ip_addr *addr); + +err_t  igmp_remove_group( struct igmp_group *group); + +void   igmp_input( struct pbuf *p, struct netif *inp, struct ip_addr *dest); + +err_t  igmp_joingroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr); + +err_t  igmp_leavegroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr); + +void   igmp_tmr(void); + +void   igmp_timeout( struct igmp_group *group); + +void   igmp_start_timer( struct igmp_group *group, u8_t max_time); + +void   igmp_stop_timer( struct igmp_group *group); + +void   igmp_delaying_member( struct igmp_group *group, u8_t maxresp); + +err_t  igmp_ip_output_if( struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t proto, struct netif *netif); + +void   igmp_send( struct igmp_group *group, u8_t type); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IGMP */ + +#endif /* __LWIP_IGMP_H__ */ diff --git a/firmware/octoclock/include/lwip/inet.h b/firmware/octoclock/include/lwip/inet.h new file mode 100644 index 000000000..ffe763d45 --- /dev/null +++ b/firmware/octoclock/include/lwip/inet.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For compatibility with BSD code */ +struct in_addr { +  u32_t s_addr; +}; + +#define INADDR_NONE         ((u32_t)0xffffffffUL)  /* 255.255.255.255 */ +#define INADDR_LOOPBACK     ((u32_t)0x7f000001UL)  /* 127.0.0.1 */ +#define INADDR_ANY          ((u32_t)0x00000000UL)  /* 0.0.0.0 */ +#define INADDR_BROADCAST    ((u32_t)0xffffffffUL)  /* 255.255.255.255 */ + +u32_t inet_addr(const char *cp); +int inet_aton(const char *cp, struct in_addr *addr); +char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ diff --git a/firmware/octoclock/include/lwip/inet_chksum.h b/firmware/octoclock/include/lwip/inet_chksum.h new file mode 100644 index 000000000..5cae59cbd --- /dev/null +++ b/firmware/octoclock/include/lwip/inet_chksum.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_INET_CHKSUM_H__ +#define __LWIP_INET_CHKSUM_H__ + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *dataptr, u16_t len); +u16_t inet_chksum_pbuf(struct pbuf *p); +u16_t inet_chksum_pseudo(struct pbuf *p, +       struct ip_addr *src, struct ip_addr *dest, +       u8_t proto, u16_t proto_len); +#if LWIP_UDPLITE +u16_t inet_chksum_pseudo_partial(struct pbuf *p, +       struct ip_addr *src, struct ip_addr *dest, +       u8_t proto, u16_t proto_len, u16_t chksum_len); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/firmware/octoclock/include/lwip/init.h b/firmware/octoclock/include/lwip/init.h new file mode 100644 index 000000000..a4dc0577f --- /dev/null +++ b/firmware/octoclock/include/lwip/init.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_INIT_H__ +#define __LWIP_INIT_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR      1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR      3U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION   1U +/** For release candidates, this is set to 1..254 +  * For official releases, this is set to 255 (LWIP_RC_RELEASE) +  * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC         255U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE         255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */ +#define LWIP_RC_DEVELOPMENT     0U + +#define LWIP_VERSION_IS_RELEASE     (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC          ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION   (LWIP_VERSION_MAJOR << 24   | LWIP_VERSION_MINOR << 16 | \ +                        LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INIT_H__ */ diff --git a/firmware/octoclock/include/lwip/ip.h b/firmware/octoclock/include/lwip/ip.h new file mode 100644 index 000000000..14eba3ca5 --- /dev/null +++ b/firmware/octoclock/include/lwip/ip.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND   LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP    1 +#define IP_PROTO_UDP     17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP     6 + +/* This is passed as the destination address to ip_output_if (not +   to ip_output), meaning that an IP header already is constructed +   in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL  NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the +   beginning of a PCB type definition. It is located here so that +   changes to this common part are made in one location instead of +   having to change all PCB structs. */ +#define IP_PCB \ +  /* ip addresses in network byte order */ \ +  struct ip_addr local_ip; \ +  struct ip_addr remote_ip; \ +   /* Socket options */  \ +  u16_t so_options;      \ +   /* Type Of Service */ \ +  u8_t tos;              \ +  /* Time To Live */     \ +  u8_t ttl               \ +  /* link layer address resolution hint */ \ +  IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ +  IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX. + */ +#define SOF_DEBUG       (u16_t)0x0001U    /* turn on debugging info recording */ +#define SOF_ACCEPTCONN  (u16_t)0x0002U    /* socket has had listen() */ +#define SOF_REUSEADDR   (u16_t)0x0004U    /* allow local address reuse */ +#define SOF_KEEPALIVE   (u16_t)0x0008U    /* keep connections alive */ +#define SOF_DONTROUTE   (u16_t)0x0010U    /* just use interface addresses */ +#define SOF_BROADCAST   (u16_t)0x0020U    /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SOF_USELOOPBACK (u16_t)0x0040U    /* bypass hardware when possible */ +#define SOF_LINGER      (u16_t)0x0080U    /* linger on close if data present */ +#define SOF_OOBINLINE   (u16_t)0x0100U    /* leave received OOB data in line */ +#define SOF_REUSEPORT   (u16_t)0x0200U    /* allow local address & port reuse */ + + +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { +  /* version / header length / type of service */ +  PACK_STRUCT_FIELD(u16_t _v_hl_tos); +  /* total length */ +  PACK_STRUCT_FIELD(u16_t _len); +  /* identification */ +  PACK_STRUCT_FIELD(u16_t _id); +  /* fragment offset field */ +  PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000        /* reserved fragment flag */ +#define IP_DF 0x4000        /* dont fragment flag */ +#define IP_MF 0x2000        /* more fragments flag */ +#define IP_OFFMASK 0x1fff   /* mask for fragmenting bits */ +  /* time to live / protocol*/ +  PACK_STRUCT_FIELD(u16_t _ttl_proto); +  /* checksum */ +  PACK_STRUCT_FIELD(u16_t _chksum); +  /* source and destination IP addresses */ +  PACK_STRUCT_FIELD(struct ip_addr src); +  PACK_STRUCT_FIELD(struct ip_addr dest);  +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +#define IPH_V(hdr)  (ntohs((hdr)->_v_hl_tos) >> 12) +#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f) +#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8) +#define IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos))) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(IPH_PROTO(hdr) | ((u16_t)(ttl) << 8))) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8))) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +#define ip_init() /* Compatibility define, not init needed. */ +struct netif *ip_route(struct ip_addr *dest); +err_t ip_input(struct pbuf *p, struct netif *inp); +err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, +       u8_t ttl, u8_t tos, u8_t proto); +err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, +       u8_t ttl, u8_t tos, u8_t proto, +       struct netif *netif); +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, +       u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint); +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, +       u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, +       u16_t optlen); +#endif /* IP_OPTIONS_SEND */ +struct netif *ip_current_netif(void); +const struct ip_hdr *ip_current_header(void); +#if IP_DEBUG +void ip_debug_print(struct pbuf *p); +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/firmware/octoclock/include/lwip/ip_addr.h b/firmware/octoclock/include/lwip/ip_addr.h new file mode 100644 index 000000000..f2e4c2233 --- /dev/null +++ b/firmware/octoclock/include/lwip/ip_addr.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" + +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr { +  PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { +  PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +struct netif; + +extern const struct ip_addr ip_addr_any; +extern const struct ip_addr ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed IP address + *  for the wildcard and the broadcast address + */ +#define IP_ADDR_ANY         ((struct ip_addr *)&ip_addr_any) +#define IP_ADDR_BROADCAST   ((struct ip_addr *)&ip_addr_broadcast) + +/* Definitions of the bits in an Internet address integer. + +   On subnets, host and network parts are found according to +   the subnet mask, not these masks.  */ + +#define IN_CLASSA(a)        ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IN_CLASSA_NET       0xff000000 +#define IN_CLASSA_NSHIFT    24 +#define IN_CLASSA_HOST      (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX       128 + +#define IN_CLASSB(a)        ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IN_CLASSB_NET       0xffff0000 +#define IN_CLASSB_NSHIFT    16 +#define IN_CLASSB_HOST      (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX       65536 + +#define IN_CLASSC(a)        ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IN_CLASSC_NET       0xffffff00 +#define IN_CLASSC_NSHIFT    8 +#define IN_CLASSC_HOST      (0xffffffff & ~IN_CLASSC_NET) + +#define IN_CLASSD(a)        (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IN_CLASSD_NET       0xf0000000          /* These ones aren't really */ +#define IN_CLASSD_NSHIFT    28                  /*   net and host fields, but */ +#define IN_CLASSD_HOST      0x0fffffff          /*   routing needn't know. */ +#define IN_MULTICAST(a)     IN_CLASSD(a) + +#define IN_EXPERIMENTAL(a)  (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IN_BADCLASS(a)      (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IN_LOOPBACKNET      127                 /* official! */ + +#define IP4_ADDR(ipaddr, a,b,c,d) \ +        (ipaddr)->addr = htonl(((u32_t)((a) & 0xff) << 24) | \ +                               ((u32_t)((b) & 0xff) << 16) | \ +                               ((u32_t)((c) & 0xff) << 8) | \ +                                (u32_t)((d) & 0xff)) + +#define ip_addr_set(dest, src) (dest)->addr = \ +                               ((src) == NULL? 0:\ +                               (src)->addr) +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ +                                              (mask)->addr) == \ +                                             ((addr2)->addr & \ +                                              (mask)->addr)) +#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0) + +u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *); + +#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000UL)) == ntohl(0xe0000000UL)) + +#define ip_addr_islinklocal(addr1) (((addr1)->addr & ntohl(0xffff0000UL)) == ntohl(0xa9fe0000UL)) + +#define ip_addr_debug_print(debug, ipaddr) \ +  LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F,              \ +                      ipaddr != NULL ?                                  \ +                      (u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff : 0,  \ +                      ipaddr != NULL ?                                  \ +                      (u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff : 0,  \ +                      ipaddr != NULL ?                                  \ +                      (u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff : 0,   \ +                      ipaddr != NULL ?                                  \ +                      (u16_t)ntohl((ipaddr)->addr) & 0xff : 0)) + +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff) +#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff) +#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff) +#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/firmware/octoclock/include/lwip/ip_frag.h b/firmware/octoclock/include/lwip/ip_frag.h new file mode 100644 index 000000000..380e604dc --- /dev/null +++ b/firmware/octoclock/include/lwip/ip_frag.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Jani Monoses <jani@iv.ro> + * + */ + +#ifndef __LWIP_IP_FRAG_H__ +#define __LWIP_IP_FRAG_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { +  struct ip_reassdata *next; +  struct pbuf *p; +  struct ip_hdr iphdr; +  u16_t datagram_len; +  u8_t flags; +  u8_t timer; +}; + +void ip_reass_init(void); +void ip_reass_tmr(void); +struct pbuf * ip_reass(struct pbuf *p); +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest); +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_FRAG_H__ */ diff --git a/firmware/octoclock/include/lwip/mem.h b/firmware/octoclock/include/lwip/mem.h new file mode 100644 index 000000000..327c2049f --- /dev/null +++ b/firmware/octoclock/include/lwip/mem.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_MEM_H__ +#define __LWIP_MEM_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include <stddef.h> /* for size_t */ + +typedef size_t mem_size_t; + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_free +#define mem_free free +#endif +#ifndef mem_malloc +#define mem_malloc malloc +#endif +#ifndef mem_calloc +#define mem_calloc calloc +#endif +#ifndef mem_realloc +static void *mem_realloc(void *mem, mem_size_t size) +{ +  LWIP_UNUSED_ARG(size); +  return mem; +} +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000l +typedef u32_t mem_size_t; +#else +typedef u16_t mem_size_t; +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_realloc is not used when using pools instead of a heap: +    we can't free part of a pool element and don't want to copy the rest */ +#define mem_realloc(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void  mem_init(void); +void *mem_realloc(void *mem, mem_size_t size); +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size); +void *mem_calloc(mem_size_t count, mem_size_t size); +void  mem_free(void *mem); +#endif /* MEM_LIBC_MALLOC */ + +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) +#endif + +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEM_H__ */ diff --git a/firmware/octoclock/include/lwip/memp.h b/firmware/octoclock/include/lwip/memp.h new file mode 100644 index 000000000..f0d073994 --- /dev/null +++ b/firmware/octoclock/include/lwip/memp.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ + +#ifndef __LWIP_MEMP_H__ +#define __LWIP_MEMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc)  MEMP_##name, +#include "lwip/memp_std.h" +  MEMP_MAX +} memp_t; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { +    /* Get the first (via: +       MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ +    MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/memp_std.h" +    ) , +    /* Get the last (via: +       MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ +    MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/memp_std.h" +    ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) +   We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST   ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC || MEM_USE_POOLS +extern const u16_t memp_sizes[MEMP_MAX]; +#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC + +#include "mem.h" + +#define memp_init() +#define memp_malloc(type)     mem_malloc(memp_sizes[type]) +#define memp_free(type, mem)  mem_free(mem) + +#else /* MEMP_MEM_MALLOC */ + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ +   memp_t poolnr; +}; +#endif /* MEM_USE_POOLS */ + +void  memp_init(void); + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line); +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type); +#endif +void  memp_free(memp_t type, void *mem); + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEMP_H__ */ diff --git a/firmware/octoclock/include/lwip/memp_std.h b/firmware/octoclock/include/lwip/memp_std.h new file mode 100644 index 000000000..344690328 --- /dev/null +++ b/firmware/octoclock/include/lwip/memp_std.h @@ -0,0 +1,102 @@ +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + *   1) MEMPOOL - standard pools + *   2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + *   3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. +   The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */  + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + *     creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB,        MEMP_NUM_RAW_PCB,         sizeof(struct raw_pcb),        "RAW_PCB") +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB,        MEMP_NUM_UDP_PCB,         sizeof(struct udp_pcb),        "UDP_PCB") +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB,        MEMP_NUM_TCP_PCB,         sizeof(struct tcp_pcb),        "TCP_PCB") +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN,  sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN") +LWIP_MEMPOOL(TCP_SEG,        MEMP_NUM_TCP_SEG,         sizeof(struct tcp_seg),        "TCP_SEG") +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA,      MEMP_NUM_REASSDATA,       sizeof(struct ip_reassdata),   "REASSDATA") +#endif /* IP_REASSEMBLY */ + +#if LWIP_NETCONN +LWIP_MEMPOOL(NETBUF,         MEMP_NUM_NETBUF,          sizeof(struct netbuf),         "NETBUF") +LWIP_MEMPOOL(NETCONN,        MEMP_NUM_NETCONN,         sizeof(struct netconn),        "NETCONN") +#endif /* LWIP_NETCONN */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API,  MEMP_NUM_TCPIP_MSG_API,   sizeof(struct tcpip_msg),      "TCPIP_MSG_API") +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg),      "TCPIP_MSG_INPKT") +#endif /* NO_SYS==0 */ + +#if ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE,      MEMP_NUM_ARP_QUEUE,       sizeof(struct etharp_q_entry), "ARP_QUEUE") +#endif /* ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP,     MEMP_NUM_IGMP_GROUP,      sizeof(struct igmp_group),     "IGMP_GROUP") +#endif /* LWIP_IGMP */ + +#if NO_SYS==0 +LWIP_MEMPOOL(SYS_TIMEOUT,    MEMP_NUM_SYS_TIMEOUT,     sizeof(struct sys_timeo),      "SYS_TIMEOUT") +#endif /* NO_SYS==0 */ + + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + *     creates a pool name MEMP_pool_name. description is used in stats.c + *     This allocates enough space for the pbuf struct and a payload. + *     (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF,      MEMP_NUM_PBUF,            0,                             "PBUF_REF/ROM") +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE,           PBUF_POOL_BUFSIZE,             "PBUF_POOL") + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/firmware/octoclock/include/lwip/netbuf.h b/firmware/octoclock/include/lwip/netbuf.h new file mode 100644 index 000000000..6d84dd073 --- /dev/null +++ b/firmware/octoclock/include/lwip/netbuf.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct netbuf { +  struct pbuf *p, *ptr; +  struct ip_addr *addr; +  u16_t port; +}; + +/* Network buffer functions: */ +struct netbuf *   netbuf_new      (void); +void              netbuf_delete   (struct netbuf *buf); +void *            netbuf_alloc    (struct netbuf *buf, u16_t size); +void              netbuf_free     (struct netbuf *buf); +err_t             netbuf_ref      (struct netbuf *buf, +           const void *dataptr, u16_t size); +void              netbuf_chain    (struct netbuf *head, +           struct netbuf *tail); + +u16_t             netbuf_len      (struct netbuf *buf); +err_t             netbuf_data     (struct netbuf *buf, +           void **dataptr, u16_t *len); +s8_t              netbuf_next     (struct netbuf *buf); +void              netbuf_first    (struct netbuf *buf); + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ +  pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf)              ((buf)->p->tot_len) +#define netbuf_fromaddr(buf)         ((buf)->addr) +#define netbuf_fromport(buf)         ((buf)->port) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/firmware/octoclock/include/lwip/netdb.h b/firmware/octoclock/include/lwip/netdb.h new file mode 100644 index 000000000..0f7b2ec04 --- /dev/null +++ b/firmware/octoclock/include/lwip/netdb.h @@ -0,0 +1,111 @@ +/* + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include <stddef.h> /* for size_t */ + +#include "lwip/sockets.h" + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME      200 +#define EAI_SERVICE     201 +#define EAI_FAIL        202 +#define EAI_MEMORY      203 + +#define HOST_NOT_FOUND  210 +#define NO_DATA         211 +#define NO_RECOVERY     212 +#define TRY_AGAIN       213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { +    char  *h_name;      /* Official name of the host. */ +    char **h_aliases;   /* A pointer to an array of pointers to alternative host names, +                           terminated by a null pointer. */ +    int    h_addrtype;  /* Address type. */ +    int    h_length;    /* The length, in bytes, of the address. */ +    char **h_addr_list; /* A pointer to an array of pointers to network addresses (in +                           network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { +    int               ai_flags;      /* Input flags. */ +    int               ai_family;     /* Address family of socket. */ +    int               ai_socktype;   /* Socket type. */ +    int               ai_protocol;   /* Protocol of socket. */ +    socklen_t         ai_addrlen;    /* Length of socket address. */ +    struct sockaddr  *ai_addr;       /* Socket address of socket. */ +    char             *ai_canonname;  /* Canonical name of service location. */ +    struct addrinfo  *ai_next;       /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessable error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, +                size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, +       const char *servname, +       const struct addrinfo *hints, +       struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ +       lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(a) +#define getaddrinfo(nodname, servname, hints, res) \ +       lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#endif /* LWIP_DNS && LWIP_SOCKET */ diff --git a/firmware/octoclock/include/lwip/netif.h b/firmware/octoclock/include/lwip/netif.h new file mode 100644 index 000000000..a32503052 --- /dev/null +++ b/firmware/octoclock/include/lwip/netif.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_NETIF_H__ +#define __LWIP_NETIF_H__ + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/inet.h" +#include "lwip/pbuf.h" +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** must be the maximum of all used hardware address lengths +    across all types of interfaces in use */ +#define NETIF_MAX_HWADDR_LEN 6U + +/** TODO: define the use (where, when, whom) of netif flags */ + +/** whether the network interface is 'up'. this is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + */ +#define NETIF_FLAG_UP           0x01U +/** if set, the netif has broadcast capability */ +#define NETIF_FLAG_BROADCAST    0x02U +/** if set, the netif is one end of a point-to-point connection */ +#define NETIF_FLAG_POINTTOPOINT 0x04U +/** if set, the interface is configured using DHCP */ +#define NETIF_FLAG_DHCP         0x08U +/** if set, the interface has an active link + *  (set by the network interface driver) */ +#define NETIF_FLAG_LINK_UP      0x10U +/** if set, the netif is an device using ARP */ +#define NETIF_FLAG_ETHARP       0x20U +/** if set, the netif has IGMP capability */ +#define NETIF_FLAG_IGMP         0x40U + +/** Generic data structure used for all lwIP network interfaces. + *  The following fields should be filled in by the initialization + *  function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ + +struct netif { +  /** pointer to next in linked list */ +  struct netif *next; + +  /** IP address configuration in network byte order */ +  struct ip_addr ip_addr; +  struct ip_addr netmask; +  struct ip_addr gw; + +  /** This function is called by the network device driver +   *  to pass a packet up the TCP/IP stack. */ +  err_t (* input)(struct pbuf *p, struct netif *inp); +  /** This function is called by the IP module when it wants +   *  to send a packet on the interface. This function typically +   *  first resolves the hardware address, then sends the packet. */ +  err_t (* output)(struct netif *netif, struct pbuf *p, +       struct ip_addr *ipaddr); +  /** This function is called by the ARP module when it wants +   *  to send a packet on the interface. This function outputs +   *  the pbuf as-is on the link medium. */ +  err_t (* linkoutput)(struct netif *netif, struct pbuf *p); +#if LWIP_NETIF_STATUS_CALLBACK +  /** This function is called when the netif state is set to up or down +   */ +  void (* status_callback)(struct netif *netif); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK +  /** This function is called when the netif link is set to up or down +   */ +  void (* link_callback)(struct netif *netif); +#endif /* LWIP_NETIF_LINK_CALLBACK */ +  /** This field can be set by the device driver and could point +   *  to state information for the device. */ +  void *state; +#if LWIP_DHCP +  /** the DHCP client state information for this netif */ +  struct dhcp *dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP +  /** the AutoIP client state information for this netif */ +  struct autoip *autoip; +#endif +#if LWIP_NETIF_HOSTNAME +  /* the hostname for this netif, NULL is a valid value */ +  char*  hostname; +#endif /* LWIP_NETIF_HOSTNAME */ +  /** number of bytes used in hwaddr */ +  u8_t hwaddr_len; +  /** link level hardware address of this interface */ +  u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; +  /** maximum transfer unit (in bytes) */ +  u16_t mtu; +  /** flags (see NETIF_FLAG_ above) */ +  u8_t flags; +  /** descriptive abbreviation */ +  char name[2]; +  /** number of this interface */ +  u8_t num; +#if LWIP_SNMP +  /** link type (from "snmp_ifType" enum from snmp.h) */ +  u8_t link_type; +  /** (estimate) link speed */ +  u32_t link_speed; +  /** timestamp at last change made (up/down) */ +  u32_t ts; +  /** counters */ +  u32_t ifinoctets; +  u32_t ifinucastpkts; +  u32_t ifinnucastpkts; +  u32_t ifindiscards; +  u32_t ifoutoctets; +  u32_t ifoutucastpkts; +  u32_t ifoutnucastpkts; +  u32_t ifoutdiscards; +#endif /* LWIP_SNMP */ +#if LWIP_IGMP +  /* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/ +  err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action); +#endif /* LWIP_IGMP */ +#if LWIP_NETIF_HWADDRHINT +  u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK +  /* List of packets to be queued for ourselves. */ +  struct pbuf *loop_first; +  struct pbuf *loop_last; +#if LWIP_LOOPBACK_MAX_PBUFS +  u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_SNMP +#define NETIF_INIT_SNMP(netif, type, speed) \ +  /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \ +  netif->link_type = type;    \ +  /* your link speed here (units: bits per second) */  \ +  netif->link_speed = speed;  \ +  netif->ts = 0;              \ +  netif->ifinoctets = 0;      \ +  netif->ifinucastpkts = 0;   \ +  netif->ifinnucastpkts = 0;  \ +  netif->ifindiscards = 0;    \ +  netif->ifoutoctets = 0;     \ +  netif->ifoutucastpkts = 0;  \ +  netif->ifoutnucastpkts = 0; \ +  netif->ifoutdiscards = 0 +#else /* LWIP_SNMP */ +#define NETIF_INIT_SNMP(netif, type, speed) +#endif /* LWIP_SNMP */ + + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +#define netif_init() /* Compatibility define, not init needed. */ + +struct netif *netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, +      struct ip_addr *gw, +      void *state, +      err_t (* init)(struct netif *netif), +      err_t (* input)(struct pbuf *p, struct netif *netif)); + +void +netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask, +    struct ip_addr *gw); +void netif_remove(struct netif * netif); + +/* Returns a network interface given its name. The name is of the form +   "et0", where the first two letters are the "name" field in the +   netif structure, and the digit is in the num field in the same +   structure. */ +struct netif *netif_find(char *name); + +void netif_set_default(struct netif *netif); + +void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr); +void netif_set_netmask(struct netif *netif, struct ip_addr *netmask); +void netif_set_gw(struct netif *netif, struct ip_addr *gw); + +void netif_set_up(struct netif *netif); +void netif_set_down(struct netif *netif); +u8_t netif_is_up(struct netif *netif); + +#if LWIP_NETIF_STATUS_CALLBACK +/* + * Set callback to be called when interface is brought up/down + */ +void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif)); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_up(struct netif *netif); +void netif_set_link_down(struct netif *netif); +u8_t netif_is_link_up(struct netif *netif); +/* + * Set callback to be called when link is brought up/down + */ +void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif)); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#ifdef __cplusplus +} +#endif + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip); +void netif_poll(struct netif *netif); +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void); +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#endif /* __LWIP_NETIF_H__ */ diff --git a/firmware/octoclock/include/lwip/netifapi.h b/firmware/octoclock/include/lwip/netifapi.h new file mode 100644 index 000000000..36c6bd0a2 --- /dev/null +++ b/firmware/octoclock/include/lwip/netifapi.h @@ -0,0 +1,100 @@ +/* + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + */ +  +#ifndef __LWIP_NETIFAPI_H__ +#define __LWIP_NETIFAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct netifapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING +  sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ +  err_t err; +  struct netif *netif; +  union { +    struct { +      struct ip_addr *ipaddr; +      struct ip_addr *netmask; +      struct ip_addr *gw; +      void *state; +      err_t (* init) (struct netif *netif); +      err_t (* input)(struct pbuf *p, struct netif *netif); +    } add; +    struct { +      void  (* voidfunc)(struct netif *netif); +      err_t (* errtfunc)(struct netif *netif); +    } common; +  } msg; +}; + +struct netifapi_msg { +  void (* function)(struct netifapi_msg_msg *msg); +  struct netifapi_msg_msg msg; +}; + + +/* API for application */ +err_t netifapi_netif_add       ( struct netif *netif, +                                 struct ip_addr *ipaddr, +                                 struct ip_addr *netmask, +                                 struct ip_addr *gw, +                                 void *state, +                                 err_t (* init)(struct netif *netif), +                                 err_t (* input)(struct pbuf *p, struct netif *netif) ); + +err_t netifapi_netif_common    ( struct netif *netif, +                                 void  (* voidfunc)(struct netif *netif), +                                 err_t (* errtfunc)(struct netif *netif) ); + +#define netifapi_netif_remove(n)      netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n)      netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n)    netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n)        netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n)         netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_autoip_start(n)      netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n)       netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* __LWIP_NETIFAPI_H__ */ diff --git a/firmware/octoclock/include/lwip/opt.h b/firmware/octoclock/include/lwip/opt.h new file mode 100644 index 000000000..e8bd8b89e --- /dev/null +++ b/firmware/octoclock/include/lwip/opt.h @@ -0,0 +1,1820 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_OPT_H__ +#define __LWIP_OPT_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/* +   ----------------------------------------------- +   ---------- Platform specific locking ---------- +   ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT            0 +#endif + +/**  + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS                          0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len)             memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len)            memcpy(dst,src,len) +#endif + +/* +   ------------------------------------ +   ---------- Memory options ---------- +   ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC                 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC                 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + *    4 byte alignment -> #define MEM_ALIGNMENT 4 + *    2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT                   1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE                        1600 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + *    MEMP_OVERFLOW_CHECK == 0 no checking + *    MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + *    MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + *      memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK             0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK               0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS                   0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL   0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your  + * inlude path somewhere.  + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS           0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* +   ------------------------------------------------ +   ---------- Internal Memory Pool Sizes ---------- +   ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF                   16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB                4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB                4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB                5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN         8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG                16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA              5 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE              30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP             8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT            3 +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF                 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN                4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication.  + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API          8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets.  + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT        8 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.  + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE                  16 +#endif + +/* +   --------------------------------- +   ---------- ARP options ---------- +   --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP                        1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE                  10 +#endif + +/** + * ARP_QUEUEING==1: Outgoing packets are queued during hardware address + * resolution. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING                    1 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC             1 +#endif + +/* +   -------------------------------- +   ---------- IP options ---------- +   -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD                      0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + *      IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + *      IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED              1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY                   1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG                         1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE                 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS              10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented. + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF         1 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU                 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL                  255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST                0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV           0 +#endif + +/* +   ---------------------------------- +   ---------- ICMP options ---------- +   ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP                       1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL                       (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING             0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING             0 +#endif + +/* +   --------------------------------- +   ---------- RAW options ---------- +   --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW                        1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL                        (IP_DEFAULT_TTL) +#endif + +/* +   ---------------------------------- +   ---------- DHCP options ---------- +   ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP                       0 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK             ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/* +   ------------------------------------ +   ---------- AUTOIP options ---------- +   ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP                     0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP           0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES     9 +#endif + +/* +   ---------------------------------- +   ---------- SNMP options ---------- +   ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP                       0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required.  + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS        1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS          1 +#endif + +/** + * SNMP_PRIVATE_MIB:  + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB                0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS              1 +#endif + +/* +   ---------------------------------- +   ---------- IGMP options ---------- +   ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module.  + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP                       0 +#endif + +/* +   ---------------------------------- +   ---------- DNS options ----------- +   ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS                        0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE                  4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH             256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS                 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK             1 +#endif + +/** DNS use a local buffer if DNS_USES_STATIC_BUF=0, a static one if +    DNS_USES_STATIC_BUF=1, or a dynamic one if DNS_USES_STATIC_BUF=2. +    The buffer will be of size DNS_MSG_SIZE */ +#ifndef DNS_USES_STATIC_BUF +#define DNS_USES_STATIC_BUF             1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE                    512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + *  you have to define + *    #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + *  (an array of structs name/address, where address is an u32_t in network + *  byte order). + * + *  Instead, you can also use an external function: + *  #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + *  that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST              0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + *  at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC   0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* +   --------------------------------- +   ---------- UDP options ---------- +   --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP                        1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE                    0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL                         (IP_DEFAULT_TTL) +#endif + +/* +   --------------------------------- +   ---------- TCP options ---------- +   --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP                        1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL                         (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window.  This must be at least  + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND                         2048 +#endif  + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX                      12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX                   6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ                 (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 128, a *very* + * conservative default.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS                         128 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS      1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes).  + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF                     256 +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN                (4 * (TCP_SND_BUF/TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than or equal + * to TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable. + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT                    (TCP_SND_BUF/2) +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG              0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG      0xff +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS             0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD   (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + *     LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + *         events (accept, sent, etc) that happen in the system. + *     LWIP_CALLBACK_API==1: The PCB callback function is called directly + *         for the event. + */ +#ifndef LWIP_EVENT_API +#define LWIP_EVENT_API                  0 +#define LWIP_CALLBACK_API               1 +#else  +#define LWIP_EVENT_API                  1 +#define LWIP_CALLBACK_API               0 +#endif + + +/* +   ---------------------------------- +   ---------- Pbuf options ---------- +   ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN                  14 +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* +   ------------------------------------------------ +   ---------- Network Interfaces options ---------- +   ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME             0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API                  0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK      0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK        0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT           0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK             0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS         0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + *    LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + *       multithreaded environment like tcpip.c. In this case, netif->input() + *       is called directly. + *    LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + *       The packets are put on a list and netif_poll() must be called in + *       the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING    (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF             0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* +   ------------------------------------ +   ---------- LOOPIF options ---------- +   ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF                0 +#endif + +/* +   ------------------------------------ +   ---------- SLIPIF options ---------- +   ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF                0 +#endif + +/* +   ------------------------------------ +   ---------- Thread options ---------- +   ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME              "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE          0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO               1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE                 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME             "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE         0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO              1 +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppMain thread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME                "pppMain" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppMain thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE            0 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppMain thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO                 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME            "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE        0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO             1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE       0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE       0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE       0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE         0 +#endif + +/* +   ---------------------------------------------- +   ---------- Sequential layer options ---------- +   ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING         0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN                    1 +#endif + +/* +   ------------------------------------ +   ---------- Socket options ---------- +   ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET                     1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS             1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES     1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE              0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO                0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF                  0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT            INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR and SO_REUSEPORT options. DO NOT USE! + */ +#ifndef SO_REUSE +#define SO_REUSE                        0 +#endif + +/* +   ---------------------------------------- +   ---------- Statistics options ---------- +   ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS                      1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY              0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS                      1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS                    (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS                        1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS                    (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS                      1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS                      (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS                       (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS                       (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS                       1 +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS                      1 +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS                       1 +#endif + +#else + +#define LINK_STATS                      0 +#define IP_STATS                        0 +#define IPFRAG_STATS                    0 +#define ICMP_STATS                      0 +#define IGMP_STATS                      0 +#define UDP_STATS                       0 +#define TCP_STATS                       0 +#define MEM_STATS                       0 +#define MEMP_STATS                      0 +#define SYS_STATS                       0 +#define LWIP_STATS_DISPLAY              0 + +#endif /* LWIP_STATS */ + +/* +   --------------------------------- +   ---------- PPP options ---------- +   --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT                     0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT                   0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT                   PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP                         1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT                     0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT                    0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT                  0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT                    0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT                     0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT                      0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT                     0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT                  6       /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS              2       /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS              10      /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS              5       /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT                 6       /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME                 30      /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT                 6       /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS               10      /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL                0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS                3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG                 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + *    limits.  See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + *    of living in lcp.h) + */ +#define PPP_MTU                         1500     /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU  65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU                      1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU                      64 +#define PPP_MRU                         1500     /* default MRU = max length of info field */ +#define PPP_MAXMRU                      1500     /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU                      296             /* Try for this */ +#endif +#define PPP_MINMRU                      128             /* No MRUs below this */ + + +#define MAXNAMELEN                      256     /* max length of hostname or name for auth */ +#define MAXSECRETLEN                    256     /* max length of password or secret */ + +#endif /* PPP_SUPPORT */ + +/* +   -------------------------------------- +   ---------- Checksum options ---------- +   -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP                 1 +#endif +  +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP                1 +#endif +  +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP                1 +#endif +  +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP               1 +#endif +  +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP              1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP              1 +#endif + +/* +   --------------------------------------- +   ---------- Debugging options ---------- +   --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_OFF +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG                    LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG                     LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG                      LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG                   LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG                   LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG                   LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG                      LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG                      LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG                      LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG                        LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG                  LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG                       LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG                       LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG                      LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG                       LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG                       LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG                    LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG                   LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG                  LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG                   LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG                   LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG                  LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG                       LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG                     LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG                       LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG                      LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG                      LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG                    LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG                  LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG                  LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG                       LWIP_DBG_OFF +#endif + +#endif /* __LWIP_OPT_H__ */ diff --git a/firmware/octoclock/include/lwip/pbuf.h b/firmware/octoclock/include/lwip/pbuf.h new file mode 100644 index 000000000..8380f65da --- /dev/null +++ b/firmware/octoclock/include/lwip/pbuf.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ + +#ifndef __LWIP_PBUF_H__ +#define __LWIP_PBUF_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PBUF_TRANSPORT_HLEN 20 +#define PBUF_IP_HLEN        20 + +typedef enum { +  PBUF_TRANSPORT, +  PBUF_IP, +  PBUF_LINK, +  PBUF_RAW +} pbuf_layer; + +typedef enum { +  PBUF_RAM, /* pbuf data is stored in RAM */ +  PBUF_ROM, /* pbuf data is stored in ROM */ +  PBUF_REF, /* pbuf comes from the pbuf pool */ +  PBUF_POOL /* pbuf payload refers to RAM */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U + +struct pbuf { +  /** next pbuf in singly linked pbuf chain */ +  struct pbuf *next; + +  /** pointer to the actual data in the buffer */ +  void *payload; +   +  /** +   * total length of this buffer and all next buffers in chain +   * belonging to the same packet. +   * +   * For non-queue packet chains this is the invariant: +   * p->tot_len == p->len + (p->next? p->next->tot_len: 0) +   */ +  u16_t tot_len; +   +  /** length of this buffer */ +  u16_t len;   + +  /** pbuf_type as u8_t instead of enum to save space */ +  u8_t /*pbuf_type*/ type; + +  /** misc flags */ +  u8_t flags; + +  /** +   * the reference count always equals the number of pointers +   * that refer to this pbuf. This can be pointers from an application, +   * the stack itself, or pbuf->next pointers from a chain. +   */ +  u16_t ref; +   +}; + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_type type); +void pbuf_realloc(struct pbuf *p, u16_t size);  +u8_t pbuf_header(struct pbuf *p, s16_t header_size); +void pbuf_ref(struct pbuf *p); +void pbuf_ref_chain(struct pbuf *p); +u8_t pbuf_free(struct pbuf *p); +u8_t pbuf_clen(struct pbuf *p);   +void pbuf_cat(struct pbuf *head, struct pbuf *tail); +void pbuf_chain(struct pbuf *head, struct pbuf *tail); +struct pbuf *pbuf_dechain(struct pbuf *p); +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from); +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset); +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_PBUF_H__ */ diff --git a/firmware/octoclock/include/lwip/raw.h b/firmware/octoclock/include/lwip/raw.h new file mode 100644 index 000000000..20b0a11bb --- /dev/null +++ b/firmware/octoclock/include/lwip/raw.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_RAW_H__ +#define __LWIP_RAW_H__ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/inet.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb { +/* Common members of all PCB types */ +  IP_PCB; + +  struct raw_pcb *next; + +  u8_t protocol; + +  /* receive callback function +   * @param arg user supplied argument (raw_pcb.recv_arg) +   * @param pcb the raw_pcb which received data +   * @param p the packet buffer that was received +   * @param addr the remote IP address from which the packet was received +   * @return 1 if the packet was 'eaten' (aka. deleted), +   *         0 if the packet lives on +   * If returning 1, the callback is responsible for freeing the pbuf +   * if it's not used any more. +   */ +  u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p, +    struct ip_addr *addr); +  /* user-supplied argument for the recv callback */ +  void *recv_arg; +}; + +/* The following functions is the application layer interface to the +   RAW code. */ +struct raw_pcb * raw_new        (u8_t proto); +void             raw_remove     (struct raw_pcb *pcb); +err_t            raw_bind       (struct raw_pcb *pcb, struct ip_addr *ipaddr); +err_t            raw_connect    (struct raw_pcb *pcb, struct ip_addr *ipaddr); + +void             raw_recv       (struct raw_pcb *pcb, +                                 u8_t (* recv)(void *arg, struct raw_pcb *pcb, +                                              struct pbuf *p, +                                              struct ip_addr *addr), +                                 void *recv_arg); +err_t            raw_sendto     (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr); +err_t            raw_send       (struct raw_pcb *pcb, struct pbuf *p); + +/* The following functions are the lower layer interface to RAW. */ +u8_t             raw_input      (struct pbuf *p, struct netif *inp); +#define raw_init() /* Compatibility define, not init needed. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* __LWIP_RAW_H__ */ diff --git a/firmware/octoclock/include/lwip/sio.h b/firmware/octoclock/include/lwip/sio.h new file mode 100644 index 000000000..7d9162e49 --- /dev/null +++ b/firmware/octoclock/include/lwip/sio.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef __SIO_H__ +#define __SIO_H__ + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, +   define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file +   or be implemented in your custom sio.c file. */ + +#ifndef sio_open +sio_fd_t sio_open(u8_t); +#endif + +#ifndef sio_send +void sio_send(u8_t, sio_fd_t); +#endif + +#ifndef sio_recv +u8_t sio_recv(sio_fd_t); +#endif + +#ifndef sio_read +u32_t sio_read(sio_fd_t, u8_t *, u32_t); +#endif + +#ifndef sio_write +u32_t sio_write(sio_fd_t, u8_t *, u32_t); +#endif + +#ifndef sio_read_abort +void sio_read_abort(sio_fd_t); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SIO_H__ */ diff --git a/firmware/octoclock/include/lwip/snmp.h b/firmware/octoclock/include/lwip/snmp.h new file mode 100644 index 000000000..dd03d5d70 --- /dev/null +++ b/firmware/octoclock/include/lwip/snmp.h @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv> + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Leon Woestenberg <leon.woestenberg@axon.tv> + * + */ +#ifndef __LWIP_SNMP_H__ +#define __LWIP_SNMP_H__ + +#include "lwip/opt.h" +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { +  snmp_ifType_other=1,                /* none of the following */ +  snmp_ifType_regular1822, +  snmp_ifType_hdh1822, +  snmp_ifType_ddn_x25, +  snmp_ifType_rfc877_x25, +  snmp_ifType_ethernet_csmacd, +  snmp_ifType_iso88023_csmacd, +  snmp_ifType_iso88024_tokenBus, +  snmp_ifType_iso88025_tokenRing, +  snmp_ifType_iso88026_man, +  snmp_ifType_starLan, +  snmp_ifType_proteon_10Mbit, +  snmp_ifType_proteon_80Mbit, +  snmp_ifType_hyperchannel, +  snmp_ifType_fddi, +  snmp_ifType_lapb, +  snmp_ifType_sdlc, +  snmp_ifType_ds1,                    /* T-1 */ +  snmp_ifType_e1,                     /* european equiv. of T-1 */ +  snmp_ifType_basicISDN, +  snmp_ifType_primaryISDN,            /* proprietary serial */ +  snmp_ifType_propPointToPointSerial, +  snmp_ifType_ppp, +  snmp_ifType_softwareLoopback, +  snmp_ifType_eon,                    /* CLNP over IP [11] */ +  snmp_ifType_ethernet_3Mbit, +  snmp_ifType_nsip,                   /* XNS over IP */ +  snmp_ifType_slip,                   /* generic SLIP */ +  snmp_ifType_ultra,                  /* ULTRA technologies */ +  snmp_ifType_ds3,                    /* T-3 */ +  snmp_ifType_sip,                    /* SMDS */ +  snmp_ifType_frame_relay +}; + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** SNMP "sysuptime" Interval */ +#define SNMP_SYSUPTIME_INTERVAL 10 + +/** fixed maximum length for object identifier type */ +#define LWIP_SNMP_OBJ_ID_LEN 32 + +/** internal object identifier representation */ +struct snmp_obj_id +{ +  u8_t len; +  s32_t id[LWIP_SNMP_OBJ_ID_LEN]; +}; + +/* system */ +void snmp_set_sysdesr(u8_t* str, u8_t* len); +void snmp_set_sysobjid(struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); +void snmp_inc_sysuptime(void); +void snmp_add_sysuptime(u32_t value); +void snmp_get_sysuptime(u32_t *value); +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen); + +/* network interface */ +void snmp_add_ifinoctets(struct netif *ni, u32_t value);  +void snmp_inc_ifinucastpkts(struct netif *ni); +void snmp_inc_ifinnucastpkts(struct netif *ni); +void snmp_inc_ifindiscards(struct netif *ni); +void snmp_add_ifoutoctets(struct netif *ni, u32_t value); +void snmp_inc_ifoutucastpkts(struct netif *ni); +void snmp_inc_ifoutnucastpkts(struct netif *ni); +void snmp_inc_ifoutdiscards(struct netif *ni); +void snmp_inc_iflist(void); +void snmp_dec_iflist(void); + +/* ARP (for atTable and ipNetToMediaTable) */ +void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip); +void snmp_delete_arpidx_tree(struct netif *ni, struct ip_addr *ip); + +/* IP */ +void snmp_inc_ipinreceives(void); +void snmp_inc_ipinhdrerrors(void); +void snmp_inc_ipinaddrerrors(void); +void snmp_inc_ipforwdatagrams(void); +void snmp_inc_ipinunknownprotos(void); +void snmp_inc_ipindiscards(void); +void snmp_inc_ipindelivers(void); +void snmp_inc_ipoutrequests(void); +void snmp_inc_ipoutdiscards(void); +void snmp_inc_ipoutnoroutes(void); +void snmp_inc_ipreasmreqds(void); +void snmp_inc_ipreasmoks(void); +void snmp_inc_ipreasmfails(void); +void snmp_inc_ipfragoks(void); +void snmp_inc_ipfragfails(void); +void snmp_inc_ipfragcreates(void); +void snmp_inc_iproutingdiscards(void); +void snmp_insert_ipaddridx_tree(struct netif *ni); +void snmp_delete_ipaddridx_tree(struct netif *ni); +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni); +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni); + +/* ICMP */ +void snmp_inc_icmpinmsgs(void); +void snmp_inc_icmpinerrors(void); +void snmp_inc_icmpindestunreachs(void); +void snmp_inc_icmpintimeexcds(void); +void snmp_inc_icmpinparmprobs(void); +void snmp_inc_icmpinsrcquenchs(void); +void snmp_inc_icmpinredirects(void); +void snmp_inc_icmpinechos(void); +void snmp_inc_icmpinechoreps(void); +void snmp_inc_icmpintimestamps(void); +void snmp_inc_icmpintimestampreps(void); +void snmp_inc_icmpinaddrmasks(void); +void snmp_inc_icmpinaddrmaskreps(void); +void snmp_inc_icmpoutmsgs(void); +void snmp_inc_icmpouterrors(void); +void snmp_inc_icmpoutdestunreachs(void); +void snmp_inc_icmpouttimeexcds(void); +void snmp_inc_icmpoutparmprobs(void); +void snmp_inc_icmpoutsrcquenchs(void); +void snmp_inc_icmpoutredirects(void);  +void snmp_inc_icmpoutechos(void); +void snmp_inc_icmpoutechoreps(void); +void snmp_inc_icmpouttimestamps(void); +void snmp_inc_icmpouttimestampreps(void); +void snmp_inc_icmpoutaddrmasks(void); +void snmp_inc_icmpoutaddrmaskreps(void); + +/* TCP */ +void snmp_inc_tcpactiveopens(void); +void snmp_inc_tcppassiveopens(void); +void snmp_inc_tcpattemptfails(void); +void snmp_inc_tcpestabresets(void); +void snmp_inc_tcpinsegs(void); +void snmp_inc_tcpoutsegs(void); +void snmp_inc_tcpretranssegs(void); +void snmp_inc_tcpinerrs(void); +void snmp_inc_tcpoutrsts(void); + +/* UDP */ +void snmp_inc_udpindatagrams(void); +void snmp_inc_udpnoports(void); +void snmp_inc_udpinerrors(void); +void snmp_inc_udpoutdatagrams(void); +void snmp_insert_udpidx_tree(struct udp_pcb *pcb); +void snmp_delete_udpidx_tree(struct udp_pcb *pcb); + +/* SNMP */ +void snmp_inc_snmpinpkts(void); +void snmp_inc_snmpoutpkts(void); +void snmp_inc_snmpinbadversions(void); +void snmp_inc_snmpinbadcommunitynames(void); +void snmp_inc_snmpinbadcommunityuses(void); +void snmp_inc_snmpinasnparseerrs(void); +void snmp_inc_snmpintoobigs(void); +void snmp_inc_snmpinnosuchnames(void); +void snmp_inc_snmpinbadvalues(void); +void snmp_inc_snmpinreadonlys(void); +void snmp_inc_snmpingenerrs(void); +void snmp_add_snmpintotalreqvars(u8_t value); +void snmp_add_snmpintotalsetvars(u8_t value); +void snmp_inc_snmpingetrequests(void); +void snmp_inc_snmpingetnexts(void); +void snmp_inc_snmpinsetrequests(void); +void snmp_inc_snmpingetresponses(void); +void snmp_inc_snmpintraps(void); +void snmp_inc_snmpouttoobigs(void); +void snmp_inc_snmpoutnosuchnames(void); +void snmp_inc_snmpoutbadvalues(void); +void snmp_inc_snmpoutgenerrs(void); +void snmp_inc_snmpoutgetrequests(void); +void snmp_inc_snmpoutgetnexts(void); +void snmp_inc_snmpoutsetrequests(void); +void snmp_inc_snmpoutgetresponses(void); +void snmp_inc_snmpouttraps(void); +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); +void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); + +/* LWIP_SNMP support not available */ +/* define everything to be empty */ +#else + +/* system */ +#define snmp_set_sysdesr(str, len) +#define snmp_set_sysobjid(oid); +#define snmp_get_sysobjid_ptr(oid) +#define snmp_inc_sysuptime() +#define snmp_add_sysuptime(value) +#define snmp_get_sysuptime(value) +#define snmp_set_syscontact(ocstr, ocstrlen); +#define snmp_set_sysname(ocstr, ocstrlen); +#define snmp_set_syslocation(ocstr, ocstrlen); + +/* network interface */ +#define snmp_add_ifinoctets(ni,value)  +#define snmp_inc_ifinucastpkts(ni) +#define snmp_inc_ifinnucastpkts(ni) +#define snmp_inc_ifindiscards(ni) +#define snmp_add_ifoutoctets(ni,value) +#define snmp_inc_ifoutucastpkts(ni) +#define snmp_inc_ifoutnucastpkts(ni) +#define snmp_inc_ifoutdiscards(ni) +#define snmp_inc_iflist() +#define snmp_dec_iflist() + +/* ARP */ +#define snmp_insert_arpidx_tree(ni,ip) +#define snmp_delete_arpidx_tree(ni,ip) + +/* IP */ +#define snmp_inc_ipinreceives() +#define snmp_inc_ipinhdrerrors() +#define snmp_inc_ipinaddrerrors() +#define snmp_inc_ipforwdatagrams() +#define snmp_inc_ipinunknownprotos() +#define snmp_inc_ipindiscards() +#define snmp_inc_ipindelivers() +#define snmp_inc_ipoutrequests() +#define snmp_inc_ipoutdiscards() +#define snmp_inc_ipoutnoroutes() +#define snmp_inc_ipreasmreqds() +#define snmp_inc_ipreasmoks() +#define snmp_inc_ipreasmfails() +#define snmp_inc_ipfragoks() +#define snmp_inc_ipfragfails() +#define snmp_inc_ipfragcreates() +#define snmp_inc_iproutingdiscards() +#define snmp_insert_ipaddridx_tree(ni) +#define snmp_delete_ipaddridx_tree(ni) +#define snmp_insert_iprteidx_tree(dflt, ni) +#define snmp_delete_iprteidx_tree(dflt, ni) + +/* ICMP */ +#define snmp_inc_icmpinmsgs() +#define snmp_inc_icmpinerrors()  +#define snmp_inc_icmpindestunreachs()  +#define snmp_inc_icmpintimeexcds() +#define snmp_inc_icmpinparmprobs()  +#define snmp_inc_icmpinsrcquenchs()  +#define snmp_inc_icmpinredirects()  +#define snmp_inc_icmpinechos()  +#define snmp_inc_icmpinechoreps() +#define snmp_inc_icmpintimestamps()  +#define snmp_inc_icmpintimestampreps() +#define snmp_inc_icmpinaddrmasks() +#define snmp_inc_icmpinaddrmaskreps() +#define snmp_inc_icmpoutmsgs() +#define snmp_inc_icmpouterrors() +#define snmp_inc_icmpoutdestunreachs()  +#define snmp_inc_icmpouttimeexcds()  +#define snmp_inc_icmpoutparmprobs() +#define snmp_inc_icmpoutsrcquenchs() +#define snmp_inc_icmpoutredirects()  +#define snmp_inc_icmpoutechos()  +#define snmp_inc_icmpoutechoreps() +#define snmp_inc_icmpouttimestamps() +#define snmp_inc_icmpouttimestampreps() +#define snmp_inc_icmpoutaddrmasks() +#define snmp_inc_icmpoutaddrmaskreps() +/* TCP */ +#define snmp_inc_tcpactiveopens() +#define snmp_inc_tcppassiveopens() +#define snmp_inc_tcpattemptfails() +#define snmp_inc_tcpestabresets() +#define snmp_inc_tcpinsegs() +#define snmp_inc_tcpoutsegs() +#define snmp_inc_tcpretranssegs() +#define snmp_inc_tcpinerrs() +#define snmp_inc_tcpoutrsts() + +/* UDP */ +#define snmp_inc_udpindatagrams() +#define snmp_inc_udpnoports() +#define snmp_inc_udpinerrors() +#define snmp_inc_udpoutdatagrams() +#define snmp_insert_udpidx_tree(pcb) +#define snmp_delete_udpidx_tree(pcb) + +/* SNMP */ +#define snmp_inc_snmpinpkts() +#define snmp_inc_snmpoutpkts() +#define snmp_inc_snmpinbadversions() +#define snmp_inc_snmpinbadcommunitynames() +#define snmp_inc_snmpinbadcommunityuses() +#define snmp_inc_snmpinasnparseerrs() +#define snmp_inc_snmpintoobigs() +#define snmp_inc_snmpinnosuchnames() +#define snmp_inc_snmpinbadvalues() +#define snmp_inc_snmpinreadonlys() +#define snmp_inc_snmpingenerrs() +#define snmp_add_snmpintotalreqvars(value) +#define snmp_add_snmpintotalsetvars(value) +#define snmp_inc_snmpingetrequests() +#define snmp_inc_snmpingetnexts() +#define snmp_inc_snmpinsetrequests() +#define snmp_inc_snmpingetresponses() +#define snmp_inc_snmpintraps() +#define snmp_inc_snmpouttoobigs() +#define snmp_inc_snmpoutnosuchnames() +#define snmp_inc_snmpoutbadvalues() +#define snmp_inc_snmpoutgenerrs() +#define snmp_inc_snmpoutgetrequests() +#define snmp_inc_snmpoutgetnexts() +#define snmp_inc_snmpoutsetrequests() +#define snmp_inc_snmpoutgetresponses() +#define snmp_inc_snmpouttraps() +#define snmp_get_snmpgrpid_ptr(oid) +#define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SNMP_H__ */ diff --git a/firmware/octoclock/include/lwip/snmp_asn1.h b/firmware/octoclock/include/lwip/snmp_asn1.h new file mode 100644 index 000000000..8a602881f --- /dev/null +++ b/firmware/octoclock/include/lwip/snmp_asn1.h @@ -0,0 +1,101 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ +  +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons <christiaan.simons@axon.tv> + */ + +#ifndef __LWIP_SNMP_ASN1_H__ +#define __LWIP_SNMP_ASN1_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#if LWIP_SNMP + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_UNIV   (!0x80 | !0x40) +#define SNMP_ASN1_APPLIC (!0x80 |  0x40) +#define SNMP_ASN1_CONTXT ( 0x80 | !0x40) + +#define SNMP_ASN1_CONSTR (0x20) +#define SNMP_ASN1_PRIMIT (!0x20) + +/* universal tags */ +#define SNMP_ASN1_INTEG  2 +#define SNMP_ASN1_OC_STR 4 +#define SNMP_ASN1_NUL    5 +#define SNMP_ASN1_OBJ_ID 6 +#define SNMP_ASN1_SEQ    16 + +/* application specific (SNMP) tags */ +#define SNMP_ASN1_IPADDR 0    /* octet string size(4) */ +#define SNMP_ASN1_COUNTER 1   /* u32_t */ +#define SNMP_ASN1_GAUGE 2     /* u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ +#define SNMP_ASN1_OPAQUE 4    /* octet string */ + +/* context specific (SNMP) tags */ +#define SNMP_ASN1_PDU_GET_REQ 0 +#define SNMP_ASN1_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 + +err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); +err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); +err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid); +err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed); +err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type); +err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length); +err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value); +err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value); +err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident); +err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_ASN1_H__ */ diff --git a/firmware/octoclock/include/lwip/snmp_msg.h b/firmware/octoclock/include/lwip/snmp_msg.h new file mode 100644 index 000000000..b2f69c4be --- /dev/null +++ b/firmware/octoclock/include/lwip/snmp_msg.h @@ -0,0 +1,311 @@ +/** + * @file + * SNMP Agent message handling structures. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons <christiaan.simons@axon.tv> + */ + +#ifndef __LWIP_SNMP_MSG_H__ +#define __LWIP_SNMP_MSG_H__ + +#include "lwip/opt.h" +#include "lwip/snmp.h" +#include "lwip/snmp_structs.h" + +#if LWIP_SNMP + +#if SNMP_PRIVATE_MIB +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to +   this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't +   work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +#define SNMP_ES_NOERROR 0 +#define SNMP_ES_TOOBIG 1 +#define SNMP_ES_NOSUCHNAME 2 +#define SNMP_ES_BADVALUE 3 +#define SNMP_ES_READONLY 4 +#define SNMP_ES_GENERROR 5 + +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + +struct snmp_varbind +{ +  /* next pointer, NULL for last in list */ +  struct snmp_varbind *next; +  /* previous pointer, NULL for first in list */ +  struct snmp_varbind *prev; + +  /* object identifier length (in s32_t) */ +  u8_t ident_len; +  /* object identifier array */ +  s32_t *ident; + +  /* object value ASN1 type */ +  u8_t value_type; +  /* object value length (in u8_t) */ +  u8_t value_len; +  /* object value */ +  void *value; + +  /* encoding varbind seq length length */ +  u8_t seqlenlen; +  /* encoding object identifier length length */ +  u8_t olenlen; +  /* encoding object value length length */ +  u8_t vlenlen; +  /* encoding varbind seq length */ +  u16_t seqlen; +  /* encoding object identifier length */ +  u16_t olen; +  /* encoding object value length */ +  u16_t vlen; +}; + +struct snmp_varbind_root +{ +  struct snmp_varbind *head; +  struct snmp_varbind *tail; +  /* number of variable bindings in list */ +  u8_t count; +  /* encoding varbind-list seq length length */ +  u8_t seqlenlen; +  /* encoding varbind-list seq length */ +  u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_resp_header_lengths +{ +  /* encoding error-index length length */ +  u8_t erridxlenlen; +  /* encoding error-status length length */ +  u8_t errstatlenlen; +  /* encoding request id length length */ +  u8_t ridlenlen; +  /* encoding pdu length length */ +  u8_t pdulenlen; +  /* encoding community length length */ +  u8_t comlenlen; +  /* encoding version length length */ +  u8_t verlenlen; +  /* encoding sequence length length */ +  u8_t seqlenlen; + +  /* encoding error-index length */ +  u16_t erridxlen; +  /* encoding error-status length */ +  u16_t errstatlen; +  /* encoding request id length */ +  u16_t ridlen; +  /* encoding pdu length */ +  u16_t pdulen; +  /* encoding community length */ +  u16_t comlen; +  /* encoding version length */ +  u16_t verlen; +  /* encoding sequence length */ +  u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_trap_header_lengths +{ +  /* encoding timestamp length length */ +  u8_t tslenlen; +  /* encoding specific-trap length length */ +  u8_t strplenlen; +  /* encoding generic-trap length length */ +  u8_t gtrplenlen; +  /* encoding agent-addr length length */ +  u8_t aaddrlenlen; +  /* encoding enterprise-id length length */ +  u8_t eidlenlen; +  /* encoding pdu length length */ +  u8_t pdulenlen; +  /* encoding community length length */ +  u8_t comlenlen; +  /* encoding version length length */ +  u8_t verlenlen; +  /* encoding sequence length length */ +  u8_t seqlenlen; + +  /* encoding timestamp length */ +  u16_t tslen; +  /* encoding specific-trap length */ +  u16_t strplen; +  /* encoding generic-trap length */ +  u16_t gtrplen; +  /* encoding agent-addr length */ +  u16_t aaddrlen; +  /* encoding enterprise-id length */ +  u16_t eidlen; +  /* encoding pdu length */ +  u16_t pdulen; +  /* encoding community length */ +  u16_t comlen; +  /* encoding version length */ +  u16_t verlen; +  /* encoding sequence length */ +  u16_t seqlen; +}; + +/* Accepting new SNMP messages. */ +#define SNMP_MSG_EMPTY                 0 +/* Search for matching object for variable binding. */ +#define SNMP_MSG_SEARCH_OBJ            1 +/* Perform SNMP operation on in-memory object. +   Pass-through states, for symmetry only. */ +#define SNMP_MSG_INTERNAL_GET_OBJDEF   2 +#define SNMP_MSG_INTERNAL_GET_VALUE    3 +#define SNMP_MSG_INTERNAL_SET_TEST     4 +#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5 +#define SNMP_MSG_INTERNAL_SET_VALUE    6 +/* Perform SNMP operation on object located externally. +   In theory this could be used for building a proxy agent. +   Practical use is for an enterprise spc. app. gateway. */ +#define SNMP_MSG_EXTERNAL_GET_OBJDEF   7 +#define SNMP_MSG_EXTERNAL_GET_VALUE    8 +#define SNMP_MSG_EXTERNAL_SET_TEST     9 +#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10 +#define SNMP_MSG_EXTERNAL_SET_VALUE    11 + +#define SNMP_COMMUNITY_STR_LEN 64 +struct snmp_msg_pstat +{ +  /* lwIP local port (161) binding */ +  struct udp_pcb *pcb; +  /* source IP address */ +  struct ip_addr sip; +  /* source UDP port */ +  u16_t sp; +  /* request type */ +  u8_t rt; +  /* request ID */ +  s32_t rid; +  /* error status */ +  s32_t error_status; +  /* error index */ +  s32_t error_index; +  /* community name (zero terminated) */ +  u8_t community[SNMP_COMMUNITY_STR_LEN + 1]; +  /* community string length (exclusive zero term) */ +  u8_t com_strlen; +  /* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */ +  u8_t state; +  /* saved arguments for MSG_EXTERNAL_x */ +  struct mib_external_node *ext_mib_node; +  struct snmp_name_ptr ext_name_ptr; +  struct obj_def ext_object_def; +  struct snmp_obj_id ext_oid; +  /* index into input variable binding list */ +  u8_t vb_idx; +  /* ptr into input variable binding list */ +  struct snmp_varbind *vb_ptr; +  /* list of variable bindings from input */ +  struct snmp_varbind_root invb; +  /* list of variable bindings to output */ +  struct snmp_varbind_root outvb; +  /* output response lengths used in ASN encoding */ +  struct snmp_resp_header_lengths rhl; +}; + +struct snmp_msg_trap +{ +  /* lwIP local port (161) binding */ +  struct udp_pcb *pcb; +  /* destination IP address in network order */ +  struct ip_addr dip; + +  /* source enterprise ID (sysObjectID) */ +  struct snmp_obj_id *enterprise; +  /* source IP address, raw network order format */ +  u8_t sip_raw[4]; +  /* generic trap code */ +  u32_t gen_trap; +  /* specific trap code */ +  u32_t spc_trap; +  /* timestamp */ +  u32_t ts; +  /* list of variable bindings to output */ +  struct snmp_varbind_root outvb; +  /* output trap lengths used in ASN encoding */ +  struct snmp_trap_header_lengths thl; +}; + +/** Agent Version constant, 0 = v1 oddity */ +extern const s32_t snmp_version; +/** Agent default "public" community string */ +extern const char snmp_publiccommunity[7]; + +extern struct snmp_msg_trap trap_msg; + +/** Agent setup, start listening to port 161. */ +void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + +/** Handle an internal (recv) or external (private response) event. */ +void snmp_msg_event(u8_t request_id); +err_t snmp_send_response(struct snmp_msg_pstat *m_stat); +err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_MSG_H__ */ diff --git a/firmware/octoclock/include/lwip/snmp_structs.h b/firmware/octoclock/include/lwip/snmp_structs.h new file mode 100644 index 000000000..9f3f8a94e --- /dev/null +++ b/firmware/octoclock/include/lwip/snmp_structs.h @@ -0,0 +1,262 @@ +/** + * @file + * Generic MIB tree structures. + * + * @todo namespace prefixes + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons <christiaan.simons@axon.tv> + */ + +#ifndef __LWIP_SNMP_STRUCTS_H__ +#define __LWIP_SNMP_STRUCTS_H__ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" + +#if SNMP_PRIVATE_MIB +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0  +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY 0 +#define MIB_OBJECT_READ_WRITE 1 +#define MIB_OBJECT_WRITE_ONLY 2 +#define MIB_OBJECT_NOT_ACCESSIBLE 3 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ +  /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ +  u8_t instance; +  /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ +  u8_t access; +  /* ASN type for this object */ +  u8_t asn_type; +  /* value length (host length) */ +  u16_t v_len; +  /* length of instance part of supplied object identifier */ +  u8_t  id_inst_len; +  /* instance part of supplied object identifier */ +  s32_t *id_inst_ptr; +}; + +struct snmp_name_ptr +{ +  u8_t ident_len; +  s32_t *ident; +}; + +/** MIB const scalar (.0) node */ +#define MIB_NODE_SC 0x01 +/** MIB const array node */ +#define MIB_NODE_AR 0x02 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x03 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x04 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x05 + +/** node "base class" layout, the mandatory fields for a node  */ +struct mib_node +{ +  /** returns struct obj_def for the given object identifier */ +  void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); +  /** returns object value for the given object identifier, +     @note the caller must allocate at least len bytes for the value */ +  void (*get_value)(struct obj_def *od, u16_t len, void *value); +  /** tests length and/or range BEFORE setting */ +  u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); +  /** sets object value, only to be called when set_test()  */ +  void (*set_value)(struct obj_def *od, u16_t len, void *value);   +  /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ +  const u8_t node_type; +  /* array or max list length */ +  const u16_t maxlength; +}; + +/** derived node for scalars .0 index */ +typedef struct mib_node mib_scalar_node; + +/** derived node, points to a fixed size const array +    of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ +  /* inherited "base class" members */ +  void (* const get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); +  void (* const get_value)(struct obj_def *od, u16_t len, void *value); +  u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); +  void (*set_value)(struct obj_def *od, u16_t len, void *value); + +  const u8_t node_type; +  const u16_t maxlength; + +  /* aditional struct members */ +  const s32_t *objid; +  struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array +    of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ +  /* inherited "base class" members */ +  void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); +  void (*get_value)(struct obj_def *od, u16_t len, void *value); +  u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); +  void (*set_value)(struct obj_def *od, u16_t len, void *value); + +  u8_t node_type; +  u16_t maxlength; + +  /* aditional struct members */ +  s32_t *objid; +  struct mib_node **nptr; +}; + +struct mib_list_node +{ +  struct mib_list_node *prev;   +  struct mib_list_node *next; +  s32_t objid; +  struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list +    of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ +  /* inherited "base class" members */ +  void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); +  void (*get_value)(struct obj_def *od, u16_t len, void *value); +  u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); +  void (*set_value)(struct obj_def *od, u16_t len, void *value); + +  u8_t node_type; +  u16_t maxlength; + +  /* aditional struct members */ +  struct mib_list_node *head; +  struct mib_list_node *tail; +  /* counts list nodes in list  */ +  u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device +    using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ +struct mib_external_node +{ +  /* inherited "base class" members */ +  void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); +  void (*get_value)(struct obj_def *od, u16_t len, void *value); +  u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); +  void (*set_value)(struct obj_def *od, u16_t len, void *value); + +  u8_t node_type; +  u16_t maxlength; + +  /* aditional struct members */ +  /** points to an extenal (in memory) record of some sort of addressing +      information, passed to and interpreted by the funtions below */ +  void* addr_inf; +  /** tree levels under this node */ +  u8_t tree_levels; +  /** number of objects at this level */ +  u16_t (*level_length)(void* addr_inf, u8_t level); +  /** compares object sub identifier with external id +      return zero when equal, nonzero when unequal */ +  s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); +  void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + +  /** async Questions */ +  void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); +  void (*get_value_q)(u8_t rid, struct obj_def *od); +  void (*set_test_q)(u8_t rid, struct obj_def *od); +  void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value); +  /** async Answers */ +  void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); +  void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); +  u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); +  void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); +  /** async Panic Close (agent returns error reply,  +      e.g. used for external transaction cleanup) */ +  void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident); +  void (*get_value_pc)(u8_t rid, struct obj_def *od); +  void (*set_test_pc)(u8_t rid, struct obj_def *od); +  void (*set_value_pc)(u8_t rid, struct obj_def *od); +}; + +/** export MIB tree from mib2.c */ +extern const struct mib_array_node internet; + +/** dummy function pointers for non-leaf MIB nodes from mib2.c */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(struct obj_def *od, u16_t len, void *value); +u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value); +void noleafs_set_value(struct obj_def *od, u16_t len, void *value); + +void snmp_oidtoip(s32_t *ident, struct ip_addr *ip); +void snmp_iptooid(struct ip_addr *ip, s32_t *ident); +void snmp_ifindextonetif(s32_t ifindex, struct netif **netif); +void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx); + +struct mib_list_node* snmp_mib_ln_alloc(s32_t id); +void snmp_mib_ln_free(struct mib_list_node *ln); +struct mib_list_rootnode* snmp_mib_lrn_alloc(void); +void snmp_mib_lrn_free(struct mib_list_rootnode *lrn); + +s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn); +s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); +struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); +struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); +u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); +u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_STRUCTS_H__ */ diff --git a/firmware/octoclock/include/lwip/sockets.h b/firmware/octoclock/include/lwip/sockets.h new file mode 100644 index 000000000..7b52e151c --- /dev/null +++ b/firmware/octoclock/include/lwip/sockets.h @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ + + +#ifndef __LWIP_SOCKETS_H__ +#define __LWIP_SOCKETS_H__ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include <stddef.h> /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* members are in network byte order */ +struct sockaddr_in { +  u8_t sin_len; +  u8_t sin_family; +  u16_t sin_port; +  struct in_addr sin_addr; +  char sin_zero[8]; +}; + +struct sockaddr { +  u8_t sa_len; +  u8_t sa_family; +  char sa_data[14]; +}; + +#ifndef socklen_t +#  define socklen_t u32_t +#endif + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM     1 +#define SOCK_DGRAM      2 +#define SOCK_RAW        3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h! + */ +#define  SO_DEBUG       0x0001 /* Unimplemented: turn on debugging info recording */ +#define  SO_ACCEPTCONN  0x0002 /* socket has had listen() */ +#define  SO_REUSEADDR   0x0004 /* Unimplemented: allow local address reuse */ +#define  SO_KEEPALIVE   0x0008 /* keep connections alive */ +#define  SO_DONTROUTE   0x0010 /* Unimplemented: just use interface addresses */ +#define  SO_BROADCAST   0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define  SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define  SO_LINGER      0x0080 /* linger on close if data present */ +#define  SO_OOBINLINE   0x0100 /* Unimplemented: leave received OOB data in line */ +#define  SO_REUSEPORT   0x0200 /* Unimplemented: allow local address & port reuse */ + +#define SO_DONTLINGER   ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF    0x1001    /* Unimplemented: send buffer size */ +#define SO_RCVBUF    0x1002    /* receive buffer size */ +#define SO_SNDLOWAT  0x1003    /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT  0x1004    /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO  0x1005    /* Unimplemented: send timeout */ +#define SO_RCVTIMEO  0x1006    /* receive timeout */ +#define SO_ERROR     0x1007    /* get error status and clear */ +#define SO_TYPE      0x1008    /* get socket type */ +#define SO_CONTIMEO  0x1009    /* Unimplemented: connect timeout */ +#define SO_NO_CHECK  0x100a    /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { +       int l_onoff;                /* option on/off */ +       int l_linger;               /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define  SOL_SOCKET  0xfff    /* options for socket level */ + + +#define AF_UNSPEC       0 +#define AF_INET         2 +#define PF_INET         AF_INET +#define PF_UNSPEC       AF_UNSPEC + +#define IPPROTO_IP      0 +#define IPPROTO_TCP     6 +#define IPPROTO_UDP     17 +#define IPPROTO_UDPLITE 136 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK       0x01    /* Peeks at an incoming message */ +#define MSG_WAITALL    0x02    /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB        0x04    /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT   0x08    /* Nonblocking i/o for this operation only */ +#define MSG_MORE       0x10    /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS             1 +#define IP_TTL             2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY    0x01    /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE  0x02    /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE   0x03    /* set pcb->keep_idle  - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL  0x04    /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT    0x05    /* set pcb->keep_cnt   - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_IGMP +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_ADD_MEMBERSHIP  3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL   5 +#define IP_MULTICAST_IF    6 +#define IP_MULTICAST_LOOP  7 + +typedef struct ip_mreq { +    struct in_addr imr_multiaddr; /* IP multicast address of group */ +    struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired.  These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network.  Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load).  The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service.  In many networks + * better performance for one of these parameters is coupled with worse + * performance on another.  Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK          0x1E +#define IPTOS_TOS(tos)          ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY          0x10 +#define IPTOS_THROUGHPUT        0x08 +#define IPTOS_RELIABILITY       0x04 +#define IPTOS_LOWCOST           0x02 +#define IPTOS_MINCOST           IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only.  The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK                 0xe0 +#define IPTOS_PREC(tos)                ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL           0xe0 +#define IPTOS_PREC_INTERNETCONTROL      0xc0 +#define IPTOS_PREC_CRITIC_ECP           0xa0 +#define IPTOS_PREC_FLASHOVERRIDE        0x80 +#define IPTOS_PREC_FLASH                0x60 +#define IPTOS_PREC_IMMEDIATE            0x40 +#define IPTOS_PREC_PRIORITY             0x20 +#define IPTOS_PREC_ROUTINE              0x00 + + +/* + * Commands for ioctlsocket(),  taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word.  The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK    0x7fU           /* parameters must be < 128 bytes */ +#define IOC_VOID        0x20000000UL    /* no parameters */ +#define IOC_OUT         0x40000000UL    /* copy out parameters */ +#define IOC_IN          0x80000000UL    /* copy in parameters */ +#define IOC_INOUT       (IOC_IN|IOC_OUT) +                                        /* 0x20000000 distinguishes new & +                                           old ioctl's */ +#define _IO(x,y)        (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t)     (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t)     (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD    _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO     _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT  _IOW('s',  0, unsigned long)  /* set high watermark */ +#define SIOCGHIWAT  _IOR('s',  1, unsigned long)  /* get high watermark */ +#define SIOCSLOWAT  _IOW('s',  2, unsigned long)  /* set low watermark */ +#define SIOCGLOWAT  _IOR('s',  3, unsigned long)  /* get low watermark */ +#define SIOCATMARK  _IOR('s',  7, unsigned long)  /* at oob mark? */ +#endif + +/* Socket flags: */ +#ifndef O_NONBLOCK +#define O_NONBLOCK    04000U +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET +  #undef  FD_SETSIZE +  /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ +  #define FD_SETSIZE    MEMP_NUM_NETCONN +  #define FD_SET(n, p)  ((p)->fd_bits[(n)/8] |=  (1 << ((n) & 7))) +  #define FD_CLR(n, p)  ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7))) +  #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] &   (1 << ((n) & 7))) +  #define FD_ZERO(p)    memset((void*)(p),0,sizeof(*(p))) + +  typedef struct fd_set { +          unsigned char fd_bits [(FD_SETSIZE+7)/8]; +        } fd_set; + +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include <sys/time.h> in cc.h */  +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { +  long    tv_sec;         /* seconds */ +  long    tv_usec;        /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +void lwip_socket_init(void); + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, +      struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, +    const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, +                struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); + +#if LWIP_COMPAT_SOCKETS +#define accept(a,b,c)         lwip_accept(a,b,c) +#define bind(a,b,c)           lwip_bind(a,b,c) +#define shutdown(a,b)         lwip_shutdown(a,b) +#define closesocket(s)        lwip_close(s) +#define connect(a,b,c)        lwip_connect(a,b,c) +#define getsockname(a,b,c)    lwip_getsockname(a,b,c) +#define getpeername(a,b,c)    lwip_getpeername(a,b,c) +#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) +#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) +#define listen(a,b)           lwip_listen(a,b) +#define recv(a,b,c,d)         lwip_recv(a,b,c,d) +#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) +#define send(a,b,c,d)         lwip_send(a,b,c,d) +#define sendto(a,b,c,d,e,f)   lwip_sendto(a,b,c,d,e,f) +#define socket(a,b,c)         lwip_socket(a,b,c) +#define select(a,b,c,d,e)     lwip_select(a,b,c,d,e) +#define ioctlsocket(a,b,c)    lwip_ioctl(a,b,c) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(a,b,c)           lwip_read(a,b,c) +#define write(a,b,c)          lwip_write(a,b,c) +#define close(s)              lwip_close(s) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* __LWIP_SOCKETS_H__ */ diff --git a/firmware/octoclock/include/lwip/stats.h b/firmware/octoclock/include/lwip/stats.h new file mode 100644 index 000000000..aa179f5c0 --- /dev/null +++ b/firmware/octoclock/include/lwip/stats.h @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_STATS_H__ +#define __LWIP_STATS_H__ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER     u32_t +#define STAT_COUNTER_F   U32_F +#else +#define STAT_COUNTER     u16_t +#define STAT_COUNTER_F   U16_F +#endif  + +struct stats_proto { +  STAT_COUNTER xmit;             /* Transmitted packets. */ +  STAT_COUNTER recv;             /* Received packets. */ +  STAT_COUNTER fw;               /* Forwarded packets. */ +  STAT_COUNTER drop;             /* Dropped packets. */ +  STAT_COUNTER chkerr;           /* Checksum error. */ +  STAT_COUNTER lenerr;           /* Invalid length error. */ +  STAT_COUNTER memerr;           /* Out of memory error. */ +  STAT_COUNTER rterr;            /* Routing error. */ +  STAT_COUNTER proterr;          /* Protocol error. */ +  STAT_COUNTER opterr;           /* Error in options. */ +  STAT_COUNTER err;              /* Misc error. */ +  STAT_COUNTER cachehit; +}; + +struct stats_igmp { +  STAT_COUNTER lenerr;           /* Invalid length error. */ +  STAT_COUNTER chkerr;           /* Checksum error. */ +  STAT_COUNTER v1_rxed;          /* */ +  STAT_COUNTER join_sent;        /* */ +  STAT_COUNTER leave_sent;       /* */ +  STAT_COUNTER unicast_query;    /* */ +  STAT_COUNTER report_sent;      /* */ +  STAT_COUNTER report_rxed;      /* */ +  STAT_COUNTER group_query_rxed; /* */ +}; + +struct stats_mem { +  mem_size_t avail; +  mem_size_t used; +  mem_size_t max; +  STAT_COUNTER err; +  STAT_COUNTER illegal; +}; + +struct stats_syselem { +  STAT_COUNTER used; +  STAT_COUNTER max; +  STAT_COUNTER err; +}; + +struct stats_sys { +  struct stats_syselem sem; +  struct stats_syselem mbox; +}; + +struct stats_ { +#if LINK_STATS +  struct stats_proto link; +#endif +#if ETHARP_STATS +  struct stats_proto etharp; +#endif +#if IPFRAG_STATS +  struct stats_proto ip_frag; +#endif +#if IP_STATS +  struct stats_proto ip; +#endif +#if ICMP_STATS +  struct stats_proto icmp; +#endif +#if IGMP_STATS +  struct stats_igmp igmp; +#endif +#if UDP_STATS +  struct stats_proto udp; +#endif +#if TCP_STATS +  struct stats_proto tcp; +#endif +#if MEM_STATS +  struct stats_mem mem; +#endif +#if MEMP_STATS +  struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS +  struct stats_sys sys; +#endif +}; + +extern struct stats_ lwip_stats; + +#define stats_init() /* Compatibility define, not init needed. */ + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#else +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp) +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \ +                                    if (lwip_stats.mem.max < lwip_stats.mem.used) { \ +                                        lwip_stats.mem.max = lwip_stats.mem.used; \ +                                    } \ +                                 } while(0) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \ +                                    if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \ +                                        lwip_stats.memp[i].max = lwip_stats.memp[i].used; \ +                                    } \ +                                 } while(0) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_DISPLAY() +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void); +void stats_display_proto(struct stats_proto *proto, char *name); +void stats_display_igmp(struct stats_igmp *igmp); +void stats_display_mem(struct stats_mem *mem, char *name); +void stats_display_memp(struct stats_mem *mem, int index); +void stats_display_sys(struct stats_sys *sys); +#else +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_STATS_H__ */ diff --git a/firmware/octoclock/include/lwip/sys.h b/firmware/octoclock/include/lwip/sys.h new file mode 100644 index 000000000..0cc84ddf1 --- /dev/null +++ b/firmware/octoclock/include/lwip/sys.h @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_SYS_H__ +#define __LWIP_SYS_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null +   definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mbox_t; +struct sys_timeo {u8_t dummy;}; + +#define sys_init() +#define sys_timeout(m,h,a) +#define sys_untimeout(m,a) +#define sys_sem_new(c) c +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_sem_wait_timeout(s,t) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_mbox_new(s) 0 +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) + +#define sys_thread_new(n,t,a,s,p) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/* sys_mbox_tryfetch returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT  + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { +  struct sys_timeo *next; +  u32_t time; +  sys_timeout_handler h; +  void *arg; +}; + +struct sys_timeouts { +  struct sys_timeo *next; +}; + +/* sys_init() must be called before anthing else. */ +void sys_init(void); + +/* + * sys_timeout(): + * + * Schedule a timeout a specified amount of milliseconds in the + * future. When the timeout occurs, the specified timeout handler will + * be called. The handler will be passed the "arg" argument when + * called. + * + */ +void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +void sys_untimeout(sys_timeout_handler h, void *arg); +struct sys_timeouts *sys_arch_timeouts(void); + +/* Semaphore functions. */ +sys_sem_t sys_sem_new(u8_t count); +void sys_sem_signal(sys_sem_t sem); +u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout); +void sys_sem_free(sys_sem_t sem); +void sys_sem_wait(sys_sem_t sem); +int sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout); + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ +#endif +#ifndef sys_jiffies +u32_t sys_jiffies(void); /* since power up. */ +#endif + +/* Mailbox functions. */ +sys_mbox_t sys_mbox_new(int size); +void sys_mbox_post(sys_mbox_t mbox, void *msg); +err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg); +u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout); +#ifndef sys_arch_mbox_tryfetch /* Allow port to override with a macro */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg); +#endif +/* For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +void sys_mbox_free(sys_mbox_t mbox); +void sys_mbox_fetch(sys_mbox_t mbox, void **msg); + +/* Thread functions. */ +sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/** Returns the current time in milliseconds. */ +u32_t sys_now(void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. +   In some implementations they can provide a more light-weight protection +   mechanism than using semaphores. Otherwise semaphores can be used for +   implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex.  This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void); +void sys_arch_unprotect(sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ +                                SYS_ARCH_DECL_PROTECT(old_level); \ +                                SYS_ARCH_PROTECT(old_level); \ +                                var += val; \ +                                SYS_ARCH_UNPROTECT(old_level); \ +                              } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ +                                SYS_ARCH_DECL_PROTECT(old_level); \ +                                SYS_ARCH_PROTECT(old_level); \ +                                var -= val; \ +                                SYS_ARCH_UNPROTECT(old_level); \ +                              } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ +                                SYS_ARCH_DECL_PROTECT(old_level); \ +                                SYS_ARCH_PROTECT(old_level); \ +                                ret = var; \ +                                SYS_ARCH_UNPROTECT(old_level); \ +                              } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ +                                SYS_ARCH_DECL_PROTECT(old_level); \ +                                SYS_ARCH_PROTECT(old_level); \ +                                var = val; \ +                                SYS_ARCH_UNPROTECT(old_level); \ +                              } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SYS_H__ */ diff --git a/firmware/octoclock/include/lwip/tcp.h b/firmware/octoclock/include/lwip/tcp.h new file mode 100644 index 000000000..8f6b9d3c1 --- /dev/null +++ b/firmware/octoclock/include/lwip/tcp.h @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_TCP_H__ +#define __LWIP_TCP_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +#define tcp_init() /* Compatibility define, not init needed. */ +void             tcp_tmr     (void);  /* Must be called every +                                         TCP_TMR_INTERVAL +                                         ms. (Typically 250 ms). */ +/* Application program's interface: */ +struct tcp_pcb * tcp_new     (void); +struct tcp_pcb * tcp_alloc   (u8_t prio); + +void             tcp_arg     (struct tcp_pcb *pcb, void *arg); +void             tcp_accept  (struct tcp_pcb *pcb, +                              err_t (* accept)(void *arg, struct tcp_pcb *newpcb, +                 err_t err)); +void             tcp_recv    (struct tcp_pcb *pcb, +                              err_t (* recv)(void *arg, struct tcp_pcb *tpcb, +                              struct pbuf *p, err_t err)); +void             tcp_sent    (struct tcp_pcb *pcb, +                              err_t (* sent)(void *arg, struct tcp_pcb *tpcb, +                              u16_t len)); +void             tcp_poll    (struct tcp_pcb *pcb, +                              err_t (* poll)(void *arg, struct tcp_pcb *tpcb), +                              u8_t interval); +void             tcp_err     (struct tcp_pcb *pcb, +                              void (* err)(void *arg, err_t err)); + +#define          tcp_mss(pcb)      ((pcb)->mss) +#define          tcp_sndbuf(pcb)   ((pcb)->snd_buf) + +#if TCP_LISTEN_BACKLOG +#define          tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--) +#else  /* TCP_LISTEN_BACKLOG */ +#define          tcp_accepted(pcb) +#endif /* TCP_LISTEN_BACKLOG */ + +void             tcp_recved  (struct tcp_pcb *pcb, u16_t len); +err_t            tcp_bind    (struct tcp_pcb *pcb, struct ip_addr *ipaddr, +                              u16_t port); +err_t            tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr, +                              u16_t port, err_t (* connected)(void *arg, +                              struct tcp_pcb *tpcb, +                              err_t err)); + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); +#define          tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void             tcp_abandon (struct tcp_pcb *pcb, int reset); +#define          tcp_abort(pcb) tcp_abandon((pcb), 1) +err_t            tcp_close   (struct tcp_pcb *pcb); + +/* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t            tcp_write   (struct tcp_pcb *pcb, const void *dataptr, u16_t len, +                              u8_t apiflags); + +void             tcp_setprio (struct tcp_pcb *pcb, u8_t prio); + +#define TCP_PRIO_MIN    1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX    127 + +/* It is also possible to call these two functions at the right +   intervals (instead of calling tcp_tmr()). */ +void             tcp_slowtmr (void); +void             tcp_fasttmr (void); + + +/* Only used by IP to pass a TCP segment to TCP: */ +void             tcp_input   (struct pbuf *p, struct netif *inp); +/* Used within the TCP code only: */ +err_t            tcp_output  (struct tcp_pcb *pcb); +void             tcp_rexmit  (struct tcp_pcb *pcb); +void             tcp_rexmit_rto  (struct tcp_pcb *pcb); +u32_t            tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb); + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + *   than one unsent segment - with lwIP, this can happen although unsent->len < mss) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ +                            ((tpcb)->flags & TF_NODELAY) || \ +                            (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ +                              ((tpcb)->unsent->len >= (tpcb)->mss))) \ +                            ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b)     ((s32_t)((a)-(b)) < 0) +#define TCP_SEQ_LEQ(a,b)    ((s32_t)((a)-(b)) <= 0) +#define TCP_SEQ_GT(a,b)     ((s32_t)((a)-(b)) > 0) +#define TCP_SEQ_GEQ(a,b)    ((s32_t)((a)-(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL       250  /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL      TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL      (2*TCP_TMR_INTERVAL)  /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT        6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef  TCP_KEEPIDLE_DEFAULT +#define  TCP_KEEPIDLE_DEFAULT     7200000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef  TCP_KEEPINTVL_DEFAULT +#define  TCP_KEEPINTVL_DEFAULT    75000UL   /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef  TCP_KEEPCNT_DEFAULT +#define  TCP_KEEPCNT_DEFAULT      9U        /* Default Counter for KEEPALIVE probes */ +#endif + +#define  TCP_MAXIDLE              TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT  /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { +  PACK_STRUCT_FIELD(u16_t src); +  PACK_STRUCT_FIELD(u16_t dest); +  PACK_STRUCT_FIELD(u32_t seqno); +  PACK_STRUCT_FIELD(u32_t ackno); +  PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); +  PACK_STRUCT_FIELD(u16_t wnd); +  PACK_STRUCT_FIELD(u16_t chksum); +  PACK_STRUCT_FIELD(u16_t urgp); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8) +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr)  (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr)) +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags)) +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) + +#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \ +          TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0)) + +enum tcp_state { +  CLOSED      = 0, +  LISTEN      = 1, +  SYN_SENT    = 2, +  SYN_RCVD    = 3, +  ESTABLISHED = 4, +  FIN_WAIT_1  = 5, +  FIN_WAIT_2  = 6, +  CLOSE_WAIT  = 7, +  CLOSING     = 8, +  LAST_ACK    = 9, +  TIME_WAIT   = 10 +}; + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET     (u8_t)0x08U   /* Connection was reset. */ +#define TF_CLOSED    (u8_t)0x10U   /* Connection was sucessfully closed. */ +#define TF_GOT_FIN   (u8_t)0x20U   /* Connection was closed by the remote end. */ + + +#if LWIP_CALLBACK_API +  /* Function to call when a listener has been connected. +   * @param arg user-supplied argument (tcp_pcb.callback_arg) +   * @param pcb a new tcp_pcb that now is connected +   * @param err an error argument (TODO: that is current always ERR_OK?) +   * @return ERR_OK: accept the new connection, +   *                 any other err_t abortsthe new connection +   */ +#define DEF_ACCEPT_CALLBACK  err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err) +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ +  type *next; /* for the linked list */ \ +  enum tcp_state state; /* TCP state */ \ +  u8_t prio; \ +  void *callback_arg; \ +  /* ports are in host byte order */ \ +  u16_t local_port; \ +  /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ +  DEF_ACCEPT_CALLBACK + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ +  IP_PCB; +/** protocol specific PCB members */ +  TCP_PCB_COMMON(struct tcp_pcb); + +  /* ports are in host byte order */ +  u16_t remote_port; +   +  u8_t flags; +#define TF_ACK_DELAY   ((u8_t)0x01U)   /* Delayed ACK. */ +#define TF_ACK_NOW     ((u8_t)0x02U)   /* Immediate ACK. */ +#define TF_INFR        ((u8_t)0x04U)   /* In fast recovery. */ +#define TF_TIMESTAMP   ((u8_t)0x08U)   /* Timestamp option enabled */ +#define TF_FIN         ((u8_t)0x20U)   /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY     ((u8_t)0x40U)   /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u8_t)0x80U)   /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ + +  /* the rest of the fields are in host byte order +     as we have to do some math with them */ +  /* receiver variables */ +  u32_t rcv_nxt;   /* next seqno expected */ +  u16_t rcv_wnd;   /* receiver window available */ +  u16_t rcv_ann_wnd; /* receiver window to announce */ +  u32_t rcv_ann_right_edge; /* announced right edge of window */ + +  /* Timers */ +  u32_t tmr; +  u8_t polltmr, pollinterval; +   +  /* Retransmission timer. */ +  s16_t rtime; +   +  u16_t mss;   /* maximum segment size */ +   +  /* RTT (round trip time) estimation variables */ +  u32_t rttest; /* RTT estimate in 500ms ticks */ +  u32_t rtseq;  /* sequence number being timed */ +  s16_t sa, sv; /* @todo document this */ + +  s16_t rto;    /* retransmission time-out */ +  u8_t nrtx;    /* number of retransmissions */ + +  /* fast retransmit/recovery */ +  u32_t lastack; /* Highest acknowledged seqno. */ +  u8_t dupacks; +   +  /* congestion avoidance/control variables */ +  u16_t cwnd;   +  u16_t ssthresh; + +  /* sender variables */ +  u32_t snd_nxt;   /* next new seqno to be sent */ +  u16_t snd_wnd;   /* sender window */ +  u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last +                             window update. */ +  u32_t snd_lbb;       /* Sequence number of next byte to be buffered. */ + +  u16_t acked; +   +  u16_t snd_buf;   /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3) +  u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ +   +   +  /* These are ordered by sequence number: */ +  struct tcp_seg *unsent;   /* Unsent (queued) segments. */ +  struct tcp_seg *unacked;  /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ   +  struct tcp_seg *ooseq;    /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + +  struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API +  /* Function to be called when more send buffer space is available. +   * @param arg user-supplied argument (tcp_pcb.callback_arg) +   * @param pcb the tcp_pcb which has send buffer space available +   * @param space the amount of bytes available +   * @return ERR_OK: try to send some data by calling tcp_output +   */ +  err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space); +   +  /* Function to be called when (in-sequence) data has arrived. +   * @param arg user-supplied argument (tcp_pcb.callback_arg) +   * @param pcb the tcp_pcb for which data has arrived +   * @param p the packet buffer which arrived +   * @param err an error argument (TODO: that is current always ERR_OK?) +   * @return ERR_OK: try to send some data by calling tcp_output +   */ +  err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); + +  /* Function to be called when a connection has been set up. +   * @param arg user-supplied argument (tcp_pcb.callback_arg) +   * @param pcb the tcp_pcb that now is connected +   * @param err an error argument (TODO: that is current always ERR_OK?) +   * @return value is currently ignored +   */ +  err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err); + +  /* Function which is called periodically. +   * The period can be adjusted in multiples of the TCP slow timer interval +   * by changing tcp_pcb.polltmr. +   * @param arg user-supplied argument (tcp_pcb.callback_arg) +   * @param pcb the tcp_pcb to poll for +   * @return ERR_OK: try to send some data by calling tcp_output +   */ +  err_t (* poll)(void *arg, struct tcp_pcb *pcb); + +  /* Function to be called whenever a fatal error occurs. +   * There is no pcb parameter since most of the times, the pcb is +   * already deallocated (or there is no pcb) when this function is called. +   * @param arg user-supplied argument (tcp_pcb.callback_arg) +   * @param err an indication why the error callback is called: +   *            ERR_ABRT: aborted through tcp_abort or by a TCP timer +   *            ERR_RST: the connection was reset by the remote host +   */ +  void (* errf)(void *arg, err_t err); +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS +  u32_t ts_lastacksent; +  u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + +  /* idle time before KEEPALIVE is sent */ +  u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE +  u32_t keep_intvl; +  u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ +   +  /* Persist timer counter */ +  u32_t persist_cnt; +  /* Persist timer back-off */ +  u8_t persist_backoff; + +  /* KEEPALIVE counter */ +  u8_t keep_cnt_sent; +}; + +struct tcp_pcb_listen {   +/* Common members of all PCB types */ +  IP_PCB; +/* Protocol specific PCB members */ +  TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG +  u8_t backlog; +  u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { +  LWIP_EVENT_ACCEPT, +  LWIP_EVENT_SENT, +  LWIP_EVENT_RECV, +  LWIP_EVENT_CONNECTED, +  LWIP_EVENT_POLL, +  LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, +         enum lwip_event, +         struct pbuf *p, +         u16_t size, +         err_t err); + +#define TCP_EVENT_ACCEPT(pcb,err,ret)    ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ +                LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ +                   LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ +                LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ +                LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret)       ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ +                LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err)  lwip_tcp_event((arg), NULL, \ +                LWIP_EVENT_ERR, NULL, 0, (err)) +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret)                          \ +  do {                                                         \ +    if((pcb)->accept != NULL)                                  \ +      (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err));  \ +    else (ret) = ERR_OK;                                       \ +  } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret)                          \ +  do {                                                         \ +    if((pcb)->sent != NULL)                                    \ +      (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space));  \ +    else (ret) = ERR_OK;                                       \ +  } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret)                           \ +  do {                                                          \ +    if((pcb)->recv != NULL) {                                   \ +      (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \ +    } else {                                                    \ +      (ret) = ERR_OK;                                           \ +      if (p != NULL)                                            \ +        pbuf_free(p);                                           \ +    }                                                           \ +  } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret)                         \ +  do {                                                           \ +    if((pcb)->connected != NULL)                                 \ +      (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ +    else (ret) = ERR_OK;                                         \ +  } while (0) + +#define TCP_EVENT_POLL(pcb,ret)                                \ +  do {                                                         \ +    if((pcb)->poll != NULL)                                    \ +      (ret) = (pcb)->poll((pcb)->callback_arg,(pcb));          \ +    else (ret) = ERR_OK;                                       \ +  } while (0) + +#define TCP_EVENT_ERR(errf,arg,err)                            \ +  do {                                                         \ +    if((errf) != NULL)                                         \ +      (errf)((arg),(err));                                     \ +  } while (0) + +#endif /* LWIP_EVENT_API */ + +/* This structure represents a TCP segment on the unsent and unacked queues */ +struct tcp_seg { +  struct tcp_seg *next;    /* used when putting segements on a queue */ +  struct pbuf *p;          /* buffer containing data + TCP header */ +  void *dataptr;           /* pointer to the TCP data in the pbuf */ +  u16_t len;               /* the TCP length of this segment */ +  u8_t  flags; +#define TF_SEG_OPTS_MSS   (u8_t)0x01U   /* Include MSS option. */ +#define TF_SEG_OPTS_TS    (u8_t)0x02U   /* Include timestamp option. */ +  struct tcp_hdr *tcphdr;  /* the TCP header */ +}; + +#define LWIP_TCP_OPT_LENGTH(flags)              \ +  (flags & TF_SEG_OPTS_MSS ? 4  : 0) +          \ +  (flags & TF_SEG_OPTS_TS  ? 12 : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) |          \ +                                            ((u32_t)4 << 16) |          \ +                                            (((u32_t)TCP_MSS / 256) << 8) | \ +                                            (TCP_MSS & 255)) + +/* Internal functions and global variables: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb); +void tcp_pcb_purge(struct tcp_pcb *pcb); +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb); + +u8_t tcp_segs_free(struct tcp_seg *seg); +u8_t tcp_seg_free(struct tcp_seg *seg); +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg); + +#define tcp_ack(pcb)                               \ +  do {                                             \ +    if((pcb)->flags & TF_ACK_DELAY) {              \ +      (pcb)->flags &= ~TF_ACK_DELAY;               \ +      (pcb)->flags |= TF_ACK_NOW;                  \ +      tcp_output(pcb);                             \ +    }                                              \ +    else {                                         \ +      (pcb)->flags |= TF_ACK_DELAY;                \ +    }                                              \ +  } while (0) + +#define tcp_ack_now(pcb)                           \ +  do {                                             \ +    (pcb)->flags |= TF_ACK_NOW;                    \ +    tcp_output(pcb);                               \ +  } while (0) + +err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags); +err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len, +                  u8_t flags, u8_t apiflags, u8_t optflags); + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg); + +void tcp_rst(u32_t seqno, u32_t ackno, +       struct ip_addr *local_ip, struct ip_addr *remote_ip, +       u16_t local_port, u16_t remote_port); + +u32_t tcp_next_iss(void); + +void tcp_keepalive(struct tcp_pcb *pcb); +void tcp_zero_window_probe(struct tcp_pcb *pcb); + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr); +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr); +void tcp_debug_print_flags(u8_t flags); +void tcp_debug_print_state(enum tcp_state s); +void tcp_debug_print_pcbs(void); +s16_t tcp_pcbs_sane(void); +#else +#  define tcp_debug_print(tcphdr) +#  define tcp_debug_print_flags(flags) +#  define tcp_debug_print_state(s) +#  define tcp_debug_print_pcbs() +#  define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +#if NO_SYS +#define tcp_timer_needed() +#else +void tcp_timer_needed(void); +#endif + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ +  struct tcp_pcb_listen *listen_pcbs;  +  struct tcp_pcb *pcbs; +}; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs;  /* List of all TCP PCBs that are in a +              state in which they accept or send +              data. */ +extern struct tcp_pcb *tcp_tw_pcbs;      /* List of all TCP PCBs in TIME-WAIT. */ + +extern struct tcp_pcb *tcp_tmp_pcb;      /* Only used for temporary storage. */ + +/* Axioms about the above lists:    +   1) Every TCP PCB that is not CLOSED is in one of the lists. +   2) A PCB is only in one of the lists. +   3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. +   4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ + +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB +   with a PCB list or removes a PCB from a list, respectively. */ +#if 0 +#define TCP_REG(pcbs, npcb) do {\ +                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \ +                            for(tcp_tmp_pcb = *pcbs; \ +          tcp_tmp_pcb != NULL; \ +        tcp_tmp_pcb = tcp_tmp_pcb->next) { \ +                                LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \ +                            } \ +                            LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \ +                            npcb->next = *pcbs; \ +                            LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \ +                            *(pcbs) = npcb; \ +                            LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ +              tcp_timer_needed(); \ +                            } while(0) +#define TCP_RMV(pcbs, npcb) do { \ +                            LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \ +                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \ +                            if(*pcbs == npcb) { \ +                               *pcbs = (*pcbs)->next; \ +                            } else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ +                               if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \ +                                  tcp_tmp_pcb->next = npcb->next; \ +                                  break; \ +                               } \ +                            } \ +                            npcb->next = NULL; \ +                            LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ +                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \ +                            } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb)                        \ +  do {                                             \ +    npcb->next = *pcbs;                            \ +    *(pcbs) = npcb;                                \ +    tcp_timer_needed();                            \ +  } while (0) + +#define TCP_RMV(pcbs, npcb)                        \ +  do {                                             \ +    if(*(pcbs) == npcb) {                          \ +      (*(pcbs)) = (*pcbs)->next;                   \ +    }                                              \ +    else {                                         \ +      for(tcp_tmp_pcb = *pcbs;                                         \ +          tcp_tmp_pcb != NULL;                                         \ +          tcp_tmp_pcb = tcp_tmp_pcb->next) {                           \ +        if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) {   \ +          tcp_tmp_pcb->next = npcb->next;          \ +          break;                                   \ +        }                                          \ +      }                                            \ +    }                                              \ +    npcb->next = NULL;                             \ +  } while(0) + +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/firmware/octoclock/include/lwip/tcpip.h b/firmware/octoclock/include/lwip/tcpip.h new file mode 100644 index 000000000..75393ee91 --- /dev/null +++ b/firmware/octoclock/include/lwip/tcpip.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_TCPIP_H__ +#define __LWIP_TCPIP_H__ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" +#include "lwip/netifapi.h" +#include "lwip/pbuf.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_sem_t lock_tcpip_core; +#define LOCK_TCPIP_CORE()     sys_sem_wait(lock_tcpip_core) +#define UNLOCK_TCPIP_CORE()   sys_sem_signal(lock_tcpip_core) +#define TCPIP_APIMSG(m)       tcpip_apimsg_lock(m) +#define TCPIP_APIMSG_ACK(m) +#define TCPIP_NETIFAPI(m)     tcpip_netifapi_lock(m) +#define TCPIP_NETIFAPI_ACK(m) +#else +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#define TCPIP_APIMSG(m)       tcpip_apimsg(m) +#define TCPIP_APIMSG_ACK(m)   sys_sem_signal(m->conn->op_completed) +#define TCPIP_NETIFAPI(m)     tcpip_netifapi(m) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(m->sem) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +void tcpip_init(void (* tcpip_init_done)(void *), void *arg); + +#if LWIP_NETCONN +err_t tcpip_apimsg(struct api_msg *apimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_apimsg_lock(struct api_msg *apimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +#if LWIP_NETIF_API +err_t tcpip_netifapi(struct netifapi_msg *netifapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block); +#define tcpip_callback(f, ctx)              tcpip_callback_with_block(f, ctx, 1) + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); + +enum tcpip_msg_type { +#if LWIP_NETCONN +  TCPIP_MSG_API, +#endif /* LWIP_NETCONN */ +  TCPIP_MSG_INPKT, +#if LWIP_NETIF_API +  TCPIP_MSG_NETIFAPI, +#endif /* LWIP_NETIF_API */ +  TCPIP_MSG_CALLBACK, +  TCPIP_MSG_TIMEOUT, +  TCPIP_MSG_UNTIMEOUT +}; + +struct tcpip_msg { +  enum tcpip_msg_type type; +  sys_sem_t *sem; +  union { +#if LWIP_NETCONN +    struct api_msg *apimsg; +#endif /* LWIP_NETCONN */ +#if LWIP_NETIF_API +    struct netifapi_msg *netifapimsg; +#endif /* LWIP_NETIF_API */ +    struct { +      struct pbuf *p; +      struct netif *netif; +    } inp; +    struct { +      void (*f)(void *ctx); +      void *ctx; +    } cb; +    struct { +      u32_t msecs; +      sys_timeout_handler h; +      void *arg; +    } tmo; +  } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* __LWIP_TCPIP_H__ */ diff --git a/firmware/octoclock/include/lwip/udp.h b/firmware/octoclock/include/lwip/udp.h new file mode 100644 index 000000000..d7b2a3820 --- /dev/null +++ b/firmware/octoclock/include/lwip/udp.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved.  + *  + * Redistribution and use in source and binary forms, with or without modification,  + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + *    derived from this software without specific prior written permission.  + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + *  + * Author: Adam Dunkels <adam@sics.se> + * + */ +#ifndef __LWIP_UDP_H__ +#define __LWIP_UDP_H__ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { +  PACK_STRUCT_FIELD(u16_t src); +  PACK_STRUCT_FIELD(u16_t dest);  /* src/dest UDP ports */ +  PACK_STRUCT_FIELD(u16_t len); +  PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +#  include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE  0x02U +#define UDP_FLAGS_CONNECTED  0x04U + +struct udp_pcb { +/* Common members of all PCB types */ +  IP_PCB; + +/* Protocol specific PCB members */ + +  struct udp_pcb *next; + +  u8_t flags; +  /* ports are in host byte order */ +  u16_t local_port, remote_port; + +#if LWIP_IGMP +  /* outgoing network interface for multicast packets */ +  struct ip_addr multicast_ip; +#endif /* LWIP_IGMP */ + +#if LWIP_UDPLITE +  /* used for UDP_LITE only */ +  u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + +  /* receive callback function +   * addr and port are in same byte order as in the pcb +   * The callback is responsible for freeing the pbuf +   * if it's not used any more. +   * +   * @param arg user supplied argument (udp_pcb.recv_arg) +   * @param pcb the udp_pcb which received data +   * @param p the packet buffer that was received +   * @param addr the remote IP address from which the packet was received +   * @param port the remote port from which the packet was received +   */ +  void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p, +    struct ip_addr *addr, u16_t port); +  /* user-supplied argument for the recv callback */ +  void *recv_arg;   +}; +/* udp_pcbs export for exernal reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the +   UDP code. */ +struct udp_pcb * udp_new        (void); +void             udp_remove     (struct udp_pcb *pcb); +err_t            udp_bind       (struct udp_pcb *pcb, struct ip_addr *ipaddr, +                 u16_t port); +err_t            udp_connect    (struct udp_pcb *pcb, struct ip_addr *ipaddr, +                 u16_t port); +void             udp_disconnect    (struct udp_pcb *pcb); +void             udp_recv       (struct udp_pcb *pcb, +         void (* recv)(void *arg, struct udp_pcb *upcb, +                 struct pbuf *p, +                 struct ip_addr *addr, +                 u16_t port), +         void *recv_arg); +err_t            udp_sendto_if  (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif); +err_t            udp_sendto     (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port); +err_t            udp_send       (struct udp_pcb *pcb, struct pbuf *p); + +#define          udp_flags(pcb)  ((pcb)->flags) +#define          udp_setflags(pcb, f)  ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void             udp_input      (struct pbuf *p, struct netif *inp); + +#define udp_init() /* Compatibility define, not init needed. */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr); +#else +#define udp_debug_print(udphdr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* __LWIP_UDP_H__ */ diff --git a/firmware/octoclock/include/lwipopts.h b/firmware/octoclock/include/lwipopts.h new file mode 100644 index 000000000..3839eea83 --- /dev/null +++ b/firmware/octoclock/include/lwipopts.h @@ -0,0 +1,196 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + *  + * This file is part of GNU Radio + *  + * GNU Radio 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, or (at your option) + * any later version. + *  + * GNU Radio 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/* + * Our lwip options + */ + +#define NO_SYS				1 + + +// ---------- Memory options ---------- +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + *    4 byte alignment -> #define MEM_ALIGNMENT 4 + *    2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#define MEM_ALIGNMENT      		4 + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#define MEM_SIZE        		256 + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the lenght needed is returned. + */ +#define MEM_USE_POOLS                   0 + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your  + * inlude path somewhere.  + */ +#define MEMP_USE_CUSTOM_POOLS           0 + +// ---------- Internal Memory Pool Sizes ---------- +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#define MEMP_NUM_PBUF                   8 + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#define MEMP_NUM_UDP_PCB                4 + +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#define PBUF_LINK_HLEN                  16 +#define	ETH_PAD_SIZE			2 + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.  + */ +#define PBUF_POOL_SIZE                  8 + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +//#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#define PBUF_POOL_BUFSIZE               LWIP_MEM_ALIGN_SIZE(128+28+PBUF_LINK_HLEN) + + +// ---------- ARP options ---------- +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#define ARP_TABLE_SIZE                  5 + +/** + * ARP_QUEUEING==1: Outgoing packets are queued during hardware address + * resolution. + */ +#define ARP_QUEUEING                    0 + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#define MEMP_NUM_ARP_QUEUE              5 + +// ---------- IP options ---------- +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + *      IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + *      IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#define IP_OPTIONS_ALLOWED              0 + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#define IP_REASSEMBLY                   0 + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#define IP_FRAG                         0 + +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#define LWIP_DHCP                       0 + +/** + * LWIP_IGMP==1: Turn on IGMP module.  + */ +#define LWIP_IGMP                       0 + +/** + * LWIP_UDP==1: Turn on UDP. + */ +#define LWIP_UDP                        1 + +/** + * LWIP_TCP==1: Turn on TCP. + */ +#define LWIP_TCP                        0 + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#define LWIP_NETCONN                    0 + +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#define LWIP_SOCKET                     0 + +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#define LWIP_STATS                      0 + +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#define CHECKSUM_GEN_IP                 0 +  +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#define CHECKSUM_GEN_UDP                0 +  +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#define CHECKSUM_CHECK_IP               0 + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#define CHECKSUM_CHECK_UDP              0 + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#define LWIP_NETIF_LINK_CALLBACK        1 diff --git a/firmware/octoclock/include/lwippools.h b/firmware/octoclock/include/lwippools.h new file mode 100644 index 000000000..caee23c82 --- /dev/null +++ b/firmware/octoclock/include/lwippools.h @@ -0,0 +1,24 @@ +#ifndef INCLUDED_LWIPPOOLS_H +#define INCLUDED_LWIPPOOLS_H + +/* + * from comment at top of mem.c: + * + * To let mem_malloc() use pools (prevents fragmentation and is much faster than + * a heap but might waste some memory), define MEM_USE_POOLS to 1, define + * MEM_USE_CUSTOM_POOLS to 1 and create a file "lwippools.h" that includes a list + * of pools like this (more pools can be added between _START and _END): + * + * Define three pools with sizes 256, 512, and 1512 bytes + * LWIP_MALLOC_MEMPOOL_START + * LWIP_MALLOC_MEMPOOL(20, 256) + * LWIP_MALLOC_MEMPOOL(10, 512) + * LWIP_MALLOC_MEMPOOL(5, 1512) + * LWIP_MALLOC_MEMPOOL_END + */ + +LWIP_MALLOC_MEMPOOL_START +LWIP_MALLOC_MEMPOOL(2, 256) +LWIP_MALLOC_MEMPOOL_END + +#endif /* INCLUDED_LWIPPOOLS_H */ diff --git a/firmware/octoclock/include/net/enc28j60.h b/firmware/octoclock/include/net/enc28j60.h new file mode 100644 index 000000000..463303f3c --- /dev/null +++ b/firmware/octoclock/include/net/enc28j60.h @@ -0,0 +1,299 @@ +/*! \file enc28j60.h \brief Microchip ENC28J60 Ethernet Interface Driver. */ +//***************************************************************************** +// +// File Name	: 'enc28j60.h' +// Title		: Microchip ENC28J60 Ethernet Interface Driver +// Author		: Pascal Stang (c)2005 +// Created		: 9/22/2005 +// Revised		: 9/22/2005 +// Version		: 0.1 +// Target MCU	: Atmel AVR series +// Editor Tabs	: 4 +// +///	\ingroup network +///	\defgroup enc28j60 Microchip ENC28J60 Ethernet Interface Driver (enc28j60.c) +///	\code #include "net/enc28j60.h" \endcode +///	\par Overview +///		This driver provides initialization and transmit/receive +///	functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY. +/// This chip is novel in that it is a full MAC+PHY interface all in a 28-pin +/// chip, using an SPI interface to the host processor. +/// +// +//***************************************************************************** +//@{ + +#ifndef ENC28J60_H +#define ENC28J60_H + +#include <avrlibdefs.h> + +#include "enc28j60conf.h" + +// ENC28J60 Control Registers +// Control register definitions are a combination of address, +// bank number, and Ethernet/MAC/PHY indicator bits. +// - Register address	(bits 0-4) +// - Bank number		(bits 5-6) +// - MAC/PHY indicator	(bit 7) +#define ADDR_MASK	0x1F +#define BANK_MASK	0x60 +#define SPRD_MASK	0x80 +// All-bank registers +#define EIE			0x1B +#define EIR			0x1C +#define ESTAT		0x1D +#define ECON2		0x1E +#define ECON1		0x1F +// Bank 0 registers +#define ERDPTL		(0x00|0x00) +#define ERDPTH		(0x01|0x00) +#define EWRPTL		(0x02|0x00) +#define EWRPTH		(0x03|0x00) +#define ETXSTL		(0x04|0x00) +#define ETXSTH		(0x05|0x00) +#define ETXNDL		(0x06|0x00) +#define ETXNDH		(0x07|0x00) +#define ERXSTL		(0x08|0x00) +#define ERXSTH		(0x09|0x00) +#define ERXNDL		(0x0A|0x00) +#define ERXNDH		(0x0B|0x00) +#define ERXRDPTL	(0x0C|0x00) +#define ERXRDPTH	(0x0D|0x00) +#define ERXWRPTL	(0x0E|0x00) +#define ERXWRPTH	(0x0F|0x00) +#define EDMASTL		(0x10|0x00) +#define EDMASTH		(0x11|0x00) +#define EDMANDL		(0x12|0x00) +#define EDMANDH		(0x13|0x00) +#define EDMADSTL	(0x14|0x00) +#define EDMADSTH	(0x15|0x00) +#define EDMACSL		(0x16|0x00) +#define EDMACSH		(0x17|0x00) +// Bank 1 registers +#define EHT0		(0x00|0x20) +#define EHT1		(0x01|0x20) +#define EHT2		(0x02|0x20) +#define EHT3		(0x03|0x20) +#define EHT4		(0x04|0x20) +#define EHT5		(0x05|0x20) +#define EHT6		(0x06|0x20) +#define EHT7		(0x07|0x20) +#define EPMM0		(0x08|0x20) +#define EPMM1		(0x09|0x20) +#define EPMM2		(0x0A|0x20) +#define EPMM3		(0x0B|0x20) +#define EPMM4		(0x0C|0x20) +#define EPMM5		(0x0D|0x20) +#define EPMM6		(0x0E|0x20) +#define EPMM7		(0x0F|0x20) +#define EPMCSL		(0x10|0x20) +#define EPMCSH		(0x11|0x20) +#define EPMOL		(0x14|0x20) +#define EPMOH		(0x15|0x20) +#define EWOLIE		(0x16|0x20) +#define EWOLIR		(0x17|0x20) +#define ERXFCON		(0x18|0x20) +#define EPKTCNT		(0x19|0x20) +// Bank 2 registers +#define MACON1		(0x00|0x40|0x80) +#define MACON2		(0x01|0x40|0x80) +#define MACON3		(0x02|0x40|0x80) +#define MACON4		(0x03|0x40|0x80) +#define MABBIPG		(0x04|0x40|0x80) +#define MAIPGL		(0x06|0x40|0x80) +#define MAIPGH		(0x07|0x40|0x80) +#define MACLCON1	(0x08|0x40|0x80) +#define MACLCON2	(0x09|0x40|0x80) +#define MAMXFLL		(0x0A|0x40|0x80) +#define MAMXFLH		(0x0B|0x40|0x80) +#define MAPHSUP		(0x0D|0x40|0x80) +#define MICON		(0x11|0x40|0x80) +#define MICMD		(0x12|0x40|0x80) +#define MIREGADR	(0x14|0x40|0x80) +#define MIWRL		(0x16|0x40|0x80) +#define MIWRH		(0x17|0x40|0x80) +#define MIRDL		(0x18|0x40|0x80) +#define MIRDH		(0x19|0x40|0x80) +// Bank 3 registers +#define MAADR1		(0x00|0x60|0x80) +#define MAADR0		(0x01|0x60|0x80) +#define MAADR3		(0x02|0x60|0x80) +#define MAADR2		(0x03|0x60|0x80) +#define MAADR5		(0x04|0x60|0x80) +#define MAADR4		(0x05|0x60|0x80) +#define EBSTSD		(0x06|0x60) +#define EBSTCON		(0x07|0x60) +#define EBSTCSL		(0x08|0x60) +#define EBSTCSH		(0x09|0x60) +#define MISTAT		(0x0A|0x60|0x80) +#define EREVID		(0x12|0x60) +#define ECOCON		(0x15|0x60) +#define EFLOCON		(0x17|0x60) +#define EPAUSL		(0x18|0x60) +#define EPAUSH		(0x19|0x60) +// PHY registers +#define PHCON1		0x00 +#define PHSTAT1		0x01 +#define PHHID1		0x02 +#define PHHID2		0x03 +#define PHCON2		0x10 +#define PHSTAT2		0x11 +#define PHIE		0x12 +#define PHIR		0x13 +#define PHLCON		0x14 + +// ENC28J60 EIE Register Bit Definitions +#define EIE_INTIE		0x80 +#define EIE_PKTIE		0x40 +#define EIE_DMAIE		0x20 +#define EIE_LINKIE		0x10 +#define EIE_TXIE		0x08 +#define EIE_WOLIE		0x04 +#define EIE_TXERIE		0x02 +#define EIE_RXERIE		0x01 +// ENC28J60 EIR Register Bit Definitions +#define EIR_PKTIF		0x40 +#define EIR_DMAIF		0x20 +#define EIR_LINKIF		0x10 +#define EIR_TXIF		0x08 +#define EIR_WOLIF		0x04 +#define EIR_TXERIF		0x02 +#define EIR_RXERIF		0x01 +// ENC28J60 ESTAT Register Bit Definitions +#define ESTAT_INT		0x80 +#define ESTAT_LATECOL	0x10 +#define ESTAT_RXBUSY	0x04 +#define ESTAT_TXABRT	0x02 +#define ESTAT_CLKRDY	0x01 +// ENC28J60 ECON2 Register Bit Definitions +#define ECON2_AUTOINC	0x80 +#define ECON2_PKTDEC	0x40 +#define ECON2_PWRSV		0x20 +#define ECON2_VRPS		0x08 +// ENC28J60 ECON1 Register Bit Definitions +#define ECON1_TXRST		0x80 +#define	ECON1_RXRST		0x40 +#define ECON1_DMAST		0x20 +#define ECON1_CSUMEN	0x10 +#define ECON1_TXRTS		0x08 +#define	ECON1_RXEN		0x04 +#define ECON1_BSEL1		0x02 +#define ECON1_BSEL0		0x01 +// ENC28J60 MACON1 Register Bit Definitions +#define MACON1_LOOPBK	0x10 +#define MACON1_TXPAUS	0x08 +#define MACON1_RXPAUS	0x04 +#define MACON1_PASSALL	0x02 +#define MACON1_MARXEN	0x01 +// ENC28J60 MACON2 Register Bit Definitions +#define MACON2_MARST	0x80 +#define MACON2_RNDRST	0x40 +#define MACON2_MARXRST	0x08 +#define MACON2_RFUNRST	0x04 +#define MACON2_MATXRST	0x02 +#define MACON2_TFUNRST	0x01 +// ENC28J60 MACON3 Register Bit Definitions +#define MACON3_PADCFG2	0x80 +#define MACON3_PADCFG1	0x40 +#define MACON3_PADCFG0	0x20 +#define MACON3_TXCRCEN	0x10 +#define MACON3_PHDRLEN	0x08 +#define MACON3_HFRMLEN	0x04 +#define MACON3_FRMLNEN	0x02 +#define MACON3_FULDPX	0x01 +// ENC28J60 MICMD Register Bit Definitions +#define MICMD_MIISCAN	0x02 +#define MICMD_MIIRD		0x01 +// ENC28J60 MISTAT Register Bit Definitions +#define MISTAT_NVALID	0x04 +#define MISTAT_SCAN		0x02 +#define MISTAT_BUSY		0x01 +// ENC28J60 PHY PHCON1 Register Bit Definitions +#define	PHCON1_PRST		0x8000 +#define	PHCON1_PLOOPBK	0x4000 +#define	PHCON1_PPWRSV	0x0800 +#define	PHCON1_PDPXMD	0x0100 +// ENC28J60 PHY PHSTAT1 Register Bit Definitions +#define	PHSTAT1_PFDPX	0x1000 +#define	PHSTAT1_PHDPX	0x0800 +#define	PHSTAT1_LLSTAT	0x0004 +#define	PHSTAT1_JBSTAT	0x0002 +// ENC28J60 PHY PHCON2 Register Bit Definitions +#define PHCON2_FRCLINK	0x4000 +#define PHCON2_TXDIS	0x2000 +#define PHCON2_JABBER	0x0400 +#define PHCON2_HDLDIS	0x0100 + +// ENC28J60 Packet Control Byte Bit Definitions +#define PKTCTRL_PHUGEEN		0x08 +#define PKTCTRL_PPADEN		0x04 +#define PKTCTRL_PCRCEN		0x02 +#define PKTCTRL_POVERRIDE	0x01 + +// SPI operation codes +#define ENC28J60_READ_CTRL_REG	0x00 +#define ENC28J60_READ_BUF_MEM	0x3A +#define ENC28J60_WRITE_CTRL_REG	0x40 +#define ENC28J60_WRITE_BUF_MEM	0x7A +#define ENC28J60_BIT_FIELD_SET	0x80 +#define ENC28J60_BIT_FIELD_CLR	0xA0 +#define ENC28J60_SOFT_RESET		0xFF + + +// buffer boundaries applied to internal 8K ram +//	entire available packet buffer space is allocated +#define TXSTART_INIT   	0x0000	// start TX buffer at 0 +#define RXSTART_INIT   	0x0600	// give TX buffer space for one full ethernet frame (~1500 bytes) +#define RXSTOP_INIT    	0x1FFF	// receive buffer gets the rest + +#define	MAX_FRAMELEN	1518	// maximum ethernet frame length + +// Ethernet constants +#define ETHERNET_MIN_PACKET_LENGTH	0x3C +//#define ETHERNET_HEADER_LENGTH		0x0E + +// setup ports for I/O +//void ax88796SetupPorts(void); + +//! do a ENC28J60 read operation +u08 enc28j60ReadOp(u08 op, u08 address); +//! do a ENC28J60 write operation +void enc28j60WriteOp(u08 op, u08 address, u08 data); +//! read the packet buffer memory +void enc28j60ReadBuffer(u16 len, u08* data); +//! write the packet buffer memory +void enc28j60WriteBuffer(u16 len, u08* data); +//! set the register bank for register at address +void enc28j60SetBank(u08 address); +//! read ax88796 register +u08 enc28j60Read(u08 address); +//! write ax88796 register +void enc28j60Write(u08 address, u08 data); +//! read a PHY register +u16 enc28j60PhyRead(u08 address); +//! write a PHY register +void enc28j60PhyWrite(u08 address, u16 data); + +//! initialize the ethernet interface for transmit/receive +void enc28j60Init(u08* macaddr); + +//! Packet transmit function. +/// Sends a packet on the network.  It is assumed that the packet is headed by a valid ethernet header. +/// \param len		Length of packet in bytes. +/// \param packet	Pointer to packet data. +/// \param len2		Length of the secound packet in bytes, can be 0. +/// \param packet2	Pointer to the secound packet data, can be NULL. +void enc28j60PacketSend(unsigned int len1, unsigned char* packet1, unsigned int len2, unsigned char* packet2); + +//! Packet receive function. +/// Gets a packet from the network receive buffer, if one is available. +/// The packet will by headed by an ethernet header. +/// \param	maxlen	The maximum acceptable length of a retrieved packet. +/// \param  buf 	Pointer to buffer. +/// \return Packet length in bytes if a packet was retrieved, zero otherwise. +unsigned int enc28j60PacketReceive(unsigned int maxlen, u08* buf); + +#endif +//@} + diff --git a/firmware/octoclock/include/net/enc28j60conf.h b/firmware/octoclock/include/net/enc28j60conf.h new file mode 100644 index 000000000..0acf5473c --- /dev/null +++ b/firmware/octoclock/include/net/enc28j60conf.h @@ -0,0 +1,49 @@ +/*! \file enc28j60conf.h \brief Microchip ENC28J60 Ethernet Interface Driver Configuration. */ +//***************************************************************************** +// +// File Name	: 'enc28j60conf.h' +// Title		: Microchip ENC28J60 Ethernet Interface Driver Configuration +// Author		: Pascal Stang +// Created		: 10/5/2004 +// Revised		: 8/22/2005 +// Version		: 0.1 +// Target MCU	: Atmel AVR series +// Editor Tabs	: 4 +// +// Description	: This driver provides initialization and transmit/receive +//		functions for the ENC28J60 10Mb Ethernet Controller and PHY. +// +// This code is distributed under the GNU Public License +//		which can be found at http://www.gnu.org/licenses/gpl.txt +// +//***************************************************************************** + +#ifndef ENC28J60CONF_H +#define ENC28J60CONF_H + +#include <stdint.h> +typedef uint8_t  u08; +typedef uint16_t u16; +typedef uint32_t u32; + +// ENC28J60 SPI port +#define ENC28J60_SPI_PORT		PORTB +#define ENC28J60_SPI_DDR		DDRB +#define ENC28J60_SPI_SCK		PORTB1 +#define ENC28J60_SPI_MOSI		PORTB2 +#define ENC28J60_SPI_MISO		PORTB3 +#define ENC28J60_SPI_SS			PORTB0 +// ENC28J60 control port +#define ENC28J60_CONTROL_PORT	PORTB +#define ENC28J60_CONTROL_DDR	DDRB +#define ENC28J60_CONTROL_CS		PORTB0 + +// MAC address for this interface +#define ENC28J60_MAC0 '0' +#define ENC28J60_MAC1 'F' +#define ENC28J60_MAC2 'F' +#define ENC28J60_MAC3 'I' +#define ENC28J60_MAC4 'C' +#define ENC28J60_MAC5 'E' + +#endif /* ENC28J60CONF_H */ diff --git a/firmware/octoclock/include/net/eth_hdr.h b/firmware/octoclock/include/net/eth_hdr.h new file mode 100644 index 000000000..9d5356c66 --- /dev/null +++ b/firmware/octoclock/include/net/eth_hdr.h @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2014 Ettus Research LLC + * + * 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/>. + */ +#ifndef INCLUDED_ETH_HDR_H +#define INCLUDED_ETH_HDR_H + +#include <compiler.h> +#include <net/eth_mac_addr.h> + +#define ETH_HLEN 14 + +/*! + * \brief Standard 14-byte ethernet header. + */ + +typedef struct { +  eth_mac_addr_t dst; +  eth_mac_addr_t src; +  uint16_t ethertype; +} _AL2 eth_hdr_t; + +#endif /* INCLUDED_ETH_HDR_H */ diff --git a/firmware/octoclock/include/net/eth_mac_addr.h b/firmware/octoclock/include/net/eth_mac_addr.h new file mode 100644 index 000000000..0c790aa4f --- /dev/null +++ b/firmware/octoclock/include/net/eth_mac_addr.h @@ -0,0 +1,31 @@ +/* + * Copyright 2009-2011,2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef INCLUDED_ETH_MAC_ADDR_H +#define INCLUDED_ETH_MAC_ADDR_H + +#include <stdint.h> + +// Ethernet MAC address + +#pragma pack(push,1) +typedef struct { +  uint8_t	addr[6]; +} eth_mac_addr_t; +#pragma pack(pop) + +#endif /* INCLUDED_ETH_MAC_ADDR_H */ diff --git a/firmware/octoclock/include/net/ethertype.h b/firmware/octoclock/include/net/ethertype.h new file mode 100644 index 000000000..0cfab8d65 --- /dev/null +++ b/firmware/octoclock/include/net/ethertype.h @@ -0,0 +1,27 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2011,2014 Ettus Research LLC + * + * 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/>. + */ +#ifndef INCLUDED_ETHERTYPE_H +#define INCLUDED_ETHERTYPE_H + +// all we care about + +#define	ETHERTYPE_IPV4	0x0800 +#define	ETHERTYPE_ARP	0x0806 + + +#endif /* INCLUDED_ETHERTYPE_H */ diff --git a/firmware/octoclock/include/net/if_arp.h b/firmware/octoclock/include/net/if_arp.h new file mode 100644 index 000000000..63519c4be --- /dev/null +++ b/firmware/octoclock/include/net/if_arp.h @@ -0,0 +1,153 @@ +/* + * INET		An implementation of the TCP/IP protocol suite for the LINUX + *		operating system.  INET is implemented using the  BSD Socket + *		interface as the means of communication with the user level. + * + *		Global definitions for the ARP (RFC 826) protocol. + * + * Version:	@(#)if_arp.h	1.0.1	04/16/93 + * + * Authors:	Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 + *		Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source. + *		Ross Biro + *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> + *		Florian La Roche, + *		Jonathan Layes <layes@loran.com> + *		Arnaldo Carvalho de Melo <acme@conectiva.com.br> ARPHRD_HWX25 + * + *		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 + *		2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IF_ARP_H +#define _LINUX_IF_ARP_H + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM	0		/* from KA9Q: NET/ROM pseudo	*/ +#define ARPHRD_ETHER 	1		/* Ethernet 10Mbps		*/ +#define	ARPHRD_EETHER	2		/* Experimental Ethernet	*/ +#define	ARPHRD_AX25	3		/* AX.25 Level 2		*/ +#define	ARPHRD_PRONET	4		/* PROnet token ring		*/ +#define	ARPHRD_CHAOS	5		/* Chaosnet			*/ +#define	ARPHRD_IEEE802	6		/* IEEE 802.2 Ethernet/TR/TB	*/ +#define	ARPHRD_ARCNET	7		/* ARCnet			*/ +#define	ARPHRD_APPLETLK	8		/* APPLEtalk			*/ +#define ARPHRD_DLCI	15		/* Frame Relay DLCI		*/ +#define ARPHRD_ATM	19		/* ATM 				*/ +#define ARPHRD_METRICOM	23		/* Metricom STRIP (new IANA id)	*/ +#define	ARPHRD_IEEE1394	24		/* IEEE 1394 IPv4 - RFC 2734	*/ +#define ARPHRD_EUI64	27		/* EUI-64                       */ +#define ARPHRD_INFINIBAND 32		/* InfiniBand			*/ + +/* Dummy types for non ARP hardware */ +#define ARPHRD_SLIP	256 +#define ARPHRD_CSLIP	257 +#define ARPHRD_SLIP6	258 +#define ARPHRD_CSLIP6	259 +#define ARPHRD_RSRVD	260		/* Notional KISS type 		*/ +#define ARPHRD_ADAPT	264 +#define ARPHRD_ROSE	270 +#define ARPHRD_X25	271		/* CCITT X.25			*/ +#define ARPHRD_HWX25	272		/* Boards with X.25 in firmware	*/ +#define ARPHRD_CAN	280		/* Controller Area Network      */ +#define ARPHRD_PPP	512 +#define ARPHRD_CISCO	513		/* Cisco HDLC	 		*/ +#define ARPHRD_HDLC	ARPHRD_CISCO +#define ARPHRD_LAPB	516		/* LAPB				*/ +#define ARPHRD_DDCMP    517		/* Digital's DDCMP protocol     */ +#define ARPHRD_RAWHDLC	518		/* Raw HDLC			*/ + +#define ARPHRD_TUNNEL	768		/* IPIP tunnel			*/ +#define ARPHRD_TUNNEL6	769		/* IP6IP6 tunnel       		*/ +#define ARPHRD_FRAD	770             /* Frame Relay Access Device    */ +#define ARPHRD_SKIP	771		/* SKIP vif			*/ +#define ARPHRD_LOOPBACK	772		/* Loopback device		*/ +#define ARPHRD_LOCALTLK 773		/* Localtalk device		*/ +#define ARPHRD_FDDI	774		/* Fiber Distributed Data Interface */ +#define ARPHRD_BIF      775             /* AP1000 BIF                   */ +#define ARPHRD_SIT	776		/* sit0 device - IPv6-in-IPv4	*/ +#define ARPHRD_IPDDP	777		/* IP over DDP tunneller	*/ +#define ARPHRD_IPGRE	778		/* GRE over IP			*/ +#define ARPHRD_PIMREG	779		/* PIMSM register interface	*/ +#define ARPHRD_HIPPI	780		/* High Performance Parallel Interface */ +#define ARPHRD_ASH	781		/* Nexus 64Mbps Ash		*/ +#define ARPHRD_ECONET	782		/* Acorn Econet			*/ +#define ARPHRD_IRDA 	783		/* Linux-IrDA			*/ +/* ARP works differently on different FC media .. so  */ +#define ARPHRD_FCPP	784		/* Point to point fibrechannel	*/ +#define ARPHRD_FCAL	785		/* Fibrechannel arbitrated loop */ +#define ARPHRD_FCPL	786		/* Fibrechannel public loop	*/ +#define ARPHRD_FCFABRIC	787		/* Fibrechannel fabric		*/ +	/* 787->799 reserved for fibrechannel media types */ +#define ARPHRD_IEEE802_TR 800		/* Magic type ident for TR	*/ +#define ARPHRD_IEEE80211 801		/* IEEE 802.11			*/ +#define ARPHRD_IEEE80211_PRISM 802	/* IEEE 802.11 + Prism2 header  */ +#define ARPHRD_IEEE80211_RADIOTAP 803	/* IEEE 802.11 + radiotap header */ + +#define ARPHRD_VOID	  0xFFFF	/* Void type, nothing is known */ +#define ARPHRD_NONE	  0xFFFE	/* zero header length */ + +/* ARP protocol opcodes. */ +#define	ARPOP_REQUEST	1		/* ARP request			*/ +#define	ARPOP_REPLY	2		/* ARP reply			*/ +#define	ARPOP_RREQUEST	3		/* RARP request			*/ +#define	ARPOP_RREPLY	4		/* RARP reply			*/ +#define	ARPOP_InREQUEST	8		/* InARP request		*/ +#define	ARPOP_InREPLY	9		/* InARP reply			*/ +#define	ARPOP_NAK	10		/* (ATM)ARP NAK			*/ + + +/* ARP Flag values. */ +#define ATF_COM		0x02		/* completed entry (ha valid)	*/ +#define	ATF_PERM	0x04		/* permanent entry		*/ +#define	ATF_PUBL	0x08		/* publish entry		*/ +#define	ATF_USETRAILERS	0x10		/* has requested trailers	*/ +#define ATF_NETMASK     0x20            /* want to use a netmask (only +					   for proxy entries) */ +#define ATF_DONTPUB	0x40		/* don't answer this addresses	*/ + +typedef unsigned short  __be16; + +/* + *	This structure defines an ethernet arp header. + */ +struct arphdr +{ +	__be16		ar_hrd;		/* format of hardware address	*/ +	__be16		ar_pro;		/* format of protocol address	*/ +	unsigned char	ar_hln;		/* length of hardware address	*/ +	unsigned char	ar_pln;		/* length of protocol address	*/ +	__be16		ar_op;		/* ARP opcode (command)		*/ + +#if 0 +	 /* +	  *	 Ethernet looks like this : This bit is variable sized however... +	  */ +	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/ +	unsigned char		ar_sip[4];		/* sender IP address		*/ +	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/ +	unsigned char		ar_tip[4];		/* target IP address		*/ +#endif + +}; + +/* + *	This structure defines an ethernet arp header. + */ +struct arp_eth_ipv4 +{ +	__be16		ar_hrd;		/* format of hardware address	*/ +	__be16		ar_pro;		/* format of protocol address	*/ +	unsigned char	ar_hln;		/* length of hardware address	*/ +	unsigned char	ar_pln;		/* length of protocol address	*/ +	__be16		ar_op;		/* ARP opcode (command)		*/ + +	unsigned char	ar_sha[6];	/* sender hardware address	*/ +	unsigned char	ar_sip[4];	/* sender IP address		*/ +	unsigned char	ar_tha[6];	/* target hardware address	*/ +	unsigned char	ar_tip[4];	/* target IP address		*/ +}; + + +#endif	/* _LINUX_IF_ARP_H */ diff --git a/firmware/octoclock/include/net/socket_address.h b/firmware/octoclock/include/net/socket_address.h new file mode 100644 index 000000000..9d4b4c5b3 --- /dev/null +++ b/firmware/octoclock/include/net/socket_address.h @@ -0,0 +1,41 @@ +/* -*- c -*- */ +/* + * Copyright 2010,2014 Ettus Research LLC + * + * 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/>. + */ +#ifndef INCLUDED_SOCKET_ADDRESS_H +#define INCLUDED_SOCKET_ADDRESS_H + +#include <lwip/ip_addr.h> + +// port and address are in network byte order + +typedef struct socket_address { +  unsigned short   port; +  struct ip_addr   addr; +} socket_address_t; + +static inline struct socket_address  +make_socket_address(struct ip_addr addr, int port) +{ +  struct socket_address r; +  r.port = port; +  r.addr = addr; +  return r; +} + + + +#endif /* INCLUDED_SOCKET_ADDRESS_H */ diff --git a/firmware/octoclock/include/net/udp_handlers.h b/firmware/octoclock/include/net/udp_handlers.h new file mode 100644 index 000000000..3abc26a24 --- /dev/null +++ b/firmware/octoclock/include/net/udp_handlers.h @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _NET_UDP_HANDLERS_H_ +#define _NET_UDP_HANDLERS_H_ + +#include <network.h> +#include <net/socket_address.h> + +void handle_udp_ctrl_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +); + +void handle_udp_gpsdo_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +); + +#endif /* _NET_UDP_HANDLERS_H */ diff --git a/firmware/octoclock/include/network.h b/firmware/octoclock/include/network.h new file mode 100644 index 000000000..83e398bc5 --- /dev/null +++ b/firmware/octoclock/include/network.h @@ -0,0 +1,102 @@ +/* + * Copyright 2009-2012,2014 Ettus Research LLC + * + * 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/>. + */ +#ifndef INCLUDED_NETWORK_H +#define INCLUDED_NETWORK_H + +#include <stdint.h> +#include <stddef.h> + +#include <octoclock.h> +#include <net/socket_address.h> +#include <net/eth_mac_addr.h> + +#include "octoclock/common.h" + +/* + * Without its own HTON[LS] included in this build, + * some of lwIP's #defines do nothing. + * These are substitutions with our own HTON[LS]. + */ +#define htons(n) (((((uint16_t)(n) & 0xFF)) << 8) | (((uint16_t)(n) & 0xFF00) >> 8)) +#define ntohs(n) htons(n) + +#define htonl(n) (((((uint32_t)(n) & 0xFF)) << 24) | \ +                  ((((uint32_t)(n) & 0xFF00)) << 8) | \ +                  ((((uint32_t)(n) & 0xFF0000)) >> 8) | \ +                  ((((uint32_t)(n) & 0xFF000000)) >> 24)) + +#define ntohl(n) htonl(n) + +#define _MAC_ADDR(mac_addr,a,b,c,d,e,f) mac_addr[0] = a; \ +                                        mac_addr[1] = b; \ +                                        mac_addr[2] = c; \ +                                        mac_addr[3] = d; \ +                                        mac_addr[4] = e; \ +                                        mac_addr[5] = f; + +#define _MAC_SET_EQUAL(mac_addr1,mac_addr2) for(uint8_t i = 0; i < 6; i++) mac_addr1[i] = mac_addr2[i]; + +#define _IP(a,b,c,d) (((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | ((uint32_t)d << 0)) +#define _IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12) +#define _IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f) +#define _IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff) +#define _IPH_LEN(hdr) (ntohs((hdr)->_len)) +#define _IPH_ID(hdr) (ntohs((hdr)->_id)) +#define _IPH_OFFSET(hdr) (ntohs((hdr)->_offset)) +#define _IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8) +#define _IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff) +#define _IPH_CHKSUM(hdr) (ntohs((hdr)->_chksum)) + +#define _IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos))) +#define _IPH_LEN_SET(hdr, len) (hdr)->_len = (htons(len)) +#define _IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define _IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define _IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(_IPH_PROTO(hdr) | ((u16_t)(ttl) << 8))) +#define _IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (_IPH_TTL(hdr) << 8))) +#define _IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +bool using_network_defaults; + +// Ethernet I/O buffers +uint8_t buf_in[512]; +uint8_t buf_out[512]; + +// Default values loaded if EEPROM is incomplete +static const uint32_t blank_eeprom_ip = _IP(255,255,255,255); +static const uint32_t default_ip      = _IP(192,168,10,3); +static const uint32_t default_dr      = _IP(192,168,10,1); +static const uint32_t default_netmask = _IP(255,255,255,0); + +typedef void (*udp_receiver_t)(struct socket_address src, struct socket_address dst, +			       unsigned char *payload, int payload_len); + +void init_udp_listeners(void); + +void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_addr); + +void register_udp_listener(int port, udp_receiver_t rcvr); + +void send_udp_pkt(int src_port, struct socket_address dst, +		  const void *buf, size_t len); + +void handle_eth_packet(size_t recv_len); + +void network_check(void); + +void network_init(void); + +#endif /* INCLUDED_NETWORK_H */ diff --git a/firmware/octoclock/include/octoclock.h b/firmware/octoclock/include/octoclock.h new file mode 100644 index 000000000..849ab7f96 --- /dev/null +++ b/firmware/octoclock/include/octoclock.h @@ -0,0 +1,105 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _OCTOCLOCK_H_ +#define _OCTOCLOCK_H_ + +#include "octoclock/common.h" + +#include <stdbool.h> +#include <stdint.h> + +// Define frequency +#define F_CPU 12500000UL + +/* + * Timer 0 (8-bit) + *  * Set prescaler to 8 + *  * Enable overflow interrupt + *  * Set timer to 0 + */ +#define TIMER0_INIT() TCCR0 = (1 << CS01); \ +                      TIMSK |= (1 << TOIE0); \ +                      TCNT0 = 0; +/* + * Timer 1 (16-bit) + *  * Set prescaler to 1024 + *  * Enable overflow interrupt + *  * Set timer to 0 + */ +#define TIMER1_INIT() TCCR1B = (1 << CS12) | (1 << CS10); \ +        TIMSK |= (1<<TOIE1); \ +        TCNT1 = 0; + +#define TIMER1_ONE_SECOND ((uint32_t)(12207)) + +// Locations of OctoClock information in EEPROM +#define OCTOCLOCK_EEPROM_MAC_ADDR   0 +#define OCTOCLOCK_EEPROM_IP_ADDR    6 +#define OCTOCLOCK_EEPROM_DR_ADDR   10 +#define OCTOCLOCK_EEPROM_NETMASK   14 +#define OCTOCLOCK_EEPROM_SERIAL    18 +#define OCTOCLOCK_EEPROM_NAME      28 +#define OCTOCLOCK_EEPROM_REVISION  38 + +#define OCTOCLOCK_EEPROM_APP_LEN   100 +#define OCTOCLOCK_EEPROM_APP_CRC   102 + +/* turn a numeric literal into a hex constant + * (avoids problems with leading zeros) + * 8-bit constants max value 0x11111111, always fits in unsigned long + */ +#define HEX__(n) 0x##n##LU + +/* 8-bit conversion function */ +#define B8__(x) ((x&0x0000000FLU)?1:0) \ +    +((x&0x000000F0LU)?2:0) \ +    +((x&0x00000F00LU)?4:0) \ +    +((x&0x0000F000LU)?8:0) \ +    +((x&0x000F0000LU)?16:0) \ +    +((x&0x00F00000LU)?32:0) \ +    +((x&0x0F000000LU)?64:0) \ +    +((x&0xF0000000LU)?128:0) + +/* for up to 8-bit binary constants */ +#define Bits_8(d) ((unsigned char)B8__(HEX__(d))) + +/* for up to 16-bit binary constants, MSB first */ +#define Bits_16(dmsb,dlsb) (((unsigned short)Bits_8(dmsb)<<8) \ +    + Bits_8(dlsb)) + +/* for up to 32-bit binary constants, MSB first */ +#define Bits_32(dmsb,db2,db3,dlsb) (((unsigned long)Bits_8(dmsb)<<24) \ +    + ((unsigned long)Bits_8(db2)<<16) \ +    + ((unsigned long)Bits_8(db3)<<8) \ +    + Bits_8(dlsb)) + +/* Sample usage: + * Bits_8(01010101) = 85 + * Bits_16(10101010,01010101) = 43605 + * Bits_32(10000000,11111111,10101010,01010101) = 2164238933 + */ + +typedef enum { +    Top, +    Middle, +    Bottom +} LEDs; + +void setup_atmel_io_ports(void); + +#endif /* _OCTOCLOCK_H_ */ diff --git a/firmware/octoclock/include/serial.h b/firmware/octoclock/include/serial.h new file mode 100644 index 000000000..48a065dc5 --- /dev/null +++ b/firmware/octoclock/include/serial.h @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _SERIAL_H_ +#define _SERIAL_H_ + +#include <stdint.h> +#include <stdbool.h> + +#include <octoclock.h> + +#define BAUD_DELAY(baud) ((1.0 / (double)baud) * ((double)F_CPU / 8.0)) +#define BAUD_115200_DELAY BAUD_DELAY(115200) + +void serial_init(volatile uint8_t* port, uint8_t index); +void serial_tx_P(const char* message, volatile uint8_t* port, uint8_t index, bool newline); +void serial_tx(const char* message, volatile uint8_t* port, uint8_t index, bool newline); +void serial_tx_byte(uint8_t byte, volatile uint8_t* port, uint8_t index, bool newline); +void serial_tx_hex(uint8_t byte, volatile uint8_t* port, uint8_t index, bool newline); +char serial_rx_char(volatile uint8_t* port, uint8_t index); +char serial_rx_char_nowait(volatile uint8_t* port, uint8_t index); + +#endif /* _SERIAL_H_ */ diff --git a/firmware/octoclock/include/state.h b/firmware/octoclock/include/state.h new file mode 100644 index 000000000..9734948cf --- /dev/null +++ b/firmware/octoclock/include/state.h @@ -0,0 +1,44 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _STATE_H_ +#define _STATE_H_ + +#include <stdbool.h> + +#include <octoclock.h> + +// NOT PRESENT unless proven so... +static ref_t global_which_ref = NO_REF; +static bool global_gps_present = false; +static bool global_ext_ref_is_present = false; + +void led(LEDs which, int turn_it_on); + +void LEDs_off(void); + +void force_internal(void); + +void prefer_internal(void); + +void prefer_external(void); + +ref_t which_ref(void); + +switch_pos_t get_switch_pos(void); + +#endif /* _STATE_H_ */ diff --git a/firmware/octoclock/include/usart.h b/firmware/octoclock/include/usart.h new file mode 100644 index 000000000..35ee9eb95 --- /dev/null +++ b/firmware/octoclock/include/usart.h @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#ifndef _USART_H_ +#define _USART_H_ + +#define USART_BAUDRATE 115200 +#define BAUD_PRESCALE 3 + +void usart_init(void); + +char usart_getc(void); + +char usart_getc_noblock(void); + +void usart_putc(char ch); + +void usart_putc_nowait(char ch); + +#endif /* _USART_H_ */ diff --git a/firmware/octoclock/lib/CMakeLists.txt b/firmware/octoclock/lib/CMakeLists.txt new file mode 100644 index 000000000..3c992399e --- /dev/null +++ b/firmware/octoclock/lib/CMakeLists.txt @@ -0,0 +1,37 @@ +# +# Copyright 2014 Ettus Research LLC +# +# 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/>. +# + +SET(lib_files +    arp_cache.c +    clkdist.c +    enc28j60.c +    gpsdo.c +    init.c +    network.c +    state.c +    udp_handlers.c +    usart.c +) + +IF(OCTOCLOCK_DEBUG) +    LIST(APPEND lib_files serial.c) +ENDIF(OCTOCLOCK_DEBUG) + +ADD_LIBRARY(octoclock ${lib_files}) +SET_TARGET_PROPERTIES(octoclock +    PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -O2 -g" +) diff --git a/firmware/octoclock/lib/arp_cache.c b/firmware/octoclock/lib/arp_cache.c new file mode 100644 index 000000000..558632d7f --- /dev/null +++ b/firmware/octoclock/lib/arp_cache.c @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2011,2014 Ettus Research LLC + * + * 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/>. + */ +#include "arp_cache.h" +#include <stddef.h> + +typedef struct { +  struct ip_addr	ip; +  eth_mac_addr_t	mac; +} arp_cache_t; + +#define	NENTRIES 8	// power-of-2 + +static size_t nentries; +static size_t victim; +static arp_cache_t cache[NENTRIES]; + +void +arp_cache_init(void) +{ +  nentries = 0; +  victim = 0; +} + +// returns non-negative index if found, else -1 +static int +arp_cache_lookup(const struct ip_addr *ip) +{ +  int i; +  for (i = 0; i < nentries; i++) +    if (cache[i].ip.addr == ip->addr) +      return i; + +  return -1; +} + +static int +arp_cache_alloc(void) +{ +  if (nentries < NENTRIES) +    return nentries++; + +  int i = victim; +  victim = (victim + 1) % NENTRIES; +  return i; +} + +void  +arp_cache_update(const struct ip_addr *ip, +		 const eth_mac_addr_t *mac) +{ +  int i = arp_cache_lookup(ip); +  if (i < 0){ +    i = arp_cache_alloc(); +    cache[i].ip = *ip; +    cache[i].mac = *mac; +  } +  else { +    cache[i].mac = *mac; +  } +} + +bool +arp_cache_lookup_mac(const struct ip_addr *ip, +		     eth_mac_addr_t *mac) +{ +  int i = arp_cache_lookup(ip); +  if (i < 0) +    return false; + +  *mac = cache[i].mac; +  return true; +} diff --git a/firmware/octoclock/lib/arp_cache.h b/firmware/octoclock/lib/arp_cache.h new file mode 100644 index 000000000..38ac0a198 --- /dev/null +++ b/firmware/octoclock/lib/arp_cache.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2011,2014 Ettus Research LLC + * + * 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/>. + */ +#ifndef INCLUDED_ARP_CACHE_H +#define INCLUDED_ARP_CACHE_H + +#include <lwip/ip_addr.h> +#include <net/eth_mac_addr.h> +#include <stdbool.h> + +void arp_cache_init(void); + +void arp_cache_update(const struct ip_addr *ip, +		      const eth_mac_addr_t *mac); + +bool arp_cache_lookup_mac(const struct ip_addr *ip, +			  eth_mac_addr_t *mac); + +#endif /* INCLUDED_ARP_CACHE_H */ diff --git a/firmware/octoclock/lib/clkdist.c b/firmware/octoclock/lib/clkdist.c new file mode 100644 index 000000000..ed29510b6 --- /dev/null +++ b/firmware/octoclock/lib/clkdist.c @@ -0,0 +1,182 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#include <avr/io.h> + +#include <octoclock.h> +#include <clkdist.h> +#include <state.h> + +#define wait() for(uint16_t u=14000; u; u--) asm("nop"); + +#define CLK   (PA0) // Shift by 0 bits +#define CE_   (PA1) // Is really the "Chip Disable" signal, as Hi disables SPI +#define MOSI  (PA2) +#define MISO  (PA3) +#define PD_   (PA4) +#define SYNC_ (PA5) + +// Table of 32-bit constants to be written to the TI chip's registers. These are +// from the "Special Settings" on Page 35 of the datasheet. +// For the GPS's 10 MHz output +static uint32_t table_Pri_Ref[] = { +    Bits_32(1,01010100,0,0),    // Reg 0 +    Bits_32(1,01010100,0,0),    // Outputs LVCMOS Positive&Negative Active - Non-inverted +    Bits_32(1,01010100,0,0), +    Bits_32(1,01010100,0,0), +    Bits_32(1,01010100,0,0),    // All have output divide ratio to be 1; Aux Output is OFF +    Bits_32(0,0,1001,11010100), // Reg 5  LVCMOS in; p31 of TI datasheet +    Bits_32(1,0,0010000,0),     // Reg 6    // SCAS863A <96> NOVEMBER 2008 <96> REVISED JUNE 2011 +    Bits_32(1,01000000,0,0),    // Reg 7 +    Bits_32(0,0,1,10000000)     // Reg8  Status/Control +}; + +// For the External 10 MHz input LVDS with external termination,  +// Effectively DC coupled +static uint32_t table_Sec_Ref[] = { +    Bits_32(0001,01010100,0,100000),    // Reg 0 -- use Secondary Reference for all channels +    Bits_32(0001,01010100,0,100000),    // Outputs LVCMOS Positive&Negative Active - Non-inverted +    Bits_32(0001,01010100,0,100000), +    Bits_32(0001,01010100,0,100000), +    Bits_32(0001,01010100,0,100000), +    Bits_32(0,0,1,10011011),            // Reg 5, Failsafe OFF   b5.11 = 0 +    Bits_32(1,0,10000,0),               // Reg 6; try again +    Bits_32(1,01000000,0,0), +    Bits_32(0,0,1,10000000)             // Reg8  Status/Control +}; + +// Table 19 conflicts with Tables 5 thru 9 - in how LVCMOS outputs are defined +// extra error in Table 9, for bits 24 and 25 +static int table_size = sizeof (table_Pri_Ref) / sizeof(uint32_t); + +static void set_bit(uint8_t  bit_number, Levels bit_value) { + +    if(bit_value == Hi) +        PORTA |= 1<<bit_number; +    else +        PORTA &= ~ (1<<bit_number); +} + +static bool get_bit(uint8_t  bit_number) { +    asm("nop"); + +    uint8_t portA = PINA; +    return (portA &  1<< bit_number) > 0 ? true : false; +} + +// Send 32 bits to TI chip, LSB first. +// Don't worry about reading any bits back at this time +static void send_SPI(uint32_t bits) { + +    // Basically, when the clock is low, one can set MOSI to anything, as it's +    // ignored. +    set_bit(CE_, Lo);    // Start SPI transaction with TI chip + +    // Send each bit, LSB first, add a bit of delay before the clock, and then +    // toggle the clock line. +    for (uint8_t i=0; i<32; i++) { +        set_bit(MOSI, ((bits & (1UL<<i)) ? Hi : Lo) ); +        asm("nop"); +        set_bit(CLK, Hi); +        set_bit(CLK, Lo); +    } + +    // OK, transaction is over +    set_bit(CE_, Hi); +} + +static uint32_t receive_SPI() { +    uint32_t bits = 0; + +    set_bit(CE_, Hi); // Make sure we're inactive +    set_bit(CLK, Lo); // and clk line is inactive, too +    set_bit(MOSI,Lo); // Make our bit output zero, for good measure +    set_bit(CE_, Lo); // Start SPI transaction with TI chip; MOSI is don't care + +    // For each bit we are receiving, prep, clock in the bit LSB first +    for (uint8_t i=0; i<32; i++){ +        bits >>= 1; +        set_bit(CLK, Hi); +        if( get_bit(MISO) ) bits |= 0x80000000; +        set_bit(CLK, Lo); +    } + +    // OK, transaction is over +    set_bit(CE_, Hi); + +    // Ditch the lower 4 bits, which only contain the address +    return (uint32_t)(bits >> 4); +} + +void setup_TI_CDCE18005(TI_Input_10_MHz which_input) { +    // Send the table of data to init the clock distribution chip.  Uses SPI. +    uint32_t temp; + +    if(which_input == Primary_GPS) { +        for(uint8_t i=0; i<table_size; i++){ +            temp = table_Pri_Ref[i]<<4; +            temp |= i; +            send_SPI(temp); // Make sure the register's address is in the LSBs +        } +    } else { +        // is Secondary_Ext -- External 10 MHz input from SMA connector +        for(uint8_t i=0; i<table_size; i++){ +            temp = table_Sec_Ref[i]<<4; +            temp |= i; +            // Make sure the register's address is in the LSBs +            send_SPI(temp); +         } +    } +} + +void reset_TI_CDCE18005(void) { +    // First, reset the chip.  Or, if you will, pull /SYNC low then high +    set_bit(CE_, Hi); +    set_bit(PD_, Lo); +    wait(); + +    // Out of Power Down state +    set_bit(PD_, Hi); +    wait(); + +    set_bit(SYNC_, Lo); +    wait(); +    set_bit(SYNC_, Hi); + +    wait(); +} + +uint32_t get_TI_CDCE18005(CDCE18005 which_register){ +    uint32_t get_reg_value = 0; +    get_reg_value = (0xf0 & (which_register << 4)) | Read_Command; + +    // This tells the TI chip to send us the reg. value requested +    send_SPI(get_reg_value); +    return receive_SPI(); +} + +bool check_TI_CDCE18005(TI_Input_10_MHz which_input, +        CDCE18005 which_register) { + +    if(which_input == Primary_GPS){ +        uint32_t read_value = get_TI_CDCE18005(which_register); +        return read_value == table_Pri_Ref[which_register]; +    } else { +        uint32_t read_value = get_TI_CDCE18005(which_register); +        return read_value == table_Sec_Ref[which_register]; +    } +} diff --git a/firmware/octoclock/lib/enc28j60.c b/firmware/octoclock/lib/enc28j60.c new file mode 100644 index 000000000..f0bbee0e7 --- /dev/null +++ b/firmware/octoclock/lib/enc28j60.c @@ -0,0 +1,337 @@ +/*! \file enc28j60.c \brief Microchip ENC28J60 Ethernet Interface Driver. */ +//***************************************************************************** +// +// File Name	: 'enc28j60.c' +// Title		: Microchip ENC28J60 Ethernet Interface Driver +// Author		: Pascal Stang (c)2005 +// Created		: 9/22/2005 +// Revised		: 5/19/2014 +// Version		: 0.1 +// Target MCU	: Atmel AVR series +// Editor Tabs	: 4 +// +// Description	: This driver provides initialization and transmit/receive +//	functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY. +// This chip is novel in that it is a full MAC+PHY interface all in a 28-pin +// chip, using an SPI interface to the host processor. +// +//***************************************************************************** + +#include <octoclock.h> + +#include <net/enc28j60.h> +#include <net/enc28j60conf.h> + +#include <avr/io.h> +#include <util/delay.h> + +u08 Enc28j60Bank; +u16 NextPacketPtr; + +u08 enc28j60ReadOp(u08 op, u08 address) +{ +	u08 data; +    +	// assert CS +	ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); +	 +	// issue read command +	SPDR = op | (address & ADDR_MASK); +	while(!(SPSR & (1<<SPIF))); +	// read data +	SPDR = 0x00; +	while(!(SPSR & (1<<SPIF))); +	// do dummy read if needed +	if(address & 0x80) +	{ +		SPDR = 0x00; +		while(!(inb(SPSR) & (1<<SPIF))); +	} +	data = SPDR; +	 +	// release CS +	ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); + +	return data; +} + +void enc28j60WriteOp(u08 op, u08 address, u08 data) +{ +	// assert CS +	ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); + +	// issue write command +	SPDR = op | (address & ADDR_MASK); +	while(!(SPSR & (1<<SPIF))); +	// write data +	SPDR = data; +	while(!(SPSR & (1<<SPIF))); + +	// release CS +	ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); +} + +void enc28j60ReadBuffer(u16 len, u08* data) +{ +	// assert CS +	ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); +	 +	// issue read command +	SPDR = ENC28J60_READ_BUF_MEM; +	while(!(SPSR & (1<<SPIF))); +	while(len--) +	{ +		// read data +		SPDR = 0x00; +		while(!(SPSR & (1<<SPIF))); +		*data++ = SPDR; +	}	 +	// release CS +	ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); +} + +void enc28j60WriteBuffer(u16 len, u08* data) +{ +	// assert CS +	ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); +	 +	// issue write command +	SPDR = ENC28J60_WRITE_BUF_MEM; +	while(!(SPSR & (1<<SPIF))); +	while(len--) +	{ +		// write data +		SPDR = *data++; +		while(!(SPSR & (1<<SPIF))); +	}	 +	// release CS +	ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); +} + +void enc28j60SetBank(u08 address) +{ +	// set the bank (if needed) +	if((address & BANK_MASK) != Enc28j60Bank) +	{ +		// set the bank +		enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); +		enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); +		Enc28j60Bank = (address & BANK_MASK); +	} +} + +u08 enc28j60Read(u08 address) +{ +	// set the bank +	enc28j60SetBank(address); +	// do the read +	return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address); +} + +void enc28j60Write(u08 address, u08 data) +{ +	// set the bank +	enc28j60SetBank(address); +	// do the write +	enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +u16 enc28j60PhyRead(u08 address) +{ +	u16 data; + +	// Set the right address and start the register read operation +	enc28j60Write(MIREGADR, address); +	enc28j60Write(MICMD, MICMD_MIIRD); + +	// wait until the PHY read completes +	while(enc28j60Read(MISTAT) & MISTAT_BUSY); + +	// quit reading +	enc28j60Write(MICMD, 0x00); +	 +	// get data value +	data  = enc28j60Read(MIRDL); +	data |= enc28j60Read(MIRDH); +	// return the data +	return data; +} + +void enc28j60PhyWrite(u08 address, u16 data) +{ +	// set the PHY register address +	enc28j60Write(MIREGADR, address); +	 +	// write the PHY data +	enc28j60Write(MIWRL, data);	 +	enc28j60Write(MIWRH, data>>8); + +	// wait until the PHY write completes +	while(enc28j60Read(MISTAT) & MISTAT_BUSY); +} + +void enc28j60Init(u08* macaddr) +{ +	// initialize I/O +	sbi(ENC28J60_CONTROL_DDR, ENC28J60_CONTROL_CS); +	sbi(ENC28J60_CONTROL_PORT, ENC28J60_CONTROL_CS); + +	// setup SPI I/O pins +	sbi(ENC28J60_SPI_PORT, ENC28J60_SPI_SCK);	// set SCK hi +	sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SCK);	// set SCK as output +	cbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MISO);	// set MISO as input +	sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_MOSI);	// set MOSI as output +	sbi(ENC28J60_SPI_DDR, ENC28J60_SPI_SS);		// SS must be output for Master mode to work +	// initialize SPI interface +	// master mode +	sbi(SPCR, MSTR); +	// select clock phase positive-going in middle of data +	cbi(SPCR, CPOL); +	// Data order MSB first +	cbi(SPCR,DORD); +	// switch to f/4 2X = f/2 bitrate +	cbi(SPCR, SPR0); +	cbi(SPCR, SPR1); +	sbi(SPSR, SPI2X); +	// enable SPI +	sbi(SPCR, SPE); + +	// perform system reset +	enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); + +    /* +     * "After sending an SPI Reset command, the PHY +     * clock is stopped but the ESTAT.CLKRDY bit is not +     * cleared. Therefore, polling the CLKRDY bit will not +     * work to detect if the PHY is ready. +     * +     * Additionally, the hardware start-up time of 300 us +     * may expire before the device is ready to operate. +     * +     * Work around +     * After issuing the Reset command, wait at least +     * 1 ms in firmware for the device to be ready." +     * +     * Source: http://ww1.microchip.com/downloads/en/DeviceDoc/80349c.pdf +     */ +	_delay_ms(1); + +	// do bank 0 stuff +	// initialize receive buffer +	// 16-bit transfers, must write low byte first +	// set receive buffer start address +	NextPacketPtr = RXSTART_INIT; +	enc28j60Write(ERXSTL, RXSTART_INIT&0xFF); +	enc28j60Write(ERXSTH, RXSTART_INIT>>8); +	// set receive pointer address +	enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF); +	enc28j60Write(ERXRDPTH, RXSTART_INIT>>8); +	// set receive buffer end +	// ERXND defaults to 0x1FFF (end of ram) +	enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF); +	enc28j60Write(ERXNDH, RXSTOP_INIT>>8); +	// set transmit buffer start +	// ETXST defaults to 0x0000 (beginnging of ram) +	enc28j60Write(ETXSTL, TXSTART_INIT&0xFF); +	enc28j60Write(ETXSTH, TXSTART_INIT>>8); + +	// do bank 2 stuff +	// enable MAC receive +	enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); +	// bring MAC out of reset +	enc28j60Write(MACON2, 0x00); +	// enable automatic padding and CRC operations +	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); +	// set inter-frame gap (non-back-to-back) +	enc28j60Write(MAIPGL, 0x12); +	enc28j60Write(MAIPGH, 0x0C); +	// set inter-frame gap (back-to-back) +	enc28j60Write(MABBIPG, 0x12); +	// Set the maximum packet size which the controller will accept +	enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);	 +	enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8); + +	// do bank 3 stuff +	// write MAC address +	// NOTE: MAC address in ENC28J60 is byte-backward +	enc28j60Write(MAADR5, macaddr[0]); +	enc28j60Write(MAADR4, macaddr[1]); +	enc28j60Write(MAADR3, macaddr[2]); +	enc28j60Write(MAADR2, macaddr[3]); +	enc28j60Write(MAADR1, macaddr[4]); +	enc28j60Write(MAADR0, macaddr[5]); + +	// no loopback of transmitted frames +	enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS); + +	// switch to bank 0 +	enc28j60SetBank(ECON1); +	// enable interrutps +	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); +	// enable packet reception +	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); +} + +void enc28j60PacketSend(unsigned int len1, unsigned char* packet1, unsigned int len2, unsigned char* packet2) +{ +	//Errata: Transmit Logic reset +	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); +	enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); + +	// Set the write pointer to start of transmit buffer area +	enc28j60Write(EWRPTL, TXSTART_INIT&0xff); +	enc28j60Write(EWRPTH, TXSTART_INIT>>8); +	// Set the TXND pointer to correspond to the packet size given +	enc28j60Write(ETXNDL, (TXSTART_INIT+len1+len2)); +	enc28j60Write(ETXNDH, (TXSTART_INIT+len1+len2)>>8); + +	// write per-packet control byte +	enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); + +	// copy the packet into the transmit buffer +	enc28j60WriteBuffer(len1, packet1); +	if(len2>0) enc28j60WriteBuffer(len2, packet2); +	 +	// send the contents of the transmit buffer onto the network +	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); +} + +unsigned int enc28j60PacketReceive(unsigned int maxlen, u08* buf) +{ +	u16 rxstat; +	u16 len; + +	// check if a packet has been received and buffered +	if( !enc28j60Read(EPKTCNT) ) +		return 0; + +	// Set the read pointer to the start of the received packet +	enc28j60Write(ERDPTL, (NextPacketPtr)); +	enc28j60Write(ERDPTH, (NextPacketPtr)>>8); +	// read the next packet pointer +	NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); +	NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; +	// read the packet length +	len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); +	len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; +	// read the receive status +	rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); +	rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; + +	// limit retrieve length +	// (we reduce the MAC-reported length by 4 to remove the CRC) +	len = MIN(len, maxlen); + +	// copy the packet from the receive buffer +	enc28j60ReadBuffer(len, buf); + +	// Move the RX read pointer to the start of the next received packet +	// This frees the memory we just read out +	enc28j60Write(ERXRDPTL, (NextPacketPtr)); +	enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8); + +	// decrement the packet counter indicate we are done with this packet +	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); + +	return len; +} diff --git a/firmware/octoclock/lib/gpsdo.c b/firmware/octoclock/lib/gpsdo.c new file mode 100644 index 000000000..a6a7daaca --- /dev/null +++ b/firmware/octoclock/lib/gpsdo.c @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#include <avr/interrupt.h> + +#include <octoclock.h> +#include <gpsdo.h> +#include <usart.h> + +void send_gpsdo_cmd(char* buf, uint8_t size){ +    for(uint8_t i = 0; i < size; i++) usart_putc(buf[i]); +} + +//Serial out +ISR(USART1_RX_vect){ +    gpsdo_buf[gpsdo_state.pos] = UDR1; + +    if(gpsdo_state.pos == (POOLSIZE-1)){ +        gpsdo_state.num_wraps++; +        gpsdo_state.pos = 0; +    } +    else gpsdo_state.pos++; +} diff --git a/firmware/octoclock/lib/init.c b/firmware/octoclock/lib/init.c new file mode 100644 index 000000000..827ccb376 --- /dev/null +++ b/firmware/octoclock/lib/init.c @@ -0,0 +1,175 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +/* + * Welcome to the firmware code for the USRP Octoclock accessory product! + * + * Notes regarding this firmware: + *      NOT in M103 compatibility mode + *      CKOPT full rail-to-rail + *      xtal osc + *      16K CK (16K clock cycles) + *      additional delay 65ms for Crystal Oscillator + *      slowly rising power + * + * These settings are very conservative. If a lower power oscillator is + * required, change CKOPT to '1' (UNPROGRAMMED). + * + * M103C     = [ ] + * WDTON     = [ ] + * OCDEN     = [ ] + * JTAGEN    = [X] + * SPIEN     = [X] + * EESAVE    = [X] + * BOOTSZ    = 4096W_F000 + * BOOTRST   = [X] + * CKOPT     = [X] + * BODLEVEL  = 2V7 + * BODEN     = [ ] + * SUT_CKSEL = EXTHIFXTALRES_16KCK_64MS + * + * EXTENDED  = 0xFF (valid) + * HIGH      = 0x80 (valid) + * LOW       = 0xFF (valid) + * + */ + +#include <avr/io.h> + +#include <octoclock.h> + +void setup_atmel_io_ports(){ +/* + * PORT A + * + * pin# Sig   Our Functional Name + * + * p51 PA0    CLK_CDCE    to U205 pin 24 --   L-->H edge latches MOSI and MISO in CDCE18005 + * p50 PA1    CE_CDCE    	Low = Chip Enabled for SPI comm  to U205 pin 25 + * p49 PA2    MOSI_CDCE    Goes to CDCE18005 - U205 pin 23 + * p48 PA3    MISO_CDCE    Input	Comes from U205 pin 22 + * p47 PA4    PD_CDCE    	Low = Chip is in Power-Down state; is Hi for normal operation U205 pin 12 + * p46 PA5    SYNC_CDCE    Low = Chip is sync'd with interal dividers; Hi for normal operation U205 pin 14 + * p45 PA6    PPS_SEL    	Low --> PPS_EXT selected; Hi -> PPS_GPS selected;    to U203 pin 1 + * p44 PA7    gps_lock    Input	Comes from M9107 - U206 pin 3 + * + */ + +// /pd_cdcd, /sync_code, /ce need to be 1 (disabled) to start +// all bits are outputs, except PA7 (gps_lock) and PA3 (MISO_CDCE) are inputs +PORTA = Bits_8(00110010); +DDRA =   1<<DDA6 | 1<<DDA5 | 1<<DDA4 | 1<<DDA2 | 1<<DDA1 | 1<<DDA0; + +/* + * Port B + * + * pin# Sig   Our Functional Name + * + * p10 PB0    Ethernet /SEN + * p11 PB1    Ethernet SCLK + * p12 PB2    Ethernet MOSI + * p13 PB3    Ethernet MISO + * p14 PB4    Not connected, set as output with value 0 + * p15 PB5    Ethernet /RESET  -- Set to HI for normal use, weak input + * p16 PB6    Ethernet /WOL  --- Wake on LAN -- set, weak input + * p17 PB7    Not connected, set as output with value 0 + * + */ + +PORTB = Bits_8(01100001);        // Initial Value is all zeros +DDRB = 1<<DDB2 | 1<<DDB4 | 1<<DDB7;  // MOSI is an output; the Not Connected pins are also outputs + +/* + * Port C + * + * pin# Sig   Our Functional Name + * + * p34 PC0    Not connected, set as output with value 0 + * p35 PC1    Reference Select Switch INPUT + * p36 PC2    Not connected, set as output with value 0 + * p37 PC3    Not connected, set as output with value 0 + * p38 PC4    Not connected, set as output with value 0 + * p40 PC5    "Top LED" of D103 3-stack of green LEDs + * p41 PC6    "Middle LED" + * p43 PC7    "Bottom LED" + * + */ + +PORTC = 0;        // Initial Value is all zeros +DDRC =  ~( 1<<DDC1 );     // All bits are outputs, except PC1. including the 5 Not Connected bits + +/* + * Port D + * + * pin# Sig   Our Functional Name + * + * p25 PD0    Ethernet /INT input + * p26 PD1    GPS NMEA bit, (INT1) INPUT + * p27 PD2    GPS Serial Out  (RXD)  INPUT + * p28 PD3    GPS Serial In   (TXD)        OUTPUT + * p29 PD4    GPS Present, INPUT  hi = Present + * p30 PD5    Not connected, set as output with value 0 + * p31 PD6    Not connected, set as output with value 0 + * p32 PD7    Not connected, set as output with value 0 + * + */ + +PORTD = 0;        // Initial Value is all zeros +DDRD =  1<<DDD3; + +/* + * Port E + * + * pin# Sig Dir Our Functional Name + * + * p2 PE0 In    avr_rxd (Also MOSI [PDI] when used for SPI programming of the chip) + * p3 PE1 Out   avr_txd (Also MISO [PDO] when used for SPI programming of the chip) + * p4 PE2 In    avr_cts + * p5 PE3 Out   avr_rts + * p6 PE4 In    PPS_GPS + * p7 PE5 In    PPS_EXT_n + * p8 PE6 In    Not Connected + * p9 PE7 In    Not Connected + * + */ + +PORTE = 0; +DDRE =  1<<DDE1; // make outputs, set to zero.  PE1 is usart0 TXD + +/* + * Port F + * + * Split into 2 nibbles; goes to Amp/Filter board to select ENABLE and two bits + * to select band one bit per nibble is not connected. + * + * pin Sig Dir        Our Functional Name + * + * p61 PF0 Out        J117 pin 3  (J117 pins 1 and 2 are GND) + * p60 PF1 Out        J117 pin 4 + * p59 PF2 Out        J117 pin 5 + * p58 PF3 Out        J117 pin 6 + * p57 PF4 Out        J118 pin 3  (J118 pins 1 and 2 are GND) + * p56 PF5 Out        J118 pin 4 + * p55 PF6 Out        J118 pin 5 + * p54 PF7 Out        J118 pin 6 + * + */ + +PORTF = 0;        // Initial Value is all zeros; be sure ENABLE bits are active high!!!! +DDRF =  0xff;    // All bits are outputs + +} diff --git a/firmware/octoclock/lib/network.c b/firmware/octoclock/lib/network.c new file mode 100644 index 000000000..bb49de4f6 --- /dev/null +++ b/firmware/octoclock/lib/network.c @@ -0,0 +1,450 @@ +/* + * Copyright 2009-2012,2014 Ettus Research LLC + * + * 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/>. + */ + +#include <stdint.h> +#include <string.h> + +#include <avr/eeprom.h> +#include <avr/interrupt.h> + +#include <lwip/ip.h> +#include <lwip/udp.h> +#include <lwip/icmp.h> + +#include <debug.h> +#include <octoclock.h> +#include <network.h> + +#include <net/enc28j60.h> +#include <net/eth_hdr.h> +#include <net/if_arp.h> +#include <net/ethertype.h> + +#include "arp_cache.h" + +/*********************************************************************** + * Constants + Globals + **********************************************************************/ +static const size_t out_buff_size = 512; +static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; +#define MAX_UDP_LISTENERS 10 + +/*********************************************************************** + * 16-bit one's complement sum + **********************************************************************/ +static uint32_t chksum_buffer( +    uint16_t *buf, size_t nshorts, +    uint32_t initial_chksum +){ +    uint32_t chksum = initial_chksum; +    for (size_t i = 0; i < nshorts; i++) chksum += buf[i]; + +    while (chksum >> 16) chksum = (chksum & 0xffff) + (chksum >> 16); + +    return chksum; +} + +/*********************************************************************** + * Listener registry + **********************************************************************/ +static eth_mac_addr_t _local_mac_addr; +static struct ip_addr _local_ip_addr; + +struct listener_entry { +    unsigned short	port; +    udp_receiver_t	rcvr; +}; + +static struct listener_entry listeners[MAX_UDP_LISTENERS]; + +void init_udp_listeners(void){ +    for (int i = 0; i < MAX_UDP_LISTENERS; i++) +        listeners[i].rcvr = NULL; +} + +static struct listener_entry * +find_listener_by_port(unsigned short port) +{ +    port = ntohs(port); + +    for (int i = 0; i < MAX_UDP_LISTENERS; i++){ +        if (port == listeners[i].port) +          return &listeners[i]; +    } +    return 0; +} + +static struct listener_entry * +find_free_listener(void) +{ +    for (int i = 0; i < MAX_UDP_LISTENERS; i++){ +    if (listeners[i].rcvr == NULL) +        return &listeners[i]; +    } +    abort(); +} + +void +register_udp_listener(int port, udp_receiver_t rcvr) +{ +    struct listener_entry *lx = find_listener_by_port(port); +    if (lx) +        lx->rcvr = rcvr; +    else { +        lx = find_free_listener(); +        lx->port = port; +        lx->rcvr = rcvr; +    } +} + +/*! + * low level routine to assembly an ethernet frame and send it. + * + * \param dst destination mac address + * \param ethertype ethertype field + * \param buf0 first part of data + * \param len0 length of first part of data + * \param buf1 second part of data + * \param len1 length of second part of data + * \param buf2 third part of data + * \param len2 length of third part of data + */ +static void +send_pkt( +    eth_mac_addr_t dst, int ethertype, +    const void *buf0, size_t len0, +    const void *buf1, size_t len1, +    const void *buf2, size_t len2 +){ +    //assemble the ethernet header +    eth_hdr_t ehdr; +    ehdr.dst = dst; +    ehdr.src = _local_mac_addr; +    ehdr.ethertype = ethertype; + +    //grab an out buffer and pointer +    //select the output buffer based on type of packet +    uint8_t *p; +    p = buf_out; +    size_t total_len = 0; + +    //create a list of all buffers to copy +    const void *buffs[] = {&ehdr, buf0, buf1, buf2}; +    size_t lens[] = {sizeof(ehdr), len0, len1, len2}; + +    //copy each buffer into the out buffer +    for (size_t i = 0; i < sizeof(buffs)/sizeof(buffs[0]); i++){ +        total_len += lens[i]; //use full length (not clipped) +        size_t bytes_remaining = out_buff_size - (size_t)(p - (uint8_t*)buf_out); +        if (lens[i] > bytes_remaining) lens[i] = bytes_remaining; +        memcpy(p, buffs[i], lens[i]); +        p += lens[i]; +    } + +    //ensure that minimum length requirements are met +    if (total_len < 64) total_len = 64; //60 + ctrl word + +    //For some reason, the ENC28J60 won't send the CRC +    //if you don't tell it to send another byte after +    //the given packet +    enc28j60PacketSend(total_len+1, buf_out, 0, 0); +} + +static void +send_ip_pkt(struct ip_addr dst, int protocol, +    const void *buf0, uint16_t len0, +    const void *buf1, uint16_t len1) +{ +    struct ip_hdr ip; +    _IPH_VHLTOS_SET(&ip, 4, 5, 0); +    _IPH_LEN_SET(&ip, (IP_HLEN + len0 + len1)); +    _IPH_ID_SET(&ip, 0); +    _IPH_OFFSET_SET(&ip, htons(IP_DF));	/* don't fragment */ +    _IPH_TTL_SET(&ip, 64); +    _IPH_PROTO_SET(&ip, protocol); +    _IPH_CHKSUM_SET(&ip, 0); +    ip.src.addr = htonl(_local_ip_addr.addr); +    ip.dest = dst; + +    _IPH_CHKSUM_SET(&ip, ~chksum_buffer( +        (uint16_t *) &ip, sizeof(ip)/sizeof(int16_t), 0 +    )); + +    eth_mac_addr_t dst_mac; +    bool found = arp_cache_lookup_mac(&ip.dest, &dst_mac); +    if (!found) return; + +    send_pkt(dst_mac, htons(ETHERTYPE_IPV4), +       &ip, sizeof(ip), buf0, len0, buf1, len1); +} + +void  +send_udp_pkt(int src_port, struct socket_address dst, +    const void *buf, size_t len) +{ +    struct udp_hdr udp _AL2; +    udp.src = htons(src_port); +    udp.dest = htons(dst.port); +    udp.len = htons(UDP_HLEN + len); +    udp.chksum = 0; + +    send_ip_pkt(dst.addr, IP_PROTO_UDP, +        &udp, sizeof(udp), buf, len); +} + +static void +handle_udp_packet(struct ip_addr src_ip, struct ip_addr dst_ip, +    struct udp_hdr *udp, size_t len) +{ +    unsigned char *payload = ((unsigned char *) udp) + UDP_HLEN; +    int payload_len = len - UDP_HLEN; + +    struct listener_entry *lx = find_listener_by_port(udp->dest); +    if (lx){ +        struct socket_address src = make_socket_address(src_ip, ntohs(udp->src)); +        struct socket_address dst = make_socket_address(dst_ip, ntohs(udp->dest)); +        lx->rcvr(src, dst, payload, payload_len); +    } +} + +static void +handle_icmp_packet(struct ip_addr src, struct ip_addr dst, +    struct icmp_echo_hdr *icmp, size_t len) +{ +    switch (icmp->type){ +        case ICMP_DUR:	// Destination Unreachable +            if (icmp->code == ICMP_DUR_PORT){	// port unreachable +                //filter out non udp data response +                struct ip_hdr *ip = (struct ip_hdr *)(((uint8_t*)icmp) + sizeof(struct icmp_echo_hdr)); +                struct udp_hdr *udp = (struct udp_hdr *)(((char *)ip) + IP_HLEN); +                uint8_t protocol = ntohs(ip->_ttl_proto) & 0xff; +                if (protocol != IP_PROTO_UDP) break; + +                struct listener_entry *lx = find_listener_by_port(udp->src); +                if (lx){ +                    struct socket_address src = make_socket_address(ip->src, udp->src); +                    struct socket_address dst = make_socket_address(ip->dest, udp->dest); +                    lx->rcvr(src, dst, NULL, 0); +                } +            } +            break; + +        case ICMP_ECHO:{ +            const void *icmp_data_buff = ((uint8_t*)icmp) + sizeof(struct icmp_echo_hdr); +            uint16_t icmp_data_len = len - sizeof(struct icmp_echo_hdr); + +            struct icmp_echo_hdr echo_reply; +            echo_reply.type = 0; +            echo_reply.code = 0; +            echo_reply.chksum = 0; +            echo_reply.id = icmp->id; +            echo_reply.seqno = icmp->seqno; +            echo_reply.chksum = ~chksum_buffer( //data checksum +                (uint16_t *)icmp_data_buff, +                icmp_data_len/sizeof(int16_t), +                chksum_buffer(                  //header checksum +                    (uint16_t *)&echo_reply, +                    sizeof(echo_reply)/sizeof(int16_t), +                0) +            ); + +            send_ip_pkt( +                src, IP_PROTO_ICMP, +                &echo_reply, sizeof(echo_reply), +                icmp_data_buff, icmp_data_len +            ); +            break; +        } + +        default: +            break; +    } +} + +static void +send_arp_reply(struct arp_eth_ipv4 *req, eth_mac_addr_t our_mac) +{ +    struct arp_eth_ipv4 reply _AL4; +    reply.ar_hrd = req->ar_hrd; +    reply.ar_pro = req->ar_pro; +    reply.ar_hln = req->ar_hln; +    reply.ar_pln = req->ar_pln; +    reply.ar_op = htons(ARPOP_REPLY); +    memcpy(reply.ar_sha, &our_mac, 6); +    memcpy(reply.ar_sip, req->ar_tip, 4); +    memcpy(reply.ar_tha, req->ar_sha, 6); +    memcpy(reply.ar_tip, req->ar_sip, 4); + +    eth_mac_addr_t t; +    memcpy(t.addr, reply.ar_tha, 6); +    send_pkt(t, htons(ETHERTYPE_ARP), &reply, sizeof(reply), 0, 0, 0, 0); +} + +static void +handle_arp_packet(struct arp_eth_ipv4 *p, size_t size) +{ +    if (size < sizeof(struct arp_eth_ipv4)) +        return; + +    if (ntohs(p->ar_hrd) != ARPHRD_ETHER +        || ntohs(p->ar_pro) != ETHERTYPE_IPV4 +        || p->ar_hln != 6 +        || p->ar_pln != 4) +        return; + +    if(ntohs(p->ar_op) == ARPOP_REPLY){ +        struct ip_addr ip_addr; +        memcpy(&ip_addr, p->ar_sip, sizeof(ip_addr)); +        eth_mac_addr_t mac_addr; +        memcpy(&mac_addr, p->ar_sha, sizeof(mac_addr)); +        arp_cache_update(&ip_addr, &mac_addr); +    } + +    if (ntohs(p->ar_op) != ARPOP_REQUEST) +        return; + +    struct ip_addr sip; +    struct ip_addr tip; + +    memcpy(&(sip.addr), &(p->ar_sip), 4); +    memcpy(&(tip.addr), &(p->ar_tip), 4); +    sip.addr = ntohl(sip.addr); +    tip.addr = ntohl(tip.addr); + +    if(memcmp(&tip, &_local_ip_addr, sizeof(_local_ip_addr)) == 0){	//They're looking for us +        send_arp_reply(p, _local_mac_addr); +    } +} + +void +handle_eth_packet(size_t recv_len) +{ +    eth_hdr_t *eth_hdr = (eth_hdr_t *)buf_in; +    uint16_t ethertype = htons(eth_hdr->ethertype); + +    if (ethertype == ETHERTYPE_ARP){ +        struct arp_eth_ipv4 *arp = (struct arp_eth_ipv4 *)(buf_in + sizeof(eth_hdr_t)); +        handle_arp_packet(arp, recv_len-ETH_HLEN); +    } +    else if (ethertype == ETHERTYPE_IPV4){ +        struct ip_hdr *ip = (struct ip_hdr *)(buf_in + sizeof(eth_hdr_t)); + +        if (_IPH_V(ip) != 4 || _IPH_HL(ip) != 5)	// ignore pkts w/ bad version or options +            return; + +        if (_IPH_OFFSET(ip) & (IP_MF | IP_OFFMASK))	// ignore fragmented packets +            return; + +        // filter on dest ip addr (should be broadcast or for us) +        bool is_bcast = memcmp(ð_hdr->dst, &BCAST_MAC_ADDR, sizeof(BCAST_MAC_ADDR)) == 0; +        struct ip_addr htonl_local_ip_addr; +        htonl_local_ip_addr.addr = htonl(_local_ip_addr.addr); + +        bool is_my_ip = memcmp(&ip->dest, &htonl_local_ip_addr, sizeof(_local_ip_addr)) == 0; +        if (!is_bcast && !is_my_ip) return; + +        arp_cache_update(&ip->src, (eth_mac_addr_t *)(((char *)buf_in)+6)); + +        switch (_IPH_PROTO(ip)){ +            case IP_PROTO_UDP: +                handle_udp_packet(ip->src, ip->dest, (struct udp_hdr *)(((char *)ip) + IP_HLEN), (recv_len-ETH_HLEN-IP_HLEN)); +                break; + +            case IP_PROTO_ICMP: +                handle_icmp_packet(ip->src, ip->dest, (struct icmp_echo_hdr *)(((char *)ip) + IP_HLEN), (recv_len-ETH_HLEN-IP_HLEN)); +                break; + +            default:	// ignore +                break; +        } +    } +    else +        return;	// Not ARP or IPV4, ignore +} + +/*********************************************************************** + * Timer+GARP stuff + **********************************************************************/ + +static bool send_garp = false; +static bool sent_initial_garp = false; +static uint32_t num_overflows = 0; + +// Six overflows is the closest overflow count to one minute. +ISR(TIMER1_OVF_vect){ +    num_overflows++; +    if(!(num_overflows % 6)) send_garp = true; +} + +static void +send_gratuitous_arp(){ +    send_garp = false; + +    //Need to htonl IP address +    struct ip_addr htonl_ip_addr; +    htonl_ip_addr.addr = htonl(_local_ip_addr.addr); + +    struct arp_eth_ipv4 req _AL4; +    req.ar_hrd = htons(ARPHRD_ETHER); +    req.ar_pro = htons(ETHERTYPE_IPV4); +    req.ar_hln = sizeof(eth_mac_addr_t); +    req.ar_pln = sizeof(struct ip_addr); +    req.ar_op = htons(ARPOP_REQUEST); +    memcpy(req.ar_sha, &_local_mac_addr, sizeof(eth_mac_addr_t)); +    memcpy(req.ar_sip, &htonl_ip_addr,   sizeof(struct ip_addr)); +    memset(req.ar_tha, 0x00,             sizeof(eth_mac_addr_t)); +    memcpy(req.ar_tip, &htonl_ip_addr,   sizeof(struct ip_addr)); + +    //Send the request with the broadcast MAC address +    send_pkt(BCAST_MAC_ADDR, htons(ETHERTYPE_ARP), &req, sizeof(req), 0, 0, 0, 0); +} + +// Executed every loop +void network_check(void){ +    size_t recv_len = enc28j60PacketReceive(512, buf_in); +    if(recv_len > 0) handle_eth_packet(recv_len); + +    /* +     * Send a gratuitous ARP packet two seconds after Ethernet +     * initialization. +     */ +    if(!sent_initial_garp && (num_overflows == 0 && TCNT1 > (TIMER1_ONE_SECOND*2))){ +        sent_initial_garp = true; +        send_garp = true; +    } + +    if(send_garp) send_gratuitous_arp(); +} + +void network_init(void){ +    /* +     * Read MAC address from EEPROM and initialize Ethernet driver. If EEPROM is blank, +     * use default MAC address instead. +     */ +    if(eeprom_read_byte(0) == 0xFF){ +        _MAC_ADDR(_local_mac_addr.addr, 0x00,0x80,0x2F,0x11,0x22,0x33); +        _local_ip_addr.addr = default_ip; +        using_network_defaults = true; +    } +    else{ +        eeprom_read_block((void*)&_local_mac_addr, (void*)OCTOCLOCK_EEPROM_MAC_ADDR, 6); +        eeprom_read_block((void*)&_local_ip_addr,  (void*)OCTOCLOCK_EEPROM_IP_ADDR, 4); +        using_network_defaults = false; +    } + +    enc28j60Init((uint8_t*)&_local_mac_addr); +} diff --git a/firmware/octoclock/lib/serial.c b/firmware/octoclock/lib/serial.c new file mode 100644 index 000000000..298cdff8d --- /dev/null +++ b/firmware/octoclock/lib/serial.c @@ -0,0 +1,156 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#include <stdbool.h> + +#include <octoclock.h> +#include <serial.h> + +#include <avr/pgmspace.h> +#include <util/delay.h> +#include <avr/io.h> +#include <avr/interrupt.h> + +void serial_init(volatile uint8_t* port, uint8_t index){ +    *port |= _BV(index); +} + +static void _serial_tx_send(uint8_t* buffer, volatile uint8_t* port, uint8_t index){ +    const uint8_t delay = BAUD_115200_DELAY; +    uint8_t countdown; + +    for(uint8_t i = 0; i < 10; ++i){ +        if(buffer[i]) *port |= _BV(index); +        else *port &= ~_BV(index); + +        countdown = delay; +        while(--countdown) asm("nop"); +    } +} + +static void _serial_tx_char(char c, volatile uint8_t* port, uint8_t index){ +	uint8_t buffer[10]; +	uint8_t i = 0; + +	buffer[i++] = 0;	// START +	for (int idx = 0; idx < 8; ++idx) +	buffer[i++] = (((uint8_t)(c) & ((uint8_t)1<<((idx)))) ? 0x01 : 0x00);	// Endianness: 7- +	buffer[i++] = 1;	// STOP + +	_serial_tx_send(buffer, port, index); +} + +void serial_tx_P(const char* message, volatile uint8_t* port, uint8_t index, bool newline){ +    char c = pgm_read_byte(message); +    if(c == '\0') return; + +    do{ +        _serial_tx_char(c, port, index); +        c = pgm_read_byte(++message); +    } while(c != '\0'); + +    if(newline){ +        _serial_tx_char('\r', port, index); +        _serial_tx_char('\n', port, index); +    } + +    *port |= _BV(index); +} + +void serial_tx(const char* message, volatile uint8_t* port, uint8_t index, bool newline){ +    if (message[0] == '\0') +    return; + +    do +    { +        _serial_tx_char(*message, port, index); +    } while (*(++message) != '\0'); + +    if (newline){ +        _serial_tx_char('\r', port, index); +        _serial_tx_char('\n', port, index); +    } + +    *port |= _BV(index); +} + +void serial_tx_byte(uint8_t byte, volatile uint8_t* port, uint8_t index, bool newline){ +    char ch[4]; +    ch[0] = '0' + (byte / 100); +    ch[1] = '0' + ((byte % 100) / 10); +    ch[2] = '0' + (byte % 10); +    ch[3] = '\0'; +    serial_tx(ch, port, index, newline); +} + +void serial_tx_hex(uint8_t byte, volatile uint8_t* port, uint8_t index, bool newline){ +    char ch[3]; +    uint8_t _byte = byte >> 4; +    if (_byte < 10) +        ch[0] = '0' + _byte; +    else +        ch[0] = 'A' + (_byte - 10); +    byte &= 0x0F; +    if (byte < 10) +        ch[1] = '0' + byte; +    else +        ch[1] = 'A' + (byte - 10); +    ch[2] = '\0'; +    serial_tx(ch, port, index, newline); +} + +char serial_rx_char(volatile uint8_t* port, uint8_t index){ +    char c = 0; +    const uint8_t delay = BAUD_115200_DELAY; +    uint8_t countdown; + +    //Wait for character to appear, 0 will act as start marker +    while(*port & _BV(index)); + +    //With start marker there, wait for next bit +    countdown = delay; +    while(--countdown) asm("nop"); + +    for(uint8_t i = 0; i < 8; ++i){ +        if(*port & _BV(index)) c &= (uint8_t)(1 << i); + +        countdown = delay; +        while(--countdown) asm("nop"); +    } + +    return c; +} + +//Assume ready (probably risky) +char serial_rx_char_nowait(volatile uint8_t* port, uint8_t index){ +    char c = 0; +    const uint8_t delay = BAUD_115200_DELAY; +    uint8_t countdown; + +    //Wait for start marker to pass +    countdown = delay; +    while(--countdown) asm("nop"); + +    for(uint8_t i = 0; i < 8; ++i){ +        if(*port & _BV(index)) c &= (uint8_t)(1 << i); + +        countdown = delay; +        while(--countdown) asm("nop"); +    } + +    return c; +} diff --git a/firmware/octoclock/lib/state.c b/firmware/octoclock/lib/state.c new file mode 100644 index 000000000..0dbcc6ece --- /dev/null +++ b/firmware/octoclock/lib/state.c @@ -0,0 +1,124 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#include <avr/interrupt.h> +#include <avr/io.h> + +#include <debug.h> +#include <octoclock.h> +#include <clkdist.h> +#include <state.h> + +void led(LEDs which, int turn_it_on) { + +    // selects the proper bit +    uint8_t LED = 0x20 << which; + +    if(turn_it_on) +        PORTC |= LED; +    else +        PORTC &= ~LED; +} + +void LEDs_Off(void){ +    led(Top,false); +    led(Middle,false); +    led(Bottom,false); +} + +void force_internal(void){ +    led(Top,true); +    led(Middle,false); +    led(Bottom,true); + +    setup_TI_CDCE18005(Primary_GPS); + +    // Set PPS to Primary (1) n.b.:  "1" in general means "Internal" for all +    // such signals +    PORTA |= (1<<PA6); +} + +void force_external(void){ +    led(Top, false); +    led(Middle, true); +    led(Bottom, true); + +    setup_TI_CDCE18005(Secondary_Ext); + +    // Set PPS to External +    PORTA &= ~(1<<PA6); +} + +void prefer_internal(void){ +    // if internal is NOT OK, then force external +    if(global_gps_present) +        force_internal(); +    else if(global_ext_ref_is_present) +        force_external(); +    else +        LEDs_Off(); +} + +void prefer_external(void){ +    // if external is NOT OK, then force internal +    if(global_ext_ref_is_present) +        force_external(); +    else if(global_gps_present) +        force_internal(); +    else +        LEDs_Off(); +} + +static uint8_t prev_PE7 = 0; +static uint32_t timer0_num_overflows = 0; + +ISR(TIMER0_OVF_vect){ +    global_gps_present = (PIND & (1<<DDD4)); + +    // Every ~1/10 second +    if(!(timer0_num_overflows % 610)){ +        prev_PE7 = (PINE & (1<<DDE7)); + +        if(get_switch_pos() == UP) prefer_internal(); +        else prefer_external(); + +        global_ext_ref_is_present = false; +    } + +    if(!global_ext_ref_is_present){ +        global_ext_ref_is_present = (prev_PE7 != (PINE & (1<<DDE7))); +    } + +    timer0_num_overflows++; +} + +ref_t which_ref(void){ +    if(!global_gps_present && !global_ext_ref_is_present) global_which_ref = NO_REF; +    else if(global_gps_present && !global_ext_ref_is_present) global_which_ref = INTERNAL; +    else if(!global_gps_present && global_ext_ref_is_present) global_which_ref = EXTERNAL; +    else global_which_ref = (get_switch_pos() == UP) ? INTERNAL : EXTERNAL; + +    return global_which_ref; +} + +switch_pos_t get_switch_pos(void){ +    uint8_t portC = PINC; + +    // UP is prefer internal, +    // DOWN is prefer external +    return (portC & (1<<DDC1)) ? DOWN : UP; +} diff --git a/firmware/octoclock/lib/udp_handlers.c b/firmware/octoclock/lib/udp_handlers.c new file mode 100644 index 000000000..1f20112c9 --- /dev/null +++ b/firmware/octoclock/lib/udp_handlers.c @@ -0,0 +1,165 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#include <string.h> + +#include <avr/eeprom.h> +#include <avr/io.h> +#include <avr/wdt.h> + +#include <octoclock.h> +#include <gpsdo.h> +#include <network.h> +#include <state.h> +#include <net/udp_handlers.h> + +void handle_udp_ctrl_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +){ +    const octoclock_packet_t *pkt_in = (octoclock_packet_t*)payload; +    octoclock_packet_t pkt_out; +    pkt_out.proto_ver = OCTOCLOCK_FW_COMPAT_NUM; +    pkt_out.sequence = pkt_in->sequence; + +    //If the firmware is incompatible, only respond to queries +    if(pkt_in->code == OCTOCLOCK_QUERY_CMD){ +        pkt_out.code = OCTOCLOCK_QUERY_ACK; +        pkt_out.len = 0; +        send_udp_pkt(OCTOCLOCK_UDP_CTRL_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t)); +    } +    else if(pkt_in->proto_ver == OCTOCLOCK_FW_COMPAT_NUM){ +        switch(pkt_in->code){ +            case SEND_EEPROM_CMD: +                pkt_out.code = SEND_EEPROM_ACK; +                pkt_out.len = sizeof(octoclock_fw_eeprom_t); + +                octoclock_fw_eeprom_t *eeprom_info = (octoclock_fw_eeprom_t*)pkt_out.data; + +                //Read values from EEPROM into packet +                eeprom_read_block(eeprom_info, 0, sizeof(octoclock_fw_eeprom_t)); + +                //If EEPROM network fields are not fully populated, copy defaults +                if(using_network_defaults){ +                    _MAC_ADDR(eeprom_info->mac_addr, 0x00,0x80,0x2F,0x11,0x22,0x33); +                    eeprom_info->ip_addr = default_ip; +                    eeprom_info->dr_addr = default_dr; +                    eeprom_info->netmask = default_netmask; +                } + +                //Check if strings or revision is empty +                if(eeprom_info->serial[0] == 0xFF) memset(eeprom_info->serial, 0, 10); +                if(eeprom_info->name[0] == 0xFF) memset(eeprom_info->name, 0, 10); +                if(eeprom_info->revision == 0xFF) eeprom_info->revision = 0; +                break; + +            case BURN_EEPROM_CMD:{ +                //Confirm length of data +                if(pkt_in->len != sizeof(octoclock_fw_eeprom_t)){ +                    pkt_out.code = BURN_EEPROM_FAILURE_ACK; +                    break; +                } + +                /* +                 * In all cases, a full octoclock_fw_eeprom_t is written to lower the overall +                 * number of writes due to this EEPROM's smaller amount of safe writes. +                 * It is up to the host to make sure that the values that should be +                 * preserved are present in the octoclock_fw_eeprom_t struct. +                 */ +                const octoclock_fw_eeprom_t *eeprom_pkt = (octoclock_fw_eeprom_t*)pkt_in->data; +                pkt_out.len = 0; + +                //Write EEPROM data from packet +                eeprom_write_block(eeprom_pkt, 0, sizeof(octoclock_fw_eeprom_t)); + +                //Read back and compare to packet to confirm successful write +                uint8_t eeprom_contents[sizeof(octoclock_fw_eeprom_t)]; +                eeprom_read_block(eeprom_contents, 0, sizeof(octoclock_fw_eeprom_t)); +                uint8_t n = memcmp(eeprom_contents, eeprom_pkt, sizeof(octoclock_fw_eeprom_t)); +                pkt_out.code = n ? BURN_EEPROM_FAILURE_ACK +                                 : BURN_EEPROM_SUCCESS_ACK; +                break; +            } + +            case SEND_STATE_CMD: +                pkt_out.code = SEND_STATE_ACK; +                pkt_out.len = sizeof(octoclock_state_t); + +                //Populate octoclock_state_t fields +                octoclock_state_t *state = (octoclock_state_t*)pkt_out.data; +                state->external_detected = global_ext_ref_is_present ? 1 : 0; +                state->gps_detected = (PIND & _BV(DDD4)) ? 1 : 0; +                state->which_ref = (uint8_t)which_ref(); +                state->switch_pos = (uint8_t)get_switch_pos(); +                break; + +            case RESET_CMD: +                pkt_out.code = RESET_ACK; +                send_udp_pkt(OCTOCLOCK_UDP_CTRL_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t)); +                wdt_enable(WDTO_30MS); +                while(1); +                return; + +            default: +                return; +        } + +        send_udp_pkt(OCTOCLOCK_UDP_CTRL_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t)); +    } +} + +void handle_udp_gpsdo_packet( +    struct socket_address src, struct socket_address dst, +    unsigned char *payload, int payload_len +){ +    const octoclock_packet_t *pkt_in = (octoclock_packet_t*)payload; +    octoclock_packet_t pkt_out; +    pkt_out.proto_ver = OCTOCLOCK_FW_COMPAT_NUM; +    pkt_out.sequence = pkt_in->sequence; + +    if(pkt_in->proto_ver == OCTOCLOCK_FW_COMPAT_NUM){ +        switch(pkt_in->code){ +            case HOST_SEND_TO_GPSDO_CMD: +                send_gpsdo_cmd((char*)pkt_in->data, pkt_in->len); +                pkt_out.code = HOST_SEND_TO_GPSDO_ACK; +                pkt_out.len = 0; +                break; + +            case SEND_POOLSIZE_CMD: +                pkt_out.code = SEND_POOLSIZE_ACK; +                pkt_out.len = 0; +                pkt_out.poolsize = POOLSIZE; +                break; + +            case SEND_CACHE_STATE_CMD: +                pkt_out.code = SEND_CACHE_STATE_ACK; +                pkt_out.state = gpsdo_state; +                break; + +            case SEND_GPSDO_CACHE_CMD: +                pkt_out.code = SEND_GPSDO_CACHE_ACK; +                pkt_out.state = gpsdo_state; +                memcpy(pkt_out.data, gpsdo_buf, POOLSIZE); +                break; + +            default: +                return; +        } + +        send_udp_pkt(OCTOCLOCK_UDP_GPSDO_PORT, src, (void*)&pkt_out, sizeof(octoclock_packet_t)); +    } +} diff --git a/firmware/octoclock/lib/usart.c b/firmware/octoclock/lib/usart.c new file mode 100644 index 000000000..3620ac5e9 --- /dev/null +++ b/firmware/octoclock/lib/usart.c @@ -0,0 +1,49 @@ +/* + * Copyright 2014 Ettus Research LLC + * + * 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/>. + */ + +#include <octoclock.h> +#include <usart.h> + +#include <util/delay.h> +#include <avr/io.h> + +void usart_init(void){ +    UCSR1B = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE); //Turn on TX/RX circuitry, enable RX interrupts +    UCSR1C = (3 << UCSZ0); //Use 8-bit character sizes, 1 stop bit, no parity +    UBRR1H = (uint8_t)(BAUD_PRESCALE >> 8); +    UBRR1L = (uint8_t)BAUD_PRESCALE; +} + +char usart_getc(void){ +    while((UCSR1A & (1 << RXC)) == 0); + +    return UDR1; +} + +char usart_getc_noblock(void){ +    return ((UCSR1A & (1 << RXC))) ? UDR1 : -1; +} + +void usart_putc(char ch){ +    while((UCSR1A & (1 << UDRE1)) == 0); + +    UDR1 = ch; +} + +void usart_putc_nowait(char ch){ +    if((UCSR1A & (1 << UDRE1)) != 0) UDR1 = ch; +} diff --git a/firmware/octoclock/octoclock_r4/CMakeLists.txt b/firmware/octoclock/octoclock_r4/CMakeLists.txt new file mode 100644 index 000000000..c3559d8d4 --- /dev/null +++ b/firmware/octoclock/octoclock_r4/CMakeLists.txt @@ -0,0 +1,50 @@ +# +# Copyright 2014 Ettus Research LLC +# +# 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/>. +# + +add_executable(octoclock_r4_fw.elf octoclock_r4_main.c) +target_link_libraries(octoclock_r4_fw.elf octoclock) +set_target_properties(octoclock_r4_fw.elf PROPERTIES +    LINK_FLAGS "-Wl,--relax,-Map=octoclock_r4_fw.map,--cref" +) + +add_custom_command( +    OUTPUT ${CMAKE_BINARY_DIR}/octoclock_r4_fw.bin +    DEPENDS octoclock_r4_fw.elf +    COMMENT "Generating octoclock_r4_fw.bin" +    COMMAND ${AVR_OBJCOPY} -O binary ${CMAKE_CURRENT_BINARY_DIR}/octoclock_r4_fw.elf ${CMAKE_BINARY_DIR}/octoclock_r4_fw.bin +) +add_custom_target( +    octoclock_r4_fw_bin ALL +    DEPENDS ${CMAKE_BINARY_DIR}/octoclock_r4_fw.bin +) +add_custom_command( +    OUTPUT ${CMAKE_BINARY_DIR}/octoclock_r4_fw.hex +    DEPENDS octoclock_r4_fw.elf +    COMMENT "Generating octoclock_r4_fw.hex" +    COMMAND ${AVR_OBJCOPY} -O ihex ${CMAKE_CURRENT_BINARY_DIR}/octoclock_r4_fw.elf ${CMAKE_BINARY_DIR}/octoclock_r4_fw.hex +) +add_custom_target( +    octoclock_r4_fw_hex ALL +    DEPENDS ${CMAKE_BINARY_DIR}/octoclock_r4_fw.hex +) +add_custom_target( +    upload_r4 +    ${AVRDUDE} -p atmega128 -c ${PROGRAMMER} -P usb -U efuse:w:0xFF:m -U hfuse:w:0x81:m -U lfuse:w:0xFF:m -U flash:w:octoclock_r4_fw.hex:i +    WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +    DEPENDS octoclock_r4_fw_hex +    COMMENT "Uploading OctoClock firmware to device with ${PROGRAMMER}" +) diff --git a/firmware/octoclock/octoclock_r4/octoclock_r4_main.c b/firmware/octoclock/octoclock_r4/octoclock_r4_main.c new file mode 100644 index 000000000..5e8e6d09b --- /dev/null +++ b/firmware/octoclock/octoclock_r4/octoclock_r4_main.c @@ -0,0 +1,105 @@ +/* + * Copyright 2013-2014 Ettus Research LLC + * + * 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/>. + */ + +/* + * Welcome to the firmware code for the USRP Octoclock accessory product! + * + * Notes regarding this firmware: + *      NOT in M103 compatibility mode + *      CKOPT full rail-to-rail + *      xtal osc + *      16K CK (16K clock cycles) + *      additional delay 65ms for Crystal Oscillator + *      slowly rising power + *      persistent EEPROM + * + * These settings are very conservative. If a lower power oscillator is + * required, change CKOPT to '1' (UNPROGRAMMED). + * + * M103C     = [ ] + * WDTON     = [ ] + * OCDEN     = [ ] + * JTAGEN    = [X] + * SPIEN     = [X] + * EESAVE    = [X] + * BOOTSZ    = 4096W_F000 + * BOOTRST   = [ ] + * CKOPT     = [X] + * BODLEVEL  = 2V7 + * BODEN     = [ ] + * SUT_CKSEL = EXTHIFXTALRES_16KCK_64MS + * + * EXTENDED  = 0xFF (valid) + * HIGH      = 0x81 (valid) + * LOW       = 0xFF (valid) + * + */ + +#include <string.h> +#include <stdint.h> +#include <stdbool.h> + +#include <avr/eeprom.h> +#include <avr/io.h> + +#include <octoclock.h> +#include <clkdist.h> +#include <debug.h> +#include <state.h> +#include <network.h> +#include <usart.h> +#include <gpsdo.h> +#include <net/enc28j60.h> +#include <net/udp_handlers.h> + +/******************************************************************************* +*   Main Routine +*******************************************************************************/ + +int main(void){ + +    asm("cli"); + +    setup_atmel_io_ports(); +    network_init(); + +    #ifndef DEBUG +    asm("sei"); +    #endif + +    init_udp_listeners(); +    register_udp_listener(OCTOCLOCK_UDP_CTRL_PORT, handle_udp_ctrl_packet); +    register_udp_listener(OCTOCLOCK_UDP_GPSDO_PORT, handle_udp_gpsdo_packet); + +    DEBUG_INIT(); // Does nothing when not in debug mode +    DEBUG_LOG(" "); //Force a newline between runs +    usart_init(); + +    //Set initial ClkDist and front panel settings +    led(Middle,true); +    setup_TI_CDCE18005(Primary_GPS);    // 10 MHz from Internal Source + +    led(Top,true); +    PORTA |= (1<<PA6);    // PPS from Internal source + +    TIMER0_INIT(); +    TIMER1_INIT(); + +    while(true) { +        network_check(); +    } +}  | 
