eWicht: Version tracking

Version tracking

Version 1.1 Latest
Bug Fixes
  • IP address could not be entered in the Server URL field of the web interface
  • Entries in the GA database were not accessible
  • ESC support of the database dialog (GA and GL) did not correctly work.

Version 1.1 Build 201
License Changed the name of the license from eWSL to MBCSL.

Projects Splitted the project in two sub-projects:

  • SRCP client
  • Rocrail client

Also the project is prepared for more sub projects to come.

Rocrail client A first try includes:

  • Connection handler
  • XML communication module
  • Loco database browser
  • Loco control (adopted from the SRCP version)
  • Power control

EEPROM Migration The internal EEPROM data representation has fundamentally changed and therefore the old EEPROM set will be lost during an update from 1.0.X.

Edited the MPFS tool (and the MPFS2 module)

  • All characters < 0x20 and > 0x7F are removed from the html files while packing the HTML image.
  • Removed all the dynamic function caller names, because the index file is used for generating the calls.
  • Added a simple huffman encoding and decoding (MPFS2 module) algorithm for html files.

Core changes

  • Moved the input encoder processing to a 2ms cycled interrupt routine.
  • Added heap functionality.
  • Added a light weight XML processor module for configuration file and Rocrail protocol processing.
  • Terminus "Quick set" changed to "Set", changed the default Set name from "FX" to "SX".
  • Added BETA support for Rocrail in parallel to SRCP
  • Extended all the function maps from 16 to 32 Bit.
  • Extended all the speed variables from 8 to 16 Bit.

eWicht Homepage

  • Removed all javascript sections - homepage is now a set of pure HTML and CSS.
  • Reworked style.css. HTML code uses more css classes now (saves a lot of space).
  • Navigation bar is dynamically generated while loading the page.
  • All type and range tests are dynamically done by the runtime environment.
  • Added more pages: SRCP is splitted into common SRCP settings, Loco protocold, Loco Sets, Accessory protocols and Accessory Sets; File page is used for download and upload of XML configuration files.
  • Common settings page is extended with fields for changing IP and server settings.
  • Server is given in an URL style input. So it is possible to implicitly specify the protocol (SRCP as default or RR) of the server communication.

Language string table

  • Implemented a string table module. Two string tables exist: a German one and a English one. These string tables store all display and website strings.
  • Added display dialog (once at startup and after factory reset) and on the common settings webpage for changing the language dynamically.

Sets

  • All data regarding EEPROM Sets for locos or accessories can be changed via a configuration website.
  • This webiste consists of two parts, summary and details.
  • The summary website list all configured sets with name and address.
  • The details website can be entered via a link from the summary website.
  • On the details website all parameters can be changed.
  • Locos: Address, name, maximum speed, function count, protocol parameters, toggle mask.
  • The toggle mask can be used to use a function button either as a toggle or switch.
  • Accessory: Address, name, delay, ports, protocol parameters.
  • The delay setting overwrites the global delay setting for accessories.
  • The first four sets are the ancient quick sets and can be activated via F1-F4 at the eWicht.
  • Other sets can be loaded via a new eWicht dialog

Else

  • Added the possibility to upgrade firmware during runtime (see DEPLOY for details).
  • Hopefully fixed a bug in the LCD code: After initial power on, the LCD sometimes stand off.
  • Enable the F1 button in server and IP menu on startup (leads to ESC).
  • Added string dialog for the Set to editing the Set name directly at the eWicht.
  • Added a second mode for toggling the loco direction via the zero point. Extended the webpages to configure the mode.
  • Fixed the "reset to factory settings" bugs (see Error)
  • Inserted a version tag in the EEPROM for indicating whether a firmware update was done. So the change of the data structure in the EEPROM is possible.
  • Support for up to 12 (+F0) functions added. Long push on F0 button leads to F4-F8, another F0 push leads to F9-F12, a second push leads back to F1-F4.
  • Added server cache feature. Up to 11 GLs are stored in the eWicht local cache. 101 INFO message leads to new entries in the cache. 102 INFO messages remove the appropriate entries in the cache. The server cache entries can be accessed by user via the generic protocol select. Also the feature can be selected as standard protocol by the web interface.
  • Changed the SRCP Menu name to Server Menu as preparation for other services (RR).

Version 1.0.7
  • Fixed a bug occured in DHCP mode: Nameservice was not started.
  • Turbo encoder for input rotary encoder is not longer default. The mode must explicitly enabled with a flag while initializing. The most of the time the turbo mode stays disabled now.
  • Shortened the long push time from 2 to 1 second.

Version 1.0.6
  • Fixed a bug in the SRCP device cache. Now the switch over between GAs and GLs works.
  • Changed the turbo encoder implementation to a speed dependent one.
  • Added so called quick buttons. After initialization of GA or GL devices they can be associated with one of the four F buttons (long push). Whenever the GA or GL is needed again simple press the GA or GL buttons and the preused F-button. The F button occupation is permanently saved in the eWicht EEPROM.

Version 1.0.5
Web interface:
  • Added a restart button to the index.htm on the web interface.
  • The protocol addresses (min and max) can be the same now.
  • Added the "Delay" value to the GA page.
  • Changed the GA maximum allowed port to 7.
  • Added a change common settings page and added LCD backlight settings to the page.
  • Changed the CSS stylesheet a bit to the look and feel of the project web pages.

Else:

  • Switching off all the F-LEDs when changing from GL to GA.
  • Restructured the manual for a better readability.
  • Added a timeout (2 seconds) when sending a command to the server and getting no answer.
  • Fixed a bug in the turbo encoder algorithm - I think the available speed steps are ok now.
  • Added quick switch over between GLs and GAs: GA active -> Single push on GL button -> Shows last active GL GL active -> Single push on GA button -> Shows last active GA (resp. port)
  • Added support for delaying GAs (Delay is always 0 when disabling a port).
  • Workarround for GA-Bug works well at srcpd now!
  • Fixed the "a"-Bug at the name dialog. Implemented F1-F4 support for all, IP and SRCP dialogs. F1 goes back to the previous menu item, F4 to the next item, F2 has the Escape function (changed from the power button), F3 has the backspace function (changed from the accessory button).
  • Fastened the switch over time between IP digits in the IP dialogs.
  • Make the LCD backlight switchable (without new display commands) and configurable from the web interface.

Version 1.0.4
  • Fixed a bug in the appl module: After a established two socket SRCP connection a switch off (with long push on the power switch) was not always successful and the eWicht started to hang!
  • Fixed a bug in IE: script interpreter of IE is not case sensitive. Changed the checkbox names of the protocols from "a" to "c" and the end of protocol line from "N" to "E".
  • Changed the css of the eWicht homepage for better readability of the sites.
  • Changed the homepage java script for checking GA and GL inputs: GA min port and max port can be the same value.
  • Changed the turbo-encoder implementation: Dependend on the initialized encoder range different turbo steps are used.
  • Shorted the switch off time: Abandon displaying the "eWicht will shut down soon"-string saves at least 5 seconds.
  • Fixed a bug in the input module - it has taken too long for detecting a single button push.
  • Locked the rotary encoder when it pushed.

Version 1.0.3
Fixed a bug on the web page: subnet mask and gateway were interchanged.

Version 1.0.2
Added tracking of the encoder value while changing the loco speed at the eWicht client. When turning fast, there was a consistency problem.

Version 1.0.1
Initial release of the eWicht project.
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: The MoBaCon Software License (MBCSL)

The MoBaCon Software License (MBCSL)

The MBCSL applies to the software's source and object code and comes with any rights that I have in it (other than trademarks).

You agree to the MBCSL by copying, distributing, or making a derivative work of the software.

You get the royalty free right to:

  • Use the software for non-commercial purposes;
  • Make derivative works of it for non-commercial (this is called a "Derived Work");
  • Copy and distribute it and any Derived Work for non-commercial purposes.

If you distribute the software or a Derived Work, you are required to give it back to the community by:

  • Attend and observe the included Microchip License Agreement (see Microchip for details);
  • Prominently noting the date of any changes you make;
  • Leaving other people's copyright notices, warranty disclaimers, and license terms in place;
  • Providing the source code, build scripts, installation scripts, and interface definitions in a form that is easy to get and best to modify;
  • Licensing it to everyone under MBCSL without adding further restrictions to the rights provided;
  • Conspicuously announcing that it is available under that license.

There are some things that you must shoulder:

  • You get NO WARRANTIES. None of any kind;
  • If the software damages you in any way, you may only recover direct damages up to the amount you paid for it (that is zero if you did not pay anything). You may not recover any other damages, including those called "consequential damages." (The state or country where you live may not allow you to limit your liability in this way, so this may not apply to you);

The MBCSL continues perpetually, except that your license rights end automatically if:

  • You do not abide by the "give back to the community" terms (your licensees get to keep their rights if they abide);
  • Anyone prevents you from distributing the software under the terms of the MBCSL.
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Folder structure and project files

Folder structure and project files

The files in the root directory are the common sources which are used by the projects.

Further files in the root directory: The central makefile including targets for building the common sources, the doxygen documentation and deploying. The Doxyfile for building the documentation The workspace file for the MPLAB IDE

All the sources which are licensed by Microchip are located in the separate Microchip folder. These are files for EEPROM access via UNIO and the TCPIP Stack modules, the MPFS sources and the bootloader.

The documentation input files like several additional text files and images are located in doc. The output of the documentation build process is also written to doc.

The final image and hex files are put into the Release folder.

Each project has a separate folder. These files are typically included:

  • The project makefile for configuring the project build process. The file uses the central Makefile in the root directory for buidling the project.
  • The project related source and header files
  • The project file for the MPLAB IDE
  • The project related linker script
  • The project related website in the web folder
  • The intermediate output files of the build process are put into the bin folder
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: How to build

How to build

What to install

Compiler

The MCC18 Compiler (V3.35 or greater) can be used under a free Student License. The latest version can be downloaded from the Microchip website. This license enables the user to compile and link the project modules (The extended mode is not used).

The MCC18 is available for Window only. For Linux and MAC you can give the PICC Compiler (http://www.htsoft.com/) a try (I have not tried this, please let me know if it works). Also I have read about users which are using MCC18 with WINE.

IDE

The MPLAB IDE (V8.5 or greater) is free but for Windows only. The latest version can be downloaded from the Microchip website. Workspace and project files for MPLAB are included in this project.

Alternatively you can use MinGW and the included makefiles to build the project. Also any IDE (i.e. Eclipse) where a make process can be started is possible.

MPFS and VisualStudio

For compiling the project web sites to a MPFS image the MPFS tool is needed. The MPFS Tool, integrated in Microchips TCP/IP Stack, was modified for this project. The sources and an already compiled executable (in the MPFS folder) are included in this software package. If you'd like to compile the sources according to your own modifications you need Microsoft Visual Studio Express for C# (freely available at Microsoft). The MPLAB project files include building of the web image as prebuild steps. The makefile includes a target for the MPFS image.

The MPFS image itself is an ANSI C file which is simply compiled within the build process.

How to build with MPLAB

Simply open the root workspace file *.mcw with the MPLAB IDE. Activate your prefered mode, the appropriate Debugger or Programmer and select "Build All". When the build process has finished the generated image file is located in the Release folder. Continue with programming or debugging the device with the output *.cof and *.hex files.

Activating the debug mode

This mode is for real time hardware debugging on i.e. a Microchip ICD2. The build image is running without the special bootloader and can therefore be flashed directly to the device target. In this mode the MAC address and the hostname of the device can freely be chosen by changing them in the appropriate code sections.

Activating the release mode

This mode generates an image which can not run without the special bootloader. Typically the user will choose this mode because no programmer device like an Microchip ICD2 is needed. Simply build the application and use a tftp client for uploading the image (see DEPLOY). For changing the MAC address and hostname the bootloader code must be changed.

How to build with MinGW

The included makefiles also can be used to build the device images. Only release images are generated by default.
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: How to deploy

How to deploy

Upload with a TFTP client

The device comes with an integrated bootloader which enables firmware updates via TFTP. The bootloader uses the assigned MAC address written on the label on the bottom of the eWicht enclosure.

The IP address is set to 192.168.97.60.

These default addresses are statically defined and can only be changed by recompiling the bootloader itself. The only services that are available during bootloader operation are TFTP and ARP. ICMP (ping) and other services are not implemented.

TFTP operation on clean or faulty devices

On clean devices the bootloader is active by default. The active bootloader is indicated by a fast blinking link LED.

If an application is installed the bootloader stays active after power cycling until the power button is pressed.

To access the bootloader directly, the bootloader's IP address must be on the same subnet as your computer. For the default 192.168.97.60 IP address, you must temporarily change the settings on your PC.

The following instructions assume you are using Microsoft Windows XP and will vary for other operating systems.

  1. Open Network Connections.

  2. Right click on the network adapter that you are using to communicate with the bootloader and choose Properties.

  3. Select Internet Protocol (TCP/IP) and click Properties.

  4. Select Use the following IP address and then enter the IP address 192.168.97.61.

    Click OK and then Close on the previous dialog to close them and set the new address.

After completing the TFTP upload process, restore your PC's IP address settings to allow normal network activity and access to the application you bootloaded.

TFTP operation on clean or faulty devices

If the running application is compiled with the Reboot module of the Microchip TCPIP Stack, the build process can be started sending TFTP packets to the device. Once a TFTP packet received the device enters the bootloader automatically. IP address and MAC address of the application are adopted by the bootloader. Therefore no network settings must be changed in case the device application was accessible before.

TFTP Operation

Most operating systems come with a TFTP client built in. In Microsoft Windows, this utility is named tftp.exe. This utility is a very simple console application which can be used to upload your application .hex file over the network to the bootloader. To perform a Flash upgrade using the tftp.exe client, follow these procedures:

  1. Enter the bootloader mode like described above.
  2. At a console, execute the following command. Make appropriate path changes to the hex file.
    tftp 192.168.97.60 put "eWicht.hex"
  3. If successful, the TFTP client will indicate how long the transfer took.
  4. The bootloader does data read back verification shortly after writing and does not need a second step to read back the Flash contents. If a verification error occurs, the error will be immediately reported to the TFTP client.

With the ICD2

When a new bootloader must be programmed or you want to debug an application you have to connect with a programming device like the ICD2.

Before connecting the enclosure of the eWicht must be opened:

  1. Remove the cap of the rotary encoder and ease the fastening nut.
  2. Remove the rotary encoder button.
  3. Unscrew the 4 screws on the backside of the enclosure.
  4. Now you can open the enclosure and look at the PCB of eWicht.

The 5 wire (VCC, GND, PGD, PGC, MCLR) interface of the ICD2 must be connected to the pads (see the red circles in the picture below).

Cutout of the eWicht top placement

Important Note: VCC must NOT be powered from the ICD2. Use an external 3.3 Volt power supply instead!

If you have problems connecting to eWicht C107 should be removed.
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: List of errors and feature requests

List of errors and feature requests

Version 1.1

  • After start searching for a server (SRCP or Rocrail) the connection process may take a very long time. This occurs if the server is started _after_ the search process is started.
  • Input of the srcp server without DNS lookup, speaking names like "srcp.heimnetz". Need a dot in the alphanumeric mode. DNS server address comes via DHCP - can not be changed manually at eWicht. If DHCP is not used (IP is given manual or AutoIP), eWicht uses zeroconf for name resolution.
  • Add SRCP lock support to eWicht.
  • Add HW version checking in the Bootloader to prevent firmware update errors.

Version 1.0.7 (100201)

Open feature requests after finishing 1.0.7

  • Senseless default bus settings: Set all bus addresses to "1" (srcpd compatibility). Workarround for this: Implementing a file upload/download on the web interface for quick changing of known server settings.
  • Implement a small database for well known GLs and GAs.
  • Immediately changing of the parameters via the web interface and not after restarting (problem of inconsistency between eWicht and web interface)
  • Input of the srcp server without DNS lookup, speaking names like "srcp.heimnetz". Need a dot in the alphanumeric mode. DNS server address comes via DHCP - can not be changed manually at eWicht. If DHCP is not used (IP is given manual or AutoIP), eWicht uses zeroconf for name resolution.
  • Deepen the size of the SRCP device cache.
  • Multilanguage support (at least English).
  • Add SRCP lock support to eWicht.
  • Add HW version checking in the Bootloader to prevent firmware update errors.

Version 1.0.6 (090904)

Known bugs and problems

  • Funny chararcters after manufacturer reset (or initial flashing) while inputing a new server or service name
  • Manual manufacturer reset from the website does not work
  • Turbo encoder pains at some settings with a small set space

Open feature requests after finishing 1.0.6

  • Senseless default bus settings: Set all bus addresses to "1" (srcpd compatibility). Workarround for this: Implementing a file upload/download on the web interface for quick changing of known server settings.
  • Implement a small database for well known GLs and GAs.
  • Immediately changing of the parameters via the web interface and not after restarting (problem of inconsistency between eWicht and web interface)
  • Input of the srcp server without DNS lookup, speaking names like "srcp.heimnetz". Need a dot in the alphanumeric mode. DNS server address comes via DHCP - can not be changed manually at eWicht. If DHCP is not used (IP is given manual or AutoIP), eWicht uses zeroconf for name resolution.
  • Deepen the size of the SRCP device cache.
  • Multilanguage support (at least English).
  • Add SRCP lock support to eWicht.

Version 1.0.5 (090809)

Known bugs and problems

  • turbo encoder does not work intuitively enough. Maybe implement it as speed dependent.
  • Overflow in SRCP device cache leads to a change from GAs to GAs and not to GLs when pressed the GL button.

Open feature requests after finishing 1.0.5

  • Senseless default bus settings: Set all bus addresses to "1" (srcpd compatibility). Workarround for this: Implementing a file upload/download on the web interface for quick changing of known server settings.
  • Implement a small database for well known GLs and GAs.
  • Immediately changing of the parameters via the web interface and not after restarting (problem of inconsistency between eWicht and web interface)
  • Input of the srcp server without DNS lookup, speaking names like "srcp.heimnetz". Need a dot in the alphanumeric mode. DNS server address comes via DHCP - can not be changed manually at eWicht. If DHCP is not used (IP is given manual or AutoIP), eWicht uses zeroconf for name resolution.
  • Deepen the size of the SRCP device cache.
  • Multi-language support (at least English).
  • Add SRCP lock support to eWicht.

Version 1.0.4 (090509)

Known bugs and problems

  • While entering a name at the name input dialog (i.e. for server network names) and finishing this dialog with a double push an 'a' is added to the name.
  • Wrong port interpretation of the SRCP GA ports in the srcp client module leads to the possebility that two ports drive current at the same time. Solution: Display both ports as one (toggle).
  • srcpd logs two seperate timestamps per port of one GA address, DDW only one timestamp per GA address. eWicht has problems to handle the srcpd case.
  • Shorten the single push time
  • One more speed step for turbo encoding is needed
  • Currently the GA delay is -1 (unlimited), that better should be a value between 100ms and 500ms. Furthermore this value should be requested if needed.

Open feature requests after finishing 1.0.4

  • Senseless default bus settings: Set all busaddresses to "1" (srcpd compatibility). Started a discussion on the DDW mailinglist to this topic.
  • Give the last used address when making an address change (GA and GL).
  • Double push of the rotary switch - Less intuitive than long pushes or pushes on other buttons
  • Immediately changing of the parameters via the web interface and not after restarting (problem of inconsistency between eWicht and web interface -> Workarround: button for restarting on the webinterface)
  • Input of the srcp server without DNS lookup, speaking names like "srcp.heimnetz". Need a dot in the alphanumeric mode. DNS server address comes via DHCP - can not be changed manually at eWicht. If DHCP is not used (IP is given manual or AutoIP), eWicht uses zeroconf for name resolution.
  • Switch off the LCD light after 1-2 minutes doing nothing.
  • Reorder the manual for a better readability.

Version 1.0.3 (090404)

Problems - Discovered by David Ruetti (tested on srcpd 2.0.13 pre (from svn)) and priorized by svesch

  1. Rotary switch in Turbo mode: At some speed the value jumps undefined
  2. GA crashes. Input of address & protocol and the first switching works fine, but after this nothing works anymore. Solution: Switch off or another push on the accessory button.
  3. Delay after input (rotary switch) or button pushing is too big. For example IP input: 192.168. ... change between the octets by simply pushing the rotary switch. Danger through unwanted changing of the value of the last octet while changing fast because of the mentioned delay.
  4. Senseless default bus settings: Set all bus addresses to "1" (srcpd compatibility). Speak with Michael Graefe for changing this in DDW.

Features requests for version 1.0.3 (090404) from David

Ruetti:
  • Time for switching off the device is too long. How shorten it?
  • Give the last used address when making an address change (GA and GL).
  • Double push of the rotary switch - Less intuitive than long pushes or pushes on other buttons
  • Immediately changing of the parameters via the web interface and not after restarting (problem of inconsistency between eWicht and web interface -> Workarround: button for restarting on the webinterface)
  • List of devices (GAs and GLs) with "speaking" names, history of the last addresses
  • Input of the srcp server without DNS lookup, speaking names like "srcp.heimnetz". Need a dot in the alphanumeric mode. DNS server address comes via DHCP - can not be changed manually at eWicht. If DHCP is not used (IP is given manual or AutoIP), eWicht uses zeroconf for name resolution.
  • Switch off the LCD light after 1-2 minutes doing nothing.

Changing suggestions in the manual

  • Change the order of the chapters. Use the importance for ordering. Quick access without background knowledge at the beginning, Prerequisites: (MoBa+SRCPD/DDL/DDW, supported srcp versions) and base operation. Details later.
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Todo List

Todo List

File DHCP.c
Generate a doxygen page for discussing the eWicht project and the DHCP and AutoIP behavior (High level).

Global DHCPFlags
Remove the DHCP externals?!

Global _CheckForQueryResponse
Message compression.

Global _eHandShake
Revise the error messages.

File TCP.c
Change from AppConfig structure to sIPConfig

File TCP.h
TCPIsClosed was removed.

Group INPUT
Place a graphic here for showing the buttons.

Group OUTPUT
Place a graphic here for showing the buttons and display.

Group OUTPUT
Define a command interface for the LCD as a function. Centralize and internationalize the displayed strings.

Global OutInit
Which symbols: document?

Global DHCPTask
Save the probed auto IP-Address in EEPROM

Global IPConvertMaskToSubnet
Add the (DWORD) output values.

Global IPConvertMaskToSubnet
Move this function to the helpers.

Global IPConvertSubnetToMask
Move this function to the helpers.

Global MACIsLinked
Maybe an access to the LATA register is better?!
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Module Index

Modules

Here is a list of all modules:
  • Application module
  • Application network and initialization module
  • Input devices
  • IP dialogues
  • Multicast DNS
    • Resolving records
  • LED and LCD routines
    • Display commands
    • LED masks
  • String tables
  • Web interface
  • XML parser
  • TCP/IP Stack from Microchip Version 4.50 (Modified)
    • ARP
    • DHCP
    • HTTP
    • ICMP
    • IP
    • MAC
    • MPFS
    • Reboot
    • Stack Task
    • TCP
    • Tick
    • UDP
    • EEPROM
  • SRCP Client
  • Rocrail Client
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Application module

Application module

Detailed Description

This module manages the application stuff from bringing up the TCPIP Stack, doing all the user interactions for this, searching for a SRCP server and open and manages the TCP connection to this server.

Files

file | appl.c
This file implements the eWicht application module.
file | appl.h
This file includes the eWicht application module API.
file | appldefs.h
This file defines some basic structures and enumerators for the application module.
file | dialog.c
This file implements the dialog module.
file | dialog.h
This file includes the dialog module API.
file | eeprom_adds.h
This file includes a global address partion table for the eWicht EEPROM.
file | error.c
This file implements error print functions.
file | error.h
This file includes some common error codes.

Data Structures

struct | SPAPPLDATA
This typedef defines the peristent structure for common application settings. More...

Defines

#define | BOOTUP_EEPROM_ADD (0x0000u)
EEPROM byte address for application network data.
#define | APPL_EEPROM_ADD (0x0100u)
EEPROM byte address for common application data.

Enumerations

enum | _SEARCH_MODES { SEARCH_UNKNOWN = 0, SEARCH_IP, SEARCH_NAME, SEARCH_SERVICE }
This typedef defines the different ways to find and connect a server. More...

Functions

void | ApplInit (void)
Call this function to initialize the application module.
void | ApplMain (void)
Call this function periodically to execute the application module.
IP_ADDR * | ApplGetServerIP (void)
Call this function to determine the IP address of the configured server for this device.
NODE_INFO * | ApplGetServerNodeInfo (void)
Call this function to determine the node info (MAC and IP address) of the configured server for this device.
WORD_VAL | ApplGetServerPort (void)
Call this function to determine the port (TCP/UDP) of the configured server for this device.
BOOL | ApplIsConnected (void)
This proxy function delivers the connect state of the current project.
void | ApplResetToFactory (BOOL KeepBootup)
This function restores the EEPROM content to a well known state.
void | ApplShutDown (void)
The function initiates the shut down sequence while the application is still running.
BOOL | ApplIsRunning (void)
The function is the indicator for the running application.
void | ApplStop (void)
This function finally stops the application, i.e.
void | ApplChangeLocoDirMode (BOOL Mode)
Call this function to change the current mode for changing the direction of a controlled loco.
void | ApplRestart (BOOL ResetToFactory)
This function initiate a restart of the device.

Variables

SPAPPLDATA sPApplConfig
The persistent data field for common application data.
BYTE | u8ApplTimer
The application timer runs backwards in units of 10 ms if different from zero.

Define Documentation

#define APPL_EEPROM_ADD (0x0100u)

EEPROM byte address for common application data.

See SPAPPLDATA for a detailed documentation of the structure elements. On startup the data is loaded into RAM (sPApplConfig).

Definition at line 26 of file eeprom_adds.h.

#define BOOTUP_EEPROM_ADD (0x0000u)

EEPROM byte address for application network data.

See PCOMMON_CONFIG for a detailed documentation of the structure elements. On startup the data is loaded into RAM (sPCommonConfig).

Definition at line 18 of file eeprom_adds.h.

Enumeration Type Documentation

enum _SEARCH_MODES

This typedef defines the different ways to find and connect a server.

Enumerator:
SEARCH_UNKNOWN Placeholder for initial startups and factory resets.

SEARCH_IP | The search uses the prior set IP address and TCP port.
SEARCH_NAME | The search uses the prior set network name and TCP port.
SEARCH_SERVICE | The search uses the prior set service name.

Definition at line 61 of file appl.h.

Function Documentation

void ApplChangeLocoDirMode ( BOOL Mode )

Call this function to change the current mode for changing the direction of a controlled loco.

Parameters:
Mode See TOGGLEDIRMODE_CLICK and TOGGLEDIRMODE_ZERO for details.

Definition at line 594 of file appl.c.

IP_ADDR* ApplGetServerIP ( void )

Call this function to determine the IP address of the configured server for this device.

Returns:
A pointer to the 32 bit IP address of the server.

Definition at line 133 of file appl.c.

NODE_INFO* ApplGetServerNodeInfo ( void )

Call this function to determine the node info (MAC and IP address) of the configured server for this device.

Returns:
A pointer to the node info structure (NODE_INFO).

Definition at line 141 of file appl.c.

WORD_VAL ApplGetServerPort ( void )

Call this function to determine the port (TCP/UDP) of the configured server for this device.

Returns:
The configured TCP/UDP port

Definition at line 149 of file appl.c.

BOOL ApplIsConnected ( void )

This proxy function delivers the connect state of the current project.

It calls the appropriate project function for this.

Return values:
TRUE | The application is in connected state.
FALSE | The application is not in connected state.

Definition at line 157 of file appl.c.

BOOL ApplIsRunning ( void )

The function is the indicator for the running application.

Return values:
TRUE | The application module is running.
FALSE | The application has reached the final state (shut down).

Definition at line 539 of file appl.c.

void ApplMain ( void )

Call this function periodically to execute the application module.

Definition at line 197 of file appl.c.

void ApplResetToFactory ( BOOL KeepBootup )

This function restores the EEPROM content to a well known state.

Parameters:
KeepBootup If TRUE the bootup content is restored from RAM after deleting the EEPROM content, if FALSE the bootup content is also reseted.

Definition at line 554 of file appl.c.

void ApplRestart ( BOOL ResetToFactory )

This function initiate a restart of the device.

Parameters:
ResetToFactory If TRUE, the content of the EEPROM is restored to a well known state, if FALSE only a restart is performed.

Definition at line 608 of file appl.c.

void ApplShutDown ( void )

The function initiates the shut down sequence while the application is still running.

Definition at line 518 of file appl.c.

void ApplStop ( void )

This function finally stops the application, i.e.

in case of shut down.

Definition at line 173 of file appl.c.

Variable Documentation

SPAPPLDATA sPApplConfig

The persistent data field for common application data.

The field stores common settings of the eWicht application. ApplInit loads the data which is stored in the data EEPROM into this SRAM field. The SRCP Menu, the eWicht web interface or the function BootupResetToFactory can change this fields and store it back to the EEPROM.

Definition at line 119 of file appl.h.

BYTE u8ApplTimer

The application timer runs backwards in units of 10 ms if different from zero.

Simply write a value to it to start it

Definition at line 125 of file appl.h.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Application network and initialization module

Application network and initialization module

Detailed Description

The module brings up the eWicht and the TCP/IP stack as configured by the user.

The module therefore loads the persistent stored EEPROM data for the network stack. After configuring the network it starts the network stack and checks for occuring errors. If the start fails, the user and the application are informed. If no error occurs, the application can start with the usage of a configured network.

Files

file | bootup.c
Implementation of the boot process of the eWicht application.
file | bootup.h
Prototypes for calling the eWicht application boot up and network routines.

Data Structures

struct | _IP_CONFIG
This typedef defines the local structure for TCP/IP stack parameters. More...
struct | sIPFlags
This structure is used in the PCOMMON_CONFIG structure to define some IP related flags. More...
struct | PCOMMON_CONFIG
This typedef defines the peristent structure for common settings and TCP/IP stack parameters. More...

Defines

#define | HOSTNAME ((ROM BYTE *) 0x01fbf0)
The hostname of this device located in flash memory.

Enumerations

enum | eWichtProjects
Enumerates the different projects an eWicht can be used for. More...

Functions

void | BootupInit (void)
This function initializes the application network module.
BOOL | bBootupMain (void)
This function must be called periodically by the application.
void | BootupSetIP (void)
By calling this function the eWicht enters the IP Menu.
void | BootupResetToFactory (void)
Sometimes the reset of the persistent data in the EEPROM to a well known state is needed.
void | BootupEnterBootloader (void)
Calling this function prepares the bootloader entry.
void | BootupRestoreState (void)
Writes back the current bootup state (located in RAM) to persistent storage (EEPROM).

Variables

static SM_BOOTUP | _eBootUpSM
The local state machine.
static BOOL | _bFirstTime
Indicator for being here the first time (After bootup).
static BYTE | _au8NetworkDataForBootloader [12]
Stores the network related data like MAC address and IP address for reboot.
IP_CONFIG sIPConfig
This field stores the local TCP/IP parameters.
PCOMMON_CONFIG sPCommonConfig
The persistent data field.

Define Documentation

#define HOSTNAME ((ROM BYTE *) 0x01fbf0)

The hostname of this device located in flash memory.

Release versions of the firmware get the name from the bootloader section.

Definition at line 63 of file bootup.h.

Enumeration Type Documentation

enum eWichtProjects

Enumerates the different projects an eWicht can be used for.

Definition at line 101 of file bootup.h.

Function Documentation

BOOL bBootupMain ( void )

This function must be called periodically by the application.

First of all the function displays the current installed firmware version and does a LED blinking check. After it the function tries to configure and to start the network due directly accessing the TCP/IP stack and its parameters. Several reasons in the network or on the local device can lead to a non working network. The function is able to detect this and report it to the calling application and displaying it to the user as well.

Possible reasons for network failures:

  • The network cable is unplugged or disconnected somewhere.
  • An address conflict is detected on the network.

As long the eWicht has no valid IP address, it is possible to enter the IP menu. The function checks for a pressed encoder button by itself. After a valid IP is obtained, the application can start the IP Menu due calling the function BootupSetIP.

Precondition:
The application network module must be initialized by a call of BootupInit.
Return values:
TRUE | The network module is ready, the application can start using the network.
FALSE | The network is not ready due several reasons (see above).
Remarks:
None

Definition at line 147 of file bootup.c.

void BootupEnterBootloader ( void )

Calling this function prepares the bootloader entry.

After restarting the device the bootloader remains active and uses the prepared MAC and IP address.

Definition at line 557 of file bootup.c.

void BootupInit ( void )

This function initializes the application network module.

The network data persitant stored in EEPROM is loaded and the TCP/IP Stack is configured with this settings. If the function detects an empty EEPROM it loads the factory settings to ensure proper operation of the eWicht device.

Returns:
None
Remarks:
None

Definition at line 94 of file bootup.c.

void BootupResetToFactory ( void )

Sometimes the reset of the persistent data in the EEPROM to a well known state is needed.

The call of this function resets eWicht to the following parameters:

Manual settings: IP: 192.168.0.10 Subnet: 255.255.255.0 (/24) Gateway: 192.168.0.1

The network address is accquired automatically (by DHCP or AutoIP), the first AutoIP address is generated and saved in EEPROM.

Definition at line 579 of file bootup.c.

void BootupSetIP ( void )

By calling this function the eWicht enters the IP Menu.

The call only configures the internal application network module state machine. Due calling periodically the main routine bBootupMain, the Menu will be handled. After the menu has been finished, the main routine configures the network stack with the new data and tries to restart the stack. If succeeded, the application can use the new configured network stack.

Precondition:
The application network module must be initialized by a call of BootupInit.
Remarks:
None

Definition at line 138 of file bootup.c.

Variable Documentation

BYTE _au8NetworkDataForBootloader[12] [static]

Stores the network related data like MAC address and IP address for reboot.

Definition at line 81 of file bootup.c.

BOOL _bFirstTime [static]

Indicator for being here the first time (After bootup).

Definition at line 75 of file bootup.c.

SM_BOOTUP _eBootUpSM [static]

The local state machine.

Definition at line 70 of file bootup.c.

IP_CONFIG sIPConfig

This field stores the local TCP/IP parameters.

Some of them will be loaded from the persistent data fields. Other fields are updated dynamically if the TCP/IP stack configuration changes.

Definition at line 148 of file bootup.h.

PCOMMON_CONFIG sPCommonConfig

The persistent data field.

The field stores common settings of the eWicht and for the network. At the beginning the application must call BootupInit. This function loads the data which is stored in the data EEPROM into this SRAM field. The IP Menu or the function BootupResetToFactory can change these fields and store it back to the EEPROM.

Definition at line 156 of file bootup.h.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Input devices

Input devices

Detailed Description

The routines gain access to the input devices of eWicht as simple bit values.

For a correct reading of the input values an internal state machine handles debouncing and counting.

Todo:
Place a graphic here for showing the buttons.

Files

file | input.c
Button routines for input status of eWicht.
file | input.h
Input module defines and global function prototypes for eWicht.

Defines

#define | BTN_COUNT 0x09
The count of buttons.
#define | ENC_ENDSTOP_MASK 0x01
Flag for configuring the state machine (SM) of the rotary encoder button.
#define | ENC_TURBO_MASK 0x02
Flag for configuring the state machine (SM) of the rotary encoder button.
#define | ENC_NOCHANGE_MASK 0x04
Flag for configuring the state machine (SM) of the rotary encoder button.
#define | BTN_LONG_PUSH_TIME (100u)
This value is used to measure the first push time (unit is the cycle call time of the InputMain routine) of a button after a reset of the appropriate state machine and the first push.
#define | BTN_DOUBLE_PUSH_TIME (60u)
A button state machine waits between to single pushes until this time is elapsed (unit is the cycle call time of the InputMain routine).

Enumerations

enum eButtonID {
PWR_BTN = 0, SEL_BTN, ACC_BTN, FL_BTN,
F1_BTN, F2_BTN, F3_BTN, F4_BTN,
ENC_BTN, ALL_BTN
}
IDs for accessing the buttons. More...

Functions

void | InputInit (void)
Initializes the input module.
void | InputMain (void)
The input state machines are feeded, handled and checked.
void | InputButtonReset (eButtonID eBtn)
The state machine of the given button will be reseted or all if ALL_BTN is the parameter.
void | InputResetPowerButton (void)
The power button state machine is something special and can be reset by this function.
void | InputResetButtonPush (eButtonID eBtn)
This function can be used to reset single push events in the state machine.
BOOL | bInputButtonPushedOnce (eButtonID eBtn)
The application can ask the input module for a given button if there was a single push since the last call of InputButtonReset.
BOOL | bInputButtonPushedTwice (eButtonID eBtn)
The application can ask the input module for a given button if there was a double push since the last call of InputButtonReset or InputInit.
BOOL | bInputButtonPushedLong (eButtonID eBtn)
The application can ask the input module for a given button if there was a long push since the last call of InputButtonReset or InputInit.
BOOL | bInputButtonPushed (eButtonID eBtn)
This function combines the functions bInputButtonPushedLong, bInputButtonPushedOnce and bInputButtonPushedTwice.
SHORT | s16InputEncoderGetValue (void)
This function returns the actual value of rotary encoder state machine.
void | InputEncoderInit (SHORT s16Val, SHORT s16Min, SHORT s16Max, BYTE u8Flags)
This function initializes the rotary encoder.
BOOL | bInputEncoderValueChanged (void)
This function returns TRUE if the value of rotary encoder state machine has changed after the last call of s16InputEncoderGetValue.
void | InputEncoderSetValue (short s16NewVal, BOOL bRemember)
The function sets the internal encoder value to the given value.
void | InputForceChangedEncoderValue (void)
After calling this function the function bInputEncoderValueChanged delivers a TRUE when calling after this function call.
BOOL | InputEncoderGetDirection (void)
This function delivers the current or last rotary direction of the encoder button.
BYTE | u8InputButtonQuickPushed (void)
The function delivers the ID of any pushed quick button (F1-F4).
BOOL | bInputButtonPressed (eButtonID eBtn)
The function checks whether the requested button is currently pressed or released.
BOOL | IsEncoderTurning (void)
The function checks whether the input encoder is turning.
void | InputInterruptHandler (void)
This function handles the periodic requested interrupts.

Define Documentation

#define BTN_DOUBLE_PUSH_TIME (60u)

A button state machine waits between to single pushes until this time is elapsed (unit is the cycle call time of the InputMain routine).

If the time is shorter the SM sets a flag for a double push requestable by bInputButtonPushedTwice.

Definition at line 78 of file input.h.

#define BTN_LONG_PUSH_TIME (100u)

This value is used to measure the first push time (unit is the cycle call time of the InputMain routine) of a button after a reset of the appropriate state machine and the first push.

If this time has elapsed, a flag for a long push is set and can requested by bInputButtonPushedLong.

Definition at line 71 of file input.h.

#define ENC_ENDSTOP_MASK 0x01

Flag for configuring the state machine (SM) of the rotary encoder button.

In case the SM detects an over- or underflow it stops the decrement or increment if the ENDSTOP flag is set. If the flag is not set, the encoder value rolls over from maximum to minimum (in case of overflow) or from minimum to maximum (in case of underflow).

Definition at line 52 of file input.h.

#define ENC_NOCHANGE_MASK 0x04

Flag for configuring the state machine (SM) of the rotary encoder button.

In case the flag is set a bInputEncoderValueChanged() call returns FALSE afterwards.

Definition at line 64 of file input.h.

#define ENC_TURBO_MASK 0x02

Flag for configuring the state machine (SM) of the rotary encoder button.

When given then the turbo encoder is enabled. That flag should be used when the encoder is configured for a great value space.

Definition at line 58 of file input.h.

Enumeration Type Documentation

enum eButtonID

IDs for accessing the buttons.

Enumerator:
PWR_BTN

ID for the Power button.

SEL_BTN

ID for the Select button.

ACC_BTN

ID for the Accessory button.

FL_BTN

ID for the FL button.

F1_BTN

ID for the F1 button (Quick ID 0).

F2_BTN

ID for the F2 button (Quick ID 1).

F3_BTN

ID for the F3 button (Quick ID 2).

F4_BTN

ID for the F4 button (Quick ID 3).

ENC_BTN

ID for the rotary encoder button.

ALL_BTN Special ID to access all buttons.

Definition at line 88 of file input.h.

Function Documentation

BOOL bInputButtonPressed ( eButtonID eBtn )

The function checks whether the requested button is currently pressed or released.

The request is done independently of the button state machine due the direct button value access.

Precondition:
The input devices must be initialized by a InputInit call.
Return values:
TRUE | The requested button is currently pressed.
FALSE | The requested button is currently released.

Definition at line 401 of file input.c.

BOOL bInputButtonPushed ( eButtonID eBtn )

This function combines the functions bInputButtonPushedLong, bInputButtonPushedOnce and bInputButtonPushedTwice.

The caller can test for a push button event if the detailed source is not important.

Precondition:
The input devices must be initialized by a InputInit call or the asked button state machine must reseted with InputButtonReset at least once.
Parameters:
eBtn The button state machine which should be checked for any push. The value ALL_BTN checks if any of the buttons was pushed.
Return values:
TRUE | There was a push since the last InputButtonReset.
FALSE | There was no push since the last InputButtonReset.
Remarks:
None

Definition at line 414 of file input.c.

BOOL bInputButtonPushedLong ( eButtonID eBtn )

The application can ask the input module for a given button if there was a long push since the last call of InputButtonReset or InputInit.

A long push is detected if a button was pushed at least BTN_LONG_PUSH_TIME ms.

Precondition:
The input devices must be initialized by a InputInit call or the asked button state machine must reseted with InputButtonReset at least once.
Parameters:
eBtn The button state machine which should be checked for the long push. The return value for ALL_BTN is meaningless and the behaviour is undefined.
Return values:
TRUE | There was a long push since the last InputButtonReset.
FALSE | There was no long push since the last InputButtonReset.
Remarks:
None

Definition at line 334 of file input.c.

BOOL bInputButtonPushedOnce ( eButtonID eBtn )

The application can ask the input module for a given button if there was a single push since the last call of InputButtonReset.

A single push is detected if a button was pushed at least 8 ms and released afterwards.

Precondition:
The input devices must be initialized by a InputInit call or the asked button state machine must reseted with InputButtonReset at least once.
Parameters:
eBtn The button state machine which should be checked for the single push. The return value for ALL_BTN is meaningless and the behaviour is undefined.
Return values:
TRUE | There was a single push since the last InputButtonReset.
FALSE | There was no single push since the last InputButtonReset.
Remarks:
None

Definition at line 287 of file input.c.

BOOL bInputButtonPushedTwice ( eButtonID eBtn )

The application can ask the input module for a given button if there was a double push since the last call of InputButtonReset or InputInit.

A double push is detected if the state machine has seen two single pushes inbetween a time of BTN_DOUBLE_PUSH_TIME ms.

Precondition:
The input devices must be initialized by a InputInit call or the asked button state machine must reseted with InputButtonReset at least once.
Parameters:
eBtn The button state machine which should be checked for the double push. The return value for ALL_BTN is meaningless and the behaviour is undefined.
Return values:
TRUE | There was a double push since the last InputButtonReset.
FALSE | There was no double push since the last InputButtonReset.
Remarks:
None

Definition at line 319 of file input.c.

BOOL bInputEncoderValueChanged ( void )

This function returns TRUE if the value of rotary encoder state machine has changed after the last call of s16InputEncoderGetValue.

Precondition:
The rotary encoder must be initialized by a InputEncoderInit call.
Return values:
TRUE | The value has changed.
FALSE | The value has not changed.
Remarks:
The function also returns TRUE after a initialization with a call of InputEncoderInit (if ENC_NOCHANGE_MASK is not set) or InputEncoderSetValue.

Definition at line 521 of file input.c.

void InputButtonReset ( eButtonID eBtn )

The state machine of the given button will be reseted or all if ALL_BTN is the parameter.

The state machine processes basic inputs like short single pushes (requestable with bInputButtonPushedOnce), single long pushes (requestable with bInputButtonPushedLong) and double short pushes (requestable with bInputButtonPushedTwice). To reset this occured button events the application must call this function.

Precondition:
The input devices must be initialized by a InputInit call.
Parameters:
eBtn The button state machine which should be reset.
Returns:
None
Remarks:
None

Definition at line 268 of file input.c.

BOOL InputEncoderGetDirection ( void )

This function delivers the current or last rotary direction of the encoder button.

Precondition:
The rotary encoder must be initialized by a InputEncoderInit call.
Return values:
TRUE | The current (or last) rotary direction of the encoder button is right.
FALSE | The current (or last) rotary direction of the encoder button is left.

Definition at line 555 of file input.c.

void InputEncoderInit | ( | SHORT | s16Val,
 |  | SHORT | s16Min,
 |  | SHORT | s16Max,
 |  | BYTE | u8Flags
 | ) |  |

This function initializes the rotary encoder.

The state machine of the rotary encoder can be configured in some flags, value range and the start value as well.

Precondition:
The input devices must be initialized by a InputInit call.
Parameters:
s16Val | Thats the initial start value of the rotary encoder. If the user do not move the encoder after the initialization a call of s16InputEncoderGetValue would return this value.
s16Min | The minimum value of the encoder. The state machine checks for this value to prevent an underflow.
s16Max | The maximum value of the encoder. The state machine checks for this value to prevent an overflow.
u8Flags | Some flags which configure the behaviour on over- and underflow situations. See ENC_ENDSTOP_MASK, ENC_NOCHANGE_MASK and ENC_TURBO_MASK for details.

Definition at line 437 of file input.c.

void InputEncoderSetValue | ( | short | s16NewVal,
 |  | BOOL | bRemember
 | ) |  |

The function sets the internal encoder value to the given value.

Precondition:
The rotary encoder must be initialized by a InputEncoderInit call.
Parameters:
s16NewVal | The new value for the encoder.
bRemember | If TRUE the function bInputEncoderValueChanged delivers a TRUE when calling after this function call.

Definition at line 497 of file input.c.

void InputForceChangedEncoderValue ( void )

After calling this function the function bInputEncoderValueChanged delivers a TRUE when calling after this function call.

Precondition:
The rotary encoder must be initialized by a InputEncoderInit call.

Definition at line 541 of file input.c.

void InputInit ( void )

Initializes the input module.

The modules includes the buttons and their state machines.

Precondition:
None.
Returns:
None
Remarks:
None

Definition at line 71 of file input.c.

void InputInterruptHandler ( void )

This function handles the periodic requested interrupts.

The routine processes the rotary encoder state machines.

Definition at line 641 of file input.c.

void InputMain ( void )

The input state machines are feeded, handled and checked.

The application must call this routine periodically (cycle must be 10 ms).

Precondition:
The input devices are initialized by a InputInit call.
Returns:
None
Remarks:
None

Definition at line 110 of file input.c.

void InputResetButtonPush ( eButtonID eBtn )

This function can be used to reset single push events in the state machine.

Other events like long and double pushes are not affected. If the application also waits for this events it should use InputButtonReset rather than this function to prevent missing them.

Parameters:
eBtn The button state machine which single push flag should be reset. The return value for ALL_BTN is meaningless and the behaviour not defined.
Returns:
None
Remarks:
None

Definition at line 302 of file input.c.

void InputResetPowerButton ( void )

The power button state machine is something special and can be reset by this function.

The power button is not only used for normal application. The input module has a special state machine for this button to react on long pushes. After a long push was noticed by the state machine and processed by the application it should acknowledged and reseted by call of InputResetPowerButton. In fact the power button has two state machines. The first one is handled like the other push buttons and can be reset due a call of InputButtonReset. The second one handles only single long pushes which are used by eWicht to handle power on and off. This SM is divorced from the first SM to prevent missing long pushes. Single and double pushes are not affected.

Precondition:
The input devices must be initialized by a InputInit call.
Returns:
None
Remarks:
None

Definition at line 310 of file input.c.

BOOL IsEncoderTurning ( void )

The function checks whether the input encoder is turning.

Precondition:
The input devices must be initialized by a InputInit call.
Return values:
TRUE | The encoder button is turning.
FALSE | The encoder button is not turning.

Definition at line 563 of file input.c.

SHORT s16InputEncoderGetValue ( void )

This function returns the actual value of rotary encoder state machine.

Precondition:
The rotary encoder must be initialized by a InputEncoderInit call.
Returns:
The current rotary encoder value. This value will be in the configured range.
Remarks:
None

Definition at line 477 of file input.c.

BYTE u8InputButtonQuickPushed ( void )

The function delivers the ID of any pushed quick button (F1-F4).

Precondition:
The input devices must be initialized by a InputInit call or the asked button state machine must reseted with InputButtonReset at least once.
Returns:
The ID of the quick button or 0xFF if non of the buttons was pushed for a long time.

Definition at line 356 of file input.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: IP dialogues

IP dialogues

Detailed Description

This routines handle the input of various IP settings needed for eWicht and the connection to SRCP server(s).

The dialogues can be aborted or confirmed. In case of a positive acknowledgement the IPSET routines save the data to the eWicht EEPROM.

Files

file | ipset.c
Implementation of IP input dialogs.
file | ipset.h
Prototypes for calling the IP input dialogues.

Functions

void | IPSetInit (BOOL bServer)
The function inits the internal state machine (SM) of the IP dialogues and some internal variables.
BOOL | IPSetMain (void)
This function handles the dialogues.

Function Documentation

void IPSetInit ( BOOL bServer )

The function inits the internal state machine (SM) of the IP dialogues and some internal variables.

Parameters:
bServer If TRUE, the IP dialogs requests the input of server parameters like address of the server and port. If FALSE the internal SM requests the common IP parameters (IP address, subnet mask and gateway IP address).

Definition at line 108 of file ipset.c.

BOOL IPSetMain ( void )

This function handles the dialogues.

The main application must call this function periodically until it returns TRUE. The user can abort the dialog pressing the PWR_BTN.

Precondition:
The function IPSetInit must be called.
Return values:
TRUE | The user has finished or aborted the dialog. In case the user has finished, the dialog stores the new data peristent in EEPROM memory of eWicht. After the dialog has finished, the main application can directly work with the new data.
FALSE | The dialog is still running, call again later.

Definition at line 146 of file ipset.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Multicast DNS

Multicast DNS

Detailed Description

As networked devices become smaller, more portable, and more ubiquitous, the ability to operate with less configured infrastructure is increasingly important.

In particular, the ability to look up DNS resource record data types (including, but not limited to, host names) in the absence of a conventionally managed DNS server, is becoming essential.

Multicast DNS (mDNS) provides the ability to do DNS-like operations on the local link in the absence of any conventional unicast DNS server. In addition, mDNS designates a portion of the DNS namespace to be free for local use, without the need to pay any annual fee, and without the need to set up delegations or otherwise configure a conventional DNS server to answer for those names (Source: Abstract of the Multicast DNS internet draft from 2006).

DNS Service Discovery is a way of using standard DNS programming interfaces, servers, and packet formats to browse the network for services (Source: www.dns-sd.org).

References and recommended reading: RFC 1034, RFC 1035, Internet drafts for mDNS and DNS-SD.

Files

file | mdns.c
Multicast Domain Name System (MDNS) implementation file for the eWicht application.
file | mdns.h
MDNS Client Module Header file for the eWicht application.

Modules

Resolving records
The module includes functions for resolving unique records like hostname or service records.

Defines

#define | MDNS_PORT 5353u
The MDNS UDP port.
#define | DNS_TYPE_A (0x0001u)
DNS type for hostnames.
#define | DNS_TYPE_PTR (0x000cu)
DNS type for pointer records.
#define | DNS_TYPE_MX (0x000fu)
DNS type for mailbox records.
#define | DNS_TYPE_SRV (0x0021u)
DNS type for service records.
#define | DNS_TYPE_TXT (0x0010u)
DNS type for text records.
#define | DNS_TYPE_ANY (0x00FFu)
DNS type for all records.

Enumerations

enum | _MDNS_STATE { MDNS_HAS_STOPPED = 0, MDNS_IS_STARTING_UP, MDNS_IS_RUNNING }
Possible states of the MDNS responder service. More...

Functions

BOOL | bInitMDNSResponder (void)
The function initializes the MDNS service.
void | StartMDNSResponder (void)
The service is started by a call of this function.
void | StopMDNSResponder (void)
The service is stopped by a call of this function.
void | MDNSResponder (void)
The function implements the state machine of the MDNS responder.
void | MDNSProcessFrame (NODE_INFO *remoteNode, IP_ADDR *localIP)
In the MDNS module the state machine and the receiption of frames are divorced.
MDNS_STATE | eGetMDNSState (void)
The function retrieves the state of the MDNS responder.

Enumeration Type Documentation

enum _MDNS_STATE

Possible states of the MDNS responder service.

The state of the service can be requested by the eGetMDNSState function.

Enumerator:
MDNS_HAS_STOPPED | The MDNS service has stopped.
MDNS_IS_STARTING_UP | The service is starting.
MDNS_IS_RUNNING | The service is running.

Definition at line 83 of file mdns.h.

Function Documentation

BOOL bInitMDNSResponder ( void )

The function initializes the MDNS service.

The application must call this function at least once before starting and using the service. After the sucessful init the application can start the service with StartMDNSResponder. Every time the network interface changes, the application must call this function to ensure the correct functionality of the service.

Return values:
TRUE | The initialization was successful.
FALSE | The initialization was not successful and therefore the service can not be used.
Precondition:
First call this function after got the IP address and checked the validness.

Definition at line 330 of file mdns.c.

MDNS_STATE eGetMDNSState ( void )

The function retrieves the state of the MDNS responder.

For a simplified API only a few states from the internal MDNS state machine are returned.

Returns:
The state of the MDNS responder.

Definition at line 422 of file mdns.c.

void MDNSProcessFrame | ( | NODE_INFO * | remoteNode,
 |  | IP_ADDR * | localIP
 | ) |  |

In the MDNS module the state machine and the receiption of frames are divorced.

The receiption of frames is handled stateless and answers will be promptly generated. For quick processing the UDP module should check for the MDNS socket or event he MDNS port in received messages and call this function directly. With the given parameters the function filters for relevant frames.

Precondition:
The responder must be initialzed by a bInitMDNSResponder call and started by a StartMDNSResponder call.
Parameters:
remoteNode | Extracted information about the remote node (MAC and IP).
localIP | The IP address where the frame was send to (can be a unicast or multicast address).

Definition at line 534 of file mdns.c.

void MDNSResponder ( void )

The function implements the state machine of the MDNS responder.

The application must call this function periodically. The state machine handles the starting and the resolve procedures.

Precondition:
The responder must be initialzed by a bInitMDNSResponder call and started by a StartMDNSResponder call.

Definition at line 435 of file mdns.c.

void StartMDNSResponder ( void )

The service is started by a call of this function.

The application should check the state of the service with eGetMDNSState if the service was started successfully. The starting procedure can take some milliseconds or seconds. The procedure includes a so called probing, where all the unique DNS records (see MDNS draft for a detailed discussion about unique and shared records). will be announced to the network. The procedures fails, if the network knows some of this unique records (i.e. the hostname is already taken by another host).

Precondition:
The responder must be initialzed by a bInitMDNSResponder call.

Definition at line 369 of file mdns.c.

void StopMDNSResponder ( void )

The service is stopped by a call of this function.

This function is called automatically in case the starting procedure fails. If the starting procedure was successful and the service is running before the call so-called "goodbye" announcements (see MDNS draft for details) for shared records will be sent.

Precondition:
The responder must be initialized by a bInitMDNSResponder call.

Definition at line 400 of file mdns.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Resolving records

Resolving records
[Multicast DNS]

Detailed Description

The module includes functions for resolving unique records like hostname or service records.

For all the included functions the precondition takes affect that the MDNS responder was successfully initialized by bInitMDNSResponder and started by StartMDNSResponder.

Functions

void | MDNSResolveService (char *pName, ROM char *pServiceName)
The function resolves a service record via MDNS.
void | MDNSResolveName (char *pName)
The function resolves a hostname record via MDNS to an IP address.
void | MDNSStopResolving (void)
A pending resolving process will be stopped.
BOOL | bMDNSServiceIsResolved (IP_ADDR *pIP, WORD_VAL *pu16Port)
After calling MDNSResolveService the application should check periodically the resolvation progress with a call of this function.
BOOL | bMDNSNameIsResolved (IP_ADDR *pIP)
After calling MDNSResolveName the application should check periodically the resolvation progress with a call of this function.

Function Documentation

BOOL bMDNSNameIsResolved ( IP_ADDR * pIP )

After calling MDNSResolveName the application should check periodically the resolvation progress with a call of this function.

Return values:
TRUE | The hostname was completely resolved. Check the pIP parameter.
FALSE | The resolvation progress is pending or not yet started.
Parameters:
[out] pIP In case the hostname is resolved this parameter stores the IP address of the requested host.
Precondition:
MDNSResolveName must be called.

Definition at line 697 of file mdns.c.

BOOL bMDNSServiceIsResolved | ( | IP_ADDR * | pIP,
 |  | WORD_VAL * | pu16Port
 | ) |  |

After calling MDNSResolveService the application should check periodically the resolvation progress with a call of this function.

Return values:
TRUE | The service was completely resolved. Check the parameters pIP and pu16Port for the requested information.
FALSE | The resolvation progress is pending or not yet started.
Parameters:
[out] | pIP | In case the service is resolved this parameter stores the IP address of the host where the service is running.
[out] | pu16Port | In case the service is resolved this parameter stores the port number of the service.
Precondition:
MDNSResolveService must be called.

Definition at line 708 of file mdns.c.

void MDNSResolveName ( char * pName )

The function resolves a hostname record via MDNS to an IP address.

The hostname is set to the .local domain automatically.

Parameters:
pName A pointer to a hostname label in RAM. The label must be DNS conform.

Definition at line 729 of file mdns.c.

void MDNSResolveService | ( | char * | pName,
 |  | ROM char * | pServiceName
 | ) |  |

The function resolves a service record via MDNS.

The resolve is done in two steps. First the service record query is answered by a remote network device with a valid service record. The service record includes the port of the requested service for example. The query answer also includes the hostname where the service is running. The second step resolves the hostname into an IP address. For this issue the function MDNSResolveName is called internally.

Example: From the given parameters (pName = "DDW-Server", pServiceName = "_srcp") the search string is "DDW-Server._srcp._tcp.local.".

Parameters:
pName | A pointer to a name label in RAM. The label must be DNS conform. The name is the name of the service, NOT of a hostname!
pServiceName | A pointer to a service name label in ROM (i.e. _srcp). The label must be DNS conform.
Remarks:
Actually the function only supports the resolvation of TCP services.

Definition at line 756 of file mdns.c.

void MDNSStopResolving ( void )

A pending resolving process will be stopped.

This function will be called automatically when stopping the MDNS service with StopMDNSResponder.

Definition at line 721 of file mdns.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: LED and LCD routines

LED and LCD routines

Detailed Description

The routines of this module provide basic access to the eWicht display (2-row text display) and the indicator LEDs of the F1-F4, FL, PWR, ACC and SEL buttons.

Todo:
Place a graphic here for showing the buttons and display.
Todo:
Define a command interface for the LCD as a function. Centralize and internationalize the displayed strings.

Files

file | output.c
Display and LED routines for output status of eWicht.
file | output.h
Output module defines and global function prototypes for eWicht.

Modules

Display commands
Display commands which can be sent to the LCD via the lcd_status variable.
LED masks
Masks for LED access.

Defines

#define | LCD_CHARS_IN_A_ROW 16
Defines the count of maximum characters per display row.
#define | LED_BLINK_INTERVAL 1u
The time of the blinking interval of an LED in LED_BLINK mode in seconds.

Enumerations

enum | eLED_Modes { LED_ON = 0, LED_OFF, LED_BLINK, LED_TOGGLE }
Modes for LED access. More...

Functions

void | OutInit (void)
Initializes the display and LEDs.
void | OutMain (void)
Handles the display access and LED blinking if enabled.
void | OutDebugOut (BYTE u8Value)
The function displays the given value at the LEDs.
void | OutSwitchOffLCD (void)
The function turns off the backlight of the LCD and the LCD itself.
void | OutSwitchLCDBacklight (BOOL On)
The function turns the backlight of the LCD on or off.
BOOL | OutIsLCDBusy (void)
The function determines, if all commands are handled by the display and the appropriate actions are done.
void | OutEnableCursor (BOOL On)
The function enables the cursor in the display.
void | OutSetCursor (BYTE Column, BYTE Row)
The function sets the position of the cursor independently of the visibility of the cursor.
void | OutSwitchOffAllLEDs (void)
All button LEDs will be turned off.
void | OutSetLED (BYTE LedMask, eLED_Modes Mode)
Gives access to the LEDs.
void | OutSetLEDMask (BYTE LedMask, BYTE LedSwitchMask)
Gives boolean access to the LEDs via a switch mask.
void | OutTriggerDisplay (void)
Retriggers the time the LCD backlight stays on.
eLED_Modes | OutGetLEDMode (BYTE Led)
Obtain the mode of the specified LED.
void | OutConvertNameForDisplay (BYTE *pString)
Converts a string from the website to the display encoding.

Variables

BYTE | lcd_status
This byte is the global access to send commands to the display and get knowledge about the state of the LCD.

Define Documentation

#define LCD_CHARS_IN_A_ROW 16

Defines the count of maximum characters per display row.

Definition at line 67 of file output.h.

Enumeration Type Documentation

enum eLED_Modes

Modes for LED access.

Enumerator:
LED_ON | Turns the LED on.
LED_OFF | Turns the LED off.
LED_BLINK | Starts blinkink the LED in a LED_BLINK_INTERVAL interval.
LED_TOGGLE | Toggles the LED.

Definition at line 48 of file output.h.

Function Documentation

void OutConvertNameForDisplay ( BYTE * pString )

Converts a string from the website to the display encoding.

Precondition:
None
Parameters:
pString The string to convert.
Remarks:
None

Definition at line 717 of file output.c.

void OutDebugOut ( BYTE u8Value )

The function displays the given value at the LEDs.

The appropriate digits can be taken from LED masks.

Precondition:
The LEDs are initialized by a OutInit call.
Parameters:
u8Value The value to display on the LEDs.
Returns:
None
Remarks:
This function is only available in the Extended Debug mode (The macro DEBEXT_MODE must be defined).

void OutEnableCursor ( BOOL On )

The function enables the cursor in the display.

The cursor occurs as a underscore at the current cursor position.

Precondition:
The LCD must be initialized by a call of OutInit.
Parameters:
On If TRUE the cursor will be enabled and therefore visible. If FALSE the cursor will be disabled and not visible anymore.

Definition at line 391 of file output.c.

eLED_Modes OutGetLEDMode ( BYTE Led )

Obtain the mode of the specified LED.

Precondition:
None
Parameters:
Led A bit mask which specifies the LED to access. See LED masks for possible mask values. Only the mask value for one LED is possible.
Returns:
This enumerator gives the actual mode of the LED. The state LED_TOGGLE will never be returned by this function.
Remarks:
None

Definition at line 529 of file output.c.

void OutInit ( void )

Initializes the display and LEDs.

Precondition:
The timer module is accessable.
Returns:
None
Remarks:
None

Todo:
Which symbols: document?

Definition at line 51 of file output.c.

BOOL OutIsLCDBusy ( void )

The function determines, if all commands are handled by the display and the appropriate actions are done.

Precondition:
None.
Return values:
TRUE | The display is busy with running operations.
FALSE | The display is ready.

Definition at line 376 of file output.c.

void OutMain ( void )

Handles the display access and LED blinking if enabled.

The application must call this routine periodically.

Precondition:
The output devices are initialized by a OutInit call.
Returns:
None
Remarks:
None

Definition at line 214 of file output.c.

void OutSetCursor | ( | BYTE | Column,
 |  | BYTE | Row
 | ) |  |

The function sets the position of the cursor independently of the visibility of the cursor.

Precondition:
The LCD must be initialized by a call of OutInit.
Parameters:
Column | Specify the column of the position. For the eWicht display that must be a value inbetween 0 and 15 (including).
Row | Specify the row of the position. For the eWicht display that must be a value inbetween 0 and 1 (including).

Definition at line 406 of file output.c.

void OutSetLED | ( | BYTE | LedMask,
 |  | eLED_Modes | Mode
 | ) |  |

Gives access to the LEDs.

Precondition:
None
Parameters:
LedMask | A bit mask which specifies the LEDs to access. See LED masks for possible mask values.
Mode | This enumerator gives the access mode.
Returns:
None
Remarks:
None

Definition at line 438 of file output.c.

void OutSetLEDMask | ( | BYTE | LedMask,
 |  | BYTE | LedSwitchMask
 | ) |  |

Gives boolean access to the LEDs via a switch mask.

Precondition:
None
Parameters:
LedMask | A bit mask which specifies the LEDs to access. See LED masks for possible mask values.
LedSwitchMask | A '1' in this mask means LED on, a '0' means LED off. Each set bit in the u8LedMask parameter leads to a LED change. All other LEDs remain unchanged.
Returns:
None
Remarks:
None

Definition at line 427 of file output.c.

void OutSwitchLCDBacklight ( BOOL On )

The function turns the backlight of the LCD on or off.

Precondition:
None.
Parameters:
On If TRUE the display will be switched on. If FALSE the display will be switched off.
Returns:
None.
Remarks:

Definition at line 361 of file output.c.

void OutSwitchOffAllLEDs ( void )

All button LEDs will be turned off.

Precondition:
The LEDs are initialized by a OutInit call.
Returns:
None
Remarks:
None

Definition at line 414 of file output.c.

void OutSwitchOffLCD ( void )

The function turns off the backlight of the LCD and the LCD itself.

Precondition:
None.
Returns:
None.
Remarks:
After calling the function, the application must call OutInit before it can use the LCD again.

Definition at line 353 of file output.c.

void OutTriggerDisplay ( void )

Retriggers the time the LCD backlight stays on.

If the backlight is already switched off it is turned on again. See LCD_IDLE_TIME for more details.

Precondition:
None
Returns:
None
Remarks:
None

Definition at line 192 of file output.c.

Variable Documentation

BYTE lcd_status

This byte is the global access to send commands to the display and get knowledge about the state of the LCD.

See Display commands for a detailed description of the supported commands.

Definition at line 153 of file output.h.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Display commands

Display commands
[LED and LCD routines]

Detailed Description

Display commands which can be sent to the LCD via the lcd_status variable.

Some commands initiate or overwrite other commands implicitly. For example the LCD_CLR_PROG_MASK command issues a clearing of the second row and overwrites a running LCD_ROW2_MASK command. All finished commands will be implicitly cleared in lcd_status. The eWicht application can poll lcd_status for finished command executions it waits for.

Defines

#define | LCD_CLR_MASK 0x01
Clear Display.
#define | LCD_ROW1_MASK 0x02
Write to the first display row.
#define | LCD_ROW2_MASK 0x04
Write to the second display row.
#define | LCD_ROW3_MASK 0x08
Write data to row 3. Not used by eWicht and not implemented yet.
#define | LCD_PROGRESS_MASK 0x10
Writes a progress bar in the second row.
#define | LCD_CLR_PROG_MASK 0x20
The command deletes the second row.
#define | LCD_CENTER1_MASK 0x40
Center the text in the first row.
#define | LCD_CENTER2_MASK 0x80
Center the text in the second row.

Define Documentation

#define LCD_CLR_PROG_MASK 0x20

The command deletes the second row.

This command overwrites a LCD_ROW2_MASK command. Clear Progress bar.

Definition at line 99 of file output.h.

#define LCD_PROGRESS_MASK 0x10

Writes a progress bar in the second row.

The character LCD_PROGRESS_CHAR is shifted across the display in time steps of LCD_PROGRESS_TIME. This command overwrites a LCD_ROW2_MASK command.

Definition at line 93 of file output.h.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: LED masks

LED masks
[LED and LCD routines]

Detailed Description

Masks for LED access.

Defines

#define | LED_FL 0x01
Gains access to FL button LED.
#define | LED_F1 0x02
Gains access to F1 button LED.
#define | LED_F2 0x04
Gains access to F2 button LED.
#define | LED_F3 0x08
Gains access to F3 button LED.
#define | LED_F4 0x10
Gains access to F4 button LED.
#define | LED_PWR 0x20
Gains access to PWR button LED.
#define | LED_ACC 0x40
Gains access to ACC button LED.
#define | LED_SEL 0x80
Gains access to SEL button LED.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: String tables

String tables

Detailed Description

Here are defined some language string tables.

The application code can access strings for multiple languages. Once the language identifier is set, the module automatically returns the correct strings.

Files

file | stringtable.c
This file implements the string tables for multi language support.
file | stringtable.h
This file includes the eWicht string table defines and API.

Defines

#define | LANGID_NOTSPECIFIED (0xFFu)
Language ID for factory resets and initial startups.
#define | LANGID_GERMAN (0x00u)
Language ID for the German string table.
#define | LANGID_ENGLISH (0x01u)
Language ID for the English string table.
#define | LANGID_MAX (0x01u)
The latest Language ID. Increment this ID if you add further languages.

Enumerations

enum | STRTBLIDS
String ID table for accessing the string table entries.

Functions

void | StrTbl_SetLanguage (BYTE u8LangId)
The function sets the actual string table for this session (not permanently).
void | StrTbl_GetString (BYTE *pString, WORD u16StrId)
The function copies the string with the given ID to the given RAM location.
void | StrTbl_GetStringN (BYTE *pString, BYTE u8BufferSize, WORD u16StrId)
The function copies the string with the given ID to the given RAM location.
ROM char * | StrTbl_cau8GetStringPointer (WORD u16StrId)
The function delivers a ROM pointer to the given string ID.
ROM char * | StrTbl_cau8GetLanguageStringPointer (BYTE u8LangId, WORD u16StrId)
The function delivers a ROM pointer to the given string ID on a given string table.

Function Documentation

ROM char* StrTbl_cau8GetLanguageStringPointer | ( | BYTE | u8LangId,
 |  | WORD | u16StrId
 | ) |  |

The function delivers a ROM pointer to the given string ID on a given string table.

The language ID which was set before with StrTbl_SetLanguage is not affected by this function.

Precondition:
None.
Parameters:
u8LangId | One of the valid language IDs like LANGID_GERMAN or LANGID_ENGLISH for example.
u16StrId | String ID of the string to load.
Returns:
The pointer to the string in the flash memory.

Definition at line 594 of file stringtable.c.

ROM char* StrTbl_cau8GetStringPointer ( WORD u16StrId )

The function delivers a ROM pointer to the given string ID.

Precondition:
StrTbl_SetLanguage should be called. Else the result is always a string from the German string table.
Parameters:
u16StrId String ID of the string to load.
Returns:
The pointer to the string in the flash memory.

Definition at line 584 of file stringtable.c.

void StrTbl_GetString | ( | BYTE * | pString,
 |  | WORD | u16StrId
 | ) |  |

The function copies the string with the given ID to the given RAM location.

Precondition:
StrTbl_SetLanguage should be called. Else the result is always a string from the German string table.
Parameters:
pString | Pointer to a buffer in RAM. Ensure that in the buffer is enough space.
u16StrId | String ID of the string to load.

Definition at line 574 of file stringtable.c.

void StrTbl_GetStringN | ( | BYTE * | pString,
 |  | BYTE | u8BufferSize,
 |  | WORD | u16StrId
 | ) |  |

The function copies the string with the given ID to the given RAM location.

Precondition:
StrTbl_SetLanguage should be called. Else the result is always a string from the German string table.
Parameters:
pString | Pointer to a buffer in RAM.
u8BufferSize | Size of the given buffer.
u16StrId | String ID of the string to load.

Definition at line 607 of file stringtable.c.

void StrTbl_SetLanguage ( BYTE u8LangId )

The function sets the actual string table for this session (not permanently).

Precondition:
None.
Parameters:
u8LangId One of the valid language IDs like LANGID_GERMAN or LANGID_ENGLISH for example.

Definition at line 561 of file stringtable.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Web interface

Web interface

Detailed Description

The routines process the cgi scripts of the HTTP server.

That means that prepared variables in the cgi files which are sent to a client are filled with data. The routines also process commands received via input buttons in forms on the websites.

Files

file | config.c
This file implements the eWicht XML configuration module.
file | config.h
This file includes the eWicht XML configuration module API.
file | web.c
The integrated web interface implementation of eWicht.
file | web.h
Web interface module defines and global function prototypes for eWicht.
file | webprocess.h
Web interface module defines and global function prototypes for eWicht.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: XML parser

XML parser

Detailed Description

Some XML parser helper functions for direct processing of XML data in a TCP stream.

Files

file | xml.c
XML parser implementation file for the eWicht application.
file | xml.h
XML Module Header file for the eWicht application.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: TCP/IP Stack from Microchip Version 4.50 (Modified)

TCP/IP Stack from Microchip Version 4.50 (Modified)

Detailed Description

Chosen Microchips Ethernet controller family among PIC18F97J60 enables the eWicht project to use the free open source TCP/IP stack of microchip.

Note: The first versions of eWicht based on some older stack versions since V4.0. I have merged periodically with new stack versions to get the latest bug fixes from Microchip.

For more informations regarding the Microchip Stack see AN833.

Some parts of the stack are modified according to the requirements of eWicht. These parts are marked directly in the code (look after the keyword MODIFIX) or in case of large modifications at the headers of the files.

Doxygen comments are also added to used functions to generate a more detailed documentation for a better understanding of eWicht.

Software License Agreement
Copyright (C) 2002-2008 Microchip Technology Inc. All rights reserved.

Microchip licenses to you the right to use, modify, copy, and distribute: (i) the Software when embedded on a Microchip microcontroller or digital signal controller product ("Device") which is integrated into Licensee's product; or (ii) ONLY the Software driver source files ENC28J60.c and ENC28J60.h ported to a non-Microchip device used in conjunction with a Microchip Ethernet controller for the sole purpose of interfacing with the Ethernet controller.

You should refer to the license agreement accompanying this Software for additional information regarding your rights and obligations.

THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.

Click here for a printable version.

Modules

ARP
The Address Resolution Protocol, or ARP, is a foundation layer of TCP/IP.
DHCP
Dynamic Host Configuration Protocol (DHCP) is a protocol used by networked devices (clients) to obtain various parameters necessary for the clients to operate in an Internet Protocol (IP) network.
HTTP
Hypertext Transfer Protocol (HTTP) is a communications protocol for the transfer of information on the intranet and the World Wide Web.
ICMP
Implements a PING server as the only ICMP service.
IP
This group implements the IP or network layer.
MAC
The MAC or data link layer provides basic functions to access the underlaying physical layer.
MPFS
The MPFS2 file system module provides a light-weight read-only file system that can be stored in external EEPROM, external serial Flash, or internal Flash program memory.
Reboot
This UDP based module listens continously for UDP packets addressing the TFTP port.
Stack Task
The Stack Manager coordinates the other Microchip TCP/IP Stack modules.
TCP
TCP is a standard transport layer protocol described in RFC 793.
Tick
The Tick module provides accurate time-keeping capabilities based on the hardware clock.
UDP
UDP is a standard transport layer protocol described in RFC 768.
EEPROM

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: ARP

ARP
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

The Address Resolution Protocol, or ARP, is a foundation layer of TCP/IP.

It translates IP addresses to physical MAC addresses, or locates a gateway through which a machine may be located. TCP applications will not need to access ARP directly. The TCPOpen function will handle both ARP and DNS operations transparently. UDP applications however will likely need to use ARP. Responses to incoming ARP requests are processed automatically. Resolution of ARP requests follows a simple state machine, as indicated in the following diagram.

Files

file | ARP.c
Address Resolution Protocol (ARP) Client and Server Module for Microchip TCP/IP Stack.
file | ARP.h
ARP Module Defs for Microchip TCP/IP Stack.

Functions

void | ARPResolve (IP_ADDR *IPAddr)
Transmits an ARP request to resolve an IP address.
BOOL | ARPIsResolved (IP_ADDR *IPAddr, MAC_ADDR *MACAddr)
Determines if an ARP request has been resolved yet.
void | ARPFlush (void)
Flushes the ARP cache.

Function Documentation

BOOL ARPIsResolved | ( | IP_ADDR * | IPAddr,
 |  | MAC_ADDR * | MACAddr
 | ) |  |

Determines if an ARP request has been resolved yet.

This function checks if an ARP request has been resolved yet, and if so, stores the resolved MAC address in the pointer provided.

Precondition:
ARP packet is ready in the MAC buffer.
Parameters:
IPAddr | - The IP address to be resolved
MACAddr | - A buffer to store the corresponding MAC address
Return values:
TRUE | The IP address has been resolved and MAC address indicates the response.
FALSE | The IP address is not resolved.
Remarks:
None

Definition at line 409 of file ARP.c.

void ARPResolve ( IP_ADDR * IPAddr )

Transmits an ARP request to resolve an IP address.

This function transmits and ARP request to determine the hardware address of a given IP address.

Precondition:
ARP packet is ready in the MAC buffer.
Parameters:
IPAddr - The IP address to be resolved
Returns:
None
Remarks:
None

Definition at line 357 of file ARP.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: DHCP

DHCP
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

Dynamic Host Configuration Protocol (DHCP) is a protocol used by networked devices (clients) to obtain various parameters necessary for the clients to operate in an Internet Protocol (IP) network.

By using this protocol, system administration workload greatly decreases, and devices can be added to the network with minimal or no manual configurations (Source: Wikipedia).

Files

file | DHCP.c
Dynamic Host Configuration Protocol (DHCP) Client Module for Microchip TCP/IP Stack.
file | DHCP.h
DHCP Defs for Microchip TCP/IP Stack.

Defines

#define | DHCPIsBound() (DHCPFlags.bits.bIsBound)
Determines if the DHCP server is currently bound.

Functions

void | DHCPReset (BOOL bNoAutoIP)
Resets the DHCP Client.
void | DHCPTask (void)
Performs periodic DHCP tasks.
void | DHCPDisable (void)
Disables the DHCP client.
void | DHCPEnable (void)
Enables the DHCP client.
IP_ADDR | GenerateAutoIP (IP_ADDR *lastIP)
Generates an IPv4 address from the 169.254.X.X auto IP pool.

Define Documentation

#define DHCPIsBound ( ) (DHCPFlags.bits.bIsBound)

Determines if the DHCP server is currently bound.

Return values:
TRUE | DHCP is bound to given configuration.
FALSE | DHCP has not yet been bound.
Remarks:
This function is a MACRO to DHCPFlags.bits.bIsBound.

Definition at line 279 of file DHCP.h.

Function Documentation

void DHCPDisable ( void )

Disables the DHCP client.

Disables the DHCP client by sending the state machine to "SM_DHCP_DISABLED". If the board was previously configured by DHCP, the configuration will continue to be used but the module will no longer preform any renewals.

Precondition:
None
Returns:
None
Remarks:
Since the board continues using its old configuration, it is possible that the lease may expire and the DHCP server provide the IP to another client. The application should replace the current IP address and other configuration with static information following a call to this function.

Definition at line 233 of file DHCP.c.

void DHCPEnable ( void )

Enables the DHCP client.

Enables the DHCP client if it is disabled. If it is already enabled, nothing is done.

Precondition:
None
Returns:
None

Definition at line 269 of file DHCP.c.

void DHCPReset ( BOOL bNoAutoIP )

Resets the DHCP Client.

Resets the DHCP Client, giving up any current lease, knowledge of DHCP servers, etc.

Precondition:
None
Parameters:
bNoAutoIP Enables or disables the Auto IP service.
Returns:
None
MODIFIX: Added AutoIP support.

Definition at line 172 of file DHCP.c.

void DHCPTask ( void )

Performs periodic DHCP tasks.

This function performs any periodic tasks requied by the DHCP module, such as sending and receiving messages involved with obtaining and maintaining a lease.

Precondition:
None
Returns:
None
MODIFIX: Added AutoIP support.

Todo:
Save the probed auto IP-Address in EEPROM

Definition at line 307 of file DHCP.c.

IP_ADDR GenerateAutoIP ( IP_ADDR * lastIP )

Generates an IPv4 address from the 169.254.X.X auto IP pool.

This function was added for the eWicht project. The new IP address must be checked for there uniqueness in the network before using!

Parameters:
lastIP This parameter can point to a IP address used before. The function than constructs the new address based on the last one.
Returns:
Returns the new IP address.

Definition at line 1017 of file DHCP.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: HTTP

HTTP
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

Hypertext Transfer Protocol (HTTP) is a communications protocol for the transfer of information on the intranet and the World Wide Web.

Its original purpose was to provide a way to publish and retrieve hypertext pages over the Internet (Source Wikipedia).

Files

file | HTTP2.c
HyperText Transfer Protocol (HTTP) Server Module for Microchip TCP/IP Stack.
file | HTTP2.h
HTTP definitions on Microchip TCP/IP Stack.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: ICMP

ICMP
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

Implements a PING server as the only ICMP service.

Other nodes in an ethernet network can ping the eWicht for testing the connection.

Files

file | ICMP.c
Internet Control Message Protocol (ICMP) Server Module for Microchip TCP/IP Stack.
file | ICMP.h
ICMP Module Defs for Microchip TCP/IP Stack.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: IP

IP
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

This group implements the IP or network layer.

Almost all functions of the group are used by UDP and TCP functions.

Files

file | IP.c
Internet Protocol (IP) Version 4 Communications Layer Module for Microchip TCP/IP Stack.
file | IP.h
IP Defs for Microchip TCP/IP Stack.

Functions

DWORD | IPConvertSubnetToMask (BYTE Subnet)
This function converts the CIDR subnet expression to the long IP expression.
BYTE | IPConvertMaskToSubnet (BYTE *MaskArray)
This function converts the long IP subnet expression to the CIDR expression.

Function Documentation

BYTE IPConvertMaskToSubnet ( BYTE * MaskArray )

This function converts the long IP subnet expression to the CIDR expression.

Examples for subnet expression relations:
CIDR | Netmask
/8 | 255.0.0.0
/12 | 255.240.0.0
/16 | 255.255.0.0
/20 | 255.255.240.0
/24 | 255.255.255.0
/30 | 255.255.255.252
This function is added for the eWicht project.

Todo:
Add the (DWORD) output values.
Todo:
Move this function to the helpers.
Parameters:
MaskArray The subnet as long IP expression (i.e {255,0,0,0}).
Returns:
The subnet mask as CIDR expression.

Definition at line 334 of file IP.c.

DWORD IPConvertSubnetToMask ( BYTE Subnet )

This function converts the CIDR subnet expression to the long IP expression.

Examples for subnet expression relations:
CIDR | Netmask
/8 | 255.0.0.0
/12 | 255.240.0.0
/16 | 255.255.0.0
/20 | 255.255.240.0
/24 | 255.255.255.0
/30 | 255.255.255.252
This function is added for the eWicht project.

Todo:
Move this function to the helpers.
Parameters:
Subnet The subnet in CIDR notation.
Returns:
The subnet mask as long IP expression.

Definition at line 321 of file IP.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: MAC

MAC
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

The MAC or data link layer provides basic functions to access the underlaying physical layer.

This physical layer and parts of the MAC layer are part of the ethernet transceiver. Additional functions like hardware initialisization, packet transmission and receiption must be done in software. The functions of this group do this job.

Files

file | ETH97J60.c
Medium Access Control (MAC) Layer for Microchip PIC18F97J60 family.
file | ETH97J60.h
Ethernet registers/bits for PIC18F97J60.
file | MAC.h
MAC Module Defs for Microchip Stack.

Functions

BOOL | MACIsLinked (void)
Returns the link status of the PHY/MAC.

Function Documentation

BOOL MACIsLinked ( void )

Returns the link status of the PHY/MAC.

Precondition:
None
Return values:
TRUE | If the PHY reports that a link partner is present and the link has been up continuously since the last call to MACIsLinked().
FALSE | If the PHY reports no link partner, or the link went down momentarily since the last call to MACIsLinked()
Remarks:
None

Todo:
Maybe an access to the LATA register is better?!

Definition at line 248 of file ETH97J60.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: MPFS

MPFS
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

The MPFS2 file system module provides a light-weight read-only file system that can be stored in external EEPROM, external serial Flash, or internal Flash program memory.

This file system serves as the basis for the HTTP2 web server module, but is also used by the SNMP module and is available to other applications that require basic read-only storage capabilities.

Files

file | MPFS2.c
Microchip File System (MPFS) File Access API.
file | MPFS2.h
MPFS Defines and prototypes for Microchip File System.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Reboot

Reboot
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

This UDP based module listens continously for UDP packets addressing the TFTP port.

If receiving a packet it initiates a shutdown procedure for activating the bootloader and starting a firmware update.

Files

file | Reboot.c
Module for Microchip TCP/IP Stack
  • Remotely resets the PIC
  • Reference: Internet Bootloader documentation.

file | Reboot.h
Reboot Server Module Header.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Stack Task

Stack Task
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

The Stack Manager coordinates the other Microchip TCP/IP Stack modules.

StackTask is implemented as a cooperative task; when given processing time, it polls the MAC layer for valid data packets. When one is received, it decodes it and routes it to the appropriate module for further processing.

Files

file | StackTsk.c
TCP/IP Stack Manager Module for Microchip TCP/IP Stack.
file | StackTsk.h
Microchip TCP/IP Stack Definitions.

Typedefs

typedef struct _MAC_ADDR | MAC_ADDR
This structure stores a 6 byte MAC address.
typedef struct _NODE_INFO | NODE_INFO
This structure stores informations of an network node.

Functions

void | StackInit (void)
Initializes the Microchip TCP/IP Stack and its components.
void | StackTask (void)
TCP/IP Stack FSM is executed.
void | StackApplications (void)
Calls all loaded application modules.

Function Documentation

void StackApplications ( void )

Calls all loaded application modules.

Precondition:
StackInit() is already called.
Remarks:
This function must be called periodically to ensure timely responses.

Definition at line 257 of file StackTsk.c.

void StackInit ( void )

Initializes the Microchip TCP/IP Stack and its components.

Precondition:
None
Remarks:
This function must be called before any of the stack or its component routines are used.

Definition at line 111 of file StackTsk.c.

void StackTask ( void )

TCP/IP Stack FSM is executed.

Precondition:
StackInit() is already called.
Remarks:
This FSM checks for new incoming packets, and routes it to appropriate stack components. It also performs timed operations. This function must be called periodically to ensure timely responses.

Definition at line 159 of file StackTsk.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: TCP

TCP
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

TCP is a standard transport layer protocol described in RFC 793.

It provides reliable stream-based connections over unreliable networks, and forms the foundation for HTTP, SMTP, and many other protocol standards.

Connections made over TCP guarantee data transfer at the expense of throughput. Connections are made through a three-way handshake process, ensuring a one-to- one connection. Remote nodes advertise how much data they are ready to receive, and all data transmitted must be acknowledged. If a remote node fails to acknowledge the receipt of data, it is automatically retransmitted. This ensures that network errors such as lost, corrupted, or out-of-order packets are automatically corrected.

To accomplish this, TCP must operate in a buffer. Once the transmit buffer is full, no more data can be sent until the remote node has acknowledged receipt. For the Microchip TCP/IP Stack, the application must return to the main stack loop in order for this to happen. Likewise, the remote node cannot transmit more data until the local device has acknowledged receipt and that space is available in the buffer. When a local application needs to read more data, it must return to the main stack loop and wait for a new packet to arrive.

The TCP flow diagram below provides an overview for the use of the TCP module:

Sockets are opened using TCPOpen. This function can either open a listening socket to wait for client connections, or can make a client connection to the remote node. The remote node can be specified by a host name string to be resolved in DNS, an IP address, or a NODE_INFO struct containing previously resolved IP and MAC address information.

Once connected, applications can read and write data. On each entry, the application must verify that the socket is still connected. For most applications a call to TCPIsConnected will be sufficient, but TCPWasReset may also be used for listening sockets that may turn over quickly.

To write data, call TCPIsPutReady to check how much space is available. Then, call any of the TCPPut family of functions to write data as space is available. Once complete, call TCPFlush to transmit data immediately. Alternately, return to the main stack loop. Data will be transmitted when either

  1. half of the transmit buffer becomes full or
  2. a delay time has passed (usually 40ms).

To read data, call TCPIsGetReady to determine how many bytes are ready to be retrieved. Then use the TCPGet family of functions to read data from the socket, and/or the TCPFindEx family of functions to locate data in the buffer. When no more data remains, return to the main stack loop to wait for more data to arrive.

If the application needs to close the connection, call TCPDisconnect, then return to the main stack loop and wait for the remote node to acknowledge the disconnection. Client sockets will return to the idle state, while listening sockets will wait for a new connection.

For more information read the associated RFC.

Files

file | TCP.c
Transmission Control Protocol (TCP) Communications Layer.
file | TCP.h
TCP Module Defs for Microchip TCP/IP Stack.

Functions

BOOL | TCPWasReset (TCP_SOCKET hTCP)
Self-clearing semaphore inidicating socket reset.
BOOL | TCPIsConnected (TCP_SOCKET hTCP)
Determines if a socket has an established connection.
void | TCPDisconnect (TCP_SOCKET hTCP)
Disconnects an open socket.
WORD | TCPIsPutReady (TCP_SOCKET hTCP)
Determines how much free space is available in the TCP TX buffer.
BOOL | TCPPut (TCP_SOCKET hTCP, BYTE byte)
Writes a single byte to a TCP socket.
WORD | TCPPutArray (TCP_SOCKET hTCP, BYTE *Data, WORD Len)
Writes an array from RAM to a TCP socket.
BYTE * | TCPPutString (TCP_SOCKET hTCP, BYTE *Data)
Writes a null-terminated string from RAM to a TCP socket.
WORD | TCPIsGetReady (TCP_SOCKET hTCP)
Determines how many bytes can be read from the TCP RX buffer.
BOOL | TCPGet (TCP_SOCKET hTCP, BYTE *byte)
Retrieves a single byte to a TCP socket.
WORD | TCPFindEx (TCP_SOCKET hTCP, BYTE cFind, WORD wStart, WORD wSearchLen, BOOL bTextCompare)
Searches for a byte in the TCP RX buffer.
void | TCPFlush (TCP_SOCKET hTCP)
Immediately transmits all pending TX data.
TCP_SOCKET | TCPOpen (DWORD dwRemoteHost, BYTE vRemoteHostType, WORD wPort, BYTE vSocketPurpose)
Opens a TCP socket for listening or as a client.

Function Documentation

void TCPDisconnect ( TCP_SOCKET hTCP )

Disconnects an open socket.

This function closes a connection to a remote node by sending a FIN. The function can be called a second time to force a socket closed by sending a RST packet. This is useful when the application knows that the remote node will not send an ACK (if it has crashed or lost its link), or when the application needs to reuse the socket immediately regardless of whether or not the remote node would like to transmit more data before closing.

Precondition:
TCP is initialized.
Parameters:
hTCP The socket to check.
Returns:
None
Remarks:
This function does nothing if the socket is not already connected. If the socket is using SSL, a CLOSE_NOTIFY record will be transmitted first to allow the SSL session to be resumed at a later time.

Definition at line 740 of file TCP.c.

WORD TCPFindEx | ( | TCP_SOCKET | hTCP,
 |  | BYTE | cFind,
 |  | WORD | wStart,
 |  | WORD | wSearchLen,
 |  | BOOL | bTextCompare
 | ) |  |

Searches for a byte in the TCP RX buffer.

This function finds the first occurrance of a byte in the TCP RX buffer. It can be used by an application to abstract searches out of their own application code. For increased efficiency, the function is capable of limiting the scope of search to a specific range of bytes. It can also perform a case-insensitive search if required.

For example, if the buffer contains "I love PIC MCUs!" and the cFind byte is ' ', a value of 1 will be returned.

Precondition:
TCP is initialized.
Parameters:
hTCP | The socket to search within.
cFind | The byte to find in the buffer.
wStart | Zero-indexed starting position within the buffer.
wSearchLen | Length from wStart to search in the buffer.
bTextCompare | TRUE for case-insensitive text search, FALSE for binary search
Return values:
0xFFFF | Search array not found
Otherwise | Zero-indexed position of the first occurrance
Remarks:
Since this function usually must transfer data from external storage to internal RAM for comparison, its performance degrades significantly when the buffer is full and the array is not found. For better performance, try to search for characters that are expected to exist or limit the scope of the search as much as possible. The HTTP2 module, for example, uses this function to parse headers. However, it searches for newlines, then the separating colon, then reads the header name to RAM for final comparison. This has proven to be significantly faster than searching for full header name strings outright.

Definition at line 2008 of file TCP.c.

void TCPFlush ( TCP_SOCKET hTCP )

Immediately transmits all pending TX data.

This function immediately transmits all pending TX data with a PSH flag. If this function is not called, data will automatically be sent when either a) the TX buffer is half full or b) the TCP_AUTO_TRANSMIT_TIMEOUT_VAL (default: 40ms) has elapsed.

Precondition:
TCP is initialized and the socket is connected.
Parameters:
hTCP The socket whose data is to be transmitted.
Returns:
None
Remarks:
SSL application data is automatically flushed, so this function has no effect for SSL sockets.

Definition at line 887 of file TCP.c.

BOOL TCPGet | ( | TCP_SOCKET | hTCP,
 |  | BYTE * | byte
 | ) |  |

Retrieves a single byte to a TCP socket.

Precondition:
TCP is initialized.
Parameters:
hTCP | The socket from which to read.
byte | Pointer to location in which the read byte should be stored.
Return values:
TRUE | A byte was read from the buffer.
FALSE | The buffer was empty, or the socket is not connected.

Definition at line 1453 of file TCP.c.

BOOL TCPIsConnected ( TCP_SOCKET hTCP )

Determines if a socket has an established connection.

This function determines if a socket has an established connection to a remote node. Call this function after calling TCPOpen to determine when the connection is set up and ready for use. This function was historically used to check for disconnections, but TCPWasReset is now a more appropriate solution.

Precondition:
TCP is initialized.
Parameters:
hTCP - The socket to check.
Return values:
TRUE | The socket has an established connection to a remote node.
FALSE | The socket is not currently connected.
Remarks:
A socket is said to be connected only if it is in the TCP_ESTABLISHED state. Sockets in the process of opening or closing will return FALSE.

Definition at line 702 of file TCP.c.

WORD TCPIsGetReady ( TCP_SOCKET hTCP )

Determines how many bytes can be read from the TCP RX buffer.

Call this function to determine how many bytes can be read from the TCP RX buffer. If this function returns zero, the application must return to the main stack loop before continuing in order to wait for more data to arrive.

Precondition:
TCP is initialized.
Parameters:
hTCP The socket to check.
Returns:
The number of bytes available to be read from the TCP RX buffer.

Definition at line 1424 of file TCP.c.

WORD TCPIsPutReady ( TCP_SOCKET hTCP )

Determines how much free space is available in the TCP TX buffer.

Call this function to determine how many bytes can be written to the TCP TX buffer. If this function returns zero, the application must return to the main stack loop before continuing in order to transmit more data.

Precondition:
TCP is initialized.
Parameters:
hTCP The socket to check.
Returns:
The number of bytes available to be written in the TCP TX buffer.

Definition at line 924 of file TCP.c.

TCP_SOCKET TCPOpen | ( | DWORD | dwRemoteHost,
 |  | BYTE | vRemoteHostType,
 |  | WORD | wPort,
 |  | BYTE | vSocketPurpose
 | ) |  |

Opens a TCP socket for listening or as a client.

Provides a unified method for opening TCP sockets. This function can open both client and server sockets. For client sockets, it can accept host name string to query in DNS, and IP address as a string, an IP address in binary form, or a previously resolved NODE_INFO structure. When a host name or IP address only is provided, the TCP module will internally perform the necessary DNS and/or ARP resolution steps before reporting that the TCP socket is connected (via a call to TCPISConnected returning TRUE). Server sockets ignore this destination parameter and listen only on the indicated port.

The vSocketPurpose field allows sockets to be opened with varying buffer size parameters and memory storage mediums. This field corresponds to pre-defined sockets types in TCPIPConfig.h or the TCPIPConfig utility.

Sockets are statically allocated on boot, but can be claimed with this function and freed using TCPDisconnect (for client sockets). Server sockets are opened permanently for the duration of the application. Calls to TCPDisconnect will only release the socket to the listening state.

Precondition:
TCP is initialized.
Parameters:
dwRemoteHost | For client sockets only. Provide a pointer to a null\-terminated string of the remote host name (ex\: "www.microchip.com" or "192.168.1.123"), a literal destination IP address (ex\: 0x7B01A8C0 or an IP_ADDR data type), or a pointer to a NODE_INFO structure with the remote IP address and remote node or gateway MAC address specified. If a string is provided, note that it must be statically allocated in memory and cannot be modified or deallocated until TCPIsConnected returns TRUE. This parameter is ignored for server sockets.
vRemoteHostType | TCP_OPEN_SERVER, TCP_OPEN_RAM_HOST, TCP_OPEN_ROM_HOST, TCP_OPEN_IP_ADDRESS, or TCP_OPEN_NODE_INFO.
wPort | For client sockets, the remote TCP port to which a connection should be made. For server sockets, the local TCP port on which to listen for connections.
vSocketPurpose | Any of the TCP_PURPOSE_* constants defined in TCPIPConfig.h or the TCPIPConfig utility.
Return values:
INVALID_SOCKET | No sockets of the specified type were available to be opened.
Otherwise | A TCP_SOCKET handle. Save this handle and use it when calling all other TCP APIs.
Remarks:
This function replaces the old TCPConnect and TCPListen functions.
If TCP_OPEN_RAM_HOST or TCP_OPEN_ROM_HOST are used for the destination type, the DNS client module must also be enabled.

Example:
    // Open a server socket
    skt = TCPOpen(NULL, TCP_OPEN_SERVER, HTTP_PORT, TCP_PURPOSE_HTTP_SERVER);

    // Open a client socket to www.microchip.com
    // The double cast here prevents compiler warnings
    skt = TCPOpen((DWORD)(PTR_BASE)"www.microchip.com",
                    TCP_OPEN_ROM_HOST, 80, TCP_PURPOSE_DEFAULT);

    // Reopen a client socket without repeating DNS or ARP
    SOCKET_INFO cache = TCPGetSocketInfo(skt);  // Call with the old socket
    skt = TCPOpen((DWORD)(PTR_BASE)&cache.remote, TCP_OPEN_NODE_INFO,
                    cache.remotePort.Val, TCP_PURPOSE_DEFAULT);

Definition at line 530 of file TCP.c.

BOOL TCPPut | ( | TCP_SOCKET | hTCP,
 |  | BYTE | byte
 | ) |  |

Writes a single byte to a TCP socket.

Precondition:
TCP is initialized.
Parameters:
hTCP | The socket to which data is to be written.
byte | The byte to write.
Return values:
TRUE | The byte was written to the transmit buffer.
FALSE | The transmit buffer was full, or the socket is not connected.

Definition at line 981 of file TCP.c.

WORD TCPPutArray | ( | TCP_SOCKET | hTCP,
 |  | BYTE * | Data,
 |  | WORD | Len
 | ) |  |

Writes an array from RAM to a TCP socket.

Precondition:
TCP is initialized.
Parameters:
hTCP | The socket to which data is to be written.
Data | Pointer to the array to be written.
Len | Number of bytes to be written.
Returns:
The number of bytes written to the socket. If less than len, the buffer became full or the socket is not conected.

Definition at line 1058 of file TCP.c.

BYTE* TCPPutString | ( | TCP_SOCKET | hTCP,
 |  | BYTE * | Data
 | ) |  |

Writes a null-terminated string from RAM to a TCP socket.

The null-terminator is not copied to the socket.

Precondition:
TCP is initialized.
Parameters:
hTCP | The socket to which data is to be written.
Data | Pointer to the string to be written.
Returns:
Pointer to the byte following the last byte written to the socket. If this pointer does not dereference to a NUL byte, the buffer became full or the socket is not connected.
Remarks:
The return value of this function differs from that of TCPPutArray. To write long strings in a single state, initialize the *data pointer to the first byte, then call this function repeatedly (breaking to the main stack loop after each call) until the return value dereferences to a NUL byte. Save the return value as the new starting *data pointer otherwise.

Definition at line 1291 of file TCP.c.

BOOL TCPWasReset ( TCP_SOCKET hTCP )

Self-clearing semaphore inidicating socket reset.

This function is a self-clearing semaphore indicating whether or not a socket has been disconnected since the previous call. This function works for all possible disconnections: a call to TCPDisconnect, a FIN from the remote node, or an acknowledgement timeout caused by the loss of a network link. It also returns TRUE after the first call to TCPInit. Applications should use this function to reset their state machines.

This function was added due to the possibility of an error when relying on TCPIsConnected returing FALSE to check for a condition requiring a state machine reset. If a socket is closed (due to a FIN ACK) and then immediately reopened (due to a the arrival of a new SYN) in the same cycle of the stack, calls to TCPIsConnected by the application will never return FALSE even though the socket has been disconnected. This can cause errors for protocols such as HTTP in which a client will immediately open a new connection upon closing of a prior one. Relying on this function instead allows applications to trap those conditions and properly reset their internal state for the new connection.

Precondition:
TCP is initialized.
Parameters:
hTCP The socket to check.
Return values:
TRUE | The socket has been disconnected since the previous call.
FALSE | The socket has not been disconnected since the previous call.

Definition at line 660 of file TCP.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Tick

Tick
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

The Tick module provides accurate time-keeping capabilities based on the hardware clock.

By default, it uses Timer 0 on 8-bit parts and Timer 1 on 16- and 32-bit families. The module is interrupt driven, which makes the timing stable and accurate. As such, it is also suitable for a real-time clock.

The Tick module exists to assist with the implementation of non-blocking delays and timeouts. Rather than using a loop to count to a specific number, use the Tick module and compare a previous time with the current time. In this fashion applications can return its unused cycles to the stack during long delays, which increases the overall efficiency of the system.

Files

file | Tick.c
Tick Manager for Timekeeping.
file | Tick.h
Tick Manager for PIC18.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: UDP

UDP
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Detailed Description

UDP is a standard transport layer protocol described in RFC 768.

It provides fast but unreliable data-gram based transfers over networks, and forms the foundation SNTP, SNMP, DNS, and many other protocol standards.

Files

file | UDP.c
User Datagram Protocol (UDP) Communications Layer Server Module for Microchip TCP/IP Stack.
file | UDP.h
UDP Module Defs for Microchip TCP/IP Stack.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: EEPROM

EEPROM
[TCP/IP Stack from Microchip Version 4.50 (Modified)]

Files

file | SPIEEPROM.c
Data SPI EEPROM Access Routines.
file | XEEPROM.h
External serial data EEPROM Access Defs.

Functions

XEE_RESULT | XEEReadArray (XEE_ADDR address, BYTE *buffer, BYTE length)
Reads desired number of bytes in sequential mode.
void | XEEEraseEEPROM (void)
Erases the whole EEPROM.
void | XEEWriteArray (WORD u16Address, BYTE *pu8Data, BYTE u8Len)
Writes an array of bytes to a specified address in the EEPROM.

Function Documentation

void XEEEraseEEPROM ( void )

Erases the whole EEPROM.

After the erase all bytes in EEPROM have a value of 0xFF.

Precondition:
None
Returns:
None
Remarks:
Only callable if the macro EEPROM_ERASE is defined.

Definition at line 369 of file SPIEEPROM.c.

XEE_RESULT XEEReadArray | ( | XEE_ADDR | address,
 |  | BYTE * | buffer,
 |  | BYTE | length
 | ) |  |

Reads desired number of bytes in sequential mode.

This function performs all necessary steps and releases the bus when finished.

Precondition:
None
Parameters:
address | Address from where the array should be read
buffer | Caller supplied buffer to hold the data
length | Number of bytes to read.
Returns:
XEE_SUCCESS

Definition at line 161 of file SPIEEPROM.c.

void XEEWriteArray | ( | WORD | u16Address,
 |  | BYTE * | pu8Data,
 |  | BYTE | u8Len
 | ) |  |

Writes an array of bytes to a specified address in the EEPROM.

Precondition:
None.
Parameters:
u16Address | Address in EEPROM the data is written to.
pu8Data | Pointer to the data.
u8Len | Size of data to be written.
Returns:
None
Remarks:
None

Definition at line 385 of file SPIEEPROM.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: SRCP Client

SRCP Client

Detailed Description

This group implements a complete SRCP client (SRCP version 0.8.X).

It handles the handshaking, the input of new GA and GL data, the consistence view of the server data and all user inputs which changes the server data.

Files

file | srcp/projectdefs.h
This file defines some basic structures and enumerators for SRCP handling.
file | srcp.c
This file implements the SRCP client module.
file | srcp.h
This file defines the SRCP API which can be called by the web interface (Web interface) and eWicht application modules.

Data Structures

struct | SPSRCPCONFIG
The fields in this structure configure the common SRCP handling. More...
struct | _PERS_PROTOCOL_CONFIG
The structure elements define a SRCP protocol like it is stored in EEPROM. More...
struct | SPSET
The structure elements define a SRCP object (GA or GL) stored in EEPROM. More...
SPSRCPCONFIG sPSRCPConfig
The persistent data field for common SRCP configuration data.

Defines

#define | PROJECT_ID SRCP_PROJECT
The project identifier.
#define | PROJECT_NAME "srcp"
The project name used by the display and the web interface.
#define | PROJECT_SERVICE_NAME "_srcp"
The name of the service to search for (used by the MDNS module).
#define | PROJECT_DEFAULT_PORT (4303u)
The standard port for SRCP servers.
#define | SRCP_NAME_MAXLEN 16
Maximum supported name length here (protocol names, descriptions).
#define | SRCP_PROTO_MAXLEN 3
Maximum length of SRCP protocol specifiers (i.e. "N 1").
#define | SRCP_SERVERCACHE_ID 0xFE
Internal identifier for a configuration set (loco data) from server cache.
#define | SRCP_EEPROMSET_ID 0xFF
Internal identifier for a configuration set from persistent storage.
#define | MAX_PROTO_SLOTS 8
Maximum count of supported protocols (N for GL and N for GA).
#define | MAX_SRCP_FUNCTIONS 13
Maximum supported loco functions (F0 inclusive).
#define | MAX_SRCP_SPEEDSTEPS 128
Maximum supported loco speed steps.
#define | SRCP_EEPROMSET_COUNT 32
Count of maximum configurations in EEPROM (shared between GAs and GLs).
#define | SRCP_GLEEPROMSET_COUNT 16
Count of maximum GL configurations in EEPROM.
#define | SRCP_GAEEPROMSET_COUNT 4
Count of maximum GA configurations in EEPROM.
#define | SRCP_EEPROMSET_IDX_MASK 0x0F
Mask for generating the device independent EEPROM set ID.
#define | SRCP_EEPROMSET_GA_MASK 0x10
Simple identifier mask for an GA EEPROM set.
#define | SRCP_CONFIG_EEPROM_ADD (0x0200u)
EEPROM byte address for common SRCP configuration data.
#define | SRCP_PROTOS_EEPROM_ADD (0x0300u)
EEPROM byte address for SRCP protocol data.
#define | SRCP_SETS_EEPROM_ADD (0x0800u)
EEPROM byte address for SRCP set data.
#define | PROJECT_SOCKET_CONFIGURATION
This macro defines the used sockets for this project.
#define | PROJECT_INITIAL_INIT SRCPInitialInit
This macro is used as hook in the ApplInit function.
#define | PROJECT_LOCO_DIR_MODE_HAS_CHANGED SRCPLocoDirModeHasChanged
This macro is used as hook in the ApplChangeLocoDirMode function.
#define | PROJECT_HANDLE_SERVER_CONNECTION SRCPHandleServerConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_RESET_TO_FACTORY SRCPRestoreToFactory
This macro is used as hook in the ApplResetToFactory function.
#define | PROJECT_PREPARE_CONNECTION SRCPPrepareConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_START_DISCONNECT SRCPStartDisconnect
This macro is used as hook in the disconnect function of the APPL module.
#define | PROJECT_IS_CONNECTED SRCPIsConnected
This macro is used as hook in the ApplIsConnected function.
#define | PROJECT_MAIN SRCPMain
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_WEBSITES
Defines the sites for this project.

Functions

void | SRCPRestoreToFactory (void)
Resets the SRCP related stuff to a well known start configuration.
BOOL | SRCPIsConnected (void)
Delivers if the SRCP client is actually connected with the server.
void | SRCPInitialInit (void)
This function must be called on startup to load the persistent SRCP configuration data into RAM and to do some initialization.
void | SRCPStartDisconnect (void)
Start disconnecting from server.
void | SRCPPrepareConnection (void)
Prepare internal state before starting a connect to the SRCP server.
APPL_CONNECTING_RETCODE | SRCPHandleServerConnection (void)
State machine is called during connecting and handshaking to or disconnecting from SRCP server.
BOOL | SRCPMain (void)
The main state machine of the SRCP client is called during the client is connected with the SRCP server.
void | SRCPLocoDirModeHasChanged (void)
Takes changes on the changed direction mode for locos.

Define Documentation

#define PROJECT_HANDLE_SERVER_CONNECTION SRCPHandleServerConnection

This macro is used as hook in the main task of the APPL Module.

Definition at line 121 of file srcp/projectdefs.h.

#define PROJECT_INITIAL_INIT SRCPInitialInit

This macro is used as hook in the ApplInit function.

Definition at line 115 of file srcp/projectdefs.h.

#define PROJECT_IS_CONNECTED SRCPIsConnected

This macro is used as hook in the ApplIsConnected function.

Definition at line 133 of file srcp/projectdefs.h.

#define PROJECT_LOCO_DIR_MODE_HAS_CHANGED SRCPLocoDirModeHasChanged

This macro is used as hook in the ApplChangeLocoDirMode function.

Definition at line 118 of file srcp/projectdefs.h.

#define PROJECT_PREPARE_CONNECTION SRCPPrepareConnection

This macro is used as hook in the main task of the APPL Module.

Definition at line 127 of file srcp/projectdefs.h.

#define PROJECT_RESET_TO_FACTORY SRCPRestoreToFactory

This macro is used as hook in the ApplResetToFactory function.

Definition at line 124 of file srcp/projectdefs.h.

#define PROJECT_SOCKET_CONFIGURATION

Value:

{TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 300, 1500}, \
                                        {TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 300, 1000}
This macro defines the used sockets for this project.

Definition at line 111 of file srcp/projectdefs.h.

#define PROJECT_START_DISCONNECT SRCPStartDisconnect

This macro is used as hook in the disconnect function of the APPL module.

Definition at line 130 of file srcp/projectdefs.h.

#define PROJECT_WEBSITES

Value:

{STRTBLID_SYSTEMSTATE, "index.htm", NAV_CLOSE},         \
                                {STRTBLID_COMMON, "common.htm", NAV_CLOSE},             \
                                {STRTBLID_SRCP, "srcp.htm", NAV_SUBNAV},                \
                                {STRTBLID_LOCO_PROTOCOLS, "locoproto.htm", NAV_CLOSE},  \
                                {STRTBLID_LOCO_DATABASE, "locos.htm", NAV_CLOSE},       \
                                {STRTBLID_ACC_PROTOCOLS, "accproto.htm", NAV_CLOSE},    \
                                {STRTBLID_ACC_DATABASE, "accs.htm", NAV_SUBNAVEND},     \
                                {STRTBLID_FILE, "file.htm", NAV_END},
Defines the sites for this project.

Definition at line 139 of file srcp/projectdefs.h.

#define SRCP_CONFIG_EEPROM_ADD (0x0200u)

EEPROM byte address for common SRCP configuration data.

See SPSRCPCONFIG for a detailed documentation of the structure elements. On startup the data is loaded into RAM (sPSRCPConfig).

Definition at line 92 of file srcp/projectdefs.h.

#define SRCP_PROTOS_EEPROM_ADD (0x0300u)

EEPROM byte address for SRCP protocol data.

At this address an array of _PERS_PROTOCOL_CONFIG elements is located which defines several protocol data for a specific SRCP server.

Definition at line 99 of file srcp/projectdefs.h.

#define SRCP_SETS_EEPROM_ADD (0x0800u)

EEPROM byte address for SRCP set data.

At this address an array of SPSET elements is located. The sets store data about special SRCP objects like locos and accessories.

Definition at line 106 of file srcp/projectdefs.h.

Function Documentation

APPL_CONNECTING_RETCODE SRCPHandleServerConnection ( void )

State machine is called during connecting and handshaking to or disconnecting from SRCP server.

Definition at line 3959 of file srcp.c.

void SRCPInitialInit ( void )

This function must be called on startup to load the persistent SRCP configuration data into RAM and to do some initialization.

Definition at line 651 of file srcp.c.

BOOL SRCPIsConnected ( void )

Delivers if the SRCP client is actually connected with the server.

Return values:
TRUE | Client is connected.
FALSE | Client is disconnected.

Definition at line 4126 of file srcp.c.

void SRCPLocoDirModeHasChanged ( void )

Takes changes on the changed direction mode for locos.

See ApplChangeLocoDirMode for more details.

Definition at line 640 of file srcp.c.

BOOL SRCPMain ( void )

The main state machine of the SRCP client is called during the client is connected with the SRCP server.

Definition at line 663 of file srcp.c.

void SRCPPrepareConnection ( void )

Prepare internal state before starting a connect to the SRCP server.

Definition at line 3932 of file srcp.c.

void SRCPRestoreToFactory ( void )

Resets the SRCP related stuff to a well known start configuration.

Definition at line 502 of file srcp.c.

void SRCPStartDisconnect ( void )

Start disconnecting from server.

Definition at line 4142 of file srcp.c.

Variable Documentation

SPSRCPCONFIG sPSRCPConfig

The persistent data field for common SRCP configuration data.

SRCPInitialInit loads the data which is stored in the data EEPROM into this SRAM field. The eWicht web interface or the function BootupResetToFactory can change these fields and store it back to the EEPROM.

Definition at line 62 of file srcp.h.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Rocrail Client

Rocrail Client

Detailed Description

This group implements a Rocrail client.

It handles the connection, the surfing in the loco database and controlling several locos. Also the power button is supported.

Files

file | rocrail/projectdefs.h
Some project related defines and typedefs for the eWicht Rocrail project.

Defines

#define | PROJECT_ID ROCRAIL_PROJECT
The project identifier.
#define | PROJECT_NAME "Rocrail"
The project name.
#define | PROJECT_SERVICE_NAME "_rocrail"
The name of the service to search for (used by the MDNS module).
#define | PROJECT_DEFAULT_PORT (62842u)
The default server port for this project.
#define | PROJECT_SOCKET_CONFIGURATION {TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 1140, 2000}
This macro defines the used sockets for this project.
#define | PROJECT_LOCO_DIR_MODE_HAS_CHANGED RocrailLocoDirModeHasChanged
This macro is used as hook in the ApplChangeLocoDirMode function.
#define | PROJECT_INITIAL_INIT()
This macro is used as hook in the ApplInit function.
#define | PROJECT_HANDLE_SERVER_CONNECTION RocrailHandleServerConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_PREPARE_CONNECTION RocrailPrepareConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_START_DISCONNECT RocrailStartDisconnect
This macro is used as hook in the disconnect function of the APPL module.
#define | PROJECT_RESET_TO_FACTORY()
This macro is used as hook in the ApplResetToFactory function.
#define | PROJECT_IS_CONNECTED RocrailIsConnected
This macro is used as hook in the ApplIsConnected function.
#define | PROJECT_MAIN RocrailMain
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_PROCESS_POST WebIoProcessPost
This macro is used as hook in the HTTPExecutePost (see web.c) function.
#define | PROJECT_WEBSITES
Defines the sites for this project.

Functions

void | RocrailLocoDirModeHasChanged (void)
Takes changes on the changed direction mode for locos.
BOOL | RocrailIsConnected (void)
Delivers if the Rocrail client is actually connected with the server.
void | RocrailStartDisconnect (void)
Start disconnecting from Rocrail server.
void | RocrailPrepareConnection (void)
Prepare internal state before starting a connect to the Rocrail server.
APPL_CONNECTING_RETCODE | RocrailHandleServerConnection (void)
State machine is called during connecting to or disconnecting from Rocrail server.
BOOL | RocrailMain (void)
The main state machine of the Rocrail client is called during the client is connected with the Rocrail server.

Define Documentation

#define PROJECT_DEFAULT_PORT (62842u)

The default server port for this project.

Definition at line 55 of file rocrail/projectdefs.h.

#define PROJECT_HANDLE_SERVER_CONNECTION RocrailHandleServerConnection

This macro is used as hook in the main task of the APPL Module.

Definition at line 68 of file rocrail/projectdefs.h.

#define PROJECT_ID ROCRAIL_PROJECT

The project identifier.

See eWichtProjects for a complete project list.

Definition at line 42 of file rocrail/projectdefs.h.

#define PROJECT_INITIAL_INIT ( )

This macro is used as hook in the ApplInit function.

Definition at line 65 of file rocrail/projectdefs.h.

#define PROJECT_IS_CONNECTED RocrailIsConnected

This macro is used as hook in the ApplIsConnected function.

Definition at line 80 of file rocrail/projectdefs.h.

#define PROJECT_LOCO_DIR_MODE_HAS_CHANGED RocrailLocoDirModeHasChanged

This macro is used as hook in the ApplChangeLocoDirMode function.

Definition at line 62 of file rocrail/projectdefs.h.

#define PROJECT_NAME "Rocrail"

The project name.

This name is displayed on index.htm of the Netzer website.

Definition at line 47 of file rocrail/projectdefs.h.

#define PROJECT_PROCESS_POST WebIoProcessPost

This macro is used as hook in the HTTPExecutePost (see web.c) function.

Definition at line 86 of file rocrail/projectdefs.h.

#define PROJECT_RESET_TO_FACTORY ( )

This macro is used as hook in the ApplResetToFactory function.

Definition at line 77 of file rocrail/projectdefs.h.

#define PROJECT_SERVICE_NAME "_rocrail"

The name of the service to search for (used by the MDNS module).

Definition at line 51 of file rocrail/projectdefs.h.

#define PROJECT_SOCKET_CONFIGURATION {TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 1140, 2000}

This macro defines the used sockets for this project.

Definition at line 58 of file rocrail/projectdefs.h.

#define PROJECT_START_DISCONNECT RocrailStartDisconnect

This macro is used as hook in the disconnect function of the APPL module.

Definition at line 74 of file rocrail/projectdefs.h.

#define PROJECT_WEBSITES

Value:

{STRTBLID_SYSTEMSTATE, "index.htm", NAV_CLOSE}, \
                                {STRTBLID_COMMON, "common.htm", NAV_CLOSE},     \
                                {STRTBLID_FILE, "file.htm", NAV_END},
Defines the sites for this project.

Definition at line 89 of file rocrail/projectdefs.h.

Function Documentation

APPL_CONNECTING_RETCODE RocrailHandleServerConnection ( void )

State machine is called during connecting to or disconnecting from Rocrail server.

Definition at line 694 of file rocrail.c.

BOOL RocrailIsConnected ( void )

Delivers if the Rocrail client is actually connected with the server.

Return values:
TRUE | Client is connected.
FALSE | Client is disconnected.

Definition at line 187 of file rocrail.c.

void RocrailLocoDirModeHasChanged ( void )

Takes changes on the changed direction mode for locos.

See ApplChangeLocoDirMode for more details.

Definition at line 777 of file rocrail.c.

BOOL RocrailMain ( void )

The main state machine of the Rocrail client is called during the client is connected with the Rocrail server.

Definition at line 202 of file rocrail.c.

void RocrailPrepareConnection ( void )

Prepare internal state before starting a connect to the Rocrail server.

Definition at line 160 of file rocrail.c.

void RocrailStartDisconnect ( void )

Start disconnecting from Rocrail server.

Definition at line 769 of file rocrail.c.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Structures

Data Structures

Here are the data structures with brief descriptions:
_IP_CONFIG | This typedef defines the local structure for TCP/IP stack parameters
_PERS_PROTOCOL_CONFIG | The structure elements define a SRCP protocol like it is stored in EEPROM
PCOMMON_CONFIG | This typedef defines the peristent structure for common settings and TCP/IP stack parameters
sIPFlags | This structure is used in the PCOMMON_CONFIG structure to define some IP related flags
SPAPPLDATA | This typedef defines the peristent structure for common application settings
SPSET | The structure elements define a SRCP object (GA or GL) stored in EEPROM
SPSRCPCONFIG | The fields in this structure configure the common SRCP handling
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: _IP_CONFIG Struct Reference

_IP_CONFIG Struct Reference
[Application network and initialization module]

#include <bootup.h>

Detailed Description

This typedef defines the local structure for TCP/IP stack parameters.

Definition at line 75 of file bootup.h.

Data Fields

IP_ADDR | MyIPAddr
The 4 byte IP address.
IP_ADDR | MyMask
The 4 byte subnet mask.
IP_ADDR | MyGateway
The 4 byte default subnet gateway.
unsigned char | bIPunique: 1
Indicates if IP is unique.
The documentation for this struct was generated from the following file:
  • bootup.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: _PERS_PROTOCOL_CONFIG Struct Reference

_PERS_PROTOCOL_CONFIG Struct Reference
[SRCP Client]

#include <projectdefs.h>

Detailed Description

The structure elements define a SRCP protocol like it is stored in EEPROM.

Instantiated objects (GA or GL) are build up from such a protocol structure.

Definition at line 205 of file srcp/projectdefs.h.

Data Fields

WORD | u16MinAdd
Minimum possible address.
WORD | u16MaxAdd
Maximum possible address.
BYTE | u8Bus
SRCP bus number.
BYTE | au8Desc [SRCP_NAME_MAXLEN+1]
Description (name) string.
BYTE | au8Proto [SRCP_PROTO_MAXLEN+1]
SRCP protocol identifier (i.e. N 1).
BOOL | bGL
FALSE -> GA, TRUE -> GL.
BOOL | bActive
Activiy indicator (FALSE means inactive, do not use!).
BYTE | u8MaxSteps
Maximum speed steps.
BYTE | u8NrFunc
Maximum functions.
BYTE | u8MinP
Minimum allowed port number.
BYTE | u8MaxP
Maximum allowed port number.
The documentation for this struct was generated from the following file:
  • srcp/projectdefs.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: PCOMMON_CONFIG Struct Reference

PCOMMON_CONFIG Struct Reference
[Application network and initialization module]

#include <bootup.h>

Detailed Description

This typedef defines the peristent structure for common settings and TCP/IP stack parameters.

It is stored at the EEPROM address BOOTUP_EEPROM_ADD. Upon start the EEPROM data is load to sPCommonConfig.

Definition at line 112 of file bootup.h.

Data Fields

IP_ADDR | ManIPAddr
The last manual configured IP address.
BYTE | ManMask
The last manual configured subnet mask.
IP_ADDR | ManGateway
The last manual configured default gateway.
IP_ADDR | LastAutoIP
The last used Auto IP address.
sIPFlags Flags
IP related flags.
BYTE | u8LCDLight
The time in seconds after the LED backlight is switched off.
DWORD | u32VersionTag
The application can detect a firmware update due comparing the versions of the EEPROM data and the installed application and can do some migration stuff.
eWichtProjects TargetProject
This field indicates how the EEPROM data must be interpreted.
BYTE | u8LanguageID
This field stores an ID which language is selected for display and webpage output.

Field Documentation

BYTE PCOMMON_CONFIG::u8LCDLight

The time in seconds after the LED backlight is switched off.

0 Means never, 0xFF means always off.

Definition at line 122 of file bootup.h.

DWORD PCOMMON_CONFIG::u32VersionTag

The application can detect a firmware update due comparing the versions of the EEPROM data and the installed application and can do some migration stuff.

Definition at line 127 of file bootup.h.

eWichtProjects PCOMMON_CONFIG::TargetProject

This field indicates how the EEPROM data must be interpreted.

The application should keep the flash and EEPROM target consistent.

Definition at line 132 of file bootup.h.

BYTE PCOMMON_CONFIG::u8LanguageID

This field stores an ID which language is selected for display and webpage output.

Definition at line 136 of file bootup.h.

The documentation for this struct was generated from the following file:
  • bootup.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: sIPFlags Struct Reference

sIPFlags Struct Reference
[Application network and initialization module]

#include <bootup.h>

Detailed Description

This structure is used in the PCOMMON_CONFIG structure to define some IP related flags.

Definition at line 91 of file bootup.h.

Data Fields

unsigned char bIsDHCPEnabled: 1
Indicates if automatic IP address obtaining is enabled.
The documentation for this struct was generated from the following file:
  • bootup.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: SPAPPLDATA Struct Reference

SPAPPLDATA Struct Reference
[Application module]

#include <appl.h>

Detailed Description

This typedef defines the peristent structure for common application settings.

Definition at line 77 of file appl.h.

Data Fields

SEARCH_MODE | eFindMode
The search mode for finding servers.
IP_ADDR | sSrvIPAdd
The IP address of the server to connect to.
WORD_VAL | sIPPort
The TCP port of the service to connect to when connecting to the server via the manual given IP address.
WORD_VAL | sNamePort
The TCP port of the service to connect to when connecting to the server via the manual given network name.
BYTE | au8Name [LCD_CHARS_IN_A_ROW+1]
The network name of the server to connect to.
BYTE | au8Service [LCD_CHARS_IN_A_ROW+1]
The network name of the service to connect to.
BYTE | bToggleLocoDirMode: 1
The mode how to toggle the loco direction in loco mode.

Field Documentation

IP_ADDR SPAPPLDATA::sSrvIPAdd

The IP address of the server to connect to.

Used by SEARCH_IP.

Definition at line 81 of file appl.h.

WORD_VAL SPAPPLDATA::sIPPort

The TCP port of the service to connect to when connecting to the server via the manual given IP address.

Used by SEARCH_IP.

Definition at line 84 of file appl.h.

WORD_VAL SPAPPLDATA::sNamePort

The TCP port of the service to connect to when connecting to the server via the manual given network name.

Used by SEARCH_NAME.

Definition at line 87 of file appl.h.

BYTE SPAPPLDATA::au8Name[LCD_CHARS_IN_A_ROW+1]

The network name of the server to connect to.

Used by SEARCH_NAME.

Definition at line 90 of file appl.h.

BYTE SPAPPLDATA::au8Service[LCD_CHARS_IN_A_ROW+1]

The network name of the service to connect to.

Used by SEARCH_SERVICE.

Definition at line 93 of file appl.h.

The documentation for this struct was generated from the following file:
  • appl.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: SPSET Struct Reference

SPSET Struct Reference
[SRCP Client]

#include <projectdefs.h>

Detailed Description

The structure elements define a SRCP object (GA or GL) stored in EEPROM.

Definition at line 242 of file srcp/projectdefs.h.

Data Fields

BYTE | au8Name [SRCP_NAME_MAXLEN+1]
The name of the quick set.
DWORD | u32Address
The address of the quick set.
BYTE | u8BusNr
The SRCP bus of the quick set.
BYTE | au8Proto [SRCP_PROTO_MAXLEN+1]
The protocol string of the quick set.
BOOL | bGL
FALSE -> GA, TRUE -> GL.
BOOL | bActive
Activiy indicator (FALSE means inactive, do not use!).
BYTE | u8MaxSteps
Maximum speed steps.
BYTE | u8NrFunc
Maximum number of functions.
WORD | u16MaxV
Maxmimum speed (in km/h). Mask to differentiate between function toggle and push.
BYTE | u8MinP
Minimum used port number.
BYTE | u8MaxP
Maximum used port number.
long | s32Delay
Port delay.
The documentation for this struct was generated from the following file:
  • srcp/projectdefs.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: SPSRCPCONFIG Struct Reference

SPSRCPCONFIG Struct Reference
[SRCP Client]

#include <projectdefs.h>

Detailed Description

The fields in this structure configure the common SRCP handling.

SRCPInitialInit called by ApplInit loads the data which is stored in the data EEPROM into this SRAM field. The eWicht web interface or the function BootupResetToFactory can change this fields and store it back to the EEPROM.

Definition at line 159 of file srcp/projectdefs.h.

Data Fields

BYTE | u8Reserved1
This field is deprecated - not longer used.
BYTE | u8DefaultGLProtoId
The default loco protocol.
BYTE | u8Reserved2
This field is deprecated - not longer used.
BYTE | u8DefaultGAProtoId
The default accessory protocol .
LONG | s32GADelay
The port delayed "on" time of all accessories.
BYTE | bGLAskForLock: 1
Indicates if a lock for a new loco is requested.
BYTE | bGAAskForLock: 1
Indicates if a lock for a new accessory is requested.
BYTE | bGLLock: 1
Indicates if the lock for the current loco is enabled.
BYTE | bGALock: 1
Indicates if the lock for the current accessory is enabled.
BYTE | bGLAskForProto: 1
Indicates if the protocol for the new loco is requested.
BYTE | bGAAskForProto: 1
Indicates if the protocol for the new accessory is requested.

Field Documentation

BYTE SPSRCPCONFIG::u8DefaultGLProtoId

The default loco protocol.

If this value is 0xFF then the server cache is selected.

Definition at line 189 of file srcp/projectdefs.h.

BYTE SPSRCPCONFIG::u8DefaultGAProtoId

The default accessory protocol .

Definition at line 195 of file srcp/projectdefs.h.

LONG SPSRCPCONFIG::s32GADelay

The port delayed "on" time of all accessories.

After this time the SRCP Server automatically switches the port off (0).

Definition at line 199 of file srcp/projectdefs.h.

The documentation for this struct was generated from the following file:
  • srcp/projectdefs.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Variables
  • a
  • b
  • e
  • f
  • l
  • m
  • s
  • t
  • u

Here is a list of all documented struct and union fields with links to the struct/union documentation for each field:

- a -

  • au8Desc : _PERS_PROTOCOL_CONFIG
  • au8Name : SPAPPLDATA , SPSET
  • au8Proto : _PERS_PROTOCOL_CONFIG , SPSET
  • au8Service : SPAPPLDATA

- b -

  • bActive : _PERS_PROTOCOL_CONFIG , SPSET
  • bGAAskForLock : SPSRCPCONFIG
  • bGAAskForProto : SPSRCPCONFIG
  • bGALock : SPSRCPCONFIG
  • bGL : _PERS_PROTOCOL_CONFIG , SPSET
  • bGLAskForLock : SPSRCPCONFIG
  • bGLAskForProto : SPSRCPCONFIG
  • bGLLock : SPSRCPCONFIG
  • bIPunique : _IP_CONFIG
  • bIsDHCPEnabled : sIPFlags
  • bToggleLocoDirMode : SPAPPLDATA

- e -

  • eFindMode : SPAPPLDATA

- f -

  • Flags : PCOMMON_CONFIG

- l -

  • LastAutoIP : PCOMMON_CONFIG

- m -

  • ManGateway : PCOMMON_CONFIG
  • ManIPAddr : PCOMMON_CONFIG
  • ManMask : PCOMMON_CONFIG
  • MyGateway : _IP_CONFIG
  • MyIPAddr : _IP_CONFIG
  • MyMask : _IP_CONFIG

- s -

  • s32Delay : SPSET
  • s32GADelay : SPSRCPCONFIG
  • sIPPort : SPAPPLDATA
  • sNamePort : SPAPPLDATA
  • sSrvIPAdd : SPAPPLDATA

- t -

  • TargetProject : PCOMMON_CONFIG

- u -

  • u16MaxAdd : _PERS_PROTOCOL_CONFIG
  • u16MaxV : SPSET
  • u16MinAdd : _PERS_PROTOCOL_CONFIG
  • u32Address : SPSET
  • u32VersionTag : PCOMMON_CONFIG
  • u8Bus : _PERS_PROTOCOL_CONFIG
  • u8BusNr : SPSET
  • u8DefaultGAProtoId : SPSRCPCONFIG
  • u8DefaultGLProtoId : SPSRCPCONFIG
  • u8LanguageID : PCOMMON_CONFIG
  • u8LCDLight : PCOMMON_CONFIG
  • u8MaxP : _PERS_PROTOCOL_CONFIG , SPSET
  • u8MaxSteps : SPSET , _PERS_PROTOCOL_CONFIG
  • u8MinP : _PERS_PROTOCOL_CONFIG , SPSET
  • u8NrFunc : _PERS_PROTOCOL_CONFIG , SPSET
  • u8Reserved1 : SPSRCPCONFIG
  • u8Reserved2 : SPSRCPCONFIG
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: File Index

File List

Here is a list of all documented files with brief descriptions:
appl.c [code] | This file implements the eWicht application module
appl.h [code] | This file includes the eWicht application module API
appldefs.h [code] | This file defines some basic structures and enumerators for the application module
ARP.c [code] | Address Resolution Protocol (ARP) Client and Server Module for Microchip TCP/IP Stack
ARP.h [code] | ARP Module Defs for Microchip TCP/IP Stack
bootup.c [code] | Implementation of the boot process of the eWicht application
bootup.h [code] | Prototypes for calling the eWicht application boot up and network routines
Compiler.h [code] | Compiler and hardware specific definitions
config.c [code] | This file implements the eWicht XML configuration module
config.h [code] | This file includes the eWicht XML configuration module API
DHCP.c [code] | Dynamic Host Configuration Protocol (DHCP) Client Module for Microchip TCP/IP Stack
DHCP.h [code] | DHCP Defs for Microchip TCP/IP Stack
dialog.c [code] | This file implements the dialog module
dialog.h [code] | This file includes the dialog module API
eeprom_adds.h [code] | This file includes a global address partion table for the eWicht EEPROM
error.c [code] | This file implements error print functions
error.h [code] | This file includes some common error codes
ETH97J60.c [code] | Medium Access Control (MAC) Layer for Microchip PIC18F97J60 family
ETH97J60.h [code] | Ethernet registers/bits for PIC18F97J60
GenericTypeDefs.h [code] | Generic Type Definitions
Helpers.c [code] | Helper Functions for Microchip TCP/IP Stack
Helpers.h [code] | Helper Function Defs for Microchip TCP/IP Stack
HTTP2.c [code] | HyperText Transfer Protocol (HTTP) Server Module for Microchip TCP/IP Stack
HTTP2.h [code] | HTTP definitions on Microchip TCP/IP Stack
srcp/HTTPPrint.h [code]
rocrail/HTTPPrint.h [code]
srcp/huffman.h [code]
rocrail/huffman.h [code]
ICMP.c [code] | Internet Control Message Protocol (ICMP) Server Module for Microchip TCP/IP Stack
ICMP.h [code] | ICMP Module Defs for Microchip TCP/IP Stack
input.c [code] | Button routines for input status of eWicht
input.h [code] | Input module defines and global function prototypes for eWicht
IP.c [code] | Internet Protocol (IP) Version 4 Communications Layer Module for Microchip TCP/IP Stack
IP.h [code] | IP Defs for Microchip TCP/IP Stack
ipset.c [code] | Implementation of IP input dialogs
ipset.h [code] | Prototypes for calling the IP input dialogues
MAC.h [code] | MAC Module Defs for Microchip Stack
main.c [code] | This file includes the main entry function
main.h [code] | This file includes some defines for main.c and also the fuse settings for the PIC
mdns.c [code] | Multicast Domain Name System (MDNS) implementation file for the eWicht application
mdns.h [code] | MDNS Client Module Header file for the eWicht application
MPFS2.c [code] | Microchip File System (MPFS) File Access API
MPFS2.h [code] | MPFS Defines and prototypes for Microchip File System
srcp/MPFSImg.c [code]
rocrail/MPFSImg.c [code]
output.c [code] | Display and LED routines for output status of eWicht
output.h [code] | Output module defines and global function prototypes for eWicht
srcp/projectdefs.h [code] | This file defines some basic structures and enumerators for SRCP handling
rocrail/projectdefs.h [code] | Some project related defines and typedefs for the eWicht Rocrail project
Reboot.c [code] Module for Microchip TCP/IP Stack
  • Remotely resets the PIC
  • Reference: Internet Bootloader documentation
Reboot.h [code] | Reboot Server Module Header
rocrail.c [code] | This file implements the Rocrail client module
rocrail.h [code] | This file defines the Rocrail API which can be called by the web interface (Web interface) and eWicht application modules
SPIEEPROM.c [code] | Data SPI EEPROM Access Routines
srcp.c [code] | This file implements the SRCP client module
srcp.h [code] | This file defines the SRCP API which can be called by the web interface (Web interface) and eWicht application modules
StackTsk.c [code] | TCP/IP Stack Manager Module for Microchip TCP/IP Stack
StackTsk.h [code] | Microchip TCP/IP Stack Definitions
stringtable.c [code] | This file implements the string tables for multi language support
stringtable.h [code] | This file includes the eWicht string table defines and API
TCP.c [code] | Transmission Control Protocol (TCP) Communications Layer
TCP.h [code] | TCP Module Defs for Microchip TCP/IP Stack
TCPIP.h [code] | Microchip TCP/IP Stack Include File
TCPIPConfig.h [code] | Microchip TCP/IP Stack Demo Application Configuration Header
Tick.c [code] | Tick Manager for Timekeeping
Tick.h [code] | Tick Manager for PIC18
UDP.c [code] | User Datagram Protocol (UDP) Communications Layer Server Module for Microchip TCP/IP Stack
UDP.h [code] | UDP Module Defs for Microchip TCP/IP Stack
version.h [code]
web.c [code] | The integrated web interface implementation of eWicht
web.h [code] | Web interface module defines and global function prototypes for eWicht
webprocess.c [code]
webprocess.h [code] | Web interface module defines and global function prototypes for eWicht
XEEPROM.h [code] | External serial data EEPROM Access Defs
xml.c [code] | XML parser implementation file for the eWicht application
xml.h [code] | XML Module Header file for the eWicht application
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: appl.c File Reference

appl.c File Reference

Detailed Description

This file implements the eWicht application module.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-10-30

Definition in file appl.c.

Go to the source code of this file.

Functions

void | ApplInit (void)
Call this function to initialize the application module.
IP_ADDR * | ApplGetServerIP (void)
Call this function to determine the IP address of the configured server for this device.
NODE_INFO * | ApplGetServerNodeInfo (void)
Call this function to determine the node info (MAC and IP address) of the configured server for this device.
WORD_VAL | ApplGetServerPort (void)
Call this function to determine the port (TCP/UDP) of the configured server for this device.
BOOL | ApplIsConnected (void)
This proxy function delivers the connect state of the current project.
void | ApplStop (void)
This function finally stops the application, i.e.
void | ApplMain (void)
Call this function periodically to execute the application module.
void | ApplShutDown (void)
The function initiates the shut down sequence while the application is still running.
BOOL | ApplIsRunning (void)
The function is the indicator for the running application.
void | ApplResetToFactory (BOOL KeepBootup)
This function restores the EEPROM content to a well known state.
void | ApplChangeLocoDirMode (BOOL Mode)
Call this function to change the current mode for changing the direction of a controlled loco.
void | ApplRestart (BOOL ResetToFactory)
This function initiate a restart of the device.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: appl.h File Reference

appl.h File Reference

Detailed Description

This file includes the eWicht application module API.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-04-30

Definition in file appl.h.

Go to the source code of this file.

Data Structures

struct | SPAPPLDATA
This typedef defines the peristent structure for common application settings. More...

Defines

#define | TOGGLEDIRMODE_CLICK FALSE
Loco direction changes on encoder button click.
#define | TOGGLEDIRMODE_ZERO TRUE
Loco direction automatically changes on crossing the zero mark.

Enumerations

enum | _SEARCH_MODES { SEARCH_UNKNOWN = 0, SEARCH_IP, SEARCH_NAME, SEARCH_SERVICE }
This typedef defines the different ways to find and connect a server. More...

Functions

void | ApplInit (void)
Call this function to initialize the application module.
void | ApplMain (void)
Call this function periodically to execute the application module.
IP_ADDR * | ApplGetServerIP (void)
Call this function to determine the IP address of the configured server for this device.
NODE_INFO * | ApplGetServerNodeInfo (void)
Call this function to determine the node info (MAC and IP address) of the configured server for this device.
WORD_VAL | ApplGetServerPort (void)
Call this function to determine the port (TCP/UDP) of the configured server for this device.
BOOL | ApplIsConnected (void)
This proxy function delivers the connect state of the current project.
void | ApplResetToFactory (BOOL KeepBootup)
This function restores the EEPROM content to a well known state.
void | ApplShutDown (void)
The function initiates the shut down sequence while the application is still running.
BOOL | ApplIsRunning (void)
The function is the indicator for the running application.
void | ApplStop (void)
This function finally stops the application, i.e.
void | ApplChangeLocoDirMode (BOOL Mode)
Call this function to change the current mode for changing the direction of a controlled loco.
void | ApplRestart (BOOL ResetToFactory)
This function initiate a restart of the device.

Variables

SPAPPLDATA sPApplConfig
The persistent data field for common application data.
BYTE | u8ApplTimer
The application timer runs backwards in units of 10 ms if different from zero.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: appldefs.h File Reference

appldefs.h File Reference

Detailed Description

This file defines some basic structures and enumerators for the application module.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-11-06

Definition in file appldefs.h.

Go to the source code of this file.

Enumerations

enum APPL_CONNECTING_RETCODE { APPL_CR_IN_PROGRESS = 0, APPL_CR_ERROR, APPL_CR_CLOSED, APPL_CR_CONNECTED }
Return values for project related connection task functions. More...

Enumeration Type Documentation

enum APPL_CONNECTING_RETCODE

Return values for project related connection task functions.

Enumerator:
APPL_CR_IN_PROGRESS | Connecting is in progress.
APPL_CR_ERROR | Error while connecting.
APPL_CR_CLOSED | Connection closed.
APPL_CR_CONNECTED | Successfully connected.

Definition at line 24 of file appldefs.h.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ARP.c File Reference

ARP.c File Reference

Detailed Description

Address Resolution Protocol (ARP) Client and Server Module for Microchip TCP/IP Stack.

  • Provides IP address to Ethernet MAC address translation
  • Reference: RFC 826

  • Dependencies: string.h StackTsk.h Helpers.h ARP.h MAC.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Search for "MODIFIX" in the code!
  • Removed preprocessor macro STACK_CLIENT_MODE as always defined.
  • Added function ARPFlush for flushing the ARP cache.

Definition in file ARP.c.

Go to the source code of this file.

Functions

void | ARPResolve (IP_ADDR *IPAddr)
Transmits an ARP request to resolve an IP address.
BOOL | ARPIsResolved (IP_ADDR *IPAddr, MAC_ADDR *MACAddr)
Determines if an ARP request has been resolved yet.
void | ARPFlush (void)
Flushes the ARP cache.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ARP.h File Reference

ARP.h File Reference

Detailed Description

ARP Module Defs for Microchip TCP/IP Stack.

  • Dependencies: Stacktsk.h MAC.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32MX
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Removed preprocessor macro STACK_CLIENT_MODE as always defined.
  • Added doxygen comments to the function prototypes.

Definition in file ARP.h.

Go to the source code of this file.

Functions

void | ARPResolve (IP_ADDR *IPAddr)
Transmits an ARP request to resolve an IP address.
BOOL | ARPIsResolved (IP_ADDR *IPAddr, MAC_ADDR *MACAddr)
Determines if an ARP request has been resolved yet.
void | ARPFlush (void)
Flushes the ARP cache.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: bootup.c File Reference

bootup.c File Reference

Detailed Description

Implementation of the boot process of the eWicht application.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-10-30

Definition in file bootup.c.

Go to the source code of this file.

Functions

void | BootupInit (void)
This function initializes the application network module.
void | BootupSetIP (void)
By calling this function the eWicht enters the IP Menu.
BOOL | bBootupMain (void)
This function must be called periodically by the application.
void | BootupEnterBootloader (void)
Calling this function prepares the bootloader entry.
void | BootupRestoreState (void)
Writes back the current bootup state (located in RAM) to persistent storage (EEPROM).
void | BootupResetToFactory (void)
Sometimes the reset of the persistent data in the EEPROM to a well known state is needed.

Variables

static SM_BOOTUP | _eBootUpSM
The local state machine.
static BOOL | _bFirstTime
Indicator for being here the first time (After bootup).
static BYTE | _au8NetworkDataForBootloader [12]
Stores the network related data like MAC address and IP address for reboot.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: bootup.h File Reference

bootup.h File Reference

Detailed Description

Prototypes for calling the eWicht application boot up and network routines.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2008-09-26

Definition in file bootup.h.

Go to the source code of this file.

Data Structures

struct | _IP_CONFIG
This typedef defines the local structure for TCP/IP stack parameters. More...
struct | sIPFlags
This structure is used in the PCOMMON_CONFIG structure to define some IP related flags. More...
struct | PCOMMON_CONFIG
This typedef defines the peristent structure for common settings and TCP/IP stack parameters. More...

Defines

#define | HOSTNAME ((ROM BYTE *) 0x01fbf0)
The hostname of this device located in flash memory.

Enumerations

enum | eWichtProjects
Enumerates the different projects an eWicht can be used for. More...

Functions

void | BootupInit (void)
This function initializes the application network module.
BOOL | bBootupMain (void)
This function must be called periodically by the application.
void | BootupSetIP (void)
By calling this function the eWicht enters the IP Menu.
void | BootupResetToFactory (void)
Sometimes the reset of the persistent data in the EEPROM to a well known state is needed.
void | BootupEnterBootloader (void)
Calling this function prepares the bootloader entry.
void | BootupRestoreState (void)
Writes back the current bootup state (located in RAM) to persistent storage (EEPROM).

Variables

IP_CONFIG sIPConfig
This field stores the local TCP/IP parameters.
PCOMMON_CONFIG sPCommonConfig
The persistent data field.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Compiler.h File Reference

Compiler.h File Reference

Detailed Description

Compiler and hardware specific definitions.

  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
None.

Definition in file Compiler.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: config.c File Reference

config.c File Reference

Detailed Description

This file implements the eWicht XML configuration module.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-08-06

Definition in file config.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: config.h File Reference

config.h File Reference

Detailed Description

This file includes the eWicht XML configuration module API.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-08-06

Definition in file config.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: DHCP.c File Reference

DHCP.c File Reference

Detailed Description

Dynamic Host Configuration Protocol (DHCP) Client Module for Microchip TCP/IP Stack.

  • Provides automatic IP address, subnet mask, gateway address, DNS server address, and other configuration parameters on DHCP enabled networks.
  • Reference: RFC 2131, 2132

  • Dependencies: UDP
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Search for "MODIFIX" in the code !
  • Removed preprocessor macro STACK_USE_DHCP_CLIENT as always defined.
  • Implemented the AutoIP feature. If the DHCP client does not find any DHCP server and for that reason gets no IP address, a IP address in the 169.254.X.X address pool is choosen. The following functions are affected:
    1. Extended the function DHCPReset()
    2. Extended the function DHCPTask()
    3. Added the function GenerateAutoIP()
Todo:
Generate a doxygen page for discussing the eWicht project and the DHCP and AutoIP behavior (High level).

Definition in file DHCP.c.

Go to the source code of this file.

Functions

void | DHCPReset (BOOL bNoAutoIP)
Resets the DHCP Client.
void | DHCPDisable (void)
Disables the DHCP client.
void | DHCPEnable (void)
Enables the DHCP client.
void | DHCPTask (void)
Performs periodic DHCP tasks.
IP_ADDR | GenerateAutoIP (IP_ADDR *lastIP)
Generates an IPv4 address from the 169.254.X.X auto IP pool.

Variables

DHCP_CLIENT_FLAGS | DHCPFlags = {{0x00}}

Variable Documentation

DHCP_CLIENT_FLAGS DHCPFlags = {{0x00}}

Todo:
Remove the DHCP externals?!

Definition at line 112 of file DHCP.c.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: DHCP.h File Reference

DHCP.h File Reference

Detailed Description

DHCP Defs for Microchip TCP/IP Stack.

  • Dependencies: TCPIPStack.h UDP.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Added the prototype for GenerateAutoIP.
  • Changed the prototype for DHCPReset.
  • Added doxygen comments to the function prototypes.
  • Removed the prototype for the function DHCPServerTask

Definition in file DHCP.h.

Go to the source code of this file.

Defines

#define | DHCPIsBound() (DHCPFlags.bits.bIsBound)
Determines if the DHCP server is currently bound.

Functions

void | DHCPReset (BOOL bNoAutoIP)
Resets the DHCP Client.
void | DHCPTask (void)
Performs periodic DHCP tasks.
void | DHCPDisable (void)
Disables the DHCP client.
void | DHCPEnable (void)
Enables the DHCP client.
IP_ADDR | GenerateAutoIP (IP_ADDR *lastIP)
Generates an IPv4 address from the 169.254.X.X auto IP pool.

Variables

DHCP_CLIENT_FLAGS | DHCPFlags

Variable Documentation

DHCP_CLIENT_FLAGS DHCPFlags

Todo:
Remove the DHCP externals?!

Definition at line 112 of file DHCP.c.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: dialog.c File Reference

dialog.c File Reference

Detailed Description

This file implements the dialog module.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-02-16

Definition in file dialog.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: dialog.h File Reference

dialog.h File Reference

Detailed Description

This file includes the dialog module API.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-02-16

Definition in file dialog.h.

Go to the source code of this file.
#define | DIALOG_LETTERS_FLAG 0x01
 | All small letters (a-z) can be the input in the dialog.
#define | DIALOG_CAPITALS_FLAG 0x02
 | All capitals (A-Z) can be the input in the dialog.
#define | DIALOG_WHITESPACE_FLAG 0x04
 | The space character can be the input in the dialog.
#define | DIALOG_DASH_FLAG 0x08
 | The dash ('-') character can be the input in the dialog.
#define | DIALOG_NUMBERS_FLAG 0x10
 | All numbers (0-9) can be the input in the dialog.
#define | DIALOG_SPECIAL_FLAG 0x20
 | All special characters can be the input in the dialog.
#define | DIALOG_ALL_LETTERS 0xFF
 | All supported characters can be input in the dialog.
#define | DIALOG_PREV_FLAG 0x01
 | The previous/cancel button is evaluated and displayed in the dialog.
#define | DIALOG_ESC_FLAG 0x02
 | The escape button is evaluated and displayed in the dialog.
#define | DIALOG_BACKSPACE_FLAG 0x04
 | The backspace button is evaluated and displayed in the dialog.
#define | DIALOG_NEXT_FLAG 0x08
 | The next/ok button is evaluated and displayed in the dialog.
#define | DIALOG_DESCRIPTION_FLAG 0x10
 | The button description is displayed in the dialog.
#define | DIALOG_DESCTOGGLE_FLAG 0x20
 | The button description toggles with the original display content.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: eeprom_adds.h File Reference

eeprom_adds.h File Reference

Detailed Description

This file includes a global address partion table for the eWicht EEPROM.

Definition in file eeprom_adds.h.

Go to the source code of this file.

Defines

#define | BOOTUP_EEPROM_ADD (0x0000u)
EEPROM byte address for application network data.
#define | APPL_EEPROM_ADD (0x0100u)
EEPROM byte address for common application data.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: error.c File Reference

error.c File Reference

Detailed Description

This file implements error print functions.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-03-20

Definition in file error.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: error.h File Reference

error.h File Reference

Detailed Description

This file includes some common error codes.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-03-20

Definition in file error.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ETH97J60.c File Reference

ETH97J60.c File Reference

Detailed Description

Medium Access Control (MAC) Layer for Microchip PIC18F97J60 family.

Module for Microchip TCP/IP Stack:

  • Provides access to PIC18F97J60 family Ethernet controller
  • Reference: PIC18F97J60 Family data sheet, IEEE 802.3 Standard

  • Dependencies: ETH97J60.h MAC.h string.h StackTsk.h Helpers.h Delay.h
  • Processor: PIC18F97J60 family
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
Search for "MODIFIX" in the code!

Definition in file ETH97J60.c.

Go to the source code of this file.

Defines

#define | HALF_DUPLEX
D E F I N I T I O N S.

Functions

BOOL | MACIsLinked (void)
Returns the link status of the PHY/MAC.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ETH97J60.h File Reference

ETH97J60.h File Reference

Detailed Description

Ethernet registers/bits for PIC18F97J60.

  • Dependencies: None
  • Processor: PIC18F97J60 family
  • Compiler: Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
None

Definition in file ETH97J60.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: GenericTypeDefs.h File Reference

GenericTypeDefs.h File Reference

Detailed Description

Generic Type Definitions.

  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C18, C30, C32 HI-TECH PICC-18
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
None.

Definition in file GenericTypeDefs.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Helpers.c File Reference

Helpers.c File Reference

Detailed Description

Helper Functions for Microchip TCP/IP Stack.

  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • None.

Definition in file Helpers.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Helpers.h File Reference

Helpers.h File Reference

Detailed Description

Helper Function Defs for Microchip TCP/IP Stack.

  • Dependencies: stacktsk.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • None.

Definition in file Helpers.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: HTTP2.c File Reference

HTTP2.c File Reference

Detailed Description

HyperText Transfer Protocol (HTTP) Server Module for Microchip TCP/IP Stack.

  • Serves dynamic pages to web browsers such as Microsoft Internet Explorer, Mozilla Firefox, etc.
  • Reference: RFC 2068

  • Dependencies: TCP, MPFS, HTTPGetVar() callback, HTTPExecCmd() callback
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
Added the function HTTPCheckForIdle.

Definition in file HTTP2.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: HTTP2.h File Reference

HTTP2.h File Reference

Detailed Description

HTTP definitions on Microchip TCP/IP Stack.

  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Added doxygen comments to the function prototypes.
  • Added prototype for HTTPCheckForIdle function.

Definition in file HTTP2.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ICMP.c File Reference

ICMP.c File Reference

Detailed Description

Internet Control Message Protocol (ICMP) Server Module for Microchip TCP/IP Stack.

  • Provides "ping" diagnostics
  • Reference: RFC 792

  • Dependencies: IP, ARP
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Removed preprocessor macro STACK_USE_ICMP_SERVER as always defined.
  • Removed all code sections requested with STACK_USE_ICMP_CLIENT because the eWicht project does not use ping requests.

Definition in file ICMP.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ICMP.h File Reference

ICMP.h File Reference

Detailed Description

ICMP Module Defs for Microchip TCP/IP Stack.

  • Dependencies: StackTsk.h IP.h MAC.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Removed STACK_USE_ICMP_CLIENT function prototypes.

Definition in file ICMP.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: input.c File Reference

input.c File Reference

Detailed Description

Button routines for input status of eWicht.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2008-07-13

Definition in file input.c.

Go to the source code of this file.

Functions

void | InputInit (void)
Initializes the input module.
void | InputMain (void)
The input state machines are feeded, handled and checked.
void | InputButtonReset (eButtonID eBtn)
The state machine of the given button will be reseted or all if ALL_BTN is the parameter.
BOOL | bInputButtonPushedOnce (eButtonID eBtn)
The application can ask the input module for a given button if there was a single push since the last call of InputButtonReset.
void | InputResetButtonPush (eButtonID eBtn)
This function can be used to reset single push events in the state machine.
void | InputResetPowerButton (void)
The power button state machine is something special and can be reset by this function.
BOOL | bInputButtonPushedTwice (eButtonID eBtn)
The application can ask the input module for a given button if there was a double push since the last call of InputButtonReset or InputInit.
BOOL | bInputButtonPushedLong (eButtonID eBtn)
The application can ask the input module for a given button if there was a long push since the last call of InputButtonReset or InputInit.
BYTE | u8InputButtonQuickPushed (void)
The function delivers the ID of any pushed quick button (F1-F4).
BOOL | bInputButtonPressed (eButtonID eBtn)
The function checks whether the requested button is currently pressed or released.
BOOL | bInputButtonPushed (eButtonID eBtn)
This function combines the functions bInputButtonPushedLong, bInputButtonPushedOnce and bInputButtonPushedTwice.
void | InputEncoderInit (SHORT s16Val, SHORT s16Min, SHORT s16Max, BYTE u8Flags)
This function initializes the rotary encoder.
SHORT | s16InputEncoderGetValue (void)
This function returns the actual value of rotary encoder state machine.
void | InputEncoderSetValue (short s16NewVal, BOOL bRemember)
The function sets the internal encoder value to the given value.
BOOL | bInputEncoderValueChanged (void)
This function returns TRUE if the value of rotary encoder state machine has changed after the last call of s16InputEncoderGetValue.
void | InputForceChangedEncoderValue (void)
After calling this function the function bInputEncoderValueChanged delivers a TRUE when calling after this function call.
BOOL | InputEncoderGetDirection (void)
This function delivers the current or last rotary direction of the encoder button.
BOOL | IsEncoderTurning (void)
The function checks whether the input encoder is turning.
void | InputInterruptHandler (void)
This function handles the periodic requested interrupts.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: input.h File Reference

input.h File Reference

Detailed Description

Input module defines and global function prototypes for eWicht.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-10-30

Definition in file input.h.

Go to the source code of this file.

Defines

#define | BTN_COUNT 0x09
The count of buttons.
#define | ENC_ENDSTOP_MASK 0x01
Flag for configuring the state machine (SM) of the rotary encoder button.
#define | ENC_TURBO_MASK 0x02
Flag for configuring the state machine (SM) of the rotary encoder button.
#define | ENC_NOCHANGE_MASK 0x04
Flag for configuring the state machine (SM) of the rotary encoder button.
#define | BTN_LONG_PUSH_TIME (100u)
This value is used to measure the first push time (unit is the cycle call time of the InputMain routine) of a button after a reset of the appropriate state machine and the first push.
#define | BTN_DOUBLE_PUSH_TIME (60u)
A button state machine waits between to single pushes until this time is elapsed (unit is the cycle call time of the InputMain routine).

Enumerations

enum eButtonID {
PWR_BTN = 0, SEL_BTN, ACC_BTN, FL_BTN,
F1_BTN, F2_BTN, F3_BTN, F4_BTN,
ENC_BTN, ALL_BTN
}
IDs for accessing the buttons. More...

Functions

void | InputInit (void)
Initializes the input module.
void | InputMain (void)
The input state machines are feeded, handled and checked.
void | InputButtonReset (eButtonID eBtn)
The state machine of the given button will be reseted or all if ALL_BTN is the parameter.
void | InputResetPowerButton (void)
The power button state machine is something special and can be reset by this function.
void | InputResetButtonPush (eButtonID eBtn)
This function can be used to reset single push events in the state machine.
BOOL | bInputButtonPushedOnce (eButtonID eBtn)
The application can ask the input module for a given button if there was a single push since the last call of InputButtonReset.
BOOL | bInputButtonPushedTwice (eButtonID eBtn)
The application can ask the input module for a given button if there was a double push since the last call of InputButtonReset or InputInit.
BOOL | bInputButtonPushedLong (eButtonID eBtn)
The application can ask the input module for a given button if there was a long push since the last call of InputButtonReset or InputInit.
BOOL | bInputButtonPushed (eButtonID eBtn)
This function combines the functions bInputButtonPushedLong, bInputButtonPushedOnce and bInputButtonPushedTwice.
SHORT | s16InputEncoderGetValue (void)
This function returns the actual value of rotary encoder state machine.
void | InputEncoderInit (SHORT s16Val, SHORT s16Min, SHORT s16Max, BYTE u8Flags)
This function initializes the rotary encoder.
BOOL | bInputEncoderValueChanged (void)
This function returns TRUE if the value of rotary encoder state machine has changed after the last call of s16InputEncoderGetValue.
void | InputEncoderSetValue (short s16NewVal, BOOL bRemember)
The function sets the internal encoder value to the given value.
void | InputForceChangedEncoderValue (void)
After calling this function the function bInputEncoderValueChanged delivers a TRUE when calling after this function call.
BOOL | InputEncoderGetDirection (void)
This function delivers the current or last rotary direction of the encoder button.
BYTE | u8InputButtonQuickPushed (void)
The function delivers the ID of any pushed quick button (F1-F4).
BOOL | bInputButtonPressed (eButtonID eBtn)
The function checks whether the requested button is currently pressed or released.
BOOL | IsEncoderTurning (void)
The function checks whether the input encoder is turning.
void | InputInterruptHandler (void)
This function handles the periodic requested interrupts.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: IP.c File Reference

IP.c File Reference

Detailed Description

Internet Protocol (IP) Version 4 Communications Layer Module for Microchip TCP/IP Stack.

  • Provides a transport for TCP, UDP, and ICMP messages
  • Reference: RFC 791

Dependencies: Ethernet (ETH97J60.c) Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32 Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Search for "MODIFIX" in the code !
  • Added the function IPConvertSubnetToMask
  • Added the function IPConvertMaskToSubnet

Definition in file IP.c.

Go to the source code of this file.

Functions

DWORD | IPConvertSubnetToMask (BYTE Subnet)
This function converts the CIDR subnet expression to the long IP expression.
BYTE | IPConvertMaskToSubnet (BYTE *MaskArray)
This function converts the long IP subnet expression to the CIDR expression.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: IP.h File Reference

IP.h File Reference

Detailed Description

IP Defs for Microchip TCP/IP Stack.

  • Dependencies: StackTsk.h MAC.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32MX
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Search for "MODIFIX" in the code!
  • Added doxygen comments to the function prototype of u32IPConvertSubnetToMask.

Definition in file IP.h.

Go to the source code of this file.

Functions

DWORD | IPConvertSubnetToMask (BYTE Subnet)
This function converts the CIDR subnet expression to the long IP expression.
BYTE | IPConvertMaskToSubnet (BYTE *MaskArray)
This function converts the long IP subnet expression to the CIDR expression.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ipset.c File Reference

ipset.c File Reference

Detailed Description

Implementation of IP input dialogs.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-10-30

Definition in file ipset.c.

Go to the source code of this file.

Functions

void | IPSetInit (BOOL bServer)
The function inits the internal state machine (SM) of the IP dialogues and some internal variables.
BOOL | IPSetMain (void)
This function handles the dialogues.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: ipset.h File Reference

ipset.h File Reference

Detailed Description

Prototypes for calling the IP input dialogues.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2008-08-08

Definition in file ipset.h.

Go to the source code of this file.

Functions

void | IPSetInit (BOOL bServer)
The function inits the internal state machine (SM) of the IP dialogues and some internal variables.
BOOL | IPSetMain (void)
This function handles the dialogues.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: MAC.h File Reference

MAC.h File Reference

Detailed Description

MAC Module Defs for Microchip Stack.

  • Dependencies: StackTsk.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Added doxygen comments to the function prototypes used by eWicht.
  • Added MAC address which is located in flash.

Definition in file MAC.h.

Go to the source code of this file.

Functions

BOOL MACIsLinked (void)
Returns the link status of the PHY/MAC.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: main.c File Reference

main.c File Reference

Detailed Description

This file includes the main entry function.

In main all necessary initialization stuff is done. After the init calling the main loop is executed which calls all module routines periodically. In case of an user requested shut down the main routine is leaved and the eWicht is cleanly shut down.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-04-30

Definition in file main.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: main.h File Reference

main.h File Reference

Detailed Description

This file includes some defines for main.c and also the fuse settings for the PIC.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-04-30

Definition in file main.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: mdns.c File Reference

mdns.c File Reference

Detailed Description

Multicast Domain Name System (MDNS) implementation file for the eWicht application.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2008-09-26

Definition in file mdns.c.

Go to the source code of this file.

Functions

void | _CheckForQueryResponse (WORD_VAL u16Type, WORD_VAL *pu16Length, BYTE u8Startlabel)
BOOL | bInitMDNSResponder (void)
Note: Important: First call this function after got the IP address and checked the validness.
void | StartMDNSResponder (void)
The service is started by a call of this function.
void | StopMDNSResponder (void)
The service is stopped by a call of this function.
MDNS_STATE | eGetMDNSState (void)
The function retrieves the state of the MDNS responder.
void | MDNSResponder ()
The function implements the state machine of the MDNS responder.
void | MDNSProcessFrame (NODE_INFO *remoteNode, IP_ADDR *localIP)
In the MDNS module the state machine and the receiption of frames are divorced.
BOOL | bMDNSNameIsResolved (IP_ADDR *pIP)
After calling MDNSResolveName the application should check periodically the resolvation progress with a call of this function.
BOOL | bMDNSServiceIsResolved (IP_ADDR *pIP, WORD_VAL *pu16Port)
After calling MDNSResolveService the application should check periodically the resolvation progress with a call of this function.
void | MDNSStopResolving (void)
A pending resolving process will be stopped.
void | MDNSResolveName (char *pName)
The function resolves a hostname record via MDNS to an IP address.
void | MDNSResolveService (char *pName, ROM char *pServiceName)
The function resolves a service record via MDNS.

Function Documentation

void _CheckForQueryResponse | ( | WORD_VAL | u16Type,
 |  | WORD_VAL * | pu16Length,
 |  | BYTE | u8Startlabel
 | ) |  |

Todo:
Message compression.

Definition at line 1043 of file mdns.c.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: mdns.h File Reference

mdns.h File Reference

Detailed Description

MDNS Client Module Header file for the eWicht application.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2008-09-26

Definition in file mdns.h.

Go to the source code of this file.

Defines

#define | MDNS_PORT 5353u
The MDNS UDP port.
#define | DNS_TYPE_A (0x0001u)
DNS type for hostnames.
#define | DNS_TYPE_PTR (0x000cu)
DNS type for pointer records.
#define | DNS_TYPE_MX (0x000fu)
DNS type for mailbox records.
#define | DNS_TYPE_SRV (0x0021u)
DNS type for service records.
#define | DNS_TYPE_TXT (0x0010u)
DNS type for text records.
#define | DNS_TYPE_ANY (0x00FFu)
DNS type for all records.

Enumerations

enum | _MDNS_STATE { MDNS_HAS_STOPPED = 0, MDNS_IS_STARTING_UP, MDNS_IS_RUNNING }
Possible states of the MDNS responder service. More...

Functions

BOOL | bInitMDNSResponder (void)
The function initializes the MDNS service.
void | StartMDNSResponder (void)
The service is started by a call of this function.
void | StopMDNSResponder (void)
The service is stopped by a call of this function.
void | MDNSResponder (void)
The function implements the state machine of the MDNS responder.
void | MDNSProcessFrame (NODE_INFO *remoteNode, IP_ADDR *localIP)
In the MDNS module the state machine and the receiption of frames are divorced.
MDNS_STATE | eGetMDNSState (void)
The function retrieves the state of the MDNS responder.
void | MDNSResolveService (char *pName, ROM char *pServiceName)
The function resolves a service record via MDNS.
void | MDNSResolveName (char *pName)
The function resolves a hostname record via MDNS to an IP address.
void | MDNSStopResolving (void)
A pending resolving process will be stopped.
BOOL | bMDNSServiceIsResolved (IP_ADDR *pIP, WORD_VAL *pu16Port)
After calling MDNSResolveService the application should check periodically the resolvation progress with a call of this function.
BOOL | bMDNSNameIsResolved (IP_ADDR *pIP)
After calling MDNSResolveName the application should check periodically the resolvation progress with a call of this function.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: MPFS2.c File Reference

MPFS2.c File Reference

Detailed Description

Microchip File System (MPFS) File Access API.

Module for Microchip TCP/IP Stack.

  • Provides single API for accessing web pages and other files from internal program memory or an external serial EEPROM memory
  • Reference: AN833

  • Dependencies: SPIEEPROM
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

Modifications to the original file
  • Huffman decoding for indexed files added. Search MODIFIX keyword for details.

Definition in file MPFS2.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: MPFS2.h File Reference

MPFS2.h File Reference

Detailed Description

MPFS Defines and prototypes for Microchip File System.

  • Dependencies: StackTsk.H
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • None.

Definition in file MPFS2.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: output.c File Reference

output.c File Reference

Detailed Description

Display and LED routines for output status of eWicht.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-10-30

Definition in file output.c.

Go to the source code of this file.

Functions

void | OutInit (void)
Initializes the display and LEDs.
void | OutTriggerDisplay (void)
Retriggers the time the LCD backlight stays on.
void | OutMain (void)
Handles the display access and LED blinking if enabled.
void | OutSwitchOffLCD (void)
The function turns off the backlight of the LCD and the LCD itself.
void | OutSwitchLCDBacklight (BOOL On)
The function turns the backlight of the LCD on or off.
BOOL | OutIsLCDBusy (void)
The function determines, if all commands are handled by the display and the appropriate actions are done.
void | OutEnableCursor (BOOL On)
The function enables the cursor in the display.
void | OutSetCursor (BYTE Column, BYTE Row)
The function sets the position of the cursor independently of the visibility of the cursor.
void | OutSwitchOffAllLEDs (void)
All button LEDs will be turned off.
void | OutSetLEDMask (BYTE LedMask, BYTE LedSwitchMask)
Gives boolean access to the LEDs via a switch mask.
void | OutSetLED (BYTE LedMask, eLED_Modes Mode)
Gives access to the LEDs.
eLED_Modes | OutGetLEDMode (BYTE Led)
Obtain the mode of the specified LED.
void | OutConvertNameForDisplay (BYTE *pString)
Converts a string from the website to the display encoding.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: output.h File Reference

output.h File Reference

Detailed Description

Output module defines and global function prototypes for eWicht.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-11-08

Definition in file output.h.

Go to the source code of this file.

Defines

#define | LCD_CHARS_IN_A_ROW 16
Defines the count of maximum characters per display row.
#define | LCD_CLR_MASK 0x01
Clear Display.
#define | LCD_ROW1_MASK 0x02
Write to the first display row.
#define | LCD_ROW2_MASK 0x04
Write to the second display row.
#define | LCD_ROW3_MASK 0x08
Write data to row 3. Not used by eWicht and not implemented yet.
#define | LCD_PROGRESS_MASK 0x10
Writes a progress bar in the second row.
#define | LCD_CLR_PROG_MASK 0x20
The command deletes the second row.
#define | LCD_CENTER1_MASK 0x40
Center the text in the first row.
#define | LCD_CENTER2_MASK 0x80
Center the text in the second row.
#define | LCD_PROGRESS_CHAR '.'
The character for showing the progress bar.
#define | LCD_PROGRESS_TIME 1.5
The time between a progress bar shift in seconds.
#define | LCD_IDLE_TIME 20
The time for an idle display.
#define | LED_FL 0x01
Gains access to FL button LED.
#define | LED_F1 0x02
Gains access to F1 button LED.
#define | LED_F2 0x04
Gains access to F2 button LED.
#define | LED_F3 0x08
Gains access to F3 button LED.
#define | LED_F4 0x10
Gains access to F4 button LED.
#define | LED_PWR 0x20
Gains access to PWR button LED.
#define | LED_ACC 0x40
Gains access to ACC button LED.
#define | LED_SEL 0x80
Gains access to SEL button LED.
#define | LED_BLINK_INTERVAL 1u
The time of the blinking interval of an LED in LED_BLINK mode in seconds.

Enumerations

enum | eLED_Modes { LED_ON = 0, LED_OFF, LED_BLINK, LED_TOGGLE }
Modes for LED access. More...

Functions

void | OutInit (void)
Initializes the display and LEDs.
void | OutMain (void)
Handles the display access and LED blinking if enabled.
void | OutDebugOut (BYTE u8Value)
The function displays the given value at the LEDs.
void | OutSwitchOffLCD (void)
The function turns off the backlight of the LCD and the LCD itself.
void | OutSwitchLCDBacklight (BOOL On)
The function turns the backlight of the LCD on or off.
BOOL | OutIsLCDBusy (void)
The function determines, if all commands are handled by the display and the appropriate actions are done.
void | OutEnableCursor (BOOL On)
The function enables the cursor in the display.
void | OutSetCursor (BYTE Column, BYTE Row)
The function sets the position of the cursor independently of the visibility of the cursor.
void | OutSwitchOffAllLEDs (void)
All button LEDs will be turned off.
void | OutSetLED (BYTE LedMask, eLED_Modes Mode)
Gives access to the LEDs.
void | OutSetLEDMask (BYTE LedMask, BYTE LedSwitchMask)
Gives boolean access to the LEDs via a switch mask.
void | OutTriggerDisplay (void)
Retriggers the time the LCD backlight stays on.
eLED_Modes | OutGetLEDMode (BYTE Led)
Obtain the mode of the specified LED.
void | OutConvertNameForDisplay (BYTE *pString)
Converts a string from the website to the display encoding.

Variables

BYTE | lcd_status
This byte is the global access to send commands to the display and get knowledge about the state of the LCD.

Define Documentation

#define LCD_IDLE_TIME 20

The time for an idle display.

After the time has elapsed, the LCD backlight is switched off. The application can restart the timer and switching on again the LCD backlight with display commands or calling the function OutTriggerDisplay.

Definition at line 118 of file output.h.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: projectdefs.h File Reference

projectdefs.h File Reference

Detailed Description

This file defines some basic structures and enumerators for SRCP handling.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-04-30

Definition in file srcp/projectdefs.h.

Go to the source code of this file.

Data Structures

struct | SPSRCPCONFIG
The fields in this structure configure the common SRCP handling. More...
struct | _PERS_PROTOCOL_CONFIG
The structure elements define a SRCP protocol like it is stored in EEPROM. More...
struct | SPSET
The structure elements define a SRCP object (GA or GL) stored in EEPROM. More...

Defines

#define | PROJECT_ID SRCP_PROJECT
The project identifier.
#define | PROJECT_NAME "srcp"
The project name used by the display and the web interface.
#define | PROJECT_SERVICE_NAME "_srcp"
The name of the service to search for (used by the MDNS module).
#define | PROJECT_DEFAULT_PORT (4303u)
The standard port for SRCP servers.
#define | SRCP_NAME_MAXLEN 16
Maximum supported name length here (protocol names, descriptions).
#define | SRCP_PROTO_MAXLEN 3
Maximum length of SRCP protocol specifiers (i.e. "N 1").
#define | SRCP_SERVERCACHE_ID 0xFE
Internal identifier for a configuration set (loco data) from server cache.
#define | SRCP_EEPROMSET_ID 0xFF
Internal identifier for a configuration set from persistent storage.
#define | MAX_PROTO_SLOTS 8
Maximum count of supported protocols (N for GL and N for GA).
#define | MAX_SRCP_FUNCTIONS 13
Maximum supported loco functions (F0 inclusive).
#define | MAX_SRCP_SPEEDSTEPS 128
Maximum supported loco speed steps.
#define | SRCP_EEPROMSET_COUNT 32
Count of maximum configurations in EEPROM (shared between GAs and GLs).
#define | SRCP_GLEEPROMSET_COUNT 16
Count of maximum GL configurations in EEPROM.
#define | SRCP_GAEEPROMSET_COUNT 4
Count of maximum GA configurations in EEPROM.
#define | SRCP_EEPROMSET_IDX_MASK 0x0F
Mask for generating the device independent EEPROM set ID.
#define | SRCP_EEPROMSET_GA_MASK 0x10
Simple identifier mask for an GA EEPROM set.
#define | SRCP_CONFIG_EEPROM_ADD (0x0200u)
EEPROM byte address for common SRCP configuration data.
#define | SRCP_PROTOS_EEPROM_ADD (0x0300u)
EEPROM byte address for SRCP protocol data.
#define | SRCP_SETS_EEPROM_ADD (0x0800u)
EEPROM byte address for SRCP set data.
#define | PROJECT_SOCKET_CONFIGURATION
This macro defines the used sockets for this project.
#define | PROJECT_INITIAL_INIT SRCPInitialInit
This macro is used as hook in the ApplInit function.
#define | PROJECT_LOCO_DIR_MODE_HAS_CHANGED SRCPLocoDirModeHasChanged
This macro is used as hook in the ApplChangeLocoDirMode function.
#define | PROJECT_HANDLE_SERVER_CONNECTION SRCPHandleServerConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_RESET_TO_FACTORY SRCPRestoreToFactory
This macro is used as hook in the ApplResetToFactory function.
#define | PROJECT_PREPARE_CONNECTION SRCPPrepareConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_START_DISCONNECT SRCPStartDisconnect
This macro is used as hook in the disconnect function of the APPL module.
#define | PROJECT_IS_CONNECTED SRCPIsConnected
This macro is used as hook in the ApplIsConnected function.
#define | PROJECT_MAIN SRCPMain
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_WEBSITES
Defines the sites for this project.

Functions

void | SRCPRestoreToFactory (void)
Resets the SRCP related stuff to a well known start configuration.
BOOL | SRCPIsConnected (void)
Delivers if the SRCP client is actually connected with the server.
void | SRCPInitialInit (void)
This function must be called on startup to load the persistent SRCP configuration data into RAM and to do some initialization.
void | SRCPStartDisconnect (void)
Start disconnecting from server.
void | SRCPPrepareConnection (void)
Prepare internal state before starting a connect to the SRCP server.
APPL_CONNECTING_RETCODE | SRCPHandleServerConnection (void)
State machine is called during connecting and handshaking to or disconnecting from SRCP server.
BOOL | SRCPMain (void)
The main state machine of the SRCP client is called during the client is connected with the SRCP server.
void | SRCPLocoDirModeHasChanged (void)
Takes changes on the changed direction mode for locos.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: projectdefs.h File Reference

projectdefs.h File Reference

Detailed Description

Some project related defines and typedefs for the eWicht Rocrail project.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-10-29

Definition in file rocrail/projectdefs.h.

Go to the source code of this file.

Defines

#define | PROJECT_ID ROCRAIL_PROJECT
The project identifier.
#define | PROJECT_NAME "Rocrail"
The project name.
#define | PROJECT_SERVICE_NAME "_rocrail"
The name of the service to search for (used by the MDNS module).
#define | PROJECT_DEFAULT_PORT (62842u)
The default server port for this project.
#define | PROJECT_SOCKET_CONFIGURATION {TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 1140, 2000}
This macro defines the used sockets for this project.
#define | PROJECT_LOCO_DIR_MODE_HAS_CHANGED RocrailLocoDirModeHasChanged
This macro is used as hook in the ApplChangeLocoDirMode function.
#define | PROJECT_INITIAL_INIT()
This macro is used as hook in the ApplInit function.
#define | PROJECT_HANDLE_SERVER_CONNECTION RocrailHandleServerConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_PREPARE_CONNECTION RocrailPrepareConnection
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_START_DISCONNECT RocrailStartDisconnect
This macro is used as hook in the disconnect function of the APPL module.
#define | PROJECT_RESET_TO_FACTORY()
This macro is used as hook in the ApplResetToFactory function.
#define | PROJECT_IS_CONNECTED RocrailIsConnected
This macro is used as hook in the ApplIsConnected function.
#define | PROJECT_MAIN RocrailMain
This macro is used as hook in the main task of the APPL Module.
#define | PROJECT_PROCESS_POST WebIoProcessPost
This macro is used as hook in the HTTPExecutePost (see web.c) function.
#define | PROJECT_WEBSITES
Defines the sites for this project.

Functions

void | RocrailLocoDirModeHasChanged (void)
Takes changes on the changed direction mode for locos.
BOOL | RocrailIsConnected (void)
Delivers if the Rocrail client is actually connected with the server.
void | RocrailStartDisconnect (void)
Start disconnecting from Rocrail server.
void | RocrailPrepareConnection (void)
Prepare internal state before starting a connect to the Rocrail server.
APPL_CONNECTING_RETCODE | RocrailHandleServerConnection (void)
State machine is called during connecting to or disconnecting from Rocrail server.
BOOL | RocrailMain (void)
The main state machine of the Rocrail client is called during the client is connected with the Rocrail server.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Reboot.c File Reference

Reboot.c File Reference

Detailed Description

Module for Microchip TCP/IP Stack
  • Remotely resets the PIC
  • Reference: Internet Bootloader documentation.

Dependencies: UDP Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32 Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Added the call to ApplRestart for initiating the shut down procedure.

Definition in file Reboot.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Reboot.h File Reference

Reboot.h File Reference

Detailed Description

Reboot Server Module Header.

Dependencies: None Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32 Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
None.

Definition in file Reboot.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: rocrail.c File Reference

rocrail.c File Reference

Detailed Description

This file implements the Rocrail client module.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-12-01

Definition in file rocrail.c.

Go to the source code of this file.

Functions

void | RocrailPrepareConnection (void)
Prepare internal state before starting a connect to the Rocrail server.
BOOL | RocrailIsConnected (void)
Delivers if the Rocrail client is actually connected with the server.
BOOL | RocrailMain (void)
The main state machine of the Rocrail client is called during the client is connected with the Rocrail server.
APPL_CONNECTING_RETCODE | RocrailHandleServerConnection (void)
State machine is called during connecting to or disconnecting from Rocrail server.
void | RocrailStartDisconnect (void)
Start disconnecting from Rocrail server.
void | RocrailLocoDirModeHasChanged (void)
Takes changes on the changed direction mode for locos.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: rocrail.h File Reference

rocrail.h File Reference

Detailed Description

This file defines the Rocrail API which can be called by the web interface (Web interface) and eWicht application modules.

Software License
See the eWSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-12-01

Definition in file rocrail.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: SPIEEPROM.c File Reference

SPIEEPROM.c File Reference

Detailed Description

Data SPI EEPROM Access Routines.

  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

Definition in file SPIEEPROM.c.

Go to the source code of this file.

Functions

XEE_RESULT | XEEReadArray (XEE_ADDR address, BYTE *buffer, BYTE length)
Reads desired number of bytes in sequential mode.
void | XEEEraseEEPROM (void)
Erases the whole EEPROM.
void | XEEWriteArray (WORD address, BYTE *pData, BYTE len)
Writes an array of bytes to a specified address in the EEPROM.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: srcp.c File Reference

srcp.c File Reference

Detailed Description

This file implements the SRCP client module.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-10-30

Definition in file srcp.c.

Go to the source code of this file.

Functions

SRCP_HANDSHAKE_RETCODE | _eHandShake (SSRCPSOCKET *hSRCP)
static BOOL | _bGetNextWord (BYTE u8Socket, BYTE *au8Buf, BYTE u8BufSize, BOOL *bEnd)
This function delivers the next SRCP word from the TCP stream.
void | SRCPRestoreToFactory (void)
Resets the SRCP related stuff to a well known start configuration.
void | SRCPLocoDirModeHasChanged (void)
Takes changes on the changed direction mode for locos.
void | SRCPInitialInit (void)
This function must be called on startup to load the persistent SRCP configuration data into RAM and to do some initialization.
BOOL | SRCPMain (void)
The main state machine of the SRCP client is called during the client is connected with the SRCP server.
void | SRCPPrepareConnection (void)
Prepare internal state before starting a connect to the SRCP server.
APPL_CONNECTING_RETCODE | SRCPHandleServerConnection (void)
State machine is called during connecting and handshaking to or disconnecting from SRCP server.
BOOL | SRCPIsConnected (void)
Delivers if the SRCP client is actually connected with the server.
void | SRCPStartDisconnect (void)
Start disconnecting from server.

Function Documentation

static BOOL _bGetNextWord | ( | BYTE | u8Socket,
 |  | BYTE * | au8Buf,
 |  | BYTE | u8BufSize,
 |  | BOOL * | bEnd |
 | ) |  |  | [static]

This function delivers the next SRCP word from the TCP stream.

SRCP word means, that the stream is parsed for whitespace characters. The parser throws away the prepending whitespace(s), stores all following characters in the given buffer (as long as space is left) until it finds whitespace characters again. In case the parser finds the end of line, it sets the end flag. Errors while reading from the TCP stream leads to an returned FALSE. Also FALSE will returned if the end flag is already set upon function entry. Else the function returns TRUE.

Definition at line 1478 of file srcp.c.

SRCP_HANDSHAKE_RETCODE _eHandShake ( SSRCPSOCKET * hSRCP )

Todo:
Revise the error messages.

Definition at line 3310 of file srcp.c.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: srcp.h File Reference

srcp.h File Reference

Detailed Description

This file defines the SRCP API which can be called by the web interface (Web interface) and eWicht application modules.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-04-30

Definition in file srcp.h.

Go to the source code of this file.
SPSRCPCONFIG | sPSRCPConfig
 | The persistent data field for common SRCP configuration data.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: StackTsk.c File Reference

StackTsk.c File Reference

Detailed Description

TCP/IP Stack Manager Module for Microchip TCP/IP Stack.

  • Handles internal RX packet pre-processing prior to dispatching to upper application layers.
  • Reference: AN833

  • Dependencies: ARP, IP, Ethernet (ETH97J60.c)
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Search for "MODIFIX" in the code!
  • Removed several preprocessor macro requests and unneede parts.

Definition in file StackTsk.c.

Go to the source code of this file.

Functions

void | StackInit (void)
Initializes the Microchip TCP/IP Stack and its components.
void | StackTask (void)
TCP/IP Stack FSM is executed.
void | StackApplications (void)
Calls all loaded application modules.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: StackTsk.h File Reference

StackTsk.h File Reference

Detailed Description

Microchip TCP/IP Stack Definitions.

  • Dependencies: Compiler.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Search for "MODIFIX" in the code!
  • Added doxygen comments to the function prototypes.

Definition in file StackTsk.h.

Go to the source code of this file.

Typedefs

typedef struct _MAC_ADDR | MAC_ADDR
This structure stores a 6 byte MAC address.
typedef struct _NODE_INFO | NODE_INFO
This structure stores informations of an network node.

Functions

void | StackInit (void)
Initializes the Microchip TCP/IP Stack and its components.
void | StackTask (void)
TCP/IP Stack FSM is executed.
void | StackApplications (void)
Calls all loaded application modules.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: stringtable.c File Reference

stringtable.c File Reference

Detailed Description

This file implements the string tables for multi language support.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-06-11

Definition in file stringtable.c.

Go to the source code of this file.

Functions

void | StrTbl_SetLanguage (BYTE u8LangId)
The function sets the actual string table for this session (not permanently).
void | StrTbl_GetString (BYTE *pString, WORD u16StrId)
The function copies the string with the given ID to the given RAM location.
ROM char * | StrTbl_cau8GetStringPointer (WORD u16StrId)
The function delivers a ROM pointer to the given string ID.
ROM char * | StrTbl_cau8GetLanguageStringPointer (BYTE u8LangId, WORD u16StrId)
The function delivers a ROM pointer to the given string ID on a given string table.
void | StrTbl_GetStringN (BYTE *pString, BYTE u8BufferSize, WORD u16StrId)
The function copies the string with the given ID to the given RAM location.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: stringtable.h File Reference

stringtable.h File Reference

Detailed Description

This file includes the eWicht string table defines and API.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-11-06

Definition in file stringtable.h.

Go to the source code of this file.

Defines

#define | LANGID_NOTSPECIFIED (0xFFu)
Language ID for factory resets and initial startups.
#define | LANGID_GERMAN (0x00u)
Language ID for the German string table.
#define | LANGID_ENGLISH (0x01u)
Language ID for the English string table.
#define | LANGID_MAX (0x01u)
The latest Language ID. Increment this ID if you add further languages.

Enumerations

enum | STRTBLIDS
String ID table for accessing the string table entries.

Functions

void | StrTbl_SetLanguage (BYTE u8LangId)
The function sets the actual string table for this session (not permanently).
void | StrTbl_GetString (BYTE *pString, WORD u16StrId)
The function copies the string with the given ID to the given RAM location.
void | StrTbl_GetStringN (BYTE *pString, BYTE u8BufferSize, WORD u16StrId)
The function copies the string with the given ID to the given RAM location.
ROM char * | StrTbl_cau8GetStringPointer (WORD u16StrId)
The function delivers a ROM pointer to the given string ID.
ROM char * | StrTbl_cau8GetLanguageStringPointer (BYTE u8LangId, WORD u16StrId)
The function delivers a ROM pointer to the given string ID on a given string table.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCP.c File Reference

TCP.c File Reference

Detailed Description

Transmission Control Protocol (TCP) Communications Layer.

Module for Microchip TCP/IP Stack

  • Provides reliable, handshaked transport of application stream oriented data with flow control
  • Reference: RFC 793

  • Dependencies: IP, Tick, Ethernet (ETH97J60.c), ARP (optional), DNS (optional)
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Todo:
Change from AppConfig structure to sIPConfig

Modifications to the original file
  • Search for "MODIFIX" in the code!
  • Removed preprocessor macro STACK_USE_TCP as always defined.

Definition in file TCP.c.

Go to the source code of this file.

Functions

TCP_SOCKET | TCPOpen (DWORD dwRemoteHost, BYTE vRemoteHostType, WORD wPort, BYTE vSocketPurpose)
Opens a TCP socket for listening or as a client.
BOOL | TCPWasReset (TCP_SOCKET hTCP)
Self-clearing semaphore inidicating socket reset.
BOOL | TCPIsConnected (TCP_SOCKET hTCP)
Determines if a socket has an established connection.
void | TCPDisconnect (TCP_SOCKET hTCP)
Disconnects an open socket.
void | TCPFlush (TCP_SOCKET hTCP)
Immediately transmits all pending TX data.
WORD | TCPIsPutReady (TCP_SOCKET hTCP)
Determines how much free space is available in the TCP TX buffer.
BOOL | TCPPut (TCP_SOCKET hTCP, BYTE byte)
Writes a single byte to a TCP socket.
WORD | TCPPutArray (TCP_SOCKET hTCP, BYTE *data, WORD len)
Writes an array from RAM to a TCP socket.
BYTE * | TCPPutString (TCP_SOCKET hTCP, BYTE *data)
Writes a null-terminated string from RAM to a TCP socket.
WORD | TCPIsGetReady (TCP_SOCKET hTCP)
Determines how many bytes can be read from the TCP RX buffer.
BOOL | TCPGet (TCP_SOCKET hTCP, BYTE *byte)
Retrieves a single byte to a TCP socket.
WORD | TCPFindEx (TCP_SOCKET hTCP, BYTE cFind, WORD wStart, WORD wSearchLen, BOOL bTextCompare)
Searches for a byte in the TCP RX buffer.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCP.h File Reference

TCP.h File Reference

Detailed Description

TCP Module Defs for Microchip TCP/IP Stack.

  • Dependencies: StackTsk.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Todo:
TCPIsClosed was removed.

Modifications to the original file
None.

Definition in file TCP.h.

Go to the source code of this file.

Functions

BOOL | TCPWasReset (TCP_SOCKET hTCP)
Self-clearing semaphore inidicating socket reset.
BOOL | TCPIsConnected (TCP_SOCKET hTCP)
Determines if a socket has an established connection.
void | TCPDisconnect (TCP_SOCKET hTCP)
Disconnects an open socket.
WORD | TCPIsPutReady (TCP_SOCKET hTCP)
Determines how much free space is available in the TCP TX buffer.
BOOL | TCPPut (TCP_SOCKET hTCP, BYTE byte)
Writes a single byte to a TCP socket.
WORD | TCPPutArray (TCP_SOCKET hTCP, BYTE *Data, WORD Len)
Writes an array from RAM to a TCP socket.
BYTE * | TCPPutString (TCP_SOCKET hTCP, BYTE *Data)
Writes a null-terminated string from RAM to a TCP socket.
WORD | TCPIsGetReady (TCP_SOCKET hTCP)
Determines how many bytes can be read from the TCP RX buffer.
BOOL | TCPGet (TCP_SOCKET hTCP, BYTE *byte)
Retrieves a single byte to a TCP socket.
WORD | TCPFindEx (TCP_SOCKET hTCP, BYTE cFind, WORD wStart, WORD wSearchLen, BOOL bTextCompare)
Searches for a byte in the TCP RX buffer.
void | TCPFlush (TCP_SOCKET hTCP)
Immediately transmits all pending TX data.
TCP_SOCKET | TCPOpen (DWORD dwRemoteHost, BYTE vRemoteHostType, WORD wPort, BYTE vSocketPurpose)
Opens a TCP socket for listening or as a client.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCPIP.h File Reference

TCPIP.h File Reference

Detailed Description

Microchip TCP/IP Stack Include File.

  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C18, C30, C32 HI-TECH PICC-18
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
None.

Definition in file TCPIP.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCPIPConfig.h File Reference

TCPIPConfig.h File Reference

Detailed Description

Microchip TCP/IP Stack Demo Application Configuration Header.

  • Dependencies: Microchip TCP/IP Stack
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Configured for eWicht
/********************************************************************* Software License Agreement

Copyright (C) 2002-2008 Microchip Technology Inc. All rights reserved.

Microchip licenses to you the right to use, modify, copy, and distribute: (i) the Software when embedded on a Microchip microcontroller or digital signal controller product ("Device") which is integrated into Licensee's product; or (ii) ONLY the Software driver source files ENC28J60.c and ENC28J60.h ported to a non-Microchip device used in conjunction with a Microchip ethernet controller for the sole purpose of interfacing with the ethernet controller.

You should refer to the license agreement accompanying this Software for additional information regarding your rights and obligations.

THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.

Author Date Comment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Howard Schlunder 10/04/2006 Original

Definition in file TCPIPConfig.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Tick.c File Reference

Tick.c File Reference

Detailed Description

Tick Manager for Timekeeping.

  • Dependencies: Timer 0 (PIC18) or Timer 1 (PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32)
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Look for MODIFIX in the code

Definition in file Tick.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Tick.h File Reference

Tick.h File Reference

Detailed Description

Tick Manager for PIC18.

  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Prototype for function TickGetDiv64K removed
  • Prototype for function TickUpdate removed

Definition in file Tick.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: UDP.c File Reference

UDP.c File Reference

Detailed Description

User Datagram Protocol (UDP) Communications Layer Server Module for Microchip TCP/IP Stack.

  • Provides unreliable, minimum latency transport of application datagram (packet) oriented data
  • Reference: RFC 768

  • Dependencies: IP, Ethernet (ETH97J60.c)
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32MX
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • Removed preprocessor macro STACK_USE_UDP as always defined.
  • Added a hook for processing MDNS frames in UDPProcess()
  • Added a function for determining the amount of bytes already put.
  • Added a IP filter in UDPProcess

Definition in file UDP.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: UDP.h File Reference

UDP.h File Reference

Detailed Description

UDP Module Defs for Microchip TCP/IP Stack.

  • Dependencies: StackTsk.h MAC.h
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32MX
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
Add function prototypes for get functions

Definition in file UDP.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: web.c File Reference

web.c File Reference

Detailed Description

The integrated web interface implementation of eWicht.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-07-31

Definition in file web.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: web.h File Reference

web.h File Reference

Detailed Description

Web interface module defines and global function prototypes for eWicht.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-01-23

Definition in file web.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: webprocess.h File Reference

webprocess.h File Reference

Detailed Description

Web interface module defines and global function prototypes for eWicht.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2010-03-06

Definition in file webprocess.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: XEEPROM.h File Reference

XEEPROM.h File Reference

Detailed Description

External serial data EEPROM Access Defs.

  • FileName: XEEPROM.h
  • Dependencies: None
  • Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
  • Compiler: Microchip C32 v1.00 or higher Microchip C30 v3.01 or higher Microchip C18 v3.13 or higher HI-TECH PICC-18 STD 9.50PL3 or higher
  • Company: Microchip Technology, Inc.

See the Microchip License Agreement for more details.

Modifications to the original file
  • SPI access is needed only.
  • Using the macro XEE_ADDR for maintenance reasons (fast upgrade of EEPROM size).
  • Removed the XEEInit prototype. This function is not needed because the SPI bus is shared by LCD and EEPROM. Both devices work in different SPI modes. Therefore the initialization of SPI is done directly before an access to the EEPROM.
  • Added doxygen comments to the function prototypes.
  • Added the function XEEEraseEEPROM for erasing the complete EEPROM.
  • Added the function XEEWriteArray for writing data arrays into EEPROM. eWicht needs it for saving configuration settings.
  • Moved the function prototypes of XEEBeginWrite, XEEWrite, XEEEndWrite, XEEIsBusy to SPIEEPROM.c as static (private) functions of the EEPROM module.
  • Removed the functions XEEBeginRead, XEERead and XEEEndRead because no longer needed.

Definition in file XEEPROM.h.

Go to the source code of this file.

Functions

XEE_RESULT | XEEReadArray (XEE_ADDR address, BYTE *buffer, BYTE length)
Reads desired number of bytes in sequential mode.
void | XEEEraseEEPROM (void)
Erases the whole EEPROM.
void | XEEWriteArray (WORD u16Address, BYTE *pu8Data, BYTE u8Len)
Writes an array of bytes to a specified address in the EEPROM.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: xml.c File Reference

xml.c File Reference

Detailed Description

XML parser implementation file for the eWicht application.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-11-27

Definition in file xml.c.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: xml.h File Reference

xml.h File Reference

Detailed Description

XML Module Header file for the eWicht application.

Software License
See the MBCSL for details.
Author:
Sven Schlender (kontakt at mobacon dot de)
Date:
2009-11-28

Definition in file xml.h.

Go to the source code of this file.

Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- _ -

  • _au8NetworkDataForBootloader : bootup.c
  • _bFirstTime : bootup.c
  • _bGetNextWord() : srcp.c
  • _CheckForQueryResponse() : mdns.c
  • _eBootUpSM : bootup.c
  • _eHandShake() : srcp.c
  • _MDNS_STATE : mdns.h
  • _SEARCH_MODES : appl.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: ARP.c Source File

ARP.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00032 // ////////////////////////////////////////////////////////////////////////////
00033 // ////////////////////////////////////////////////////////////////////////////
00093  /*
00094  * Author               Date    Comment
00095  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00096  * Nilesh Rajbharti     5/1/01  Original        (Rev 1.0)
00097  * Nilesh Rajbharti     2/9/02  Cleanup
00098  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
00099  * Howard Schlunder     8/17/06 Combined ARP.c and ARPTsk.c into ARP.c;
00100  *                              rewrote some of it to look more linear
00101  ********************************************************************/
00102
00103 #define __ARP_C
00104
00105 #include "TCPIP.h"
00106
00107
00108 /****************************************************************************
00109   Section:
00110     Constants and Variables
00111   ***************************************************************************/
00112
00113 // ARP Operation codes.
00114 #define ARP_OPERATION_REQ       0x01u
00115 #define ARP_OPERATION_RESP      0x02u
00116
00117 // ETHERNET packet type as defined by IEEE 802.3
00118 #define HW_ETHERNET             (0x0001u)
00119 #define ARP_IP                  (0x0800u)
00120
00121
00122
00123 // This ARP task caches one ARP response.
00124 static NODE_INFO Cache;
00125
00126
00127 // ARP packet structure
00128 typedef struct __attribute__((aligned(2), packed))
00129 {
00130     WORD        HardwareType;
00131     WORD        Protocol;
00132     BYTE        MACAddrLen;
00133     BYTE        ProtocolLen;
00134     WORD        Operation;
00135     MAC_ADDR    SenderMACAddr;
00136     IP_ADDR     SenderIPAddr;
00137     MAC_ADDR    TargetMACAddr;
00138     IP_ADDR     TargetIPAddr;
00139 } ARP_PACKET;
00140
00141
00142 /****************************************************************************
00143   Section:
00144     Helper Function Prototypes
00145   ***************************************************************************/
00146 static void SwapARPPacket(ARP_PACKET *p);
00147 static BOOL ARPPut(ARP_PACKET *packet);
00148
00149
00150
00151 /****************************************************************************
00152   Section:
00153     Function Implementations
00154   ***************************************************************************/
00155
00156 /*****************************************************************************
00157   Function:
00158     static BOOL ARPPut(ARP_PACKET* packet)
00159
00160   Description:
00161     Writes an ARP packet to the MAC.
00162
00163   Precondition:
00164     None
00165
00166   Parameters:
00167     packet - A pointer to an ARP_PACKET structure with correct operation
00168                 and target preconfigured.
00169
00170   Return Values:
00171     TRUE - The ARP packet was generated properly
00172     FALSE - Not a possible return value
00173   ***************************************************************************/
00174 static BOOL ARPPut(ARP_PACKET *packet)
00175 {
00176     while(!MACIsTxReady());
00177     MACSetWritePtr(BASE_TX_ADDR);
00178
00179
00180     packet->HardwareType  = HW_ETHERNET;
00181     packet->Protocol      = ARP_IP;
00182     packet->MACAddrLen    = sizeof(MAC_ADDR);
00183     packet->ProtocolLen   = sizeof(IP_ADDR);
00184
00185     // MODIFIX: Copy the MAC adress from a flash location instead from a RAM
00186     // location.
00187     memcpypgm2ram(&packet->SenderMACAddr, ( ROM void * ) pu8MAC, sizeof(packet->SenderMACAddr));
00188     // MODIFIX: Take IP from eWicht specific sIPConfig-Structure:
00189     packet->SenderIPAddr  = sIPConfig.MyIPAddr;
00190
00191     SwapARPPacket(packet);
00192
00193     MACPutHeader(&packet->TargetMACAddr, MAC_ARP, sizeof(*packet));
00194     MACPutArray((BYTE*)packet, sizeof(*packet));
00195     MACFlush();
00196
00197     return TRUE;
00198 }
00199
00200
00201 /*****************************************************************************
00202   Function:
00203     void ARPInit(void)
00204
00205   Summary:
00206     Initializes the ARP module.
00207
00208   Description:
00209     Initializes the ARP module.  Call this function once at boot to
00210     invalidate the cached lookup.
00211
00212   Precondition:
00213     None
00214
00215   Parameters:
00216     None
00217
00218   Returns:
00219     None
00220
00221   Remarks:
00222     None
00223   ***************************************************************************/
00224
00225 void ARPInit(void)
00226 {
00227     Cache.MACAddr.v[0] = 0xff;
00228     Cache.MACAddr.v[1] = 0xff;
00229     Cache.MACAddr.v[2] = 0xff;
00230     Cache.MACAddr.v[3] = 0xff;
00231     Cache.MACAddr.v[4] = 0xff;
00232     Cache.MACAddr.v[5] = 0xff;
00233
00234     Cache.IPAddr.Val = 0x0;
00235 }
00236
00237
00238 /*****************************************************************************
00239   Function:
00240     BOOL ARPProcess(void)
00241
00242   Summary:
00243     Processes an incoming ARP packet.
00244
00245   Description:
00246     Retrieves an ARP packet from the MAC buffer and determines if it is a
00247     response to our request (in which case the ARP is resolved) or if it
00248     is a request requiring our response (in which case we transmit one.)
00249
00250   Precondition:
00251     ARP packet is ready in the MAC buffer.
00252
00253   Parameters:
00254     None
00255
00256   Return Values:
00257     TRUE - All processing of this ARP packet is complete.  Do not call
00258             again until a new ARP packet is waiting in the RX buffer.
00259     FALSE - This function must be called again.  More time is needed to
00260             send an ARP response.
00261   ***************************************************************************/
00262
00263 BOOL ARPProcess(void)
00264 {
00265     ARP_PACKET packet;
00266     static NODE_INFO Target;
00267     static enum
00268     {
00269         SM_ARP_IDLE = 0,
00270         SM_ARP_REPLY
00271     } smARP = SM_ARP_IDLE;
00272
00273     switch(smARP)
00274     {
00275         case SM_ARP_IDLE:
00276             // Obtain the incoming ARP packet
00277             MACGetArray((BYTE*)&packet, sizeof(packet));
00278             MACDiscardRx();
00279             SwapARPPacket(&packet);
00280
00281             // Validate the ARP packet
00282             if ( packet.HardwareType != HW_ETHERNET     ||
00283                  packet.MACAddrLen != sizeof(MAC_ADDR)  ||
00284                  packet.ProtocolLen != sizeof(IP_ADDR) )
00285             {
00286                  return TRUE;
00287             }
00288
00289             // Handle incoming ARP responses
00290             if(packet.Operation == ARP_OPERATION_RESP)
00291             {
00292                 Cache.MACAddr = packet.SenderMACAddr;
00293                 Cache.IPAddr = packet.SenderIPAddr;
00294                 return TRUE;
00295             }
00296
00297             // Handle incoming ARP requests for our MAC address
00298             if(packet.Operation == ARP_OPERATION_REQ)
00299             {
00300                 // MODIFIX: Changed from the Microchip AppConfig structure
00301                 // to the more eWicht specific sIPConfig structure.
00302                 if( packet.TargetIPAddr.Val != sIPConfig.MyIPAddr.Val )
00303                 {
00304                     return TRUE;
00305                 }
00306                 Target.IPAddr = packet.SenderIPAddr;
00307                 Target.MACAddr = packet.SenderMACAddr;
00308
00309                 smARP = SM_ARP_REPLY;
00310             }
00311             // Do not break.  If we get down here, we need to send a reply.
00312
00313         case SM_ARP_REPLY:
00314             packet.Operation        = ARP_OPERATION_RESP;
00315             packet.TargetMACAddr    = Target.MACAddr;
00316             packet.TargetIPAddr     = Target.IPAddr;
00317
00318             // Send an ARP response to a previously received request
00319             if(!ARPPut(&packet))
00320             {
00321                return FALSE;
00322             }
00323
00324             // Begin listening for ARP requests again
00325             smARP = SM_ARP_IDLE;
00326             break;
00327     }
00328
00329     return TRUE;
00330 }
00331
00332
00333 /*****************************************************************************
00334   Function:
00335     void ARPResolve(IP_ADDR* IPAddr)
00336
00337   Summary:
00338     Transmits an ARP request to resolve an IP address.
00339
00340   Description:
00341     This function transmits and ARP request to determine the hardware
00342     address of a given IP address.
00343
00344   Precondition:
00345     ARP packet is ready in the MAC buffer.
00346
00347   Parameters:
00348     IPAddr - The IP address to be resolved
00349
00350   Returns:
00351     None
00352
00353   Remarks:
00354     None
00355   ***************************************************************************/
00356
00357 void ARPResolve(IP_ADDR *IPAddr)
00358 {
00359     ARP_PACKET packet;
00360
00361     packet.Operation            = ARP_OPERATION_REQ;
00362     packet.TargetMACAddr.v[0]   = 0xff;
00363     packet.TargetMACAddr.v[1]   = 0xff;
00364     packet.TargetMACAddr.v[2]   = 0xff;
00365     packet.TargetMACAddr.v[3]   = 0xff;
00366     packet.TargetMACAddr.v[4]   = 0xff;
00367     packet.TargetMACAddr.v[5]   = 0xff;
00368
00369
00370     // ARP query either the IP address directly (on our subnet), or do an ARP query for our Gateway if off of our subnet
00371     // MODIFIX: Changed from the Microchip AppConfig structure
00372     // to the more eWicht specific sIPConfig structure.
00373     packet.TargetIPAddr         = ((sIPConfig.MyIPAddr.Val ^ IPAddr->Val) & sIPConfig.MyMask.Val) ? sIPConfig.MyGateway : *IPAddr;
00374
00375     // MODIFIX: Only if TargetIPAddr is a valid address, put the ARP frame to
00376     // the ethernet.
00377     if (packet.TargetIPAddr.Val)
00378         ARPPut(&packet);
00379 }
00380
00381
00382 /*****************************************************************************
00383   Function:
00384     BOOL ARPIsResolved(IP_ADDR* IPAddr, MAC_ADDR* MACAddr)
00385
00386   Summary:
00387     Determines if an ARP request has been resolved yet.
00388
00389   Description:
00390     This function checks if an ARP request has been resolved yet, and if
00391     so, stores the resolved MAC address in the pointer provided.
00392
00393   Precondition:
00394     ARP packet is ready in the MAC buffer.
00395
00396   Parameters:
00397     IPAddr - The IP address to be resolved
00398     MACAddr - A buffer to store the corresponding MAC address
00399
00400   Return Values:
00401     TRUE - The IP address has been resolved and MAC address indicates the
00402             response.
00403     FALSE - The IP address is not resolved.
00404
00405   Remarks:
00406     None
00407   ***************************************************************************/
00408
00409 BOOL ARPIsResolved(IP_ADDR *IPAddr, MAC_ADDR *MACAddr)
00410 {
00411     // MODIFIX: Changed from the Microchip AppConfig structure
00412     // to the more eWicht specific sIPConfig structure.
00413     if((Cache.IPAddr.Val == IPAddr->Val) ||
00414       ((Cache.IPAddr.Val == sIPConfig.MyGateway.Val) && Cache.IPAddr.Val))
00415     {
00416         *MACAddr = Cache.MACAddr;
00417         return TRUE;
00418     }
00419     return FALSE;
00420 }
00421
00422
00423 /*****************************************************************************
00424   Function:
00425     static void SwapARPPacket(ARP_PACKET* p)
00426
00427   Description:
00428     Swaps endian-ness of header information in an ARP packet.
00429
00430   Precondition:
00431     None
00432
00433   Parameters:
00434     p - The ARP packet to be swapped
00435
00436   Returns:
00437     None
00438   ***************************************************************************/
00439 static void SwapARPPacket(ARP_PACKET *p)
00440 {
00441     p->HardwareType     = swaps(p->HardwareType);
00442     p->Protocol         = swaps(p->Protocol);
00443     p->Operation        = swaps(p->Operation);
00444 }
00445
00446 /*****************************************************************************
00447 // MODIFIX: Added the function for flushing the ARP cache.
00448   ***************************************************************************/
00449 void ARPFlush(void)
00450 {
00451     ARPInit();
00452 }
Generated on Sun Nov 27 20:02:37 2011 for eWicht by doxygen 1.5.5


eWicht: ARP.h Source File

ARP.h

Go to the documentation of this file.
00001
00002
00003
00037 /*********************************************************************
00038  * Software License Agreement
00039  *
00040  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00041  * reserved.
00042  *
00043  * Microchip licenses to you the right to use, modify, copy, and
00044  * distribute:
00045  * (i)  the Software when embedded on a Microchip microcontroller or
00046  *      digital signal controller product ("Device") which is
00047  *      integrated into Licensee's product; or
00048  * (ii) ONLY the Software driver source files ENC28J60.c and
00049  *      ENC28J60.h ported to a non-Microchip device used in
00050  *      conjunction with a Microchip ethernet controller for the
00051  *      sole purpose of interfacing with the ethernet controller.
00052  *
00053  * You should refer to the license agreement accompanying this
00054  * Software for additional information regarding your rights and
00055  * obligations.
00056  *
00057  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00058  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00059  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00060  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00061  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00062  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00063  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00064  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00065  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00066  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00067  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00068  *
00069  *
00070  * Author               Date    Comment
00071  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00072  * Nilesh Rajbharti     5/1/01  Original        (Rev 1.0)
00073  * Nilesh Rajbharti     2/9/02  Cleanup
00074  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
00075  * Howard Schlunder     8/17/06 Combined ARP.h and ARPTsk.h into ARP.h
00076  ********************************************************************/
00077 #ifndef __ARP_H
00078 #define __ARP_H
00079
00080 void ARPInit(void);
00081 BOOL ARPProcess(void);
00082
00083
00085
00103 void ARPResolve(IP_ADDR *IPAddr);
00104
00105
00107
00127 BOOL ARPIsResolved(IP_ADDR *IPAddr, MAC_ADDR *MACAddr);
00128
00129
00131
00135 void ARPFlush(void);
00136
00137 #endif
00138
00139
Generated on Sun Nov 27 20:02:37 2011 for eWicht by doxygen 1.5.5


eWicht: Compiler.h Source File

Compiler.h

Go to the documentation of this file.
00001
00002
00003
00019 /*********************************************************************
00020  * Software License Agreement
00021  *
00022  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00023  * reserved.
00024  *
00025  * Microchip licenses to you the right to use, modify, copy, and
00026  * distribute:
00027  * (i)  the Software when embedded on a Microchip microcontroller or
00028  *      digital signal controller product ("Device") which is
00029  *      integrated into Licensee's product; or
00030  * (ii) ONLY the Software driver source files ENC28J60.c and
00031  *      ENC28J60.h ported to a non-Microchip device used in
00032  *      conjunction with a Microchip ethernet controller for the
00033  *      sole purpose of interfacing with the ethernet controller.
00034  *
00035  * You should refer to the license agreement accompanying this
00036  * Software for additional information regarding your rights and
00037  * obligations.
00038  *
00039  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00040  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00041  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00042  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00043  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00044  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00045  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00046  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00047  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00048  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00049  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00050  *
00051  *
00052  * Author               Date        Comment
00053  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00054  * Howard Schlunder     10/03/2006  Original, copied from old Compiler.h
00055  * Howard Schlunder     11/07/2007  Reorganized and simplified
00056  ********************************************************************/
00057 #ifndef __COMPILER_H
00058 #define __COMPILER_H
00059
00060 // Include proper device header file
00061 #if defined(__18CXX) || defined(HI_TECH_C)
00062     // All PIC18 processors
00063     #if defined(HI_TECH_C)  // HI TECH PICC-18 compiler
00064         #define __18CXX
00065         #include <htc.h>
00066     #else                   // Microchip C18 compiler
00067         #include <p18cxxx.h>
00068     #endif
00069 #elif defined(__PIC24F__)   // Microchip C30 compiler
00070     // PIC24F processor
00071     #include <p24Fxxxx.h>
00072 #elif defined(__PIC24H__)   // Microchip C30 compiler
00073     // PIC24H processor
00074     #include <p24Hxxxx.h>
00075 #elif defined(__dsPIC33F__) // Microchip C30 compiler
00076     // dsPIC33F processor
00077     #include <p33Fxxxx.h>
00078 #elif defined(__dsPIC30F__) // Microchip C30 compiler
00079     // dsPIC30F processor
00080     #include <p30fxxxx.h>
00081 #elif defined(__PIC32MX__)  // Microchip C32 compiler
00082     #if !defined(__C32__)
00083         #define __C32__
00084     #endif
00085     #include <p32xxxx.h>
00086     #include <plib.h>
00087 #else
00088     #error Unknown processor or compiler.  See Compiler.h
00089 #endif
00090
00091 #include <stdio.h>
00092 #include <stdlib.h>
00093 #include <string.h>
00094
00095
00096 // Base RAM and ROM pointer types for given architecture
00097 #if defined(__C32__)
00098     #define PTR_BASE        DWORD
00099     #define ROM_PTR_BASE    DWORD
00100 #elif defined(__C30__)
00101     #define PTR_BASE        WORD
00102     #define ROM_PTR_BASE    WORD
00103 #elif defined(__18CXX)
00104     #define PTR_BASE        WORD
00105     #define ROM_PTR_BASE    unsigned short long
00106 #endif
00107
00108
00109 // Definitions that apply to all compilers, except C18
00110 #if !defined(__18CXX) || defined(HI_TECH_C)
00111     #define memcmppgm2ram(a,b,c)    memcmp(a,b,c)
00112     #define strcmppgm2ram(a,b)      strcmp(a,b)
00113     #define memcpypgm2ram(a,b,c)    memcpy(a,b,c)
00114     #define strcpypgm2ram(a,b)      strcpy(a,b)
00115     #define strncpypgm2ram(a,b,c)   strncpy(a,b,c)
00116     #define strstrrampgm(a,b)       strstr(a,b)
00117     #define strlenpgm(a)            strlen(a)
00118     #define strchrpgm(a,b)          strchr(a,b)
00119     #define strcatpgm2ram(a,b)      strcat(a,b)
00120 #endif
00121
00122
00123 // Definitions that apply to all 8-bit products
00124 // (PIC18)
00125 #if defined(__18CXX)
00126     #define __attribute__(a)
00127
00128     #define FAR                         far
00129
00130     // Microchip C18 specific defines
00131     #if !defined(HI_TECH_C)
00132         #define ROM                     const rom
00133         #define strcpypgm2ram(a, b)     strcpypgm2ram(a,(far rom char*)b)
00134     #endif
00135
00136     // HI TECH PICC-18 STD specific defines
00137     #if defined(HI_TECH_C)
00138         #define ROM                     const
00139         #define rom
00140         #define Nop()                   asm("NOP");
00141         #define ClrWdt()                asm("CLRWDT");
00142         #define Reset()                 asm("RESET");
00143     #endif
00144
00145 // Definitions that apply to all 16-bit and 32-bit products
00146 // (PIC24F, PIC24H, dsPIC30F, dsPIC33F, and PIC32)
00147 #else
00148     #define ROM                     const
00149
00150     // 16-bit specific defines (PIC24F, PIC24H, dsPIC30F, dsPIC33F)
00151     #if defined(__C30__)
00152         #define Reset()             asm("reset")
00153         #define FAR                 __attribute__((far))
00154     #endif
00155
00156     // 32-bit specific defines (PIC32)
00157     #if defined(__C32__)
00158         #define persistent
00159         #define far
00160         #define FAR
00161         #define Reset()             SoftReset()
00162         #define ClrWdt()            (WDTCONSET = _WDTCON_WDTCLR_MASK)
00163         #define Nop()               asm("nop")
00164     #endif
00165 #endif
00166
00167
00168
00169 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: DHCP.c Source File

DHCP.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00036 /*********************************************************************
00037  * Software License Agreement
00038  *
00039  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00040  * reserved.
00041  *
00042  * Microchip licenses to you the right to use, modify, copy, and
00043  * distribute:
00044  * (i)  the Software when embedded on a Microchip microcontroller or
00045  *      digital signal controller product ("Device") which is
00046  *      integrated into Licensee's product; or
00047  * (ii) ONLY the Software driver source files ENC28J60.c and
00048  *      ENC28J60.h ported to a non-Microchip device used in
00049  *      conjunction with a Microchip ethernet controller for the
00050  *      sole purpose of interfacing with the ethernet controller.
00051  *
00052  * You should refer to the license agreement accompanying this
00053  * Software for additional information regarding your rights and
00054  * obligations.
00055  *
00056  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00057  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00058  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00059  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00060  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00061  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00062  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00063  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00064  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00065  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00066  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00067  *
00068  *
00069  * Author               Date    Comment
00070  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00071  * Nilesh Rajbharti     3/21/01  Original        (Rev 1.0)
00072  * Nilesh Rajbharti     7/10/02  Explicitly initialized tempIPAddress
00073  *                                               (Rev 2.11)
00074  * Nilesh Rajbharti     5/16/03 Increased DHCP_TIMEOUT to 2 seconds.
00075  * Nilesh Rajbharti     5/16/03 Fixed SM_DHCP_BROADCAST logic
00076  *                              where UDPPut was called before setting
00077  *                              active socket.
00078  * Robert Sloan         5/29/03 Improved DHCP State machine to handle
00079  *                              NAK and renew existing IP address.
00080  * Nilesh Rajbharti     8/15/03 Modified _DHCPRecieve() to check for
00081  *                              chaddr field before accpting the packet.
00082  *                              Fixed DHCPTask() where it would not
00083  *                              reply to first OFFER.
00084  * Nilesh Rajbharti     3/1/04  Used tickDiff in DHCPTask() "bind"
00085  *                              state to adjust for irregular TICK_SECOND
00086  *                              Without this logic, actual lease time count
00087  *                              down may be incorrect.
00088  * Howard Schlunder     5/11/06 Fixed tickDiff usage, reducing
00089  *                              accumulated timing error.  Fixed DHCP
00090  *                              state machine requesting IP 0.0.0.0
00091  *                              after lease expiration.
00092  * Howard Schlunder     6/01/06 Added DHCPFlags.bits.bOfferReceived flag to
00093  *                              allow operation on networks with multiple
00094  *                              DHCP servers offering multiple addresses
00095  * Howard Schlunder     8/01/06 Added DNS server option to DHCP request,
00096  *                              untested Host Name option to DHCP request
00097  * Howard Schlunder     1/09/06 Fixed a DHCP renewal not renewing lease time bug
00098  * Howard Schlunder     3/16/07 Rewrote DHCP state machine
00099  ********************************************************************/
00100 #define __DHCP_C
00101 #include "TCPIP.h"
00102
00103 // Defines how long to wait before a DHCP request times out
00104 #define DHCP_TIMEOUT                    (TICK)(2*TICK_SECOND)
00105 // MODIFIX: Added a second timeout for supporting Auto IP.
00106 #define DHCP_TIMEOUT2                   (TICK)(180*TICK_SECOND)
00107
00108 // DHCP state machien variable
00109 SM_DHCP smDHCPState = SM_DHCP_GET_SOCKET;
00110
00111 // DHCP Client Flags to use
00112 DHCP_CLIENT_FLAGS DHCPFlags = {{0x00}};
00113
00114 // Socket for DHCP client to use
00115 static UDP_SOCKET DHCPSocket = INVALID_UDP_SOCKET;
00116
00117 // MODIFIX: New member for retry counter of DHCP discoveries.
00118 BYTE DHCPDiscRetry = 0;
00119
00120 BYTE DHCPBindCount = 0;         // Counts how many times DHCP has been bound
00121 static DWORD_VAL DHCPServerID;  // DHCP Server ID cache
00122 static DWORD_VAL DHCPLeaseTime; // DHCP Lease Time
00123 static IP_ADDR tempIPAddress;   // Temporary IP address to use when no DHCP lease
00124 static IP_ADDR tempGateway;     // Temporary gateway to use when no DHCP lease
00125 static IP_ADDR tempMask;        // Temporary mask to use when no DHCP lease
00126
00127 // MODIFIX: Removed DNS variables due eWicht does not use unicast DNS.
00128
00129 // Indicates which DHCP values are currently valid
00130 static union
00131 {
00132     struct
00133     {
00134         char IPAddress:1;   // Leased IP address is valid
00135         char Gateway:1;     // Gateway address is valid
00136         char Mask:1;        // Subnet mask is valid
00137         char DNS:1;         // Primary DNS is valid
00138         char DNS2:1;        // Secondary DNS is valid
00139         char HostName:1;    // Host name is valid (not implemented)
00140     } bits;
00141     BYTE Val;
00142 } ValidValues;
00143
00144
00145 static BYTE _DHCPReceive(void);
00146 static void _DHCPSend(BYTE messageType, BOOL bRenewing);
00147
00148
00149 /*****************************************************************************
00150   Function:
00151     void DHCPReset(void)
00152
00153   Summary:
00154     Resets the DHCP Client.
00155
00156   Description:
00157     Resets the DHCP Client, giving up any current lease, knowledge of
00158     DHCP servers, etc.
00159
00160   Precondition:
00161     None
00162
00163   Parameters:
00164     None
00165
00166   Returns:
00167     None
00168
00169   MODIFIX:
00170     Added AutoIP support.
00171   ***************************************************************************/
00172 void DHCPReset( BOOL bNoAutoIP )
00173 {
00174     // Do nothing if DHCP is disabled
00175     if(smDHCPState == SM_DHCP_DISABLED)
00176         return;
00177
00178     if(DHCPSocket != INVALID_UDP_SOCKET)
00179         // MODIFIX: Starting withe Auto IP state instead of
00180         // SM_DHCP_SEND_DISCOVERY
00181         smDHCPState = SM_DHCP_AUTOIP;
00182     else
00183         smDHCPState = SM_DHCP_GET_SOCKET;
00184
00185     // MODIFIX:
00186     // Reset the eWicht structure sIPConfig to a well known state, in case
00187     // Auto IP is enabled or the last used IP was not unique in the network.
00188     if ( ( bNoAutoIP == FALSE ) || ( sIPConfig.Flags.bIPunique == FALSE ) )
00189     {
00190         sIPConfig.MyIPAddr.Val = 0;
00191         sIPConfig.MyMask.Val = 0;
00192         sIPConfig.MyGateway.Val = 0;
00193         sIPConfig.Flags.bIPunique = FALSE;
00194     }
00195
00196     DHCPBindCount = 0;
00197     DHCPDiscRetry = 0;  // MODIFIX: New member must be initialized with 0.
00198     DHCPFlags.bits.bIsBound = FALSE;
00199
00200     // MODIFIX: This flag was never reseted!
00201     DHCPFlags.bits.bDHCPServerDetected = FALSE;
00202 }
00203
00204
00205 /*****************************************************************************
00206   Function:
00207     void DHCPDisable(void)
00208
00209   Summary:
00210     Disables the DHCP Client.
00211
00212   Description:
00213     Disables the DHCP client by sending the state machine to
00214     "SM_DHCP_DISABLED".  If the board was previously configured by DHCP, the
00215     configuration will continue to be used but the module will no longer
00216     preform any renewals.
00217
00218   Precondition:
00219     None
00220
00221   Parameters:
00222     None
00223
00224   Returns:
00225     None
00226
00227   Remarks:
00228     Since the board continues using its old configuration, it is possible
00229     that the lease may expire and the DHCP server provide the IP to another
00230     client.  The application should replace the current IP address and other
00231     configuration with static information following a call to this function.
00232   ***************************************************************************/
00233 void DHCPDisable(void)
00234 {
00235     if(DHCPSocket != INVALID_UDP_SOCKET)
00236     {
00237         UDPClose(DHCPSocket);
00238         DHCPSocket = INVALID_UDP_SOCKET;
00239     }
00240
00241     smDHCPState = SM_DHCP_DISABLED;
00242
00243     // MODIFIX: The flags are stored in the persistant IP configuration
00244     // structure of eWicht.
00245     sPCommonConfig.Flags.bIsDHCPEnabled = 0;
00246 }
00247
00248
00249 /*****************************************************************************
00250   Function:
00251     void DHCPEnable(void)
00252
00253   Summary:
00254     Enables the DHCP Client.
00255
00256   Description:
00257     Enables the DHCP client if it is disabled.  If it is already enabled,
00258     nothing is done.
00259
00260   Precondition:
00261     None
00262
00263   Parameters:
00264     None
00265
00266   Returns:
00267     None
00268   ***************************************************************************/
00269 void DHCPEnable(void)
00270 {
00271     if(smDHCPState == SM_DHCP_DISABLED)
00272     {
00273         // MODIFIX: This flag is stored in the eWicht sPCommonConfig structure
00274         // and not needed here.
00275 //      AppConfig.Flags.bIsDHCPEnabled = 1;
00276         smDHCPState = SM_DHCP_GET_SOCKET;
00277         DHCPBindCount = 0;
00278         DHCPFlags.bits.bIsBound = FALSE;
00279     }
00280 }
00281
00282
00283 /*****************************************************************************
00284   Function:
00285     void DHCPTask(void)
00286
00287   Summary:
00288     Performs periodic DHCP tasks.
00289
00290   Description:
00291     This function performs any periodic tasks requied by the DHCP module,
00292     such as sending and receiving messages involved with obtaining and
00293     maintaining a lease.
00294
00295   Precondition:
00296     None
00297
00298   Parameters:
00299     None
00300
00301   Returns:
00302     None
00303
00304   MODIFIX:
00305     Added AutoIP support.
00306   ***************************************************************************/
00307 void DHCPTask(void)
00308 {
00309     static TICK eventTime;
00310
00311     switch(smDHCPState)
00312     {
00313         case SM_DHCP_GET_SOCKET:
00314             // Open a socket to send and receive broadcast messages on
00315             DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
00316             if(DHCPSocket == INVALID_UDP_SOCKET)
00317                 break;
00318
00319             smDHCPState = SM_DHCP_AUTOIP;
00320             // No break
00321
00322         // MODIFIX: Added the following case label for supporting Auto IP.
00323         case SM_DHCP_AUTOIP:
00324             if (sIPConfig.MyIPAddr.Val == 0)
00325             {
00326                 if ((DHCPDiscRetry > 0) && (DHCPDiscRetry < 4))
00327                 {
00328                     // No DHCP-Server found yet, select an so called AutoIP during the further search time
00329                     // Take an auto IP address, that worked the last time.
00330
00331                     MAC_ADDR dummy;
00332                     if (ARPIsResolved(&sPCommonConfig.LastAutoIP, &dummy) == FALSE)
00333                         ARPResolve(&sPCommonConfig.LastAutoIP);
00334                     else
00335                     {
00336                         sPCommonConfig.LastAutoIP = GenerateAutoIP(&sPCommonConfig.LastAutoIP);
00337                         // Restart probing!
00338                         DHCPDiscRetry = 1;
00339                         ARPResolve(&sPCommonConfig.LastAutoIP);
00340                     }
00341                 }
00342                 else if (DHCPDiscRetry == 4)
00343                 {
00344                     // IP is probed and no answers have received!
00345                     sIPConfig.MyIPAddr = sPCommonConfig.LastAutoIP;
00346                     sIPConfig.MyMask.Val = 0xFFFF;  // subnet mask is 255.255.0.0
00347
00348                     // ToDo: Save the probed auto IP-Address in EEPROM
00349                 }
00350             }
00351             smDHCPState = SM_DHCP_SEND_DISCOVERY;
00352             // No break
00353
00354         case SM_DHCP_SEND_DISCOVERY:
00355             if(UDPIsPutReady(DHCPSocket) < 300u)
00356                 break;
00357
00358             // Ensure that we transmit to the broadcast IP and MAC addresses
00359             // The UDP Socket remembers who it was last talking to
00360             memset((void*)&UDPSocketInfo[DHCPSocket].remoteNode, 0xFF, sizeof(UDPSocketInfo[DHCPSocket].remoteNode));
00361
00362             // Assume default IP Lease time of 60 seconds.
00363             // This should be minimum possible to make sure that if
00364             // server did not specify lease time, we try again after this minimum time.
00365             DHCPLeaseTime.Val = 60;
00366             ValidValues.Val = 0x00;
00367             DHCPBindCount = 0;
00368             DHCPFlags.bits.bIsBound = FALSE;
00369             DHCPFlags.bits.bOfferReceived = FALSE;
00370
00371             // Send the DHCP Discover broadcast
00372             _DHCPSend(DHCP_DISCOVER_MESSAGE, FALSE);
00373
00374             // Start a timer and begin looking for a response
00375             eventTime = TickGet();
00376
00377             smDHCPState = SM_DHCP_GET_OFFER;
00378             break;
00379
00380         case SM_DHCP_GET_OFFER:
00381             // Check to see if a packet has arrived
00382             if(UDPIsGetReady(DHCPSocket) < 250u)
00383             {
00384                 // MODIFIX: Added the if else block for supporting Auto IP.
00385                 DWORD tmp =  DHCP_TIMEOUT2;
00386                 if (DHCPDiscRetry != 5)
00387                     tmp = DHCP_TIMEOUT;
00388
00389                 // Go back and transmit a new discovery if we didn't get an offer after 2 seconds
00390                 if (TickGet() - eventTime >= tmp)
00391                 {
00392                     // MODIFIX: Changed from SM_DHCP_SEND_DISCOVERY to AUTOIP
00393                     smDHCPState = SM_DHCP_AUTOIP;
00394
00395                     // MODIFIX: Added the if else block for supporting Auto IP.
00396                     if (DHCPDiscRetry != 5)
00397                         DHCPDiscRetry++;
00398                 }
00399                 break;
00400             }
00401
00402             // Let the DHCP server module know that there is a DHCP server
00403             // on this network
00404             DHCPFlags.bits.bDHCPServerDetected = TRUE;
00405
00406             // Check to see if we received an offer
00407             if(_DHCPReceive() != DHCP_OFFER_MESSAGE)
00408                 break;
00409
00410             smDHCPState = SM_DHCP_SEND_REQUEST;
00411             // No break
00412
00413         case SM_DHCP_SEND_REQUEST:
00414             if(UDPIsPutReady(DHCPSocket) < 258u)
00415                 break;
00416
00417             // Send the DHCP request message
00418             _DHCPSend(DHCP_REQUEST_MESSAGE, FALSE);
00419
00420             // Start a timer and begin looking for a response
00421             eventTime = TickGet();
00422             smDHCPState = SM_DHCP_GET_REQUEST_ACK;
00423             break;
00424
00425         case SM_DHCP_GET_REQUEST_ACK:
00426             // Check to see if a packet has arrived
00427             if(UDPIsGetReady(DHCPSocket) < 250u)
00428             {
00429                 // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
00430                 if(TickGet() - eventTime >= DHCP_TIMEOUT)
00431                     smDHCPState = SM_DHCP_AUTOIP;
00432                 break;
00433             }
00434
00435             // Check to see if we received an offer
00436             switch(_DHCPReceive())
00437             {
00438                 case DHCP_ACK_MESSAGE:
00439                     UDPClose(DHCPSocket);
00440                     DHCPSocket = INVALID_UDP_SOCKET;
00441                     eventTime = TickGet();
00442                     smDHCPState = SM_DHCP_BOUND;
00443
00444                     DHCPFlags.bits.bIsBound = TRUE;
00445                     DHCPBindCount++;
00446                     if(ValidValues.bits.IPAddress)
00447                         // MODIFIX: Use eWicht struct sIPConfig
00448                         sIPConfig.MyIPAddr = tempIPAddress;
00449                     if(ValidValues.bits.Mask)
00450                         // MODIFIX: Use eWicht struct sIPConfig
00451                         sIPConfig.MyMask = tempMask;
00452                     if(ValidValues.bits.Gateway)
00453                         // MODIFIX: Use eWicht struct sIPConfig
00454                         sIPConfig.MyGateway = tempGateway;
00455                     #if defined(STACK_USE_DNS)
00456                         if(ValidValues.bits.DNS)
00457                             // MODIFIX: Use eWicht struct sIPConfig
00458                             sIPConfig.PrimaryDNSServer = tempDNS;
00459                         if(ValidValues.bits.DNS2)
00460                             // MODIFIX: Use eWicht struct sIPConfig
00461                             sIPConfig.SecondaryDNSServer = tempDNS2;
00462                     #endif
00463 //                  if(ValidValues.bits.HostName)
00464 //                      memcpy(AppConfig.NetBIOSName, (void*)tempHostName, sizeof(AppConfig.NetBIOSName));
00465
00466                     break;
00467
00468                 case DHCP_NAK_MESSAGE:
00469                     // MODIFIX Changed state from SEND_DISCOVERY to AUTOIP:
00470                     smDHCPState = SM_DHCP_AUTOIP;
00471                     break;
00472             }
00473             break;
00474
00475         case SM_DHCP_BOUND:
00476             if(TickGet() - eventTime < TICK_SECOND)
00477                 break;
00478
00479             // Check to see if our lease is still valid, if so, decrement lease
00480             // time
00481             if(DHCPLeaseTime.Val >= 2ul)
00482             {
00483                 eventTime += TICK_SECOND;
00484                 DHCPLeaseTime.Val--;
00485                 break;
00486             }
00487
00488             // Open a socket to send and receive DHCP messages on
00489             DHCPSocket = UDPOpen(DHCP_CLIENT_PORT, NULL, DHCP_SERVER_PORT);
00490             if(DHCPSocket == INVALID_UDP_SOCKET)
00491                 break;
00492
00493             smDHCPState = SM_DHCP_SEND_RENEW;
00494             // No break
00495
00496         case SM_DHCP_SEND_RENEW:
00497         case SM_DHCP_SEND_RENEW2:
00498         case SM_DHCP_SEND_RENEW3:
00499             if(UDPIsPutReady(DHCPSocket) < 258u)
00500                 break;
00501
00502             // Send the DHCP request message
00503             _DHCPSend(DHCP_REQUEST_MESSAGE, TRUE);
00504             DHCPFlags.bits.bOfferReceived = FALSE;
00505
00506             // Start a timer and begin looking for a response
00507             eventTime = TickGet();
00508             smDHCPState++;
00509             break;
00510
00511         case SM_DHCP_GET_RENEW_ACK:
00512         case SM_DHCP_GET_RENEW_ACK2:
00513         case SM_DHCP_GET_RENEW_ACK3:
00514             // Check to see if a packet has arrived
00515             if(UDPIsGetReady(DHCPSocket) < 250u)
00516             {
00517                 // Go back and transmit a new discovery if we didn't get an ACK after 2 seconds
00518                 if(TickGet() - eventTime >=  DHCP_TIMEOUT)
00519                 {
00520                     // MODIFIX: Changed the new state from SEND_DISCOVERY to
00521                     // AUTOIP:
00522                     if(++smDHCPState > SM_DHCP_GET_RENEW_ACK3)
00523                         smDHCPState = SM_DHCP_AUTOIP;
00524                 }
00525                 break;
00526             }
00527
00528             // Check to see if we received an offer
00529             switch(_DHCPReceive())
00530             {
00531                 case DHCP_ACK_MESSAGE:
00532                     UDPClose(DHCPSocket);
00533                     DHCPSocket = INVALID_UDP_SOCKET;
00534                     eventTime = TickGet();
00535                     DHCPBindCount++;
00536                     smDHCPState = SM_DHCP_BOUND;
00537                     break;
00538
00539                 case DHCP_NAK_MESSAGE:
00540                     // MODIFIX: Changed from SM_DHCP_SEND_DISCOVERY to AUTOIP.
00541                     smDHCPState = SM_DHCP_AUTOIP;
00542                     break;
00543             }
00544             break;
00545
00546         // Handle SM_DHCP_DISABLED state by doing nothing.  Default case needed
00547         // to supress compiler diagnostic.
00548         default:
00549             break;
00550     }
00551 }
00552
00553
00554 /*****************************************************************************
00555   Function:
00556     void _DHCPReceive(void)
00557
00558   Description:
00559     Receives and parses a DHCP message.
00560
00561   Precondition:
00562     A DHCP message is waiting in the UDP buffer.
00563
00564   Parameters:
00565     None
00566
00567   Returns:
00568     One of the DCHP_TYPE* contants.
00569   ***************************************************************************/
00570 static BYTE _DHCPReceive(void)
00571 {
00572     /*********************************************************************
00573             DHCP PACKET FORMAT AS PER RFC 1541
00574
00575        0                   1                   2                   3
00576        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
00577        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00578        |     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
00579        +---------------+---------------+---------------+---------------+
00580        |                            xid (4)                            |
00581        +-------------------------------+-------------------------------+
00582        |           secs (2)            |           flags (2)           |
00583        +-------------------------------+-------------------------------+
00584        |                          ciaddr  (4)                          |
00585        +---------------------------------------------------------------+
00586        |                          yiaddr  (4)                          |
00587        +---------------------------------------------------------------+
00588        |                          siaddr  (4)                          |
00589        +---------------------------------------------------------------+
00590        |                          giaddr  (4)                          |
00591        +---------------------------------------------------------------+
00592        |                                                               |
00593        |                          chaddr  (16)                         |
00594        |                                                               |
00595        |                                                               |
00596        +---------------------------------------------------------------+
00597        |                                                               |
00598        |                          sname   (64)                         |
00599        +---------------------------------------------------------------+
00600        |                                                               |
00601        |                          file    (128)                        |
00602        +---------------------------------------------------------------+
00603        |                                                               |
00604        |                          options (312)                        |
00605        +---------------------------------------------------------------+
00606
00607      ********************************************************************/
00608     BYTE v;
00609     BYTE i, j;
00610     BYTE type;
00611     BOOL lbDone;
00612     DWORD_VAL tempServerID;
00613
00614
00615     // Assume unknown message until proven otherwise.
00616     type = DHCP_UNKNOWN_MESSAGE;
00617
00618     UDPGet(&v);                             // op
00619
00620     // Make sure this is BOOT_REPLY.
00621     if ( v == BOOT_REPLY )
00622     {
00623         // Discard htype, hlen, hops, xid, secs, flags, ciaddr.
00624         for ( i = 0; i < 15u; i++ )
00625             UDPGet(&v);
00626
00627         // Check to see if this is the first offer
00628         if(DHCPFlags.bits.bOfferReceived)
00629         {
00630             // Discard offered IP address, we already have an offer
00631             for ( i = 0; i < 4u; i++ )
00632                 UDPGet(&v);
00633         }
00634         else
00635         {
00636             // Save offered IP address until we know for sure that we have it.
00637             UDPGetArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
00638             ValidValues.bits.IPAddress = 1;
00639         }
00640
00641         // Ignore siaddr, giaddr
00642         for ( i = 0; i < 8u; i++ )
00643             UDPGet(&v);
00644
00645         // Check to see if chaddr (Client Hardware Address) belongs to us.
00646         for ( i = 0; i < 6u; i++ )
00647         {
00648             UDPGet(&v);
00649             // MODIFIX: eWicht MAC address is stored in flash.
00650             if ( v != pu8MAC[i])
00651                 goto UDPInvalid;
00652         }
00653
00654
00655         // Ignore part of chaddr, sname, file, magic cookie.
00656         for ( i = 0; i < 206u; i++ )
00657             UDPGet(&v);
00658
00659         lbDone = FALSE;
00660         do
00661         {
00662             // Get the Option number
00663             // Break out eventually in case if this is a malformed
00664             // DHCP message, ie: missing DHCP_END_OPTION marker
00665             if(!UDPGet(&v))
00666             {
00667                 lbDone = TRUE;
00668                 break;
00669             }
00670
00671             switch(v)
00672             {
00673             case DHCP_MESSAGE_TYPE:
00674                 UDPGet(&v);                         // Skip len
00675                 // Len must be 1.
00676                 if ( v == 1u )
00677                 {
00678                     UDPGet(&type);                  // Get type
00679
00680                     // Throw away the packet if we know we don't need it (ie: another offer when we already have one)
00681                     if(DHCPFlags.bits.bOfferReceived && (type == DHCP_OFFER_MESSAGE))
00682                     {
00683                         goto UDPInvalid;
00684                     }
00685                 }
00686                 else
00687                     goto UDPInvalid;
00688                 break;
00689
00690             case DHCP_SUBNET_MASK:
00691                 UDPGet(&v);                     // Skip len
00692                 // Len must be 4.
00693                 if ( v == 4u )
00694                 {
00695                     // Check to see if this is the first offer
00696                     if(DHCPFlags.bits.bOfferReceived)
00697                     {
00698                         // Discard offered IP mask, we already have an offer
00699                         for ( i = 0; i < 4u; i++ )
00700                             UDPGet(&v);
00701                     }
00702                     else
00703                     {
00704                         UDPGetArray((BYTE*)&tempMask, sizeof(tempMask));
00705                         ValidValues.bits.Mask = 1;
00706                     }
00707                 }
00708                 else
00709                     goto UDPInvalid;
00710                 break;
00711
00712             case DHCP_ROUTER:
00713                 UDPGet(&j);
00714                 // Len must be >= 4.
00715                 if ( j >= 4u )
00716                 {
00717                     // Check to see if this is the first offer
00718                     if(DHCPFlags.bits.bOfferReceived)
00719                     {
00720                         // Discard offered Gateway address, we already have an offer
00721                         for ( i = 0; i < 4u; i++ )
00722                             UDPGet(&v);
00723                     }
00724                     else
00725                     {
00726                         UDPGetArray((BYTE*)&tempGateway, sizeof(tempGateway));
00727                         ValidValues.bits.Gateway = 1;
00728                     }
00729                 }
00730                 else
00731                     goto UDPInvalid;
00732
00733                 // Discard any other router addresses.
00734                 j -= 4;
00735                 while(j--)
00736                     UDPGet(&v);
00737                 break;
00738
00739 #if defined(STACK_USE_DNS)
00740             case DHCP_DNS:
00741                 UDPGet(&j);
00742                 // Len must be >= 4.
00743                 if(j < 4u)
00744                     goto UDPInvalid;
00745
00746                 // Check to see if this is the first offer
00747                 if(!DHCPFlags.bits.bOfferReceived)
00748                 {
00749                     UDPGetArray((BYTE*)&tempDNS, sizeof(tempDNS));
00750                     ValidValues.bits.DNS = 1;
00751                     j -= 4;
00752                 }
00753
00754                 // Len must be >= 4 for a secondary DNS server address
00755                 if(j >= 4u)
00756                 {
00757                     // Check to see if this is the first offer
00758                     if(!DHCPFlags.bits.bOfferReceived)
00759                     {
00760                         UDPGetArray((BYTE*)&tempDNS2, sizeof(tempDNS2));
00761                         ValidValues.bits.DNS2 = 1;
00762                         j -= 4;
00763                     }
00764                 }
00765
00766                 // Discard any other DNS server addresses
00767                 while(j--)
00768                     UDPGet(&v);
00769                 break;
00770 #endif
00771
00772 //            case DHCP_HOST_NAME:
00773 //                UDPGet(&j);
00774 //                // Len must be >= 4.
00775 //                if(j < 1u)
00776 //                  goto UDPInvalid;
00777 //
00778 //              // Check to see if this is the first offer
00779 //              if(DHCPFlags.bits.bOfferReceived)
00780 //              {
00781 //                  // Discard offered host name, we already have an offer
00782 //                  while(j--)
00783 //                      UDPGet(&v);
00784 //              }
00785 //              else
00786 //              {
00787 //                  for(i = 0; j, i < sizeof(tempHostName); i++, j--)
00788 //                  {
00789 //                      UDPGet(&tempHostName[i]);
00790 //                  }
00791 //                  while(j--)
00792 //                  {
00793 //                      UDPGet(&v);
00794 //                  }
00795 //                  ValidValues.bits.HostName = 1;
00796 //              }
00797 //
00798 //                break;
00799
00800             case DHCP_SERVER_IDENTIFIER:
00801                 UDPGet(&v);                         // Get len
00802                 // Len must be 4.
00803                 if ( v == 4u )
00804                 {
00805                     UDPGet(&tempServerID.v[3]);   // Get the id
00806                     UDPGet(&tempServerID.v[2]);
00807                     UDPGet(&tempServerID.v[1]);
00808                     UDPGet(&tempServerID.v[0]);
00809                 }
00810                 else
00811                     goto UDPInvalid;
00812                 break;
00813
00814             case DHCP_END_OPTION:
00815                 lbDone = TRUE;
00816                 break;
00817
00818             case DHCP_IP_LEASE_TIME:
00819                 UDPGet(&v);                         // Get len
00820                 // Len must be 4.
00821                 if ( v == 4u )
00822                 {
00823                     // Check to see if this is the first offer
00824                     if(DHCPFlags.bits.bOfferReceived)
00825                     {
00826                         // Discard offered lease time, we already have an offer
00827                         for ( i = 0; i < 4u; i++ )
00828                             UDPGet(&v);
00829                     }
00830                     else
00831                     {
00832                         UDPGet(&DHCPLeaseTime.v[3]);
00833                         UDPGet(&DHCPLeaseTime.v[2]);
00834                         UDPGet(&DHCPLeaseTime.v[1]);
00835                         UDPGet(&DHCPLeaseTime.v[0]);
00836
00837                         // In case if our clock is not as accurate as the remote
00838                         // DHCP server's clock, let's treat the lease time as only
00839                         // 96.875% of the value given
00840                         DHCPLeaseTime.Val -= DHCPLeaseTime.Val>>5;
00841                     }
00842                 }
00843                 else
00844                     goto UDPInvalid;
00845                 break;
00846
00847             default:
00848                 // Ignore all unsupport tags.
00849                 UDPGet(&j);                     // Get option len
00850                 while( j-- )                    // Ignore option values
00851                     UDPGet(&v);
00852             }
00853         } while( !lbDone );
00854     }
00855
00856     // If this is an OFFER message, remember current server id.
00857     if ( type == DHCP_OFFER_MESSAGE )
00858     {
00859         DHCPServerID.Val = tempServerID.Val;
00860         DHCPFlags.bits.bOfferReceived = TRUE;
00861     }
00862     else
00863     {
00864         // For other types of messages, make sure that received
00865         // server id matches with our previous one.
00866         if ( DHCPServerID.Val != tempServerID.Val )
00867             type = DHCP_UNKNOWN_MESSAGE;
00868     }
00869
00870     UDPDiscard();                             // We are done with this packet
00871     return type;
00872
00873 UDPInvalid:
00874     UDPDiscard();
00875     return DHCP_UNKNOWN_MESSAGE;
00876
00877 }
00878
00879
00880
00881 /*****************************************************************************
00882   Function:
00883     static void _DHCPSend(BYTE messageType, BOOL bRenewing)
00884
00885   Description:
00886     Sends a DHCP message.
00887
00888   Precondition:
00889     UDP is ready to write a DHCP packet.
00890
00891   Parameters:
00892     messageType - One of the DHCP_TYPE constants
00893     bRenewing - Whether or not this is a renewal request
00894
00895   Returns:
00896     None
00897   ***************************************************************************/
00898 static void _DHCPSend(BYTE messageType, BOOL bRenewing)
00899 {
00900     BYTE i;
00901     IP_ADDR MyIP;
00902
00903
00904     UDPPut(BOOT_REQUEST);                       // op
00905     UDPPut(BOOT_HW_TYPE);                       // htype
00906     UDPPut(BOOT_LEN_OF_HW_TYPE);                // hlen
00907     UDPPut(0);                                  // hops
00908     UDPPut(0x12);                               // xid[0]
00909     UDPPut(0x23);                               // xid[1]
00910     UDPPut(0x34);                               // xid[2]
00911     UDPPut(0x56);                               // xid[3]
00912     UDPPut(0);                                  // secs[0]
00913     UDPPut(0);                                  // secs[1]
00914     UDPPut(0x80);                               // flags[0] with BF set
00915     UDPPut(0);                                  // flags[1]
00916
00917     // If this is DHCP REQUEST message, use previously allocated IP address.
00918     if((messageType == DHCP_REQUEST_MESSAGE) && bRenewing)
00919     {
00920         UDPPutArray((BYTE*)&tempIPAddress, sizeof(tempIPAddress));
00921     }
00922     else
00923     {
00924         UDPPut(0x00);
00925         UDPPut(0x00);
00926         UDPPut(0x00);
00927         UDPPut(0x00);
00928     }
00929
00930     // Set yiaddr, siaddr, giaddr as zeros,
00931     for ( i = 0; i < 12u; i++ )
00932         UDPPut(0x00);
00933
00934     // Load chaddr - Client hardware address.
00935     // MODIFIX: eWicht MAC address is located in flash.
00936     UDPPutROMArray( ( ROM BYTE *) pu8MAC, sizeof( MAC_ADDR ) );
00937
00938     // Set chaddr[6..15], sname and file as zeros.
00939     for ( i = 0; i < 202u; i++ )
00940         UDPPut(0);
00941
00942     // Load magic cookie as per RFC 1533.
00943     UDPPut(99);
00944     UDPPut(130);
00945     UDPPut(83);
00946     UDPPut(99);
00947
00948     // Load message type.
00949     UDPPut(DHCP_MESSAGE_TYPE);
00950     UDPPut(DHCP_MESSAGE_TYPE_LEN);
00951     UDPPut(messageType);
00952
00953     if(messageType == DHCP_DISCOVER_MESSAGE)
00954     {
00955         // Reset offered flag so we know to act upon the next valid offer
00956         DHCPFlags.bits.bOfferReceived = FALSE;
00957     }
00958
00959
00960     if((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing)
00961     {
00962          // DHCP REQUEST message must include server identifier the first time
00963          // to identify the server we are talking to.
00964          // _DHCPReceive() would populate "serverID" when it
00965          // receives DHCP OFFER message. We will simply use that
00966          // when we are replying to server.
00967          // If this is a renwal request, we must not include server id.
00968          UDPPut(DHCP_SERVER_IDENTIFIER);
00969          UDPPut(DHCP_SERVER_IDENTIFIER_LEN);
00970          UDPPut(DHCPServerID.v[3]);
00971          UDPPut(DHCPServerID.v[2]);
00972          UDPPut(DHCPServerID.v[1]);
00973          UDPPut(DHCPServerID.v[0]);
00974      }
00975
00976     // Load our interested parameters
00977     // This is hardcoded list.  If any new parameters are desired,
00978     // new lines must be added here.
00979     UDPPut(DHCP_PARAM_REQUEST_LIST);
00980     UDPPut(DHCP_PARAM_REQUEST_LIST_LEN);
00981     UDPPut(DHCP_SUBNET_MASK);
00982     UDPPut(DHCP_ROUTER);
00983     UDPPut(DHCP_DNS);
00984     UDPPut(DHCP_HOST_NAME);
00985
00986      // Add requested IP address to DHCP Request Message
00987     if( ((messageType == DHCP_REQUEST_MESSAGE) && !bRenewing) ||
00988         ((messageType == DHCP_DISCOVER_MESSAGE) && tempIPAddress.Val))
00989     {
00990         UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS);
00991         UDPPut(DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
00992         UDPPutArray((BYTE*)&tempIPAddress, DHCP_PARAM_REQUEST_IP_ADDRESS_LEN);
00993     }
00994
00995     // Add any new paramter request here.
00996
00997     // End of Options.
00998     UDPPut(DHCP_END_OPTION);
00999
01000     // Add zero padding to ensure compatibility with old BOOTP relays that discard small packets (<300 UDP octets)
01001     while(UDPTxCount < 300u)
01002         UDPPut(0);
01003
01004     // Make sure we advertise a 0.0.0.0 IP address so all DHCP servers will respond.  If we have a static IP outside the DHCP server's scope, it may simply ignore discover messages.
01005     // MODIFIX: Use eWicht struct sIPConfig (3 times)
01006     MyIP.Val = sIPConfig.MyIPAddr.Val;
01007     if(!bRenewing)
01008         sIPConfig.MyIPAddr.Val = 0x00000000;
01009     UDPFlush();
01010     sIPConfig.MyIPAddr.Val = MyIP.Val;
01011 }
01012
01013
01014 /*********************************************************************
01015  * Function:        IP_ADDR GenerateAutoIP( IP_ADDR * lastIP )
01016  ********************************************************************/
01017 IP_ADDR GenerateAutoIP( IP_ADDR * lastIP )
01018 {
01019     IP_ADDR newIP;
01020     newIP.v[0] = 169;
01021     newIP.v[1] = 254;
01022
01023     if ( lastIP == 0 )
01024     {
01025         newIP.v[2] = pu8MAC[4];
01026         newIP.v[3] = pu8MAC[5];
01027     }
01028     else
01029         newIP.w[1] = lastIP->w[1] + TickGet();
01030
01031     while ( newIP.w[1] < 256 || newIP.w[1] > 65279 )
01032         newIP.w[1] += TickGet();
01033
01034     return newIP;
01035 }
01036
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: DHCP.h Source File

DHCP.h

Go to the documentation of this file.
00001
00002
00003
00035 /*********************************************************************
00036  * Software License Agreement
00037  *
00038  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00039  * reserved.
00040  *
00041  * Microchip licenses to you the right to use, modify, copy, and
00042  * distribute:
00043  * (i)  the Software when embedded on a Microchip microcontroller or
00044  *      digital signal controller product ("Device") which is
00045  *      integrated into Licensee's product; or
00046  * (ii) ONLY the Software driver source files ENC28J60.c and
00047  *      ENC28J60.h ported to a non-Microchip device used in
00048  *      conjunction with a Microchip ethernet controller for the
00049  *      sole purpose of interfacing with the ethernet controller.
00050  *
00051  * You should refer to the license agreement accompanying this
00052  * Software for additional information regarding your rights and
00053  * obligations.
00054  *
00055  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00056  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00057  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00058  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00059  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00060  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00061  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00062  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00063  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00064  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00065  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00066  *
00067  *
00068  * Author               Date    Comment
00069  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00070  * Nilesh Rajbharti     3/21/01  Original        (Rev 1.0)
00071  ********************************************************************/
00072 #ifndef __DHCP_H
00073 #define __DHCP_H
00074
00075 // UDP client port for DHCP Client transactions
00076 #define DHCP_CLIENT_PORT                (68u)
00077 // UDP listening port for DHCP Server messages
00078 #define DHCP_SERVER_PORT                (67u)
00079
00080 #define BOOT_REQUEST                    (1u)    // BOOT_REQUEST DHCP type
00081 #define BOOT_REPLY                      (2u)    // BOOT_REPLY DHCP type
00082 #define BOOT_HW_TYPE                    (1u)    // BOOT_HW_TYPE DHCP type
00083 #define BOOT_LEN_OF_HW_TYPE             (6u)    // BOOT_LEN_OF_HW_TYPE DHCP type
00084
00085 #define DHCP_MESSAGE_TYPE               (53u)   // DHCP Message Type constant
00086 #define DHCP_MESSAGE_TYPE_LEN           (1u)    // Length of DHCP Message Type
00087
00088 #define DHCP_UNKNOWN_MESSAGE            (0u)    // Code for unknown DHCP message
00089
00090 #define DHCP_DISCOVER_MESSAGE           (1u)    // DCHP Discover Message
00091 #define DHCP_OFFER_MESSAGE              (2u)    // DHCP Offer Message
00092 #define DHCP_REQUEST_MESSAGE            (3u)    // DHCP Request message
00093 #define DHCP_DECLINE_MESSAGE            (4u)    // DHCP Decline Message
00094 #define DHCP_ACK_MESSAGE                (5u)    // DHCP ACK Message
00095 #define DHCP_NAK_MESSAGE                (6u)    // DHCP NAK Message
00096 #define DHCP_RELEASE_MESSAGE            (7u)    // DCHP Release message
00097
00098 #define DHCP_SERVER_IDENTIFIER          (54u)   // DHCP Server Identifier
00099 #define DHCP_SERVER_IDENTIFIER_LEN      (4u)    // DHCP Server Identifier length
00100
00101 #define DHCP_OPTION_ACK_MESSAGE         (53u)   // DHCP_OPTION_ACK_MESSAGE Type
00102 #define DHCP_PARAM_REQUEST_LIST         (55u)   // DHCP_PARAM_REQUEST_LIST Type
00103 #define DHCP_PARAM_REQUEST_LIST_LEN     (4u)    // DHCP_PARAM_REQUEST_LIST_LEN Type
00104 #define DHCP_PARAM_REQUEST_IP_ADDRESS       (50u)   // DHCP_PARAM_REQUEST_IP_ADDRESS Type
00105 #define DHCP_PARAM_REQUEST_IP_ADDRESS_LEN   (4u)    // DHCP_PARAM_REQUEST_IP_ADDRESS_LEN Type
00106 #define DHCP_SUBNET_MASK                (1u)    // DHCP_SUBNET_MASK Type
00107 #define DHCP_ROUTER                     (3u)    // DHCP_ROUTER Type
00108 #define DHCP_DNS                        (6u)    // DHCP_DNS Type
00109 #define DHCP_HOST_NAME                  (12u)   // DHCP_HOST_NAME Type
00110 #define DHCP_IP_LEASE_TIME              (51u)   // DHCP_IP_LEASE_TIME Type
00111 #define DHCP_END_OPTION                 (255u)  // DHCP_END_OPTION Type
00112
00113 // DHCP or BOOTP Header structure
00114 typedef struct __attribute__((aligned(2), packed))
00115 {
00116     BYTE        MessageType;    // Message type for this message
00117     BYTE        HardwareType;   // Hardware type for this message
00118     BYTE        HardwareLen;    // Length of hardware type
00119     BYTE        Hops;           // Number of hops
00120     DWORD       TransactionID;  // DHCP Transaction ID
00121     WORD        SecondsElapsed; // Number of elapsed seconds
00122     WORD        BootpFlags;     // BOOTP Flags
00123     IP_ADDR     ClientIP;       // Client IP
00124     IP_ADDR     YourIP;         // Your IP
00125     IP_ADDR     NextServerIP;   // Next Server IP
00126     IP_ADDR     RelayAgentIP;   // Relay Agent IP
00127     MAC_ADDR    ClientMAC;      // Client MAC Address
00128 } BOOTP_HEADER;
00129
00130 // DHCP State Machine
00131 typedef enum _SM_DHCP
00132 {
00133     SM_DHCP_DISABLED = 0,       // DHCP is not currently enabled
00134     SM_DHCP_GET_SOCKET,         // DHCP is trying to obtain a socket
00135     SM_DHCP_AUTOIP,             // MODIFIX: DHCP checks for a Auto IP
00136     SM_DHCP_SEND_DISCOVERY,     // DHCP is sending a DHCP Discover message
00137     SM_DHCP_GET_OFFER,          // DHCP is waiting for a DHCP Offer
00138     SM_DHCP_SEND_REQUEST,       // DHCP is sending a DHCP Send Reequest message
00139     SM_DHCP_GET_REQUEST_ACK,    // DCHP is waiting for a Request ACK message
00140     SM_DHCP_BOUND,              // DHCP is bound
00141     SM_DHCP_SEND_RENEW,         // DHCP is sending a DHCP renew message (first try)
00142     SM_DHCP_GET_RENEW_ACK,      // DHCP is waiting for a renew ACK
00143     SM_DHCP_SEND_RENEW2,        // DHCP is sending a DHCP renew message (second try)
00144     SM_DHCP_GET_RENEW_ACK2,     // DHCP is waiting for a renew ACK
00145     SM_DHCP_SEND_RENEW3,        // DHCP is sending a DHCP renew message (third try)
00146     SM_DHCP_GET_RENEW_ACK3      // DHCP is waiting for a renew ACK
00147 } SM_DHCP;
00148
00149
00150 // Flags for the DHCP client
00151 typedef union _DHCP_CLIENT_FLAGS
00152 {
00153     struct
00154     {
00155         unsigned char bIsBound : 1;             // Whether or not DHCP is currently bound
00156         unsigned char bOfferReceived : 1;       // Whether or not an offer has been received
00157         unsigned char bDHCPServerDetected : 1;  // Indicates if a DCHP server has been detected
00158     } bits;
00159     BYTE Val;
00160 } DHCP_CLIENT_FLAGS;
00161
00163 #if !defined(__DHCP_C)
00164     extern DHCP_CLIENT_FLAGS DHCPFlags;
00165     extern SM_DHCP smDHCPState;
00166     extern BYTE DHCPBindCount;
00167 #endif
00168
00170
00186 void DHCPReset( BOOL bNoAutoIP );
00187
00188
00190
00208 void DHCPTask(void);
00209
00210
00211 // MODIFIX: ServerTask is not needed for eWicht: void DHCPServerTask(void);
00212
00214
00234 void DHCPDisable(void);
00235
00236
00238
00250 void DHCPEnable(void);
00251
00252
00254
00265 IP_ADDR GenerateAutoIP( IP_ADDR * lastIP );
00266
00267
00269
00279 #define DHCPIsBound()       (DHCPFlags.bits.bIsBound)
00280
00281 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: ETH97J60.c Source File

ETH97J60.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00031 /*********************************************************************
00032  * Software License Agreement
00033  *
00034  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00035  * reserved.
00036  *
00037  * Microchip licenses to you the right to use, modify, copy, and
00038  * distribute:
00039  * (i)  the Software when embedded on a Microchip microcontroller or
00040  *      digital signal controller product ("Device") which is
00041  *      integrated into Licensee's product; or
00042  * (ii) ONLY the Software driver source files ENC28J60.c and
00043  *      ENC28J60.h ported to a non-Microchip device used in
00044  *      conjunction with a Microchip ethernet controller for the
00045  *      sole purpose of interfacing with the ethernet controller.
00046  *
00047  * You should refer to the license agreement accompanying this
00048  * Software for additional information regarding your rights and
00049  * obligations.
00050  *
00051  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00052  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00053  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00054  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00055  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00056  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00057  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00058  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00059  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00060  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00061  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00062  *
00063  *
00064 /*********************************************************************
00065  * Author               Date     Comment
00066  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00067  * Rawin Rojvanit       07/26/05 Stuff
00068  * Howard Schlunder     11/17/05 Ported to PIC18F97J60
00069  * Howard Schlunder     06/16/06 Synchronized with ENC28J60 code
00070  * Howard Schlunder     05/21/07 Fixed a TX lockup problem
00071 ********************************************************************/
00072 #define __ETH97J60_C
00073
00074 #include "TCPIP.h"
00075
00076 // MODIFIX: Removed the macro request for the ethernet transceiver.
00077
00078
00080 // Since the Ethernet PHY doesn't support auto-negotiation, full-duplex mode is
00081 // not compatible with most switches/routers.  If a dedicated network is used
00082 // where the duplex of the remote node can be manually configured, you may
00083 // change this configuration.  Otherwise, half duplex should always be used.
00084 #define HALF_DUPLEX
00085 //#define FULL_DUPLEX
00086
00087 // Pseudo Functions
00088 #define LOW(a)                  (a & 0xFF)
00089 #define HIGH(a)                 ((a>>8) & 0xFF)
00090
00091 #define ETHER_IP    (0x00u)
00092 #define ETHER_ARP   (0x06u)
00093
00094 // A header appended at the start of all RX frames by the hardware
00095 typedef struct _ENC_PREAMBLE
00096 {
00097     WORD            NextPacketPointer;
00098     RXSTATUS        StatusVector;
00099
00100     MAC_ADDR        DestMACAddr;
00101     MAC_ADDR        SourceMACAddr;
00102     WORD_VAL        Type;
00103 } ENC_PREAMBLE;
00104
00105
00106 // Internal MAC level variables and flags.
00107 static WORD_VAL NextPacketLocation;
00108 static WORD_VAL CurrentPacketLocation;
00109 static BOOL WasDiscarded;
00110 static WORD wTXWatchdog;
00111
00112
00113 /******************************************************************************
00114  * Function:        void MACInit(void)
00115  *
00116  * PreCondition:    None
00117  *
00118  * Input:           None
00119  *
00120  * Output:          None
00121  *
00122  * Side Effects:    None
00123  *
00124  * Overview:        MACInit enables the Ethernet module, waits for the
00125  *                  to become ready, and programs all registers for future
00126  *                  TX/RX operations.
00127  *
00128  * Note:            This function blocks for at least 1ms, waiting for the
00129  *                  hardware to stabilize.
00130  *****************************************************************************/
00131 void MACInit(void)
00132 {
00133     BYTE i;
00134
00135     LATAbits.LATA0 = 0;
00136     LATAbits.LATA1 = 0;
00137
00138     TRISAbits.TRISA0 = 0;   // Set LED0 as output
00139     TRISAbits.TRISA1 = 0;   // Set LED1 as output
00140     ECON2bits.ETHEN = 1;    // Enable Ethernet!
00141
00142     // Wait for PHYRDY to become set.
00143     while(!ESTATbits.PHYRDY);
00144
00145     // Configure the receive buffer boundary pointers
00146     // and the buffer write protect pointer (receive buffer read pointer)
00147     WasDiscarded = TRUE;
00148     NextPacketLocation.Val = RXSTART;
00149     ERXST = RXSTART;
00150     ERXRDPTL = LOW(RXSTOP); // Write low byte first
00151     ERXRDPTH = HIGH(RXSTOP);// Write high byte last
00152     ERXND = RXSTOP;
00153     ETXST = TXSTART;
00154
00155     // Write a permanant per packet control byte of 0x00
00156     EWRPT = TXSTART;
00157     MACPut(0x00);
00158
00159     // Configure Receive Filters
00160     // (No need to reconfigure - Unicast OR Broadcast with CRC checking is
00161     // acceptable)
00162     //ERXFCON = ERXFCON_CRCEN;     // Promiscious mode
00163     ERXFCON = 0xA3;             // MODIFIX: Enable Multicasts
00164
00165     // Configure the MAC
00166     // Enable the receive portion of the MAC
00167     MACON1 = MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN; Nop();
00168
00169     // Pad packets to 60 bytes, add CRC, and check Type/Length field.
00170 #if defined(FULL_DUPLEX)
00171     MACON3 = MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX; Nop();
00172     MABBIPG = 0x15; Nop();
00173 #else
00174     MACON3 = MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN; Nop();
00175     MABBIPG = 0x12; Nop();
00176 #endif
00177
00178     // Allow infinite deferals if the medium is continuously busy
00179     // (do not time out a transmission if the half duplex medium is
00180     // completely saturated with other people's data)
00181     MACON4 = MACON4_DEFER; Nop();
00182
00183     // Set non-back-to-back inter-packet gap to 9.6us.  The back-to-back
00184     // inter-packet gap (MABBIPG) is set by MACSetDuplex() which is called
00185     // later.
00186     MAIPGL = 0x12; Nop();
00187     MAIPGH = 0x0C; Nop();
00188
00189     // Set the maximum packet size which the controller will accept
00190     MAMXFLL = LOW(6+6+2+1500+4); Nop();
00191     MAMXFLH = HIGH(6+6+2+1500+4); Nop();
00192
00193     // MODIFIX: Initialize physical MAC address registers from flash.
00194     MAADR1 = pu8MAC[0]; Nop();
00195     MAADR2 = pu8MAC[1]; Nop();
00196     MAADR3 = pu8MAC[2]; Nop();
00197     MAADR4 = pu8MAC[3]; Nop();
00198     MAADR5 = pu8MAC[4]; Nop();
00199     MAADR6 = pu8MAC[5]; Nop();
00200
00201     // Disable half duplex loopback in PHY and set RXAPDIS bit as per errata
00202     WritePHYReg(PHCON2, PHCON2_HDLDIS | PHCON2_RXAPDIS);
00203
00204     // Configure LEDA to display LINK status, LEDB to display TX/RX activity
00205     SetLEDConfig(0x3472);
00206
00207     // Set the PHY into the proper duplex state
00208 #if defined(FULL_DUPLEX)
00209     WritePHYReg(PHCON1, PHCON1_PDPXMD);
00210 #else
00211     WritePHYReg(PHCON1, 0x0000);
00212 #endif
00213
00214     // Enable packet reception
00215     ECON1bits.RXEN = 1;
00216 }//end MACInit
00217
00218
00219 /******************************************************************************
00220  * Function:        BOOL MACIsLinked(void)
00221  *
00222  * PreCondition:    None
00223  *
00224  * Input:           None
00225  *
00226  * Output:          TRUE: If the PHY reports that a link partner is present
00227  *                        and the link has been up continuously since the last
00228  *                        call to MACIsLinked()
00229  *                  FALSE: If the PHY reports no link partner, or the link went
00230  *                         down momentarily since the last call to MACIsLinked()
00231  *
00232  * Side Effects:    None
00233  *
00234  * Overview:        Returns the PHSTAT1.LLSTAT bit.
00235  *
00236  * Note:            None
00237  *****************************************************************************/
00238 /*BOOL MACIsLinked(void)
00239 {
00240     // LLSTAT is a latching low link status bit.  Therefore, if the link
00241     // goes down and comes back up before a higher level stack program calls
00242     // bMACIsLinked(), bMACIsLinked() will still return FALSE.  The next
00243     // call to MACIsLinked() will return TRUE (unless the link goes down
00244     // again).
00245     return ReadPHYReg(PHSTAT1).PHSTAT1bits.LLSTAT;
00246 }
00247 */
00248 BOOL MACIsLinked( void )
00249 {
00250     // MODIFIX: We simply check the link status LED, whether there is a link.
00252     return PORTAbits.RA0;
00253 }
00254
00255 /******************************************************************************
00256  * Function:        BOOL MACIsTxReady(void)
00257  *
00258  * PreCondition:    None
00259  *
00260  * Input:           None
00261  *
00262  * Output:          TRUE: If no Ethernet transmission is in progress
00263  *                  FALSE: If a previous transmission was started, and it has
00264  *                         not completed yet.  While FALSE, the data in the
00265  *                         transmit buffer and the TXST/TXND pointers must not
00266  *                         be changed.
00267  *
00268  * Side Effects:    None
00269  *
00270  * Overview:        Returns the ECON1.TXRTS bit
00271  *
00272  * Note:            None
00273  *****************************************************************************/
00274 BOOL MACIsTxReady(void)
00275 {
00276     if(!ECON1bits.TXRTS)
00277         return TRUE;
00278
00279     // Retry transmission if the current packet seems to be not completing
00280     // Wait 3ms before triggering the retry.
00281     if((WORD)TickGet() - wTXWatchdog >= (3ull*TICK_SECOND/1000ull))
00282     {
00283         ECON1bits.TXRTS = 0;
00284         MACFlush();
00285     }
00286
00287     return FALSE;
00288 }
00289
00290 /******************************************************************************
00291  * Function:        void MACDiscardRx(void)
00292  *
00293  * PreCondition:    None
00294  *
00295  * Input:           None
00296  *
00297  * Output:          None
00298  *
00299  * Side Effects:    None
00300  *
00301  * Overview:        Marks the last received packet (obtained using
00302  *                  MACGetHeader())as being processed and frees the buffer
00303  *                  memory associated with it
00304  *
00305  * Note:            Is is safe to call this function multiple times between
00306  *                  MACGetHeader() calls.  Extra packets won't be thrown away
00307  *                  until MACGetHeader() makes it available.
00308  *****************************************************************************/
00309 void MACDiscardRx(void)
00310 {
00311     WORD_VAL NewRXRDLocation;
00312
00313     // Make sure the current packet was not already discarded
00314     if(WasDiscarded)
00315         return;
00316     WasDiscarded = TRUE;
00317
00318     // Decrement the next packet pointer before writing it into
00319     // the ERXRDPT registers.  This is a silicon errata workaround.
00320     // RX buffer wrapping must be taken into account if the
00321     // NextPacketLocation is precisely RXSTART.
00322     NewRXRDLocation.Val = NextPacketLocation.Val - 1;
00323 #if RXSTART == 0
00324     if(NewRXRDLocation.Val > RXSTOP)
00325 #else
00326     if(NewRXRDLocation.Val < RXSTART || NewRXRDLocation.Val > RXSTOP)
00327 #endif
00328     {
00329         NewRXRDLocation.Val = RXSTOP;
00330     }
00331
00332     // Decrement the RX packet counter register, EPKTCNT
00333     ECON2bits.PKTDEC = 1;
00334
00335     // Move the receive read pointer to unwrite-protect the memory used by the
00336     // last packet.  The writing order is important: set the low byte first,
00337     // high byte last.
00338     ERXRDPTL = NewRXRDLocation.v[0];
00339     ERXRDPTH = NewRXRDLocation.v[1];
00340
00341     // The PKTIF flag should automatically be cleared by hardware, but
00342     // early beta silicon requires that you manually clear it.  This should be
00343     // unneeded for production A0 silicon and later.
00344     EIRbits.PKTIF = 0;
00345 }
00346
00347
00348 /******************************************************************************
00349  * Function:        WORD MACGetFreeRxSize(void)
00350  *
00351  * PreCondition:    None
00352  *
00353  * Input:           None
00354  *
00355  * Output:          A WORD estimate of how much RX buffer space is free at
00356  *                  the present time.
00357  *
00358  * Side Effects:    None
00359  *
00360  * Overview:        None
00361  *
00362  * Note:            None
00363  *****************************************************************************/
00364 WORD MACGetFreeRxSize(void)
00365 {
00366     WORD_VAL ReadPT, WritePT;
00367
00368     // Read the Ethernet hardware buffer write pointer.  Because packets can be
00369     // received at any time, it can change between reading the low and high
00370     // bytes.  A loop is necessary to make certain a proper low/high byte pair
00371     // is read.
00372     do {
00373         // Save EPKTCNT in a temporary location
00374         ReadPT.v[0] = EPKTCNT;
00375
00376         WritePT.Val = ERXWRPT;
00377     } while(EPKTCNT != ReadPT.v[0]);
00378
00379     // Determine where the write protection pointer is
00380     ReadPT.Val = ERXRDPT;
00381
00382
00383     // Calculate the difference between the pointers, taking care to account
00384     // for buffer wrapping conditions
00385     if(WritePT.Val > ReadPT.Val)
00386     {
00387         return (RXSTOP - RXSTART) - (WritePT.Val - ReadPT.Val);
00388     }
00389     else if(WritePT.Val == ReadPT.Val)
00390     {
00391         return RXSIZE - 1;
00392     }
00393     else
00394     {
00395         return ReadPT.Val - WritePT.Val - 1;
00396     }
00397 }
00398
00399 /******************************************************************************
00400  * Function:        BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
00401  *
00402  * PreCondition:    None
00403  *
00404  * Input:           *remote: Location to store the Source MAC address of the
00405  *                           received frame.
00406  *                  *type: Location of a BYTE to store the constant
00407  *                         MAC_UNKNOWN, ETHER_IP, or ETHER_ARP, representing
00408  *                         the contents of the Ethernet type field.
00409  *
00410  * Output:          TRUE: If a packet was waiting in the RX buffer.  The
00411  *                        remote, and type values are updated.
00412  *                  FALSE: If a packet was not pending.  remote and type are
00413  *                         not changed.
00414  *
00415  * Side Effects:    Last packet is discarded if MACDiscardRx() hasn't already
00416  *                  been called.
00417  *
00418  * Overview:        None
00419  *
00420  * Note:            None
00421  *****************************************************************************/
00422 BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
00423 {
00424     ENC_PREAMBLE header;
00425
00426     // Test if at least one packet has been received and is waiting
00427     if(EPKTCNT == 0u)
00428     {
00429         return FALSE;
00430     }
00431
00432     // Make absolutely certain that any previous packet was discarded
00433     if(WasDiscarded == FALSE)
00434     {
00435         MACDiscardRx();
00436         return FALSE;
00437     }
00438     // Save the location of this packet
00439     CurrentPacketLocation.Val = NextPacketLocation.Val;
00440
00441     // Set the read pointer to the beginning of the next unprocessed packet
00442     ERDPT = CurrentPacketLocation.Val;
00443
00444     // Obtain the MAC header from the Ethernet buffer
00445     MACGetArray((BYTE*)&header, sizeof(header));
00446
00447     // The EtherType field, like most items transmitted on the Ethernet medium
00448     // are in big endian.
00449     header.Type.Val = swaps(header.Type.Val);
00450
00451     // Do a sanity check.  There might be a bug in code someplace if this
00452     // Reset() ever happens.  Check for potential errors in array/pointer writing code.
00453     if(header.NextPacketPointer > RXSTOP || ((BYTE_VAL*)(&header.NextPacketPointer))->bits.b0 ||
00454        header.StatusVector.bits.Zero ||
00455        header.StatusVector.bits.CRCError ||
00456        header.StatusVector.bits.ByteCount > 1518u ||
00457        !header.StatusVector.bits.ReceiveOk)
00458     {
00459         Reset();
00460     }
00461
00462     // Save the location where the hardware will write the next packet to
00463     NextPacketLocation.Val = header.NextPacketPointer;
00464
00465     // Return the Ethernet frame's Source MAC address field to the caller
00466     // This parameter is useful for replying to requests without requiring an
00467     // ARP cycle.
00468     memcpy((void*)remote->v, (void*)header.SourceMACAddr.v, sizeof(*remote));
00469
00470     // Return a simplified version of the EtherType field to the caller
00471     *type = MAC_UNKNOWN;
00472     if( (header.Type.v[1] == 0x08u) &&
00473         ((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP)) )
00474     {
00475         *type = header.Type.v[0];
00476     }
00477
00478     // Mark this packet as discardable
00479     WasDiscarded = FALSE;
00480     return TRUE;
00481 }
00482
00483
00484 /******************************************************************************
00485  * Function:        void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
00486  *
00487  * PreCondition:    MACIsTxReady() must return TRUE.
00488  *
00489  * Input:           *remote: Pointer to memory which contains the destination
00490  *                           MAC address (6 bytes)
00491  *                  type: The constant ETHER_ARP or ETHER_IP, defining which
00492  *                        value to write into the Ethernet header's type field.
00493  *                  dataLen: Length of the Ethernet data payload
00494  *
00495  * Output:          None
00496  *
00497  * Side Effects:    None
00498  *
00499  * Overview:        None
00500  *
00501  * Note:            Because of the dataLen parameter, it is probably
00502  *                  advantagous to call this function immediately before
00503  *                  transmitting a packet rather than initially when the
00504  *                  packet is first created.  The order in which the packet
00505  *                  is constructed (header first or data first) is not
00506  *                  important.
00507  *****************************************************************************/
00508 void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
00509 {
00510     // Set the write pointer to the beginning of the transmit buffer
00511     EWRPT = TXSTART + 1;
00512
00513     // Calculate where to put the TXND pointer
00514     dataLen += (WORD)sizeof(ETHER_HEADER) + TXSTART;
00515
00516     // Write the TXND pointer into the registers, given the dataLen given
00517     ETXND = dataLen;
00518
00519     // Set the per-packet control byte and write the Ethernet destination
00520     // address
00521     MACPutArray((BYTE*)remote, sizeof(*remote));
00522
00523     // MODIFIX: Write our MAC address from flash in the Ethernet source field
00524     MACPutROMArray( ( ROM BYTE * ) pu8MAC, sizeof( MAC_ADDR ) );
00525
00526     // Write the appropriate Ethernet Type WORD for the protocol being used
00527     MACPut(0x08);
00528     MACPut((type == MAC_IP) ? ETHER_IP : ETHER_ARP);
00529 }
00530
00531 /******************************************************************************
00532  * Function:        void MACFlush(void)
00533  *
00534  * PreCondition:    A packet has been created by calling MACPut() and
00535  *                  MACPutHeader().
00536  *
00537  * Input:           None
00538  *
00539  * Output:          None
00540  *
00541  * Side Effects:    None
00542  *
00543  * Overview:        MACFlush causes the current TX packet to be sent out on
00544  *                  the Ethernet medium.  The hardware MAC will take control
00545  *                  and handle CRC generation, collision retransmission and
00546  *                  other details.
00547  *
00548  * Note:            After transmission completes (MACIsTxReady() returns TRUE),
00549  *                  the packet can be modified and transmitted again by calling
00550  *                  MACFlush() again.  Until MACPutHeader() or MACPut() is
00551  *                  called (in the TX data area), the data in the TX buffer
00552  *                  will not be corrupted.
00553  *****************************************************************************/
00554 void MACFlush(void)
00555 {
00556     // Reset the Ethernet TX logic.  This is a (suspected) errata workaround to
00557     // prevent the TXRTS bit from getting stuck set indefinitely, causing the
00558     // stack to lock up under certain bad conditions.
00559     ECON1bits.TXRST = 1;
00560     ECON1bits.TXRST = 0;
00561
00562     // Wait at least 1.6us after TX Reset before setting TXRTS.
00563     // If you don't wait long enough, the TX logic won't be finished resetting.
00564     {volatile BYTE i = 8; while(i--);}
00565     EIRbits.TXERIF = 0;
00566
00567     // Start the transmission
00568     // After transmission completes (MACIsTxReady() returns TRUE), the packet
00569     // can be modified and transmitted again by calling MACFlush() again.
00570     // Until MACPutHeader() is called, the data in the TX buffer will not be
00571     // corrupted.
00572     ECON1bits.TXRTS = 1;
00573     wTXWatchdog = TickGet();
00574 }
00575
00576
00577 /******************************************************************************
00578  * Function:        void MACSetReadPtrInRx(WORD offset)
00579  *
00580  * PreCondition:    A packet has been obtained by calling MACGetHeader() and
00581  *                  getting a TRUE result.
00582  *
00583  * Input:           offset: WORD specifying how many bytes beyond the Ethernet
00584  *                          header's type field to relocate the SPI read
00585  *                          pointer.
00586  *
00587  * Output:          None
00588  *
00589  * Side Effects:    None
00590  *
00591  * Overview:        SPI read pointer are updated.  All calls to
00592  *                  MACGet() and MACGetArray() will use these new values.
00593  *
00594  * Note:            RXSTOP must be statically defined as being > RXSTART for
00595  *                  this function to work correctly.  In other words, do not
00596  *                  define an RX buffer which spans the 0x1FFF->0x0000 memory
00597  *                  boundary.
00598  *****************************************************************************/
00599 void MACSetReadPtrInRx(WORD offset)
00600 {
00601     WORD_VAL ReadPT;
00602
00603     // Determine the address of the beginning of the entire packet
00604     // and adjust the address to the desired location
00605     ReadPT.Val = CurrentPacketLocation.Val + sizeof(ENC_PREAMBLE) + offset;
00606
00607     // Since the receive buffer is circular, adjust if a wraparound is needed
00608     if(ReadPT.Val > RXSTOP)
00609         ReadPT.Val -= RXSIZE;
00610
00611     // Set the read pointer to the new calculated value
00612     ERDPTL = ReadPT.v[0];
00613     ERDPTH = ReadPT.v[1];
00614 }
00615
00616 WORD_VAL u16MACGetCurrentReadPtrPos(void)
00617 {
00618     WORD_VAL ReadPT;
00619     ReadPT.v[0] = ERDPTL;
00620     ReadPT.v[1] = ERDPTH;
00621     return ReadPT;
00622 }
00623
00624 void MACSetCurrentReadPtrPos(WORD_VAL u16Pos)
00625 {
00626     ERDPTL = u16Pos.v[0];
00627     ERDPTH = u16Pos.v[1];
00628 }
00629
00630 /******************************************************************************
00631  * Function:        WORD MACSetWritePtr(WORD Address)
00632  *
00633  * PreCondition:    None
00634  *
00635  * Input:           Address: Address to seek to
00636  *
00637  * Output:          WORD: Old EWRPT location
00638  *
00639  * Side Effects:    None
00640  *
00641  * Overview:        SPI write pointer is updated.  All calls to
00642  *                  MACPut() and MACPutArray() will use this new value.
00643  *
00644  * Note:            None
00645  *****************************************************************************/
00646 WORD MACSetWritePtr(WORD address)
00647 {
00648     WORD oldVal;
00649
00650     oldVal = EWRPT;
00651     EWRPT = address;
00652     return oldVal;
00653 }
00654
00655 /******************************************************************************
00656  * Function:        WORD MACSetReadPtr(WORD Address)
00657  *
00658  * PreCondition:    None
00659  *
00660  * Input:           Address: Address to seek to
00661  *
00662  * Output:          WORD: Old ERDPT value
00663  *
00664  * Side Effects:    None
00665  *
00666  * Overview:        SPI write pointer is updated.  All calls to
00667  *                  MACPut() and MACPutArray() will use this new value.
00668  *
00669  * Note:            None
00670  *****************************************************************************/
00671 WORD MACSetReadPtr(WORD address)
00672 {
00673     WORD oldVal;
00674
00675     oldVal = ERDPT;
00676     ERDPT = address;
00677     return oldVal;
00678 }
00679
00680
00681 /******************************************************************************
00682  * Function:        WORD MACCalcRxChecksum(WORD offset, WORD len)
00683  *
00684  * PreCondition:    None
00685  *
00686  * Input:           offset  - Number of bytes beyond the beginning of the
00687  *                          Ethernet data (first byte after the type field)
00688  *                          where the checksum should begin
00689  *                  len     - Total number of bytes to include in the checksum
00690  *
00691  * Output:          16-bit checksum as defined by RFC 793.
00692  *
00693  * Side Effects:    None
00694  *
00695  * Overview:        This function performs a checksum calculation in the MAC
00696  *                  buffer itself
00697  *
00698  * Note:            None
00699  *****************************************************************************/
00700 WORD MACCalcRxChecksum(WORD offset, WORD len)
00701 {
00702     WORD temp;
00703     WORD RDSave;
00704
00705     // Add the offset requested by firmware plus the Ethernet header
00706     temp = CurrentPacketLocation.Val + sizeof(ENC_PREAMBLE) + offset;
00707     if(temp > RXSTOP)       // Adjust value if a wrap is needed
00708     {
00709         temp -= RXSIZE;
00710     }
00711
00712     RDSave = ERDPT;
00713     ERDPT = temp;
00714     temp = CalcIPBufferChecksum(len);
00715     ERDPT = RDSave;
00716
00717     return temp;
00718 }
00719
00720
00721 /******************************************************************************
00722  * Function:        WORD CalcIPBufferChecksum(WORD len)
00723  *
00724  * PreCondition:    Read buffer pointer set to starting of checksum data
00725  *
00726  * Input:           len: Total number of bytes to calculate the checksum over.
00727  *                       The first byte included in the checksum is the byte
00728  *                       pointed to by ERDPT, which is updated by calls to
00729  *                       MACGet(), MACSetRxBuffer(), MACSetTxBuffer(), etc.
00730  *
00731  * Output:          16-bit checksum as defined by RFC 793
00732  *
00733  * Side Effects:    None
00734  *
00735  * Overview:        This function performs a checksum calculation in the MAC
00736  *                  buffer itself.  The MAC has a hardware DMA module
00737  *                  which can calculate the checksum faster than software, so
00738  *                  this function replaces the CaclIPBufferChecksum() function
00739  *                  defined in the helpers.c file.  Through the use of
00740  *                  preprocessor defines, this replacement is automatic.
00741  *
00742  * Note:            This function works either in the RX buffer area or the TX
00743  *                  buffer area.  No validation is done on the len parameter.
00744  *****************************************************************************/
00745 /*
00746 WORD CalcIPBufferChecksum(WORD len)
00747 {
00748     WORD_VAL temp;
00749
00750     // Take care of special cases which the DMA cannot be used for
00751     if(len == 0u)
00752     {
00753         return 0xFFFF;
00754     }
00755     else if(len == 1u)
00756     {
00757         return ~((WORD)MACGet());
00758     }
00759
00760
00761     // Set the DMA starting address to the RAM read pointer value
00762     temp.Val = ERDPT;
00763     EDMAST = temp.Val;
00764
00765     // See if we are calculating a checksum within the RX buffer (where
00766     // wrapping rules apply) or TX/unused area (where wrapping rules are
00767     // not applied)
00768 #if RXSTART == 0
00769     if(temp.Val <= RXSTOP)
00770 #else
00771     if(temp.Val >= RXSTART && temp.Val <= RXSTOP)
00772 #endif
00773     {
00774         // Calculate the DMA ending address given the starting address and len
00775         // parameter.  The DMA will follow the receive buffer wrapping boundary.
00776         temp.Val += len-1;
00777         if(temp.Val > RXSTOP)
00778         {
00779             temp.Val -= RXSIZE;
00780         }
00781     }
00782     else
00783     {
00784         temp.Val += len-1;
00785     }
00786
00787     // Write the DMA end address
00788     EDMAND = temp.Val;
00789
00790     // Begin the DMA checksum calculation and wait until it is finished
00791     ECON1bits.CSUMEN = 1;
00792     ECON1bits.DMAST = 1;
00793     while(ECON1bits.DMAST);
00794
00795     // Return the resulting good stuff
00796     return (((WORD)EDMACSL)<<8) | EDMACSH;
00797 }
00798 */
00799
00800 /******************************************************************************
00801  * Function:        WORD CalcIPBufferChecksum(WORD len)
00802  *
00803  * PreCondition:    Read buffer pointer set to starting of checksum data
00804  *
00805  * Input:           len: Total number of bytes to calculate the checksum over.
00806  *                       The first byte included in the checksum is the byte
00807  *                       pointed to by ERDPT, which is updated by calls to
00808  *                       MACSetReadPtr(), MACGet(), MACGetArray(),
00809  *                       MACGetHeader(), etc.
00810  *
00811  * Output:          16-bit checksum as defined by RFC 793
00812  *
00813  * Side Effects:    None
00814  *
00815  * Overview:        This function performs a checksum calculation in the MAC
00816  *                  buffer itself
00817  *
00818  * Note:            This function works either in the RX buffer area or the TX
00819  *                  buffer area.  No validation is done on the len parameter.
00820  *****************************************************************************/
00821 WORD CalcIPBufferChecksum(WORD len)
00822 {
00823     WORD Start;
00824     DWORD_VAL Checksum = {0x00000000ul};
00825     WORD ChunkLen;
00826     BYTE DataBuffer[20];    // Must be an even size
00827     WORD *DataPtr;
00828
00829     // Save the read pointer starting address
00830     Start = ERDPT;
00831
00832     while(len)
00833     {
00834         // Obtain a chunk of data (less SPI overhead compared
00835         // to requesting one byte at a time)
00836         ChunkLen = len > sizeof(DataBuffer) ? sizeof(DataBuffer) : len;
00837         MACGetArray(DataBuffer, ChunkLen);
00838
00839         len -= ChunkLen;
00840
00841         // Take care of a last odd numbered data byte
00842         if(((WORD_VAL*)&ChunkLen)->bits.b0)
00843         {
00844             DataBuffer[ChunkLen] = 0x00;
00845             ChunkLen++;
00846         }
00847
00848         // Calculate the checksum over this chunk
00849         DataPtr = (WORD*)&DataBuffer[0];
00850         while(ChunkLen)
00851         {
00852             Checksum.Val += *DataPtr++;
00853             ChunkLen -= 2;
00854         }
00855     }
00856
00857     // Restore old read pointer location
00858     ERDPT = Start;
00859
00860     // Do an end-around carry (one's complement arrithmatic)
00861     Checksum.Val = (DWORD)Checksum.w[0] + (DWORD)Checksum.w[1];
00862
00863     // Do another end-around carry in case if the prior add
00864     // caused a carry out
00865     Checksum.w[0] += Checksum.w[1];
00866
00867     // Return the resulting checksum
00868     return ~Checksum.w[0];
00869 }
00870
00871 /******************************************************************************
00872  * Function:        void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
00873  *
00874  * PreCondition:    None
00875  *
00876  * Input:           destAddr:   Destination address in the Ethernet memory to
00877  *                              copy to.  If the MSb is set, the current EWRPT
00878  *                              value will be used instead.
00879  *                  sourceAddr: Source address to read from.  If the MSb is
00880  *                              set, the current ERDPT value will be used
00881  *                              instead.
00882  *                  len:        Number of bytes to copy
00883  *
00884  * Output:          None
00885  *
00886  * Side Effects:    None
00887  *
00888  * Overview:        Bytes are asynchrnously transfered within the buffer.  Call
00889  *                  MACIsMemCopyDone() to see when the transfer is complete.
00890  *
00891  * Note:            If a prior transfer is already in progress prior to
00892  *                  calling this function, this function will block until it
00893  *                  can start this transfer.
00894  *****************************************************************************/
00895 void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
00896 {
00897     WORD_VAL ReadSave, WriteSave;
00898     BOOL UpdateWritePointer = FALSE;
00899     BOOL UpdateReadPointer = FALSE;
00900
00901     if(((WORD_VAL*)&destAddr)->bits.b15)
00902     {
00903         UpdateWritePointer = TRUE;
00904         destAddr = EWRPT;
00905     }
00906     if(((WORD_VAL*)&sourceAddr)->bits.b15)
00907     {
00908         UpdateReadPointer = TRUE;
00909         sourceAddr = ERDPT;
00910     }
00911
00912     // Handle special conditions where len == 0 or len == 1
00913     // The DMA module is not capable of handling those corner cases
00914     if(len <= 1u)
00915     {
00916         ReadSave.Val = ERDPT;
00917         WriteSave.Val = EWRPT;
00918         ERDPT = sourceAddr;
00919         EWRPT = destAddr;
00920         while(len--)
00921             MACPut(MACGet());
00922         if(!UpdateReadPointer)
00923         {
00924             ERDPT = ReadSave.Val;
00925         }
00926         if(!UpdateWritePointer)
00927         {
00928             EWRPT = WriteSave.Val;
00929         }
00930     }
00931     else
00932     {
00933         if(UpdateWritePointer)
00934         {
00935             WriteSave.Val = destAddr + len;
00936             EWRPT = WriteSave.Val;
00937         }
00938         len += sourceAddr - 1;
00939         while(ECON1bits.DMAST);
00940         EDMAST = sourceAddr;
00941         EDMADST = destAddr;
00942         if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
00943             len -= RXSIZE;
00944         EDMAND = len;
00945         ECON1bits.CSUMEN = 0;
00946         ECON1bits.DMAST = 1;
00947         while(ECON1bits.DMAST);         // DMA errata workaround: Must not access EDATA while DMA active
00948
00949         if(UpdateReadPointer)
00950         {
00951             len++;
00952             if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
00953                 len -= RXSIZE;
00954             ERDPT = len;
00955         }
00956     }
00957 }
00958
00959 /*
00960 void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
00961 {
00962     WORD_VAL ReadSave, WriteSave;
00963     BOOL UpdateWritePointer = FALSE;
00964     BOOL UpdateReadPointer = FALSE;
00965
00966     if(((WORD_VAL*)&destAddr)->bits.b15)
00967     {
00968         UpdateWritePointer = TRUE;
00969         destAddr = EWRPT;
00970     }
00971     if(((WORD_VAL*)&sourceAddr)->bits.b15)
00972     {
00973         UpdateReadPointer = TRUE;
00974         sourceAddr = ERDPT;
00975     }
00976
00977     ReadSave.Val = ERDPT;
00978     WriteSave.Val = EWRPT;
00979     ERDPT = sourceAddr;
00980     EWRPT = destAddr;
00981     while(len--)
00982     {
00983         MACPut(MACGet());
00984     }
00985
00986     if(!UpdateReadPointer)
00987     {
00988         ERDPT = ReadSave.Val;
00989     }
00990     if(!UpdateWritePointer)
00991     {
00992         EWRPT = WriteSave.Val;
00993     }
00994 }
00995 */
00996
00997 BOOL MACIsMemCopyDone(void)
00998 {
00999     return !ECON1bits.DMAST;
01000 }
01001
01002 /******************************************************************************
01003  * Function:        BYTE MACGet()
01004  *
01005  * PreCondition:    ERDPT must point to the place to read from.
01006  *
01007  * Input:           None
01008  *
01009  * Output:          Byte read from the Ethernet's buffer RAM
01010  *
01011  * Side Effects:    None
01012  *
01013  * Overview:        MACGet returns the byte pointed to by ERDPT and
01014  *                  increments ERDPT so MACGet() can be called again.  The
01015  *                  increment will follow the receive buffer wrapping boundary.
01016  *
01017  * Note:            For better performance, implement this function as a macro:
01018  *                  #define MACGet()    (EDATA)
01019  *****************************************************************************/
01020 BYTE MACGet()
01021 {
01022     return EDATA;
01023 }//end MACGet
01024
01025
01026 /******************************************************************************
01027  * Function:        WORD MACGetArray(BYTE *val, WORD len)
01028  *
01029  * PreCondition:    ERDPT must point to the place to read from.
01030  *
01031  * Input:           *val: Pointer to storage location
01032  *                  len:  Number of bytes to read from the data buffer.
01033  *
01034  * Output:          Byte(s) of data read from the data buffer.
01035  *
01036  * Side Effects:    None
01037  *
01038  * Overview:        Reads several sequential bytes from the data buffer
01039  *                  and places them into local memory.  ERDPT is incremented
01040  *                  after each byte, following the same rules as MACGet().
01041  *
01042  * Note:            None
01043  *****************************************************************************/
01044 WORD MACGetArray(BYTE *val, WORD len)
01045 {
01046     WORD w;
01047     volatile BYTE i;
01048
01049     w = len;
01050     if(val)
01051     {
01052         while(w--)
01053         {
01054             *val++ = EDATA;
01055         }
01056     }
01057     else
01058     {
01059         while(w--)
01060         {
01061             i = EDATA;
01062         }
01063     }
01064
01065     return len;
01066 }//end MACGetArray
01067
01068
01069 /******************************************************************************
01070  * Function:        void MACPut(BYTE val)
01071  *
01072  * PreCondition:    EWRPT must point to the location to begin writing.
01073  *
01074  * Input:           Byte to write into the Ethernet buffer memory
01075  *
01076  * Output:          None
01077  *
01078  * Side Effects:    None
01079  *
01080  * Overview:        Writes to the EDATA register, which will indirectly
01081 *                   increment EWRPTH:EWRPTL.
01082  *
01083  * Note:            None
01084  *****************************************************************************/
01085 void MACPut(BYTE val)
01086 {
01087     // Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to
01088     // write to EDATA or else the read pointer (ERDPT) will inadvertently
01089     // increment.
01090     PRODL = val;
01091     #if defined(HI_TECH_C)
01092         asm("movff  _PRODL, _EDATA");
01093     #else
01094         _asm movff  PRODL, EDATA _endasm
01095     #endif
01096 }//end MACPut
01097
01098
01099 /******************************************************************************
01100  * Function:        void MACPutArray(BYTE *val, WORD len)
01101  *
01102  * PreCondition:    EWRPT must point to the location to begin writing.
01103  *
01104  * Input:           *val: Pointer to source of bytes to copy.
01105  *                  len:  Number of bytes to write to the data buffer.
01106  *
01107  * Output:          None
01108  *
01109  * Side Effects:    None
01110  *
01111  * Overview:        MACPutArray writes several sequential bytes to the
01112  *                  Ethernet buffer RAM.  It performs faster than multiple MACPut()
01113  *                  calls.  EWRPT is incremented by len.
01114  *
01115  * Note:            None
01116  *****************************************************************************/
01117 void MACPutArray(BYTE *val, WORD len)
01118 {
01119     while(len--)
01120     {
01121         // Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to
01122         // write to EDATA or else the read pointer (ERDPT) will inadvertently
01123         // increment.
01124         PRODL = *val++;
01125         #if defined(HI_TECH_C)
01126             asm("movff  _PRODL, _EDATA");
01127         #else
01128             _asm movff  PRODL, EDATA _endasm
01129         #endif
01130     }
01131 }//end MACPutArray
01132
01133 void MACPutROMArray(ROM BYTE *val, WORD len)
01134 {
01135     while(len--)
01136     {
01137         // Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to
01138         // write to EDATA or else the read pointer (ERDPT) will inadvertently
01139         // increment.
01140         PRODL = *val++;
01141         #if defined(HI_TECH_C)
01142             asm("movff  _PRODL, _EDATA");
01143         #else
01144             _asm movff  PRODL, EDATA _endasm
01145         #endif
01146     }
01147 }//end MACPutROMArray
01148
01149
01150 /******************************************************************************
01151  * Function:        ReadPHYReg
01152  *
01153  * PreCondition:    Ethernet module must be enabled (ECON1.ETHEN = 1).
01154  *
01155  * Input:           Address of the PHY register to read from.
01156  *
01157  * Output:          16 bits of data read from the PHY register.
01158  *
01159  * Side Effects:    None
01160  *
01161  * Overview:        ReadPHYReg performs an MII read operation.  While in
01162  *                  progress, it simply polls the MII BUSY bit wasting time
01163  *                  (10.24us).
01164  *
01165  * Note:            None
01166  *****************************************************************************/
01167 PHYREG ReadPHYReg(BYTE Register)
01168 {
01169     PHYREG Result;
01170
01171     // Set the right address and start the register read operation
01172     MIREGADR = Register; Nop();
01173     MICMD = MICMD_MIIRD; Nop();
01174
01175     // Loop to wait until the PHY register has been read through the MII
01176     // This requires 10.24us
01177     while(MISTATbits.BUSY);
01178
01179     // Stop reading
01180     MICMD = 0x00; Nop();
01181
01182     // Obtain results and return
01183     Result.VAL.v[0] = MIRDL;
01184     Nop();
01185     Result.VAL.v[1] = MIRDH;
01186
01187     return Result;
01188 }//end ReadPHYReg
01189
01190
01191 /******************************************************************************
01192  * Function:        WritePHYReg
01193  *
01194  * PreCondition:    Ethernet module must be enabled (ECON1.ETHEN = 1).
01195  *
01196  * Input:           Address of the PHY register to write to.
01197  *                  16 bits of data to write to PHY register.
01198  *
01199  * Output:          None
01200  *
01201  * Side Effects:    None
01202  *
01203  * Overview:        WritePHYReg performs an MII write operation.  While in
01204  *                  progress, it simply polls the MII BUSY bit wasting time
01205  *                  (10.24us).
01206  *
01207  * Note:            None
01208  *****************************************************************************/
01209 void WritePHYReg(BYTE Register, WORD Data)
01210 {
01211     BYTE GIESave;
01212
01213     // Write the register address
01214     MIREGADR = Register;
01215
01216     // Write the data through the MIIM interface
01217     // Order is important: write low byte first, high byte last
01218     //
01219     // Due to a silicon problem, you cannot access any register with LSb address
01220     // bits of 0x16 between your write to MIWRL and MIWRH or else the value in
01221     // MIWRL will be corrupted.  This inline assembly prevents this by copying
01222     // the value to PRODH:PRODL first, which is at fixed locations of
01223     // 0xFF4:0xFF3.  These addresses have LSb address bits of 0x14 and 0x13.
01224     // Interrupts must be disabled to prevent arbitrary ISR code from accessing
01225     // memory with LSb bits of 0x16 and corrupting the MIWRL value.
01226     PRODL = ((WORD_VAL*)&Data)->v[0];
01227     PRODH = ((WORD_VAL*)&Data)->v[1];
01228     GIESave = INTCON & 0xC0;        // Save GIEH and GIEL bits
01229     INTCON &= 0x3F;                 // Clear INTCONbits.GIEH and INTCONbits.GIEL
01230     #if defined(HI_TECH_C)
01231         asm("movff  _PRODL, _MIWRL");
01232         asm("nop");
01233         asm("movff  _PRODH, _MIWRH");
01234     #else
01235         _asm
01236         movff   PRODL, MIWRL
01237         nop
01238         movff   PRODH, MIWRH
01239         _endasm
01240     #endif
01241     INTCON |= GIESave;              // Restore GIEH and GIEL value
01242
01243     // Wait until the PHY register has been written
01244     // This operation requires 10.24us
01245     while(MISTATbits.BUSY);
01246 }//end WritePHYReg
01247
01248
01249 /******************************************************************************
01250  * Function:        void MACPowerDown(void)
01251  *
01252  * PreCondition:    None
01253  *
01254  * Input:           None
01255  *
01256  * Output:          None
01257  *
01258  * Side Effects:    None
01259  *
01260  * Overview:        MACPowerDown disables the Ethernet module.
01261  *                  All MAC and PHY registers should not be accessed.
01262  *
01263  * Note:            Normally, this function would be called before putting the
01264  *                  PIC to sleep.  If a packet is being transmitted while this
01265  *                  function is called, this function will block until it is
01266  *                  it complete. If anything is being received, it will be
01267  *                  completed.
01268  *
01269  *                  The Ethernet module will continue to draw significant
01270  *                  power in sleep mode if this function is not called first.
01271  *****************************************************************************/
01272 void MACPowerDown(void)
01273 {
01274     // Disable packet reception
01275     ECON1bits.RXEN = 0;
01276
01277     // Make sure any last packet which was in-progress when RXEN was cleared
01278     // is completed
01279     while(ESTATbits.RXBUSY);
01280
01281     // If a packet is being transmitted, wait for it to finish
01282     while(ECON1bits.TXRTS);
01283
01284     // Disable the Ethernet module
01285     ECON2bits.ETHEN = 0;
01286
01287     // Switch off LEDs.
01288     LATAbits.LATA0 = 0;
01289     LATAbits.LATA1 = 0;
01290
01291 }//end MACPowerDown
01292
01293 /******************************************************************************
01294  * Function:        void MACPowerUp(void)
01295  *
01296  * PreCondition:    None
01297  *
01298  * Input:           None
01299  *
01300  * Output:          None
01301  *
01302  * Side Effects:    None
01303  *
01304  * Overview:        MACPowerUp returns the Ethernet module back to normal operation
01305  *                  after a previous call to MACPowerDown().  Calling this
01306  *                  function when already powered up will have no effect.
01307  *
01308  * Note:            If a link partner is present, it will take 10s of
01309  *                  milliseconds before a new link will be established after
01310  *                  waking up.  While not linked, packets which are
01311  *                  transmitted will most likely be lost.  MACIsLinked() can
01312  *                  be called to determine if a link is established.
01313  *****************************************************************************/
01314 void MACPowerUp(void)
01315 {
01316     // Power up the Ethernet module
01317     ECON2bits.ETHEN = 1;
01318
01319     // Wait for PHY to become ready
01320     while(!ESTATbits.PHYRDY)
01321
01322     // Enable packet reception
01323     ECON1bits.RXEN = 1;
01324 }//end MACPowerUp
01325
01326
01327
01328 /******************************************************************************
01329  * Function:        void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
01330  *
01331  * PreCondition:    SPI bus must be initialized (done in MACInit()).
01332  *
01333  * Input:           DestMACAddr: 6 byte group destination MAC address to allow
01334  *                               through the Hash Table Filter
01335  *
01336  * Output:          Sets the appropriate bit in the EHT* registers to allow
01337  *                  packets sent to DestMACAddr to be received if the Hash
01338  *                  Table receive filter is enabled
01339  *
01340  * Side Effects:    None
01341  *
01342  * Overview:        Calculates a CRC-32 using polynomial 0x4C11DB7 and then,
01343  *                  using bits 28:23 of the CRC, sets the appropriate bit in
01344  *                  the EHT* registers
01345  *
01346  * Note:            This code is commented out to save code space on systems
01347  *                  that do not need this function.  Change the "#if 0" line
01348  *                  to "#if 1" to uncomment it.
01349  *****************************************************************************/
01350 #if 0
01351 void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
01352 {
01353     DWORD_VAL CRC = {0xFFFFFFFF};
01354     BYTE *HTRegister;
01355     BYTE i, j;
01356
01357     // Calculate a CRC-32 over the 6 byte MAC address
01358     // using polynomial 0x4C11DB7
01359     for(i = 0; i < sizeof(MAC_ADDR); i++)
01360     {
01361         BYTE  crcnext;
01362
01363         // shift in 8 bits
01364         for(j = 0; j < 8; j++)
01365         {
01366             crcnext = 0;
01367             if(((BYTE_VAL*)&(CRC.v[3]))->bits.b7)
01368                 crcnext = 1;
01369             crcnext ^= (((BYTE_VAL*)&DestMACAddr.v[i])->bits.b0);
01370
01371             CRC.Val <<= 1;
01372             if(crcnext)
01373                 CRC.Val ^= 0x4C11DB7;
01374             // next bit
01375             DestMACAddr.v[i] >>= 1;
01376         }
01377     }
01378
01379     // CRC-32 calculated, now extract bits 28:23
01380     // Bits 25:23 define where within the Hash Table byte the bit needs to be set
01381     // Bits 28:26 define which of the 8 Hash Table bytes that bits 25:23 apply to
01382     i = CRC.v[3] & 0x1F;
01383     HTRegister = (i >> 2) + &EHT0;
01384     i = (i << 1) & 0x06;
01385     ((BYTE_VAL*)&i)->bits.b0 = ((BYTE_VAL*)&CRC.v[2])->bits.b7;
01386
01387     // Set the proper bit in the Hash Table
01388     *HTRegister |= 1<<i;
01389 }
01390 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: ETH97J60.h Source File

ETH97J60.h

Go to the documentation of this file.
00001
00002
00003
00019 /*********************************************************************
00020  * Software License Agreement
00021  *
00022  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00023  * reserved.
00024  *
00025  * Microchip licenses to you the right to use, modify, copy, and
00026  * distribute:
00027  * (i)  the Software when embedded on a Microchip microcontroller or
00028  *      digital signal controller product ("Device") which is
00029  *      integrated into Licensee's product; or
00030  * (ii) ONLY the Software driver source files ENC28J60.c and
00031  *      ENC28J60.h ported to a non-Microchip device used in
00032  *      conjunction with a Microchip ethernet controller for the
00033  *      sole purpose of interfacing with the ethernet controller.
00034  *
00035  * You should refer to the license agreement accompanying this
00036  * Software for additional information regarding your rights and
00037  * obligations.
00038  *
00039  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00040  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00041  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00042  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00043  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00044  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00045  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00046  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00047  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00048  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00049  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00050  *
00051  *
00052  * Author               Date        Comment
00053  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00054  * Howard Schlunder     06/12/05    Modified for 97J60 (from ENC28J60)
00055  * Howard Schlunder     03/23/06    Updated for Advance Data Sheet
00056  * Howard Schlunder     06/29/06    Changed MACON3_PHDRLEN to MACON3_PHDREN
00057  * Howard Schlunder     09/13/06    Removed a lot of bits for
00058  *                                  preliminary data sheet, added RXAPDIS
00059  ********************************************************************/
00060
00061 #ifndef __ETH97J60_H
00062 #define __ETH97J60_H
00063 #include "GenericTypeDefs.h"
00064
00065 typedef union {
00066     BYTE v[7];
00067     struct {
00068         WORD     ByteCount;
00069         unsigned CollisionCount:4;
00070         unsigned CRCError:1;
00071         unsigned LengthCheckError:1;
00072         unsigned LengthOutOfRange:1;
00073         unsigned Done:1;
00074         unsigned Multicast:1;
00075         unsigned Broadcast:1;
00076         unsigned PacketDefer:1;
00077         unsigned ExcessiveDefer:1;
00078         unsigned MaximumCollisions:1;
00079         unsigned LateCollision:1;
00080         unsigned Giant:1;
00081         unsigned Underrun:1;
00082         WORD     BytesTransmittedOnWire;
00083         unsigned ControlFrame:1;
00084         unsigned PAUSEControlFrame:1;
00085         unsigned BackpressureApplied:1;
00086         unsigned VLANTaggedFrame:1;
00087         unsigned Zeros:4;
00088     } bits;
00089 } TXSTATUS;
00090
00091 typedef union {
00092     BYTE v[4];
00093     struct {
00094         WORD     ByteCount;
00095         unsigned PreviouslyIgnored:1;
00096         unsigned RXDCPreviouslySeen:1;
00097         unsigned CarrierPreviouslySeen:1;
00098         unsigned CodeViolation:1;
00099         unsigned CRCError:1;
00100         unsigned LengthCheckError:1;
00101         unsigned LengthOutOfRange:1;
00102         unsigned ReceiveOk:1;
00103         unsigned Multicast:1;
00104         unsigned Broadcast:1;
00105         unsigned DribbleNibble:1;
00106         unsigned ControlFrame:1;
00107         unsigned PauseControlFrame:1;
00108         unsigned UnsupportedOpcode:1;
00109         unsigned VLANType:1;
00110         unsigned Zero:1;
00111     } bits;
00112 } RXSTATUS;
00113
00114
00115
00116 /******************************************************************************
00117 * PHY Register Locations
00118 ******************************************************************************/
00119 #define PHCON1  0x00
00120 #define PHSTAT1 0x01
00121 #define PHCON2  0x10
00122 #define PHSTAT2 0x11
00123 #define PHIE    0x12
00124 #define PHIR    0x13
00125 #define PHLCON  0x14
00126
00127
00128 typedef union {
00129     WORD Val;
00130     WORD_VAL VAL;
00131
00132     // PHCON1 bits ----------
00133     struct {
00134         unsigned :8;
00135         unsigned PDPXMD:1;
00136         unsigned :7;
00137     } PHCON1bits;
00138
00139     // PHSTAT1 bits --------
00140     struct {
00141         unsigned :2;
00142         unsigned LLSTAT:1;
00143         unsigned :5;
00144         unsigned :8;
00145     } PHSTAT1bits;
00146
00147     // PHCON2 bits ----------
00148     struct {
00149         unsigned :4;
00150         unsigned RXAPDIS:1;
00151         unsigned :3;
00152         unsigned HDLDIS:1;
00153         unsigned :5;
00154         unsigned FRCLNK:1;
00155         unsigned :1;
00156     } PHCON2bits;
00157
00158     // PHSTAT2 bits --------
00159     struct {
00160         unsigned :8;
00161         unsigned :2;
00162         unsigned LSTAT:1;
00163         unsigned COLSTAT:1;
00164         unsigned RXSTAT:1;
00165         unsigned TXSTAT:1;
00166         unsigned :2;
00167     } PHSTAT2bits;
00168
00169     // PHIE bits -----------
00170     struct {
00171         unsigned :1;
00172         unsigned PGEIE:1;
00173         unsigned :2;
00174         unsigned PLNKIE:1;
00175         unsigned :3;
00176         unsigned :8;
00177     } PHIEbits;
00178
00179     // PHIR bits -----------
00180     struct {
00181         unsigned :2;
00182         unsigned PGIF:1;
00183         unsigned :1;
00184         unsigned PLNKIF:1;
00185         unsigned :3;
00186         unsigned :8;
00187     } PHIRbits;
00188
00189     // PHLCON bits -------
00190     struct {
00191         unsigned :1;
00192         unsigned STRCH:1;
00193         unsigned LFRQ0:1;
00194         unsigned LFRQ1:1;
00195         unsigned LBCFG0:1;
00196         unsigned LBCFG1:1;
00197         unsigned LBCFG2:1;
00198         unsigned LBCFG3:1;
00199         unsigned LACFG0:1;
00200         unsigned LACFG1:1;
00201         unsigned LACFG2:1;
00202         unsigned LACFG3:1;
00203         unsigned :4;
00204     } PHLCONbits;
00205     struct {
00206         unsigned :1;
00207         unsigned STRCH:1;
00208         unsigned LFRQ:2;
00209         unsigned LBCFG:4;
00210         unsigned LACFG:4;
00211         unsigned :4;
00212     } PHLCONbits2;
00213 } PHYREG;
00214
00215
00216 /******************************************************************************
00217 * Individual Register Bits
00218 ******************************************************************************/
00219 // ETH/MAC/MII bits
00220
00221 // EIE bits ----------
00222 #define EIE_PKTIE       (1<<6)
00223 #define EIE_DMAIE       (1<<5)
00224 #define EIE_LINKIE      (1<<4)
00225 #define EIE_TXIE        (1<<3)
00226 #define EIE_TXERIE      (1<<1)
00227 #define EIE_RXERIE      (1)
00228
00229 // EIR bits ----------
00230 #define EIR_PKTIF       (1<<6)
00231 #define EIR_DMAIF       (1<<5)
00232 #define EIR_LINKIF      (1<<4)
00233 #define EIR_TXIF        (1<<3)
00234 #define EIR_TXERIF      (1<<1)
00235 #define EIR_RXERIF      (1)
00236
00237 // ESTAT bits ---------
00238 #define ESTAT_BUFER     (1<<6)
00239 #define ESTAT_RXBUSY    (1<<2)
00240 #define ESTAT_TXABRT    (1<<1)
00241 #define ESTAT_PHYRDY    (1)
00242
00243 // ECON2 bits --------
00244 #define ECON2_AUTOINC   (1<<7)
00245 #define ECON2_PKTDEC    (1<<6)
00246 #define ECON2_ETHEN     (1<<5)
00247
00248 // ECON1 bits --------
00249 #define ECON1_TXRST     (1<<7)
00250 #define ECON1_RXRST     (1<<6)
00251 #define ECON1_DMAST     (1<<5)
00252 #define ECON1_CSUMEN    (1<<4)
00253 #define ECON1_TXRTS     (1<<3)
00254 #define ECON1_RXEN      (1<<2)
00255
00256 // ERXFCON bits ------
00257 #define ERXFCON_UCEN    (1<<7)
00258 #define ERXFCON_ANDOR   (1<<6)
00259 #define ERXFCON_CRCEN   (1<<5)
00260 #define ERXFCON_PMEN    (1<<4)
00261 #define ERXFCON_MPEN    (1<<3)
00262 #define ERXFCON_HTEN    (1<<2)
00263 #define ERXFCON_MCEN    (1<<1)
00264 #define ERXFCON_BCEN    (1)
00265
00266 // MACON1 bits --------
00267 #define MACON1_TXPAUS   (1<<3)
00268 #define MACON1_RXPAUS   (1<<2)
00269 #define MACON1_PASSALL  (1<<1)
00270 #define MACON1_MARXEN   (1)
00271
00272 // MACON3 bits --------
00273 #define MACON3_PADCFG2  (1<<7)
00274 #define MACON3_PADCFG1  (1<<6)
00275 #define MACON3_PADCFG0  (1<<5)
00276 #define MACON3_TXCRCEN  (1<<4)
00277 #define MACON3_PHDREN   (1<<3)
00278 #define MACON3_HFRMEN   (1<<2)
00279 #define MACON3_FRMLNEN  (1<<1)
00280 #define MACON3_FULDPX   (1)
00281
00282 // MACON4 bits --------
00283 #define MACON4_DEFER    (1<<6)
00284
00285 // MICMD bits ---------
00286 #define MICMD_MIISCAN   (1<<1)
00287 #define MICMD_MIIRD     (1)
00288
00289 // MISTAT bits --------
00290 #define MISTAT_NVALID   (1<<2)
00291 #define MISTAT_SCAN     (1<<1)
00292 #define MISTAT_BUSY     (1)
00293
00294 // EFLOCON bits -----
00295 #define EFLOCON_FCEN1   (1<<1)
00296 #define EFLOCON_FCEN0   (1)
00297
00298
00299
00300 // PHY bits
00301
00302 // PHCON1 bits ----------
00303 #define PHCON1_PDPXMD   (1ul<<8)
00304
00305 // PHSTAT1 bits --------
00306 #define PHSTAT1_LLSTAT  (1ul<<2)
00307
00308 // PHCON2 bits ----------
00309 #define PHCON2_FRCLNK   (1ul<<14)
00310 #define PHCON2_HDLDIS   (1ul<<8)
00311 #define PHCON2_RXAPDIS  (1ul<<4)
00312
00313 // PHSTAT2 bits --------
00314 #define PHSTAT2_TXSTAT  (1ul<<13)
00315 #define PHSTAT2_RXSTAT  (1ul<<12)
00316 #define PHSTAT2_COLSTAT (1ul<<11)
00317 #define PHSTAT2_LSTAT   (1ul<<10)
00318
00319 // PHIE bits -----------
00320 #define PHIE_PLNKIE     (1ul<<4)
00321 #define PHIE_PGEIE      (1ul<<1)
00322
00323 // PHIR bits -----------
00324 #define PHIR_PLNKIF     (1ul<<4)
00325 #define PHIR_PGIF       (1ul<<2)
00326
00327 // PHLCON bits -------
00328 #define PHLCON_LACFG3   (1ul<<11)
00329 #define PHLCON_LACFG2   (1ul<<10)
00330 #define PHLCON_LACFG1   (1ul<<9)
00331 #define PHLCON_LACFG0   (1ul<<8)
00332 #define PHLCON_LBCFG3   (1ul<<7)
00333 #define PHLCON_LBCFG2   (1ul<<6)
00334 #define PHLCON_LBCFG1   (1ul<<5)
00335 #define PHLCON_LBCFG0   (1ul<<4)
00336 #define PHLCON_LFRQ1    (1ul<<3)
00337 #define PHLCON_LFRQ0    (1ul<<2)
00338 #define PHLCON_STRCH    (1ul<<1)
00339
00340 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: GenericTypeDefs.h Source File

GenericTypeDefs.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00017 /*********************************************************************
00018  * Software License Agreement
00019  *
00020  * The software supplied herewith by Microchip Technology Incorporated
00021  * (the "Company") is intended and supplied to you, the Company's
00022  * customer, for use solely and exclusively with products manufactured
00023  * by the Company.
00024  *
00025  * The software is owned by the Company and/or its supplier, and is
00026  * protected under applicable copyright laws. All rights are reserved.
00027  * Any use in violation of the foregoing restrictions may subject the
00028  * user to criminal sanctions under applicable laws, as well as to
00029  * civil liability for the breach of the terms and conditions of this
00030  * license.
00031  *
00032  * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
00033  * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
00034  * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00035  * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
00036  * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
00037  * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
00038  *
00039  *
00040  * Author                   Date        Comment
00041  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00042  * Nilesh Rajbharti         07/12/04    Rel 0.9
00043  * Nilesh Rajbharti         11/24/04    Rel 0.9.1
00044  * Rawin Rojvanit           09/17/05    Rel 0.9.2
00045  * D Flowers & H Schlunder  08/10/06    Much better now (1.0)
00046  * D Flowers & H Schlunder  09/11/06    Add base signed types (1.1)
00047  * D Flo, H Sch, et. al     02/28/07    Add QWORD, LONGLONG, QWORD_VAL (1.2)
00048  * Bud Caldwell             02/06/08    Added def's for PIC32
00049  ********************************************************************/
00050
00051 #ifndef __GENERIC_TYPE_DEFS_H_
00052 #define __GENERIC_TYPE_DEFS_H_
00053
00054 typedef enum _BOOL { FALSE = 0, TRUE } BOOL;    // Undefined size
00055
00056 #ifndef NULL
00057 #define NULL    0//((void *)0)
00058 #endif
00059
00060 #define PUBLIC                                  // Function attributes
00061 #define PROTECTED
00062 #define PRIVATE   static
00063
00064 typedef unsigned char       BYTE;               // 8-bit unsigned
00065 typedef unsigned short int  WORD;               // 16-bit unsigned
00066 typedef unsigned long       DWORD;              // 32-bit unsigned
00067 typedef unsigned long long  QWORD;              // 64-bit unsigned
00068 typedef signed char         CHAR;               // 8-bit signed
00069 typedef signed short int    SHORT;              // 16-bit signed
00070 typedef signed long         LONG;               // 32-bit signed
00071 typedef signed long long    LONGLONG;           // 64-bit signed
00072
00073 /* Alternate definitions */
00074 typedef void                VOID;
00075
00076 typedef char                CHAR8;
00077 typedef unsigned char       UCHAR8;
00078
00079 /* Processor & Compiler independent, size specific definitions */
00080 // To Do:  We need to verify the sizes on each compiler.  These
00081 //         may be compiler specific, we should either move them
00082 //         to "compiler.h" or #ifdef them for compiler type.
00083 typedef signed int          INT;
00084 typedef signed char         INT8;
00085 typedef signed short int    INT16;
00086 typedef signed long int     INT32;
00087 typedef signed long long    INT64;
00088
00089 typedef unsigned int        UINT;
00090 typedef unsigned char       UINT8;
00091 typedef unsigned short int  UINT16;
00092 typedef unsigned long int   UINT32;  // other name for 32-bit integer
00093 typedef unsigned long long  UINT64;
00094
00095 typedef union _BYTE_VAL
00096 {
00097     BYTE Val;
00098     struct
00099     {
00100         unsigned char b0:1;
00101         unsigned char b1:1;
00102         unsigned char b2:1;
00103         unsigned char b3:1;
00104         unsigned char b4:1;
00105         unsigned char b5:1;
00106         unsigned char b6:1;
00107         unsigned char b7:1;
00108     } bits;
00109 } BYTE_VAL, BYTE_BITS;
00110
00111 typedef union _WORD_VAL
00112 {
00113     WORD Val;
00114     BYTE v[2];
00115     struct
00116     {
00117         BYTE LB;
00118         BYTE HB;
00119     } byte;
00120     struct
00121     {
00122         unsigned char b0:1;
00123         unsigned char b1:1;
00124         unsigned char b2:1;
00125         unsigned char b3:1;
00126         unsigned char b4:1;
00127         unsigned char b5:1;
00128         unsigned char b6:1;
00129         unsigned char b7:1;
00130         unsigned char b8:1;
00131         unsigned char b9:1;
00132         unsigned char b10:1;
00133         unsigned char b11:1;
00134         unsigned char b12:1;
00135         unsigned char b13:1;
00136         unsigned char b14:1;
00137         unsigned char b15:1;
00138     } bits;
00139 } WORD_VAL, WORD_BITS;
00140
00141 typedef union _DWORD_VAL
00142 {
00143     DWORD Val;
00144     WORD w[2];
00145     BYTE v[4];
00146     struct
00147     {
00148         WORD LW;
00149         WORD HW;
00150     } word;
00151     struct
00152     {
00153         BYTE LB;
00154         BYTE HB;
00155         BYTE UB;
00156         BYTE MB;
00157     } byte;
00158     struct
00159     {
00160         WORD_VAL low;
00161         WORD_VAL high;
00162     }wordUnion;
00163     struct
00164     {
00165         unsigned char b0:1;
00166         unsigned char b1:1;
00167         unsigned char b2:1;
00168         unsigned char b3:1;
00169         unsigned char b4:1;
00170         unsigned char b5:1;
00171         unsigned char b6:1;
00172         unsigned char b7:1;
00173         unsigned char b8:1;
00174         unsigned char b9:1;
00175         unsigned char b10:1;
00176         unsigned char b11:1;
00177         unsigned char b12:1;
00178         unsigned char b13:1;
00179         unsigned char b14:1;
00180         unsigned char b15:1;
00181         unsigned char b16:1;
00182         unsigned char b17:1;
00183         unsigned char b18:1;
00184         unsigned char b19:1;
00185         unsigned char b20:1;
00186         unsigned char b21:1;
00187         unsigned char b22:1;
00188         unsigned char b23:1;
00189         unsigned char b24:1;
00190         unsigned char b25:1;
00191         unsigned char b26:1;
00192         unsigned char b27:1;
00193         unsigned char b28:1;
00194         unsigned char b29:1;
00195         unsigned char b30:1;
00196         unsigned char b31:1;
00197     } bits;
00198 } DWORD_VAL;
00199
00200 #define LSB(a)          ((a).v[0])
00201 #define MSB(a)          ((a).v[1])
00202
00203 #define LOWER_LSB(a)    ((a).v[0])
00204 #define LOWER_MSB(a)    ((a).v[1])
00205 #define UPPER_LSB(a)    ((a).v[2])
00206 #define UPPER_MSB(a)    ((a).v[3])
00207
00208 typedef union _QWORD_VAL
00209 {
00210     QWORD Val;
00211     DWORD d[2];
00212     WORD w[4];
00213     BYTE v[8];
00214     struct
00215     {
00216         DWORD LD;
00217         DWORD HD;
00218     } dword;
00219     struct
00220     {
00221         WORD LW;
00222         WORD HW;
00223         WORD UW;
00224         WORD MW;
00225     } word;
00226     struct
00227     {
00228         unsigned char b0:1;
00229         unsigned char b1:1;
00230         unsigned char b2:1;
00231         unsigned char b3:1;
00232         unsigned char b4:1;
00233         unsigned char b5:1;
00234         unsigned char b6:1;
00235         unsigned char b7:1;
00236         unsigned char b8:1;
00237         unsigned char b9:1;
00238         unsigned char b10:1;
00239         unsigned char b11:1;
00240         unsigned char b12:1;
00241         unsigned char b13:1;
00242         unsigned char b14:1;
00243         unsigned char b15:1;
00244         unsigned char b16:1;
00245         unsigned char b17:1;
00246         unsigned char b18:1;
00247         unsigned char b19:1;
00248         unsigned char b20:1;
00249         unsigned char b21:1;
00250         unsigned char b22:1;
00251         unsigned char b23:1;
00252         unsigned char b24:1;
00253         unsigned char b25:1;
00254         unsigned char b26:1;
00255         unsigned char b27:1;
00256         unsigned char b28:1;
00257         unsigned char b29:1;
00258         unsigned char b30:1;
00259         unsigned char b31:1;
00260         unsigned char b32:1;
00261         unsigned char b33:1;
00262         unsigned char b34:1;
00263         unsigned char b35:1;
00264         unsigned char b36:1;
00265         unsigned char b37:1;
00266         unsigned char b38:1;
00267         unsigned char b39:1;
00268         unsigned char b40:1;
00269         unsigned char b41:1;
00270         unsigned char b42:1;
00271         unsigned char b43:1;
00272         unsigned char b44:1;
00273         unsigned char b45:1;
00274         unsigned char b46:1;
00275         unsigned char b47:1;
00276         unsigned char b48:1;
00277         unsigned char b49:1;
00278         unsigned char b50:1;
00279         unsigned char b51:1;
00280         unsigned char b52:1;
00281         unsigned char b53:1;
00282         unsigned char b54:1;
00283         unsigned char b55:1;
00284         unsigned char b56:1;
00285         unsigned char b57:1;
00286         unsigned char b58:1;
00287         unsigned char b59:1;
00288         unsigned char b60:1;
00289         unsigned char b61:1;
00290         unsigned char b62:1;
00291         unsigned char b63:1;
00292     } bits;
00293 } QWORD_VAL;
00294
00295 #endif //__GENERIC_TYPE_DEFS_H_
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: HTTP2.c Source File

HTTP2.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00026 /**********************************************************************
00027  * Software License Agreement
00028  *
00029  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00030  * reserved.
00031  *
00032  * Microchip licenses to you the right to use, modify, copy, and
00033  * distribute:
00034  * (i)  the Software when embedded on a Microchip microcontroller or
00035  *      digital signal controller product ("Device") which is
00036  *      integrated into Licensee's product; or
00037  * (ii) ONLY the Software driver source files ENC28J60.c and
00038  *      ENC28J60.h ported to a non-Microchip device used in
00039  *      conjunction with a Microchip ethernet controller for the
00040  *      sole purpose of interfacing with the ethernet controller.
00041  *
00042  * You should refer to the license agreement accompanying this
00043  * Software for additional information regarding your rights and
00044  * obligations.
00045  *
00046  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00047  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00048  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00049  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00050  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00051  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00052  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00053  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00054  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00055  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00056  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00057  *
00058  *
00059  * Author               Date        Comment
00060  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00061  * Nilesh Rajbharti     8/14/01     Original
00062  * Elliott Wood         6/4/07      Complete rewrite, known as HTTP2
00063  ********************************************************************/
00064
00065 #define __HTTP2_C
00066
00067 #include "TCPIP.h"
00068
00069 // MODIFIX: Added the web.h and stringtable.h file for parameter defines.
00070 #include "web.h"
00071 #include "stringtable.h"
00072 #include "HTTPPrint.h"
00073
00074 #if defined(STACK_USE_HTTP2_SERVER)
00075
00076 /****************************************************************************
00077   Section:
00078     String Constants
00079   ***************************************************************************/
00080     static ROM BYTE HTTP_CRLF[] = "\r\n";   // New line sequence
00081     #define HTTP_CRLF_LEN   2               // Length of above string
00082
00083 /****************************************************************************
00084   Section:
00085     File and Content Type Settings
00086   ***************************************************************************/
00087     // File type extensions corresponding to HTTP_FILE_TYPE
00088     static ROM char *httpFileExtensions[HTTP_UNKNOWN+1] =
00089     {
00090         "txt",          // HTTP_TXT
00091         "htm",          // HTTP_HTM
00092         "html",         // HTTP_HTML
00093         "cgi",          // HTTP_CGI
00094         "xml",          // HTTP_XML
00095         "css",          // HTTP_CSS
00096         "gif",          // HTTP_GIF
00097         "png",          // HTTP_PNG
00098         "jpg",          // HTTP_JPG
00099         "cla",          // HTTP_JAVA
00100         "wav",          // HTTP_WAV
00101         "\0\0\0"        // HTTP_UNKNOWN
00102     };
00103
00104     // Content-type strings corresponding to HTTP_FILE_TYPE
00105     static ROM char *httpContentTypes[HTTP_UNKNOWN+1] =
00106     {
00107         "text/plain",            // HTTP_TXT
00108         "text/html",             // HTTP_HTM
00109         "text/html",             // HTTP_HTML
00110         "text/html",             // HTTP_CGI
00111         "text/xml",              // HTTP_XML
00112         "text/css",              // HTTP_CSS
00113         "image/gif",             // HTTP_GIF
00114         "image/png",             // HTTP_PNG
00115         "image/jpeg",            // HTTP_JPG
00116         "application/java-vm",   // HTTP_JAVA
00117         "audio/x-wave",          // HTTP_WAV
00118         ""                       // HTTP_UNKNOWN
00119     };
00120
00121 /****************************************************************************
00122   Section:
00123     Commands and Server Responses
00124   ***************************************************************************/
00125
00126     // Initial response strings (Corresponding to HTTP_STATUS)
00127     static ROM char *HTTPResponseHeaders[] =
00128     {
00129         "HTTP/1.1 200 OK\r\nConnection: close\r\n",
00130         "HTTP/1.1 200 OK\r\nConnection: close\r\n",
00131         "HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"Protected\"\r\nConnection: close\r\n\r\n401 Unauthorized: Password required\r\n",
00132         #if defined(HTTP_MPFS_UPLOAD)
00133         "HTTP/1.1 404 Not found\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n404: File not found<br>Use <a href=\"/" HTTP_MPFS_UPLOAD "\">MPFS Upload</a> to program web pages\r\n",
00134         #else
00135         "HTTP/1.1 404 Not found\r\nConnection: close\r\n\r\n404: File not found\r\n",
00136         #endif
00137         "HTTP/1.1 414 Request-URI Too Long\r\nConnection: close\r\n\r\n414 Request-URI Too Long: Buffer overflow detected\r\n",
00138         "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\n\r\n500 Internal Server Error: Expected data not present\r\n",
00139         "HTTP/1.1 501 Not Implemented\r\nConnection: close\r\n\r\n501 Not Implemented: Only GET and POST supported\r\n",
00140         #if defined(HTTP_MPFS_UPLOAD)
00141         "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n<html><body style=\"margin:100px\"><form method=post action=\"/" HTTP_MPFS_UPLOAD "\" enctype=\"multipart/form-data\"><b>MPFS Image Upload</b><p><input type=file name=i size=40> &nbsp; <input type=submit value=\"Upload\"></form></body></html>",
00142         "",
00143         "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n<html><body style=\"margin:100px\"><b>MPFS Update Successful</b><p><a href=\"/\">Site main page</a></body></html>",
00144         "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n<html><body style=\"margin:100px\"><b>MPFS Image Corrupt or Wrong Version</b><p><a href=\"/" HTTP_MPFS_UPLOAD "\">Try again?</a></body></html>",
00145         #endif
00146         "HTTP/1.1 302 Found\r\nConnection: close\r\nLocation: ",
00147         "HTTP/1.1 403 Forbidden\r\nConnection: close\r\n\r\n403 Forbidden: SSL Required - use HTTPS\r\n"
00148     };
00149
00150 /****************************************************************************
00151   Section:
00152     Header Parsing Configuration
00153   ***************************************************************************/
00154     #define HTTP_NUM_HEADERS        3
00155
00156     // Header strings for which we'd like to parse
00157     static ROM char *HTTPRequestHeaders[HTTP_NUM_HEADERS] =
00158     {
00159         "Cookie:",
00160         "Authorization:",
00161         "Content-Length:"
00162     };
00163
00164     // Set to length of longest string above
00165     #define HTTP_MAX_HEADER_LEN     (15u)
00166
00167 /****************************************************************************
00168   Section:
00169     HTTP Connection State Global Variables
00170   ***************************************************************************/
00171     #pragma udata HTTP_CONNECTION_STATES
00172     HTTP_CONN curHTTP;                          // Current HTTP connection state
00173     HTTP_STUB httpStubs[MAX_HTTP_CONNECTIONS];  // HTTP stubs with state machine and socket
00174     BYTE curHTTPID;                             // ID of the currently loaded HTTP_CONN
00175     #pragma udata
00176
00177 /****************************************************************************
00178   Section:
00179     Function Prototypes
00180   ***************************************************************************/
00181     static void HTTPHeaderParseLookup(BYTE i);
00182     #if defined(HTTP_USE_COOKIES)
00183     static void HTTPHeaderParseCookie(void);
00184     #endif
00185     #if defined(HTTP_USE_AUTHENTICATION)
00186     static void HTTPHeaderParseAuthorization(void);
00187     #endif
00188     #if defined(HTTP_USE_POST)
00189     static void HTTPHeaderParseContentLength(void);
00190     static HTTP_READ_STATUS HTTPReadTo(BYTE delim, BYTE* buf, WORD len);
00191     #endif
00192
00193     static void HTTPProcess(void);
00194     static BOOL HTTPSendFile(void);
00195     static void HTTPLoadConn(BYTE hHTTP);
00196
00197     #if defined(HTTP_MPFS_UPLOAD)
00198     static HTTP_IO_RESULT HTTPMPFSUpload(void);
00199     #endif
00200
00201     #define mMIN(a, b)  ((a<b)?a:b)
00202
00203 /*****************************************************************************
00204   Function:
00205     void HTTPInit(void)
00206
00207   Summary:
00208     Initializes the HTTP server module.
00209
00210   Description:
00211     Sets all HTTP sockets to the listening state, and initializes the
00212     state machine and file handles for each connection.  If SSL is
00213     enabled, opens a socket on that port as well.
00214
00215   Precondition:
00216     TCP must already be initialized.
00217
00218   Parameters:
00219     None
00220
00221   Returns:
00222     None
00223
00224   Remarks:
00225     This function is called only one during lifetime of the application.
00226   ***************************************************************************/
00227 void HTTPInit(void)
00228 {
00229     WORD oldPtr;
00230
00231     // Make sure the file handles are invalidated
00232     curHTTP.file = MPFS_INVALID_HANDLE;
00233     curHTTP.offsets = MPFS_INVALID_HANDLE;
00234
00235     for(curHTTPID = 0; curHTTPID < MAX_HTTP_CONNECTIONS; curHTTPID++)
00236     {
00237         smHTTP = SM_HTTP_IDLE;
00238         sktHTTP = TCPOpen(0, TCP_OPEN_SERVER, HTTP_PORT, TCP_PURPOSE_HTTP_SERVER);
00239         #if defined(STACK_USE_SSL_SERVER)
00240         TCPAddSSLListener(sktHTTP, HTTPS_PORT);
00241         #endif
00242
00243         // Save the default record (just invalid file handles)
00244         oldPtr = MACSetWritePtr(BASE_HTTPB_ADDR + curHTTPID*sizeof(HTTP_CONN));
00245         MACPutArray((BYTE*)&curHTTP, sizeof(HTTP_CONN));
00246         MACSetWritePtr(oldPtr);
00247     }
00248 }
00249
00250
00251 /*****************************************************************************
00252   Function:
00253     void HTTPServer(void)
00254
00255   Summary:
00256     Performs periodic tasks for the HTTP2 module.
00257
00258   Description:
00259     Browses through each open connection and attempts to process any
00260     pending operations.
00261
00262   Precondition:
00263     HTTPInit() must already be called.
00264
00265   Parameters:
00266     None
00267
00268   Returns:
00269     None
00270
00271   Remarks:
00272     This function acts as a task (similar to one in an RTOS).  It
00273     performs its task in a co-operative manner, and the main application
00274     must call this function repeatedly to ensure that all open or new
00275     connections are served in a timely fashion.
00276   ***************************************************************************/
00277 void HTTPServer(void)
00278 {
00279     BYTE conn;
00280
00281     for(conn = 0; conn < MAX_HTTP_CONNECTIONS; conn++)
00282     {
00283         if(httpStubs[conn].socket == INVALID_SOCKET)
00284             continue;
00285
00286         // If a socket is disconnected at any time
00287         // forget about it and return to idle state.
00288         // Must do this here, otherwise we will wait until a new
00289         // connection arrives, which causes problems with Linux and with SSL
00290         if(TCPWasReset(httpStubs[conn].socket))
00291         {
00292             HTTPLoadConn(conn);
00293             smHTTP = SM_HTTP_IDLE;
00294
00295             // Make sure any opened files are closed
00296             if(curHTTP.file != MPFS_INVALID_HANDLE)
00297             {
00298                 MPFSClose(curHTTP.file);
00299                 curHTTP.file = MPFS_INVALID_HANDLE;
00300             }
00301             if(curHTTP.offsets != MPFS_INVALID_HANDLE)
00302             {
00303                 MPFSClose(curHTTP.offsets);
00304                 curHTTP.offsets = MPFS_INVALID_HANDLE;
00305             }
00306
00307             // Adjust FIFO sizes to half and half.  Default state must remain
00308             // here so that SSL handshakes, if required, can proceed
00309             TCPAdjustFIFOSize(sktHTTP, 1, 0, TCP_ADJUST_PRESERVE_RX);
00310         }
00311
00312         // Determine if this connection is eligible for processing
00313         if(httpStubs[conn].sm != SM_HTTP_IDLE || TCPIsGetReady(httpStubs[conn].socket))
00314         {
00315             HTTPLoadConn(conn);
00316             HTTPProcess();
00317         }
00318     }
00319 }
00320
00321 /*****************************************************************************
00322   Function:
00323     static void HTTPLoadConn(BYTE hHTTP)
00324
00325   Summary:
00326     Switches the currently loaded connection for the HTTP2 module.
00327
00328   Description:
00329     Saves the currently loaded HTTP connection back to Ethernet buffer
00330     RAM, then loads the selected connection into curHTTP in local RAM
00331     for processing.
00332
00333   Precondition:
00334     None
00335
00336   Parameters:
00337     hHTTP - the connection ID to load
00338
00339   Returns:
00340     None
00341   ***************************************************************************/
00342 static void HTTPLoadConn(BYTE hHTTP)
00343 {
00344     WORD oldPtr;
00345
00346     // Return if already loaded
00347     if(hHTTP == curHTTPID)
00348         return;
00349
00350     // Save the old one
00351     oldPtr = MACSetWritePtr(BASE_HTTPB_ADDR + curHTTPID*sizeof(HTTP_CONN));
00352     MACPutArray((BYTE*)&curHTTP, sizeof(HTTP_CONN));
00353     MACSetWritePtr(oldPtr);
00354
00355     // Load the new one
00356     oldPtr = MACSetReadPtr(BASE_HTTPB_ADDR + hHTTP*sizeof(HTTP_CONN));
00357     MACGetArray((BYTE*)&curHTTP, sizeof(HTTP_CONN));
00358     MACSetReadPtr(oldPtr);
00359
00360     // Remember which one is loaded
00361     curHTTPID = hHTTP;
00362
00363 }
00364
00365 /*****************************************************************************
00366   Function:
00367     static void HTTPProcess(void)
00368
00369   Description:
00370     Performs any pending operations for the currently loaded HTTP connection.
00371
00372   Precondition:
00373     HTTPInit() and HTTPLoadConn() have been called.
00374
00375   Parameters:
00376     None
00377
00378   Returns:
00379     None
00380   ***************************************************************************/
00381 static void HTTPProcess(void)
00382 {
00383     WORD lenA, lenB;
00384     BYTE c, i;
00385     BOOL isDone;
00386     BYTE *ext;
00387     BYTE buffer[HTTP_MAX_HEADER_LEN+1];
00388
00389     do
00390     {
00391         isDone = TRUE;
00392
00393         switch(smHTTP)
00394         {
00395
00396         case SM_HTTP_IDLE:
00397
00398             // Check how much data is waiting
00399             lenA = TCPIsGetReady(sktHTTP);
00400
00401             // If a connection has been made, then process the request
00402             if(lenA)
00403             {// Clear out state info and move to next state
00404                 curHTTP.ptrData = curHTTP.data;
00405                 smHTTP = SM_HTTP_PARSE_REQUEST;
00406                 curHTTP.isAuthorized = 0xff;
00407                 curHTTP.hasArgs = FALSE;
00408                 curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;
00409                 curHTTP.callbackPos = 0xffffffff;
00410                 curHTTP.byteCount = 0;
00411                 #if defined(HTTP_USE_POST)
00412                 curHTTP.smPost = 0x00;
00413                 #endif
00414
00415                 // Adjust the TCP FIFOs for optimal reception of
00416                 // the next HTTP request from the browser
00417                 TCPAdjustFIFOSize(sktHTTP, 1, 0, TCP_ADJUST_PRESERVE_RX | TCP_ADJUST_GIVE_REST_TO_RX);
00418             }
00419             else
00420                 // Don't break for new connections.  There may be
00421                 // an entire request in the buffer already.
00422                 break;
00423
00424         case SM_HTTP_PARSE_REQUEST:
00425
00426             // Verify the entire first line is in the FIFO
00427             if(TCPFind(sktHTTP, '\n', 0, FALSE) == 0xffff)
00428             {// First line isn't here yet
00429                 if(TCPGetRxFIFOFree(sktHTTP) == 0)
00430                 {// If the FIFO is full, we overflowed
00431                     curHTTP.httpStatus = HTTP_OVERFLOW;
00432                     smHTTP = SM_HTTP_SERVE_HEADERS;
00433                     isDone = FALSE;
00434                 }
00435                 if((LONG)(TickGet() - curHTTP.callbackID) > (LONG)0)
00436                 {// A timeout has occurred
00437                     TCPDisconnect(sktHTTP);
00438                     smHTTP = SM_HTTP_DISCONNECT;
00439                     isDone = FALSE;
00440                 }
00441                 break;
00442             }
00443
00444             // Reset the watchdog timer
00445             curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;
00446
00447             // Determine the request method
00448             lenA = TCPFind(sktHTTP, ' ', 0, FALSE);
00449             if(lenA > 5)
00450                 lenA = 5;
00451             TCPGetArray(sktHTTP, curHTTP.data, lenA+1);
00452
00453             if ( memcmppgm2ram(curHTTP.data, (ROM void*)"GET", 3) == 0)
00454                 curHTTP.httpStatus = HTTP_GET;
00455             #if defined(HTTP_USE_POST)
00456             else if ( memcmppgm2ram(curHTTP.data, (ROM void*)"POST", 4) == 0)
00457                 curHTTP.httpStatus = HTTP_POST;
00458             #endif
00459             else
00460             {// Unrecognized method, so return not implemented
00461                 curHTTP.httpStatus = HTTP_NOT_IMPLEMENTED;
00462                 smHTTP = SM_HTTP_SERVE_HEADERS;
00463                 isDone = FALSE;
00464                 break;
00465             }
00466
00467             // Find end of filename
00468             lenA = TCPFind(sktHTTP, ' ', 0, FALSE);
00469             lenB = TCPFindEx(sktHTTP, '?', 0, lenA, FALSE);
00470             lenA = mMIN(lenA, lenB);
00471
00472             // If the file name is too long, then reject the request
00473             if(lenA > HTTP_MAX_DATA_LEN - HTTP_DEFAULT_LEN - 1)
00474             {
00475                 curHTTP.httpStatus = HTTP_OVERFLOW;
00476                 smHTTP = SM_HTTP_SERVE_HEADERS;
00477                 isDone = FALSE;
00478                 break;
00479             }
00480
00481             // Read in the filename and decode
00482             lenB = TCPGetArray(sktHTTP, curHTTP.data, lenA);
00483             curHTTP.data[lenB] = '\0';
00484             HTTPURLDecode(curHTTP.data);
00485
00486             // Check if this is an MPFS Upload
00487             #if defined(HTTP_MPFS_UPLOAD)
00488             if(memcmppgm2ram(&curHTTP.data[1], HTTP_MPFS_UPLOAD, strlenpgm(HTTP_MPFS_UPLOAD)) == 0)
00489             {// Read remainder of line, and bypass all file opening, etc.
00490                 #if defined(HTTP_USE_AUTHENTICATION)
00491                 curHTTP.isAuthorized = HTTPNeedsAuth(&curHTTP.data[1]);
00492                 #endif
00493                 if(curHTTP.httpStatus == HTTP_GET)
00494                     curHTTP.httpStatus = HTTP_MPFS_FORM;
00495                 else
00496                     curHTTP.httpStatus = HTTP_MPFS_UP;
00497
00498                 smHTTP = SM_HTTP_PARSE_HEADERS;
00499                 isDone = FALSE;
00500                 break;
00501             }
00502             #endif
00503
00504             // If the last character is a not a directory delimiter, then try to open the file
00505             // String starts at 2nd character, because the first is always a '/'
00506             if(curHTTP.data[lenB-1] != '/')
00507                 curHTTP.file = MPFSOpen(&curHTTP.data[1]);
00508
00509             // If the open fails, then add our default name and try again
00510             if(curHTTP.file == MPFS_INVALID_HANDLE)
00511             {
00512                 // Add the directory delimiter if needed
00513                 if(curHTTP.data[lenB-1] != '/')
00514                     curHTTP.data[lenB++] = '/';
00515
00516                 // Add our default file name
00517                 #if defined(STACK_USE_SSL_SERVER)
00518                 if(TCPIsSSL(sktHTTP))
00519                 {
00520                     strcpypgm2ram((void*)&curHTTP.data[lenB], HTTPS_DEFAULT_FILE);
00521                     lenB += strlenpgm(HTTPS_DEFAULT_FILE);
00522                 }
00523                 else
00524                 #endif
00525                 {
00526                     strcpypgm2ram((void*)&curHTTP.data[lenB], HTTP_DEFAULT_FILE);
00527                     lenB += strlenpgm(HTTP_DEFAULT_FILE);
00528                 }
00529
00530                 // Try to open again
00531                 curHTTP.file = MPFSOpen(&curHTTP.data[1]);
00532             }
00533
00534             // Find the extension in the filename
00535             for(ext = curHTTP.data + lenB-1; ext != curHTTP.data; ext--)
00536                 if(*ext == '.')
00537                     break;
00538
00539             // Compare to known extensions to determine Content-Type
00540             ext++;
00541             for(curHTTP.fileType = HTTP_TXT; curHTTP.fileType < HTTP_UNKNOWN; curHTTP.fileType++)
00542                 if(!stricmppgm2ram(ext, (ROM void*)httpFileExtensions[curHTTP.fileType]))
00543                     break;
00544
00545             // Perform first round authentication (pass file name only)
00546             #if defined(HTTP_USE_AUTHENTICATION)
00547             curHTTP.isAuthorized = HTTPNeedsAuth(&curHTTP.data[1]);
00548             #endif
00549
00550             // If the file was found, see if it has an index
00551             if(curHTTP.file != MPFS_INVALID_HANDLE &&
00552                 (MPFSGetFlags(curHTTP.file) & MPFS2_FLAG_HASINDEX) )
00553             {
00554                 curHTTP.offsets = MPFSOpenID(MPFSGetID(curHTTP.file) + 1);
00555             }
00556
00557             // Read GET args, up to buffer size - 1
00558             lenA = TCPFind(sktHTTP, ' ', 0, FALSE);
00559             if(lenA != 0)
00560             {
00561                 curHTTP.hasArgs = TRUE;
00562
00563                 // Trash the '?'
00564                 TCPGet(sktHTTP, &c);
00565
00566                 // Verify there's enough space
00567                 lenA--;
00568                 if(lenA >= HTTP_MAX_DATA_LEN - 2)
00569                 {
00570                     curHTTP.httpStatus = HTTP_OVERFLOW;
00571                     smHTTP = SM_HTTP_SERVE_HEADERS;
00572                     isDone = FALSE;
00573                     break;
00574                 }
00575
00576                 // Read in the arguments and '&'-terminate in anticipation of cookies
00577                 curHTTP.ptrData += TCPGetArray(sktHTTP, curHTTP.data, lenA);
00578                 *(curHTTP.ptrData++) = '&';
00579
00580             }
00581
00582             // Clear the rest of the line
00583             lenA = TCPFind(sktHTTP, '\n', 0, FALSE);
00584             TCPGetArray(sktHTTP, NULL, lenA + 1);
00585
00586             // Move to parsing the headers
00587             smHTTP = SM_HTTP_PARSE_HEADERS;
00588
00589             // No break, continue to parsing headers
00590
00591         case SM_HTTP_PARSE_HEADERS:
00592
00593             // Loop over all the headers
00594             while(1)
00595             {
00596                 // Make sure entire line is in the FIFO
00597                 lenA = TCPFind(sktHTTP, '\n', 0, FALSE);
00598                 if(lenA == 0xffff)
00599                 {// If not, make sure we can receive more data
00600                     if(TCPGetRxFIFOFree(sktHTTP) == 0)
00601                     {// Overflow
00602                         curHTTP.httpStatus = HTTP_OVERFLOW;
00603                         smHTTP = SM_HTTP_SERVE_HEADERS;
00604                         isDone = FALSE;
00605                     }
00606                     if((LONG)(TickGet() - curHTTP.callbackID) > (LONG)0)
00607                     {// A timeout has occured
00608                         TCPDisconnect(sktHTTP);
00609                         smHTTP = SM_HTTP_DISCONNECT;
00610                         isDone = FALSE;
00611                     }
00612                     break;
00613                 }
00614
00615                 // Reset the watchdog timer
00616                 curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;
00617
00618                 // If a CRLF is immediate, then headers are done
00619                 if(lenA == 1)
00620                 {// Remove the CRLF and move to next state
00621                     TCPGetArray(sktHTTP, NULL, 2);
00622                     smHTTP = SM_HTTP_AUTHENTICATE;
00623                     isDone = FALSE;
00624                     break;
00625                 }
00626
00627                 // Find the header name, and use isDone as a flag to indicate a match
00628                 lenB = TCPFindEx(sktHTTP, ':', 0, lenA, FALSE) + 2;
00629                 isDone = FALSE;
00630
00631                 // If name is too long or this line isn't a header, ignore it
00632                 if(lenB > sizeof(buffer))
00633                 {
00634                     TCPGetArray(sktHTTP, NULL, lenA+1);
00635                     continue;
00636                 }
00637
00638                 // Read in the header name
00639                 TCPGetArray(sktHTTP, buffer, lenB);
00640                 buffer[lenB-1] = '\0';
00641                 lenA -= lenB;
00642
00643                 // Compare header read to ones we're interested in
00644                 for(i = 0; i < HTTP_NUM_HEADERS; i++)
00645                 {
00646                     if(strcmppgm2ram((char*)buffer, (ROM char *)HTTPRequestHeaders[i]) == 0)
00647                     {// Parse the header and stop the loop
00648                         HTTPHeaderParseLookup(i);
00649                         isDone = TRUE;
00650                         break;
00651                     }
00652                 }
00653
00654                 // Clear the rest of the line, and call the loop again
00655                 if(isDone)
00656                 {// We already know how much to remove unless a header was found
00657                     lenA = TCPFind(sktHTTP, '\n', 0, FALSE);
00658                 }
00659                 TCPGetArray(sktHTTP, NULL, lenA+1);
00660             }
00661
00662             break;
00663
00664         case SM_HTTP_AUTHENTICATE:
00665
00666             #if defined(HTTP_USE_AUTHENTICATION)
00667             // Check current authorization state
00668             if(curHTTP.isAuthorized < 0x80)
00669             {// 401 error
00670                 curHTTP.httpStatus = HTTP_UNAUTHORIZED;
00671                 smHTTP = SM_HTTP_SERVE_HEADERS;
00672                 isDone = FALSE;
00673
00674                 #if defined(HTTP_NO_AUTH_WITHOUT_SSL)
00675                 if(!TCPIsSSL(sktHTTP))
00676                     curHTTP.httpStatus = HTTP_SSL_REQUIRED;
00677                 #endif
00678
00679                 break;
00680             }
00681             #endif
00682
00683             // Parse the args string
00684             *curHTTP.ptrData = '\0';
00685             curHTTP.ptrData = HTTPURLDecode(curHTTP.data);
00686
00687             // If this is an MPFS upload form request, bypass to headers
00688             #if defined(HTTP_MPFS_UPLOAD)
00689             if(curHTTP.httpStatus == HTTP_MPFS_FORM)
00690             {
00691                 smHTTP = SM_HTTP_SERVE_HEADERS;
00692                 isDone = FALSE;
00693                 break;
00694             }
00695             #endif
00696
00697             // Move on to GET args, unless there are none
00698             smHTTP = SM_HTTP_PROCESS_GET;
00699             if(!curHTTP.hasArgs)
00700                 smHTTP = SM_HTTP_PROCESS_POST;
00701             isDone = FALSE;
00702             curHTTP.hasArgs = FALSE;
00703             break;
00704
00705         case SM_HTTP_PROCESS_GET:
00706
00707             // Run the application callback HTTPExecuteGet()
00708             if(HTTPExecuteGet() == HTTP_IO_WAITING)
00709             {// If waiting for asynchronous process, return to main app
00710                 break;
00711             }
00712
00713             // Move on to POST data
00714             smHTTP = SM_HTTP_PROCESS_POST;
00715
00716         case SM_HTTP_PROCESS_POST:
00717
00718             #if defined(HTTP_USE_POST)
00719
00720             // See if we have any new data
00721             if(TCPIsGetReady(sktHTTP) == curHTTP.callbackPos)
00722             {
00723                 if((LONG)(TickGet() - curHTTP.callbackID) > (LONG)0)
00724                 {// If a timeout has occured, disconnect
00725                     TCPDisconnect(sktHTTP);
00726                     smHTTP = SM_HTTP_DISCONNECT;
00727                     isDone = FALSE;
00728                     break;
00729                 }
00730             }
00731
00732             if(curHTTP.httpStatus == HTTP_POST
00733                 #if defined(HTTP_MPFS_UPLOAD)
00734                 || (curHTTP.httpStatus >= HTTP_MPFS_UP && curHTTP.httpStatus <= HTTP_MPFS_ERROR)
00735                 #endif
00736                  )
00737             {
00738                 // Run the application callback HTTPExecutePost()
00739                 #if defined(HTTP_MPFS_UPLOAD)
00740                 if(curHTTP.httpStatus >= HTTP_MPFS_UP && curHTTP.httpStatus <= HTTP_MPFS_ERROR)
00741                 {
00742                     c = HTTPMPFSUpload();
00743                     if(c == HTTP_IO_DONE)
00744                     {
00745                         smHTTP = SM_HTTP_SERVE_HEADERS;
00746                         isDone = FALSE;
00747                         break;
00748                     }
00749                 }
00750                 else
00751                 #endif
00752                 c = HTTPExecutePost();
00753
00754                 // If waiting for asynchronous process, return to main app
00755                 if(c == HTTP_IO_WAITING)
00756                 {// return to main app and make sure we don't get stuck by the watchdog
00757                     curHTTP.callbackPos = TCPIsGetReady(sktHTTP) - 1;
00758                     break;
00759                 }
00760                 else if(c == HTTP_IO_NEED_DATA)
00761                 {// If waiting for more data
00762                     curHTTP.callbackPos = TCPIsGetReady(sktHTTP);
00763                     curHTTP.callbackID = TickGet() + HTTP_TIMEOUT*TICK_SECOND;
00764
00765                     // If more is expected and space is available, return to main app
00766                     if(curHTTP.byteCount > curHTTP.callbackPos && TCPGetRxFIFOFree(sktHTTP) != 0)
00767                         break;
00768
00769                     // Handle cases where application ran out of data or buffer space
00770                     curHTTP.httpStatus = HTTP_INTERNAL_SERVER_ERROR;
00771                     smHTTP = SM_HTTP_SERVE_HEADERS;
00772                     isDone = FALSE;
00773                     break;
00774                 }
00775             }
00776             #endif
00777
00778             // We're done with POST
00779             smHTTP = SM_HTTP_PROCESS_REQUEST;
00780             // No break, continue to sending request
00781
00782         case SM_HTTP_PROCESS_REQUEST:
00783
00784             // Check for 404
00785             if(curHTTP.file == MPFS_INVALID_HANDLE)
00786             {
00787                 curHTTP.httpStatus = HTTP_NOT_FOUND;
00788                 smHTTP = SM_HTTP_SERVE_HEADERS;
00789                 isDone = FALSE;
00790                 break;
00791             }
00792
00793             // Set up the dynamic substitutions
00794             curHTTP.byteCount = 0;
00795             if(curHTTP.offsets == MPFS_INVALID_HANDLE)
00796             {// If no index file, then set next offset to huge
00797                 curHTTP.nextCallback = 0xffffffff;
00798             }
00799             else
00800             {// Read in the next callback index
00801                 MPFSGetLong(curHTTP.offsets, &(curHTTP.nextCallback));
00802             }
00803
00804             // Move to next state
00805             smHTTP = SM_HTTP_SERVE_HEADERS;
00806
00807         case SM_HTTP_SERVE_HEADERS:
00808
00809             // We're in write mode now:
00810             // Adjust the TCP FIFOs for optimal transmission of
00811             // the HTTP response to the browser
00812             TCPAdjustFIFOSize(sktHTTP, 1, 0, TCP_ADJUST_GIVE_REST_TO_TX);
00813
00814             // Send headers
00815             TCPPutROMString(sktHTTP, (ROM BYTE*)HTTPResponseHeaders[curHTTP.httpStatus]);
00816
00817             // If this is a redirect, print the rest of the Location: header
00818             if(curHTTP.httpStatus == HTTP_REDIRECT)
00819             {
00820                 TCPPutString(sktHTTP, curHTTP.data);
00821                 TCPPutROMString(sktHTTP, (ROM BYTE*)"\r\n\r\n304 Redirect: ");
00822                 TCPPutString(sktHTTP, curHTTP.data);
00823                 TCPPutROMString(sktHTTP, (ROM BYTE*)HTTP_CRLF);
00824             }
00825
00826             // If not GET or POST, we're done
00827             if(curHTTP.httpStatus != HTTP_GET && curHTTP.httpStatus != HTTP_POST)
00828             {// Disconnect
00829                 smHTTP = SM_HTTP_DISCONNECT;
00830                 break;
00831             }
00832
00833             // Output the content type, if known
00834             if(curHTTP.fileType != HTTP_UNKNOWN)
00835             {
00836                 TCPPutROMString(sktHTTP, (ROM BYTE*)"Content-Type: ");
00837                 TCPPutROMString(sktHTTP, (ROM BYTE*)httpContentTypes[curHTTP.fileType]);
00838                 TCPPutROMString(sktHTTP, HTTP_CRLF);
00839             }
00840
00841             // Output the gzip encoding header if needed
00842             if(MPFSGetFlags(curHTTP.file) & MPFS2_FLAG_ISZIPPED)
00843             {
00844                 TCPPutROMString(sktHTTP, (ROM BYTE*)"Content-Encoding: gzip\r\n");
00845             }
00846
00847             // Output the cache-control
00848             TCPPutROMString(sktHTTP, (ROM BYTE*)"Cache-Control: ");
00849             if(curHTTP.httpStatus == HTTP_POST || curHTTP.nextCallback != 0xffffffff)
00850             {// This is a dynamic page or a POST request, so no cache
00851                 TCPPutROMString(sktHTTP, (ROM BYTE*)"no-cache");
00852             }
00853             else
00854             {// This is a static page, so save it for the specified amount of time
00855                 TCPPutROMString(sktHTTP, (ROM BYTE*)"max-age=");
00856                 TCPPutROMString(sktHTTP, (ROM BYTE*)HTTP_CACHE_LEN);
00857             }
00858             TCPPutROMString(sktHTTP, HTTP_CRLF);
00859
00860             // Check if we should output cookies
00861             if(curHTTP.hasArgs)
00862                 smHTTP = SM_HTTP_SERVE_COOKIES;
00863             else
00864             {// Terminate the headers
00865                 TCPPutROMString(sktHTTP, HTTP_CRLF);
00866                 smHTTP = SM_HTTP_SERVE_BODY;
00867             }
00868
00869             // Move to next stage
00870             isDone = FALSE;
00871             break;
00872
00873         case SM_HTTP_SERVE_COOKIES:
00874
00875             #if defined(HTTP_USE_COOKIES)
00876             // If the TX FIFO runs out of space, the client will never get CRLFCRLF
00877             // Avoid writing huge cookies - keep it under a hundred bytes max
00878
00879             // Write cookies one at a time as space permits
00880             for(curHTTP.ptrRead = curHTTP.data; curHTTP.hasArgs != 0; curHTTP.hasArgs--)
00881             {
00882                 // Write the header
00883                 TCPPutROMString(sktHTTP, (ROM BYTE*)"Set-Cookie: ");
00884
00885                 // Write the name, URL encoded, one character at a time
00886                 while((c = *(curHTTP.ptrRead++)))
00887                 {
00888                     if(c == ' ')
00889                         TCPPut(sktHTTP, '+');
00890                     else if(c < '0' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a') || c > 'z')
00891                     {
00892                         TCPPut(sktHTTP, '%');
00893                         TCPPut(sktHTTP, btohexa_high(c));
00894                         TCPPut(sktHTTP, btohexa_low(c));
00895                     }
00896                     else
00897                         TCPPut(sktHTTP, c);
00898                 }
00899
00900                 TCPPut(sktHTTP, '=');
00901
00902                 // Write the value, URL encoded, one character at a time
00903                 while((c = *(curHTTP.ptrRead++)))
00904                 {
00905                     if(c == ' ')
00906                         TCPPut(sktHTTP, '+');
00907                     else if(c < '0' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a') || c > 'z')
00908                     {
00909                         TCPPut(sktHTTP, '%');
00910                         TCPPut(sktHTTP, btohexa_high(c));
00911                         TCPPut(sktHTTP, btohexa_low(c));
00912                     }
00913                     else
00914                         TCPPut(sktHTTP, c);
00915                 }
00916
00917                 // Finish the line
00918                 TCPPutROMString(sktHTTP, HTTP_CRLF);
00919
00920             }
00921             #endif
00922
00923             // We're done, move to next state
00924             TCPPutROMString(sktHTTP, HTTP_CRLF);
00925             smHTTP = SM_HTTP_SERVE_BODY;
00926
00927         case SM_HTTP_SERVE_BODY:
00928
00929             isDone = FALSE;
00930
00931             // Try to send next packet
00932             if(HTTPSendFile())
00933             {// If EOF, then we're done so close and disconnect
00934                 MPFSClose(curHTTP.file);
00935                 curHTTP.file = MPFS_INVALID_HANDLE;
00936                 smHTTP = SM_HTTP_DISCONNECT;
00937                 isDone = TRUE;
00938             }
00939
00940             // If the TX FIFO is full, then return to main app loop
00941             if(TCPIsPutReady(sktHTTP) == 0)
00942                 isDone = TRUE;
00943             break;
00944
00945         case SM_HTTP_SEND_FROM_CALLBACK:
00946
00947             isDone = TRUE;
00948
00949             // Check that at least the minimum bytes are free
00950             if(TCPIsPutReady(sktHTTP) < HTTP_MIN_CALLBACK_FREE)
00951                 break;
00952
00953             // Fill TX FIFO from callback
00954             HTTPPrint(curHTTP.callbackID);
00955
00956             if(curHTTP.callbackPos == 0)
00957             {// Callback finished its output, so move on
00958                 isDone = FALSE;
00959                 smHTTP = SM_HTTP_SERVE_BODY;
00960             }// Otherwise, callback needs more buffer space, so return and wait
00961
00962             break;
00963
00964         case SM_HTTP_DISCONNECT:
00965             // Make sure any opened files are closed
00966             if(curHTTP.file != MPFS_INVALID_HANDLE)
00967             {
00968                 MPFSClose(curHTTP.file);
00969                 curHTTP.file = MPFS_INVALID_HANDLE;
00970             }
00971             if(curHTTP.offsets != MPFS_INVALID_HANDLE)
00972             {
00973                 MPFSClose(curHTTP.offsets);
00974                 curHTTP.offsets = MPFS_INVALID_HANDLE;
00975             }
00976
00977             TCPDisconnect(sktHTTP);
00978             smHTTP = SM_HTTP_IDLE;
00979             break;
00980         }
00981     } while(!isDone);
00982
00983 }
00984
00985
00986 /*****************************************************************************
00987   Function:
00988     static BOOL HTTPSendFile(void)
00989
00990   Description:
00991     Serves up the next chunk of curHTTP's file, up to a) available TX FIFO
00992     space or b) the next callback index, whichever comes first.
00993
00994   Precondition:
00995     curHTTP.file and curHTTP.offsets have both been opened for reading.
00996
00997   Parameters:
00998     None
00999
01000   Return Values:
01001     TRUE - the end of the file was reached and reading is done
01002     FALSE - more data remains to be read
01003   ***************************************************************************/
01004 static BOOL HTTPSendFile(void)
01005 {
01006     WORD numBytes, len;
01007     BYTE c, data[64];
01008
01009     // Determine how many bytes we can read right now
01010     len = TCPIsPutReady(sktHTTP);
01011     numBytes = mMIN(len, curHTTP.nextCallback - curHTTP.byteCount);
01012
01013     // Get/put as many bytes as possible
01014     curHTTP.byteCount += numBytes;
01015     while(numBytes > 0)
01016     {
01017         len = MPFSGetArray(curHTTP.file, data, mMIN(numBytes, 64));
01018         if(len == 0)
01019             return TRUE;
01020         else
01021             TCPPutArray(sktHTTP, data, len);
01022         numBytes -= len;
01023     }
01024
01025     // Check if a callback index was reached
01026     if(curHTTP.byteCount == curHTTP.nextCallback)
01027     {
01028         // Update the state machine
01029         smHTTP = SM_HTTP_SEND_FROM_CALLBACK;
01030         curHTTP.callbackPos = 0;
01031
01032         // Read past the variable name and close the MPFS
01033 /* MODIFIX: Commented out, because in the changed MPFS utility this variables
01034 are removed from the destination image to save memory space.
01035         MPFSGet(curHTTP.file, NULL);
01036         do
01037         {
01038             if(!MPFSGet(curHTTP.file, &c))
01039                 break;
01040             curHTTP.byteCount++;
01041         } while(c != '~');
01042         curHTTP.byteCount++;
01043 */
01044         // Read in the callback address and next offset
01045         MPFSGetLong(curHTTP.offsets, &(curHTTP.callbackID));
01046         if(!MPFSGetLong(curHTTP.offsets, &(curHTTP.nextCallback)))
01047         {
01048             curHTTP.nextCallback = 0xffffffff;
01049             MPFSClose(curHTTP.offsets);
01050             curHTTP.offsets = MPFS_INVALID_HANDLE;
01051         }
01052     }
01053
01054     // We are not done sending a file yet...
01055     return FALSE;
01056 }
01057
01058 /*****************************************************************************
01059   Function:
01060     static void HTTPHeaderParseLookup(BYTE i)
01061
01062   Description:
01063     Calls the appropriate header parser based on the index of the header
01064     that was read from the request.
01065
01066   Precondition:
01067     None
01068
01069   Parameters:
01070     i - the index of the string found in HTTPRequestHeaders
01071
01072   Return Values:
01073     TRUE - the end of the file was reached and reading is done
01074     FALSE - more data remains to be read
01075   ***************************************************************************/
01076 static void HTTPHeaderParseLookup(BYTE i)
01077 {
01078     // i corresponds to an index in HTTPRequestHeaders
01079
01080     #if defined(HTTP_USE_COOKIES)
01081     if(i == 0u)
01082     {
01083         HTTPHeaderParseCookie();
01084         return;
01085     }
01086     #endif
01087
01088     #if defined(HTTP_USE_AUTHENTICATION)
01089     if(i == 1u)
01090     {
01091         HTTPHeaderParseAuthorization();
01092         return;
01093     }
01094     #endif
01095
01096     #if defined(HTTP_USE_POST)
01097     if(i == 2u)
01098     {
01099         HTTPHeaderParseContentLength();
01100         return;
01101     }
01102     #endif
01103 }
01104
01105 /*****************************************************************************
01106   Function:
01107     static void HTTPHeaderParseAuthorization(void)
01108
01109   Summary:
01110     Parses the "Authorization:" header for a request and verifies the
01111     credentials.
01112
01113   Description:
01114     Parses the "Authorization:" header for a request.  For example,
01115     "BASIC YWRtaW46cGFzc3dvcmQ=" is decoded to a user name of "admin" and
01116     a password of "password".  Once read, HTTPCheckAuth is called from
01117     CustomHTTPApp.c to determine if the credentials are acceptable.
01118
01119     The return value of HTTPCheckAuth is saved in curHTTP.isAuthorized for
01120     later use by the application.
01121
01122   Precondition:
01123     None
01124
01125   Parameters:
01126     None
01127
01128   Returns:
01129     None
01130
01131   Remarks:
01132     This function is ony available when HTTP_USE_AUTHENTICATION is defined.
01133   ***************************************************************************/
01134 #if defined(HTTP_USE_AUTHENTICATION)
01135 static void HTTPHeaderParseAuthorization(void)
01136 {
01137     WORD len;
01138     BYTE buf[40];
01139     BYTE *ptrBuf;
01140
01141     // If auth processing is not required, return
01142     if(curHTTP.isAuthorized & 0x80)
01143         return;
01144
01145     // Clear the auth type ("BASIC ")
01146     TCPGetArray(sktHTTP, NULL, 6);
01147
01148     // Find the terminating CRLF and make sure it's a multiple of four
01149     len = TCPFindROMArray(sktHTTP, HTTP_CRLF, HTTP_CRLF_LEN, 0, FALSE);
01150     len += 3;
01151     len &= 0xfc;
01152     len = mMIN(len, sizeof(buf)-4);
01153
01154     // Read in 4 bytes at a time and decode (slower, but saves RAM)
01155     for(ptrBuf = buf; len > 0; len-=4, ptrBuf+=3)
01156     {
01157         TCPGetArray(sktHTTP, ptrBuf, 4);
01158         Base64Decode(ptrBuf, 4, ptrBuf, 3);
01159     }
01160
01161     // Null terminate both, and make sure there's at least two terminators
01162     *ptrBuf = '\0';
01163     for(len = 0, ptrBuf = buf; len < sizeof(buf); len++, ptrBuf++)
01164         if(*ptrBuf == ':')
01165             break;
01166     *(ptrBuf++) = '\0';
01167
01168     // Verify credentials
01169     curHTTP.isAuthorized = HTTPCheckAuth(buf, ptrBuf);
01170
01171     return;
01172 }
01173 #endif
01174
01175 /*****************************************************************************
01176   Function:
01177     static void HTTPHeaderParseCookie(void)
01178
01179   Summary:
01180     Parses the "Cookie:" headers for a request and stores them as GET
01181     variables.
01182
01183   Description:
01184     Parses the "Cookie:" headers for a request.  For example,
01185     "Cookie: name=Wile+E.+Coyote; order=ROCKET_LAUNCHER" is decoded to
01186     "name=Wile+E.+Coyote&order=ROCKET_LAUNCHER&" and stored as any other
01187     GET variable in curHTTP.data.
01188
01189     The user application can easily access these values later using the
01190     HTTPGetArg() and HTTPGetROMArg() functions.
01191
01192   Precondition:
01193     None
01194
01195   Parameters:
01196     None
01197
01198   Returns:
01199     None
01200
01201   Remarks:
01202     This function is ony available when HTTP_USE_COOKIES is defined.
01203   ***************************************************************************/
01204 #if defined(HTTP_USE_COOKIES)
01205 static void HTTPHeaderParseCookie(void)
01206 {
01207     WORD lenA, lenB;
01208
01209     // Verify there's enough space
01210     lenB = TCPFindROMArray(sktHTTP, HTTP_CRLF, HTTP_CRLF_LEN, 0, FALSE);
01211     if(lenB >= curHTTP.data + HTTP_MAX_DATA_LEN - curHTTP.ptrData - 2)
01212     {// If not, overflow
01213         curHTTP.httpStatus = HTTP_OVERFLOW;
01214         smHTTP = SM_HTTP_SERVE_HEADERS;
01215         return;
01216     }
01217
01218     // While a CRLF is not immediate, grab a cookie value
01219     while(lenB != 0)
01220     {
01221         // Look for a ';' and use the shorter of that or a CRLF
01222         lenA = TCPFind(sktHTTP, ';', 0, FALSE);
01223
01224         // Read to the terminator
01225         curHTTP.ptrData += TCPGetArray(sktHTTP, curHTTP.ptrData, mMIN(lenA, lenB));
01226
01227         // Insert an & to anticipate another cookie
01228         *(curHTTP.ptrData++) = '&';
01229
01230         // If semicolon, trash it and whitespace
01231         if(lenA < lenB)
01232         {
01233             TCPGet(sktHTTP, NULL);
01234             while(TCPFind(sktHTTP, ' ', 0, FALSE) == 0)
01235                 TCPGet(sktHTTP, NULL);
01236         }
01237
01238         // Find the new distance to the CRLF
01239         lenB = TCPFindROMArray(sktHTTP, HTTP_CRLF, HTTP_CRLF_LEN, 0, FALSE);
01240     }
01241
01242     return;
01243
01244 }
01245 #endif
01246
01247 /*****************************************************************************
01248   Function:
01249     static void HTTPHeaderParseContentLength(void)
01250
01251   Summary:
01252     Parses the "Content-Length:" header for a request.
01253
01254   Description:
01255     Parses the "Content-Length:" header to determine how many bytes of
01256     POST data to expect after the request.  This value is stored in
01257     curHTTP.byteCount.
01258
01259   Precondition:
01260     None
01261
01262   Parameters:
01263     None
01264
01265   Returns:
01266     None
01267
01268   Remarks:
01269     This function is ony available when HTTP_USE_POST is defined.
01270   ***************************************************************************/
01271 #if defined(HTTP_USE_POST)
01272 static void HTTPHeaderParseContentLength(void)
01273 {
01274     WORD len;
01275     BYTE buf[10];
01276
01277     // Read up to the CRLF (max 9 bytes or ~1GB)
01278     len = TCPFindROMArray(sktHTTP, HTTP_CRLF, HTTP_CRLF_LEN, 0, FALSE);
01279     len = TCPGetArray(sktHTTP, buf, len);
01280     buf[len] = '\0';
01281
01282     curHTTP.byteCount = atol((char*)buf);
01283
01284     return;
01285
01286 }
01287 #endif
01288
01289 /*****************************************************************************
01290   Function:
01291     BYTE* HTTPURLDecode(BYTE* cData)
01292
01293   Summary:
01294     Parses a string from URL encoding to plain-text.
01295
01296   Description:
01297     Parses a string from URL encoding to plain-text.  The following
01298     conversions are made: ‘=’ to ‘\0’, ‘&’ to ‘\0’, ‘+’ to ‘ ‘, and
01299     “%xx” to a single hex byte.
01300
01301     After completion, the data has been decoded and a null terminator
01302     signifies the end of a name or value.  A second null terminator (or a
01303     null name parameter) indicates the end of all the data.
01304
01305   Precondition:
01306     The data parameter is null terminated and has at least one extra
01307     byte free.
01308
01309   Parameters:
01310     cData - The string which is to be decoded in place.
01311
01312   Returns:
01313     A pointer to the last null terminator in data, which is also the
01314     first free byte for new data.
01315
01316   Remarks:
01317     This function is called by the stack to parse GET arguments and
01318     cookie data.  User applications can use this function to decode POST
01319     data, but first need to verify that the string is null-terminated.
01320   ***************************************************************************/
01321 BYTE* HTTPURLDecode(BYTE* cData)
01322 {
01323     BYTE *pRead, *pWrite;
01324     WORD wLen;
01325     BYTE c;
01326     WORD_VAL hex;
01327
01328     // Determine length of input
01329     wLen = strlen((char*)cData);
01330
01331     // Read all characters in the string
01332     for(pRead = pWrite = cData; wLen != 0; )
01333     {
01334         c = *pRead++;
01335         wLen--;
01336
01337         if(c == '=' || c == '&')
01338             *pWrite++ = '\0';
01339         else if(c == '+')
01340             *pWrite++ = ' ';
01341         else if(c == '%')
01342         {
01343             if(wLen < 2)
01344                 wLen = 0;
01345             else
01346             {
01347                 hex.v[1] = *pRead++;
01348                 hex.v[0] = *pRead++;
01349                 wLen--;
01350                 wLen--;
01351                 *pWrite++ = hexatob(hex);
01352             }
01353         }
01354         else
01355             *pWrite++ = c;
01356     }
01357
01358     // Double null terminate the last value
01359     *pWrite++ = '\0';
01360     *pWrite = '\0';
01361
01362     return pWrite;
01363 }
01364
01365 /*****************************************************************************
01366   Function:
01367     BYTE* HTTPGetArg(BYTE* cData, BYTE* cArg)
01368
01369   Summary:
01370     Locates a form field value in a given data array.
01371
01372   Description:
01373     Searches through a data array to find the value associated with a
01374     given argument.  It can be used to find form field values in data
01375     received over GET or POST.
01376
01377     The end of data is assumed to be reached when a null name parameter is
01378     encountered.  This requires the string to have an even number of
01379     null-terminated strings, followed by an additional null terminator.
01380
01381   Precondition:
01382     The data array has a valid series of null terminated name/value pairs.
01383
01384   Parameters:
01385     data - the buffer to search
01386     arg - the name of the argument to find
01387
01388   Returns:
01389     A pointer to the argument value, or NULL if not found.
01390   ***************************************************************************/
01391 BYTE* HTTPGetArg(BYTE* cData, BYTE* cArg)
01392 {
01393     // Search through the array while bytes remain
01394     while(*cData != '\0')
01395     {
01396         // Look for arg at current position
01397         if(!strcmp((char*)cArg, (char*)cData))
01398         {// Found it, so return parameter
01399             return cData + strlen((char*)cArg) + 1;
01400         }
01401
01402         // Skip past two strings (NUL bytes)
01403         cData += strlen((char*)cData) + 1;
01404         cData += strlen((char*)cData) + 1;
01405     }
01406
01407     // Return NULL if not found
01408     return NULL;
01409 }
01410
01411 /*****************************************************************************
01412   Function:
01413     BYTE* HTTPGetROMArg(BYTE* cData, ROM BYTE* cArg)
01414
01415   Summary:
01416     Locates a form field value in a given data array.
01417
01418   Description:
01419     Searches through a data array to find the value associated with a
01420     given argument.  It can be used to find form field values in data
01421     received over GET or POST.
01422
01423     The end of data is assumed to be reached when a null name parameter is
01424     encountered.  This requires the string to have an even number of
01425     null-terminated strings, followed by an additional null terminator.
01426
01427   Precondition:
01428     The data array has a valid series of null terminated name/value pairs.
01429
01430   Parameters:
01431     data - the buffer to search
01432     arg - the name of the argument to find
01433
01434   Returns:
01435     A pointer to the argument value, or NULL if not found.
01436
01437   Remarks:
01438     This function is aliased to HTTPGetArg on non-PIC18 platforms.
01439   ***************************************************************************/
01440 #if defined(__18CXX)
01441 BYTE* HTTPGetROMArg(BYTE* cData, ROM BYTE* cArg)
01442 {
01443     // Search through the array while bytes remain
01444     while(*cData != '\0')
01445     {
01446         // Look for arg at current position
01447         if(!memcmppgm2ram(cData, (ROM void*)cArg, strlenpgm((ROM char*)cArg) + 1))
01448         {// Found it, so skip to next string
01449             return cData + strlenpgm((ROM char*)cArg) + 1;
01450         }
01451
01452         // Skip past two strings (NUL bytes)
01453         cData += strlen((char*)cData) + 1;
01454         cData += strlen((char*)cData) + 1;
01455     }
01456
01457     // Return NULL if not found
01458     return NULL;
01459 }
01460 #endif
01461
01462 /*****************************************************************************
01463   Function:
01464     HTTP_READ_STATUS HTTPReadPostName(BYTE* cData, WORD wLen)
01465
01466   Summary:
01467     Reads a name from a URL encoded string in the TCP buffer.
01468
01469   Description:
01470     Reads a name from a URL encoded string in the TCP buffer.  This function
01471     is meant to be called from an HTTPExecutePost callback to facilitate
01472     easier parsing of incoming data.  This function also prevents buffer
01473     overflows by forcing the programmer to indicate how many bytes are
01474     expected.  At least 2 extra bytes are needed in cData over the maximum
01475     length of data expected to be read.
01476
01477     This function will read until the next '=' character, which indicates the
01478     end of a name parameter.  It assumes that the front of the buffer is
01479     the beginning of the name paramter to be read.
01480
01481     This function properly updates curHTTP.byteCount by decrementing it
01482     by the number of bytes read.  It also removes the delimiting '=' from
01483     the buffer.
01484
01485   Precondition:
01486     Front of TCP buffer is the beginning of a name parameter, and the rest of
01487     the TCP buffer contains a URL-encoded string with a name parameter
01488     terminated by a '=' character.
01489
01490   Parameters:
01491     cData - where to store the name once it is read
01492     wLen - how many bytes can be written to cData
01493
01494   Return Values:
01495     HTTP_READ_OK - name was successfully read
01496     HTTP_READ_TRUNCTATED - entire name could not fit in the buffer, so the
01497                             value was truncated and data has been lost
01498     HTTP_READ_INCOMPLETE - entire name was not yet in the buffer, so call
01499                             this function again later to retrieve
01500   ***************************************************************************/
01501 #if defined(HTTP_USE_POST)
01502 HTTP_READ_STATUS HTTPReadPostName(BYTE* cData, WORD wLen)
01503 {
01504     HTTP_READ_STATUS status;
01505
01506     status = HTTPReadTo('=', cData, wLen);
01507
01508     // Decode the data (if not reading to null or blank) and return
01509     if(cData && !*cData)
01510         HTTPURLDecode(cData);
01511     return status;
01512 }
01513 #endif
01514
01515 /*****************************************************************************
01516   Function:
01517     HTTP_READ_STATUS HTTPReadPostValue(BYTE* cData, WORD wLen)
01518
01519   Summary:
01520     Reads a value from a URL encoded string in the TCP buffer.
01521
01522   Description:
01523     Reads a value from a URL encoded string in the TCP buffer.  This function
01524     is meant to be called from an HTTPExecutePost callback to facilitate
01525     easier parsing of incoming data.  This function also prevents buffer
01526     overflows by forcing the programmer to indicate how many bytes are
01527     expected.  At least 2 extra bytes are needed in cData above the maximum
01528     length of data expected to be read.
01529
01530     This function will read until the next '&' character, which indicates the
01531     end of a value parameter.  It assumes that the front of the buffer is
01532     the beginning of the value paramter to be read.  If curHTTP.byteCount
01533     indicates that all expected bytes are in the buffer, it assumes that
01534     all remaining data is the value and acts accordingly.
01535
01536     This function properly updates curHTTP.byteCount by decrementing it
01537     by the number of bytes read.  The terminating '&' character is also
01538     removed from the buffer.
01539
01540   Precondition:
01541     Front of TCP buffer is the beginning of a name parameter, and the rest of
01542     the TCP buffer contains a URL-encoded string with a name parameter
01543     terminated by a '=' character.
01544
01545   Parameters:
01546     cData - where to store the value once it is read
01547     wLen - how many bytes can be written to cData
01548
01549   Return Values:
01550     HTTP_READ_OK - value was successfully read
01551     HTTP_READ_TRUNCTATED - entire value could not fit in the buffer, so the
01552                             value was truncated and data has been lost
01553     HTTP_READ_INCOMPLETE - entire value was not yet in the buffer, so call
01554                             this function again later to retrieve
01555   ***************************************************************************/
01556 #if defined(HTTP_USE_POST)
01557 HTTP_READ_STATUS HTTPReadPostValue(BYTE* cData, WORD wLen)
01558 {
01559     HTTP_READ_STATUS status;
01560
01561     // Try to read the value
01562     status = HTTPReadTo('&', cData, wLen);
01563
01564     // If read was incomplete, check if we're at the end
01565     if(status == HTTP_READ_INCOMPLETE)
01566     {
01567         // If all data has arrived, read all remaining data
01568         if(curHTTP.byteCount == TCPIsGetReady(sktHTTP))
01569             status = HTTPReadTo('\0', cData, wLen);
01570     }
01571
01572     // Decode the data (if not reading to null or blank) and return
01573     if(cData && *cData)
01574         HTTPURLDecode(cData);
01575     return status;
01576 }
01577 #endif
01578
01579 /*****************************************************************************
01580   Function:
01581     static HTTP_READ_STATUS HTTPReadTo(BYTE cDelim, BYTE* cData, WORD wLen)
01582
01583   Summary:
01584     Reads to a buffer until a specified delimiter character.
01585
01586   Description:
01587     Reads from the TCP buffer to cData until either cDelim is reached, or
01588     until wLen - 2 bytes have been read.  The value read is saved to cData and
01589     null terminated.  (wLen - 2 is used so that the value can be passed to
01590     HTTPURLDecode later, which requires a null terminator plus one extra free
01591     byte.)
01592
01593     The delimiter character is removed from the buffer, but not saved to
01594     cData. If all data cannot fit into cData, it will still be removed from
01595     the buffer but will not be saved anywhere.
01596
01597     This function properly updates curHTTP.byteCount by decrementing it
01598     by the number of bytes read.
01599
01600   Precondition:
01601     None
01602
01603   Parameters:
01604     cDelim - the character at which to stop reading, or NULL to read to
01605              the end of the buffer
01606     cData - where to store the data being read
01607     wLen - how many bytes can be written to cData
01608
01609   Return Values:
01610     HTTP_READ_OK - data was successfully read
01611     HTTP_READ_TRUNCTATED - entire data could not fit in the buffer, so the
01612                             data was truncated and data has been lost
01613     HTTP_READ_INCOMPLETE - delimiter character was not found
01614   ***************************************************************************/
01615 #if defined(HTTP_USE_POST)
01616 static HTTP_READ_STATUS HTTPReadTo(BYTE cDelim, BYTE* cData, WORD wLen)
01617 {
01618     HTTP_READ_STATUS status;
01619     WORD wPos;
01620
01621     // Either look for delimiter, or read all available data
01622     if(cDelim)
01623         wPos = TCPFind(sktHTTP, cDelim, 0, FALSE);
01624     else
01625         wPos = TCPIsGetReady(sktHTTP);
01626
01627     // If not found, return incomplete
01628     if(wPos == 0xffff)
01629         return HTTP_READ_INCOMPLETE;
01630
01631     // Read the value
01632     if(wLen < 2 && cData != NULL)
01633     {// Buffer is too small, so read to NULL instead
01634         curHTTP.byteCount -= TCPGetArray(sktHTTP, NULL, wPos);
01635         status = HTTP_READ_TRUNCATED;
01636     }
01637     else if(cData == NULL)
01638     {// Just remove the data
01639         curHTTP.byteCount -= TCPGetArray(sktHTTP, NULL, wPos);
01640         status = HTTP_READ_OK;
01641     }
01642     else if(wPos > wLen - 2)
01643     {// Read data, but truncate at max length
01644         curHTTP.byteCount -= TCPGetArray(sktHTTP, cData, wLen - 2);
01645         curHTTP.byteCount -= TCPGetArray(sktHTTP, NULL, wPos - (wLen - 2));
01646         cData[wLen - 2] = '\0';
01647         status = HTTP_READ_TRUNCATED;
01648     }
01649     else
01650     {// Read the data normally
01651         curHTTP.byteCount -= TCPGetArray(sktHTTP, cData, wPos);
01652         cData[wPos] = '\0';
01653         status = HTTP_READ_OK;
01654     }
01655
01656     // Remove the delimiter
01657     if(cDelim)
01658         curHTTP.byteCount -= TCPGet(sktHTTP, NULL);
01659
01660     return status;
01661 }
01662 #endif
01663
01664 /*****************************************************************************
01665   Function:
01666     HTTP_IO_RESULT HTTPMPFSUpload(void)
01667
01668   Summary:
01669     Saves a file uploaded via POST as the new MPFS image in EEPROM or
01670     external Flash.
01671
01672   Description:
01673     Allows the MPFS image in EEPROM or external Flash to be updated via a
01674     web page by accepting a file upload and storing it to the external memory.
01675
01676   Precondition:
01677     MPFSFormat() has been called.
01678
01679   Parameters:
01680     None
01681
01682   Return Values:
01683     HTTP_IO_DONE - on success
01684     HTTP_IO_NEED_DATA - if more data is still expected
01685
01686   Remarks:
01687     This function is only available when MPFS uploads are enabled and
01688     the MPFS image is stored in EEPROM.
01689
01690   Internal:
01691     After the headers, the first line from the form will be the MIME
01692     separator.  Following that is more headers about the file, which
01693     are discarded.  After another CRLFCRLF pair the file data begins,
01694     which is read 16 bytes at a time and written to external memory.
01695   ***************************************************************************/
01696 #if defined(HTTP_MPFS_UPLOAD)
01697 static HTTP_IO_RESULT HTTPMPFSUpload(void)
01698 {
01699     BYTE c[16];
01700     WORD lenA, lenB;
01701
01702     switch(curHTTP.httpStatus)
01703     {
01704         // New upload, so look for the CRLFCRLF
01705         case HTTP_MPFS_UP:
01706
01707             lenA = TCPFindROMArray(sktHTTP, (ROM BYTE*)"\r\n\r\n", 4, 0, FALSE);
01708
01709             if(lenA != 0xffff)
01710             {// Found it, so remove all data up to and including
01711                 lenA = TCPGetArray(sktHTTP, NULL, lenA);
01712                 curHTTP.byteCount -= lenA;
01713
01714                 // Make sure first 6 bytes are also in
01715                 if(TCPIsGetReady(sktHTTP) < (4 + 6) )
01716                 {
01717                     lenA++;
01718                     return HTTP_IO_NEED_DATA;
01719                 }
01720
01721                 // Make sure it's an MPFS of the correct version
01722                 lenA = TCPGetArray(sktHTTP, c, 10);
01723                 curHTTP.byteCount -= lenA;
01724                 if(memcmppgm2ram(c, (ROM void*)"\r\n\r\nMPFS\x02\x01", 10) == 0)
01725                 {// Read as Ver 2.1
01726                     curHTTP.httpStatus = HTTP_MPFS_OK;
01727
01728                     // Format MPFS storage and put 6 byte tag
01729                     curHTTP.file = MPFSFormat();
01730                     MPFSPutArray(curHTTP.file, &c[4], 6);
01731                 }
01732                 else
01733                 {// Version is wrong
01734                     curHTTP.httpStatus = HTTP_MPFS_ERROR;
01735                 }
01736             }
01737             else
01738             {// Otherwise, remove as much as possible
01739                 lenA = TCPGetArray(sktHTTP, NULL, TCPIsGetReady(sktHTTP) - 4);
01740                 curHTTP.byteCount -= lenA;
01741             }
01742
01743             break;
01744
01745         // Received file is invalid
01746         case HTTP_MPFS_ERROR:
01747             curHTTP.byteCount -= TCPIsGetReady(sktHTTP);
01748             TCPDiscard(sktHTTP);
01749             if(curHTTP.byteCount < 100 || curHTTP.byteCount > 0x80000000)
01750             {// If almost all data was read, or if we overflowed, then return
01751                 smHTTP = SM_HTTP_SERVE_HEADERS;
01752                 return HTTP_IO_DONE;
01753             }
01754             break;
01755
01756         // File is verified, so write the data
01757         case HTTP_MPFS_OK:
01758             // Determine how much to read
01759             lenA = TCPIsGetReady(sktHTTP);
01760             if(lenA > curHTTP.byteCount)
01761                 lenA = curHTTP.byteCount;
01762
01763             while(lenA > 0)
01764             {
01765                 lenB = TCPGetArray(sktHTTP, c, mMIN(lenA,16));
01766                 curHTTP.byteCount -= lenB;
01767                 lenA -= lenB;
01768                 MPFSPutArray(curHTTP.file, c, lenB);
01769             }
01770
01771             // If we've read all the data
01772             if(curHTTP.byteCount == 0)
01773             {
01774                 MPFSPutEnd(TRUE);
01775                 smHTTP = SM_HTTP_SERVE_HEADERS;
01776                 return HTTP_IO_DONE;
01777             }
01778
01779         // Other states are not valid here
01780         default:
01781             break;
01782     }
01783
01784     // Ask for more data
01785     return HTTP_IO_NEED_DATA;
01786
01787 }
01788 #endif
01789
01790 /*****************************************************************************
01791   Function:
01792     void HTTPIncFile(ROM BYTE* cFile)
01793
01794   Summary:
01795     Writes a file byte-for-byte to the currently loaded TCP socket.
01796
01797   Description:
01798     Allows an entire file to be included as a dynamic variable, providing
01799     a basic templating system for HTML web pages.  This reduces unneeded
01800     duplication of visual elements such as headers, menus, etc.
01801
01802     When curHTTP.callbackPos is 0, the file is opened and as many bytes
01803     as possible are written.  The current position is then saved to
01804     curHTTP.callbackPos and the file is closed.  On subsequent calls,
01805     reading begins at the saved location and continues.  Once the end of
01806     the input file is reached, curHTTP.callbackPos is set back to 0 to
01807     indicate completion.
01808
01809   Precondition:
01810     None
01811
01812   Parameters:
01813     cFile - the name of the file to be sent
01814
01815   Returns:
01816     None
01817
01818   Remarks:
01819     Users should not call this function directly, but should instead add
01820     dynamic variables in the form of ~inc:filename.ext~ in their HTML code
01821     to include (for example) the file "filename.ext" at that specified
01822     location.  The MPFS2 Generator utility will handle the rest.
01823   ***************************************************************************/
01824 void HTTPIncFile(ROM BYTE* cFile)
01825 {
01826     WORD wCount, wLen;
01827     BYTE data[64];
01828     MPFS_HANDLE fp;
01829
01830     // Check if this is a first round call
01831     if(curHTTP.callbackPos == 0x00)
01832     {// On initial call, open the file and save its ID
01833         fp = MPFSOpenROM(cFile);
01834         if(fp == MPFS_INVALID_HANDLE)
01835         {// File not found, so abort
01836             return;
01837         }
01838         ((DWORD_VAL*)&curHTTP.callbackPos)->w[0] = MPFSGetID(fp);
01839     }
01840     else
01841     {// The file was already opened, so load up its ID and seek
01842         fp = MPFSOpenID(((DWORD_VAL*)&curHTTP.callbackPos)->w[0]);
01843         if(fp == MPFS_INVALID_HANDLE)
01844         {// No file handles available, so wait for now
01845             return;
01846         }
01847         MPFSSeek(fp, ((DWORD_VAL*)&curHTTP.callbackPos)->w[1], MPFS_SEEK_FORWARD);
01848     }
01849
01850     // Get/put as many bytes as possible
01851     wCount = TCPIsPutReady(sktHTTP);
01852     while(wCount > 0)
01853     {
01854         wLen = MPFSGetArray(fp, data, mMIN(wCount, 64));
01855         if(wLen == 0)
01856         {// If no bytes were read, an EOF was reached
01857             MPFSClose(fp);
01858             curHTTP.callbackPos = 0x00;
01859             return;
01860         }
01861         else
01862         {// Write the bytes to the socket
01863             TCPPutArray(sktHTTP, data, wLen);
01864             wCount -= wLen;
01865         }
01866     }
01867
01868     // Save the new address and close the file
01869     ((DWORD_VAL*)&curHTTP.callbackPos)->w[1] = MPFSTell(fp);
01870     MPFSClose(fp);
01871
01872     return;
01873 }
01874
01875
01876 #endif
01877
01878 // MODIFIX: Added this function to check for busy HTTP connection in case of
01879 // shut down.
01880 BOOL HTTPCheckForIdle(void)
01881 {
01882     BYTE conn;
01883
01884     for(conn = 0; conn < MAX_HTTP_CONNECTIONS; conn++)
01885     {
01886         if((httpStubs[conn].sm != SM_HTTP_IDLE) || TCPIsGetReady(httpStubs[conn].socket))
01887         {
01888             return FALSE;
01889         }
01890     }
01891
01892     return TRUE;
01893 }
01894
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: HTTP2.h Source File

HTTP2.h

Go to the documentation of this file.
00001
00002
00003
00031 /*********************************************************************
00032  * Software License Agreement
00033  *
00034  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00035  * reserved.
00036  *
00037  * Microchip licenses to you the right to use, modify, copy, and
00038  * distribute:
00039  * (i)  the Software when embedded on a Microchip microcontroller or
00040  *      digital signal controller product ("Device") which is
00041  *      integrated into Licensee's product; or
00042  * (ii) ONLY the Software driver source files ENC28J60.c and
00043  *      ENC28J60.h ported to a non-Microchip device used in
00044  *      conjunction with a Microchip ethernet controller for the
00045  *      sole purpose of interfacing with the ethernet controller.
00046  *
00047  * You should refer to the license agreement accompanying this
00048  * Software for additional information regarding your rights and
00049  * obligations.
00050  *
00051  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00052  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00053  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00054  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00055  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00056  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00057  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00058  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00059  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00060  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00061  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00062  *
00063  *
00064  * Author               Date    Comment
00065  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00066  * Nilesh Rajbharti     8/14/01 Original
00067  * Elliott Wood         6/4/07  Complete rewrite (known as HTTP2)
00068 ********************************************************************/
00069
00070 #ifndef __HTTP2_H
00071 #define __HTTP2_H
00072
00073 #include "TCPIP.h"
00074
00075 #if defined(STACK_USE_HTTP2_SERVER)
00076
00077 /****************************************************************************
00078   Section:
00079     Server Configuration Settings
00080   ***************************************************************************/
00081
00082     #define HTTP_PORT               (80u)   // Listening port for HTTP server
00083     #define HTTPS_PORT              (443u)  // Listening port for HTTPS server (when SSL enabled)
00084     #define HTTP_MAX_DATA_LEN       (100u)  // Max bytes to store get and cookie args
00085 // MODIFIX: Increased define from 16 to 256.
00086     #define HTTP_MIN_CALLBACK_FREE  (256u)  // Min bytes free in TX FIFO before callbacks execute
00087     #define HTTP_CACHE_LEN          ("600") // Max lifetime (sec) of static responses as string
00088     #define HTTP_TIMEOUT            (45u)   // Max time (sec) to await more data before
00089
00090     // Authentication requires Base64 decoding
00091     #if defined(HTTP_USE_AUTHENTICATION)
00092         #ifndef STACK_USE_BASE64_DECODE
00093             #define STACK_USE_BASE64_DECODE
00094         #endif
00095     #endif
00096
00097 /****************************************************************************
00098   Section:
00099     Commands and Server Responses
00100   ***************************************************************************/
00101
00102     //Supported Commands and Server Response Codes
00103     typedef enum
00104     {
00105         HTTP_GET = 0u,                  // GET command is being processed
00106         HTTP_POST,                      // POST command is being processed
00107         HTTP_UNAUTHORIZED,              // 401 Unauthorized will be returned
00108         HTTP_NOT_FOUND,                 // 404 Not Found will be returned
00109         HTTP_OVERFLOW,                  // 414 Request-URI Too Long will be returned
00110         HTTP_INTERNAL_SERVER_ERROR,     // 500 Internal Server Error will be returned
00111         HTTP_NOT_IMPLEMENTED,           // 501 Not Implemented (not a GET or POST command)
00112         #if defined(HTTP_MPFS_UPLOAD)
00113         HTTP_MPFS_FORM,                 // Show the MPFS Upload form
00114         HTTP_MPFS_UP,                   // An MPFS Upload is being processed
00115         HTTP_MPFS_OK,                   // An MPFS Upload was successful
00116         HTTP_MPFS_ERROR,                // An MPFS Upload was not a valid image
00117         #endif
00118         HTTP_REDIRECT,                  // 302 Redirect will be returned
00119         HTTP_SSL_REQUIRED               // 403 Forbidden is returned, indicating SSL is required
00120     } HTTP_STATUS;
00121
00122 /****************************************************************************
00123   Section:
00124     HTTP State Definitions
00125   ***************************************************************************/
00126
00127     // Basic HTTP Connection State Machine
00128     typedef enum
00129     {
00130         SM_HTTP_IDLE = 0u,              // Socket is idle
00131         SM_HTTP_PARSE_REQUEST,          // Parses the first line for a file name and GET args
00132         SM_HTTP_PARSE_HEADERS,          // Reads and parses headers one at a time
00133         SM_HTTP_AUTHENTICATE,           // Validates the current authorization state
00134         SM_HTTP_PROCESS_GET,            // Invokes user callback for GET args or cookies
00135         SM_HTTP_PROCESS_POST,           // Invokes user callback for POSTed data
00136         SM_HTTP_PROCESS_REQUEST,        // Begins the process of returning data
00137         SM_HTTP_SERVE_HEADERS,          // Sends any required headers for the response
00138         SM_HTTP_SERVE_COOKIES,          // Adds any cookies to the response
00139         SM_HTTP_SERVE_BODY,             // Serves the actual content
00140         SM_HTTP_SEND_FROM_CALLBACK,     // Invokes a dynamic variable callback
00141         SM_HTTP_DISCONNECT              // Disconnects the server and closes all files
00142     } SM_HTTP2;
00143
00144     // Result states for execution callbacks
00145     typedef enum
00146     {
00147         HTTP_IO_DONE = 0u,  // Finished with procedure
00148         HTTP_IO_NEED_DATA,  // More data needed to continue, call again later
00149         HTTP_IO_WAITING     // Waiting for asynchronous process to complete, call again later
00150     } HTTP_IO_RESULT;
00151
00152     // Result states for HTTPPostReadName and HTTPPostReadValue
00153     typedef enum
00154     {
00155         HTTP_READ_OK = 0u,      // Read was successful
00156         HTTP_READ_TRUNCATED,    // Buffer overflow prevented by truncating value
00157         HTTP_READ_INCOMPLETE    // Entire object is not yet in the buffer.  Try again later.
00158     } HTTP_READ_STATUS;
00159
00160     // File type definitions
00161     typedef enum
00162     {
00163         HTTP_TXT = 0u,      // File is a text document
00164         HTTP_HTM,           // File is HTML (extension .htm)
00165         HTTP_HTML,          // File is HTML (extension .html)
00166         HTTP_CGI,           // File is HTML (extension .cgi)
00167         HTTP_XML,           // File is XML (extension .xml)
00168         HTTP_CSS,           // File is stylesheet (extension .css)
00169         HTTP_GIF,           // File is GIF image (extension .gif)
00170         HTTP_PNG,           // File is PNG image (extension .png)
00171         HTTP_JPG,           // File is JPG image (extension .jpg)
00172         HTTP_JAVA,          // File is java (extension .java)
00173         HTTP_WAV,           // File is audio (extension .wav)
00174         HTTP_UNKNOWN        // File type is unknown
00175     } HTTP_FILE_TYPE;
00176
00177     // HTTP Connection Struct
00178     // Stores partial state data for each connection
00179     // Meant for storage in fast access RAM
00180     typedef struct
00181     {
00182         SM_HTTP2 sm;                        // Current connection state
00183         TCP_SOCKET socket;                  // Socket being served
00184     } HTTP_STUB;
00185
00186     #define sktHTTP     httpStubs[curHTTPID].socket     // Access the current socket
00187     #define smHTTP      httpStubs[curHTTPID].sm         // Access the current state machine
00188
00189     // Stores extended state data for each connection
00190     typedef struct
00191     {
00192         DWORD byteCount;                    // How many bytes have been read so far
00193         DWORD nextCallback;                 // Byte index of the next callback
00194         DWORD callbackID;                   // Callback ID to execute, also used as watchdog timer
00195         DWORD callbackPos;                  // Callback position indicator
00196         BYTE *ptrData;                      // Points to first free byte in data
00197         BYTE *ptrRead;                      // Points to current read location
00198         MPFS_HANDLE file;                   // File pointer for the file being served
00199         MPFS_HANDLE offsets;                // File pointer for any offset info being used
00200         BYTE hasArgs;                       // True if there were get or cookie arguments
00201         BYTE isAuthorized;                  // 0x00-0x79 on fail, 0x80-0xff on pass
00202         HTTP_STATUS httpStatus;             // Request method/status
00203         HTTP_FILE_TYPE fileType;            // File type to return with Content-Type
00204         BYTE data[HTTP_MAX_DATA_LEN];       // General purpose data buffer
00205         #if defined(HTTP_USE_POST)
00206         BYTE smPost;                        // POST state machine variable
00207         #endif
00208     } HTTP_CONN;
00209
00210     #define RESERVED_HTTP_MEMORY ( (DWORD)MAX_HTTP_CONNECTIONS * (DWORD)sizeof(HTTP_CONN))
00211
00212 /****************************************************************************
00213   Section:
00214     Global HTTP Variables
00215   ***************************************************************************/
00216
00217 extern HTTP_CONN curHTTP;
00218 extern HTTP_STUB httpStubs[MAX_HTTP_CONNECTIONS];
00219 extern BYTE curHTTPID;
00220
00221 /****************************************************************************
00222   Section:
00223     Function Prototypes
00224   ***************************************************************************/
00225
00226 void HTTPInit(void);
00227 void HTTPServer(void);
00228 BYTE* HTTPURLDecode(BYTE* cData);
00229 BYTE* HTTPGetArg(BYTE* cData, BYTE* cArg);
00230 void HTTPIncFile(ROM BYTE* cFile);
00231 BOOL HTTPCheckForIdle(void);    // MODIFIX: Added this prototype.
00232
00233 #if defined(__18CXX)
00234     BYTE* HTTPGetROMArg(BYTE* cData, ROM BYTE* cArg);
00235 #else
00236     // Non-ROM variant for C30 / C32
00237     #define HTTPGetROMArg(a,b)  HTTPGetArg(a,(BYTE*)b)
00238 #endif
00239
00240 #if defined(HTTP_USE_POST)
00241     HTTP_READ_STATUS HTTPReadPostName(BYTE* cData, WORD wLen);
00242     HTTP_READ_STATUS HTTPReadPostValue(BYTE* cData, WORD wLen);
00243 #endif
00244
00245 /*****************************************************************************
00246   Function:
00247     HTTP_READ_STATUS HTTPReadPostPair(BYTE* cData, WORD wLen)
00248
00249   Summary:
00250     Reads a name and value pair from a URL encoded string in the TCP buffer.
00251
00252   Description:
00253     Reads a name and value pair from a URL encoded string in the TCP buffer.
00254     This function is meant to be called from an HTTPExecutePost callback to
00255     facilitate easier parsing of incoming data.  This function also prevents
00256     buffer overflows by forcing the programmer to indicate how many bytes are
00257     expected.  At least 2 extra bytes are needed in cData over the maximum
00258     length of data expected to be read.
00259
00260     This function will read until the next '&' character, which indicates the
00261     end of a value parameter.  It assumes that the front of the buffer is
00262     the beginning of the name paramter to be read.
00263
00264     This function properly updates curHTTP.byteCount by decrementing it
00265     by the number of bytes read.  It also removes the delimiting '&' from
00266     the buffer.
00267
00268     Once complete, two strings will exist in the cData buffer.  The first is
00269     the parameter name that was read, while the second is the associated
00270     value.
00271
00272   Precondition:
00273     Front of TCP buffer is the beginning of a name parameter, and the rest of
00274     the TCP buffer contains a URL-encoded string with a name parameter
00275     terminated by a '=' character and a value parameter terminated by a '&'.
00276
00277   Parameters:
00278     cData - where to store the name and value strings once they are read
00279     wLen - how many bytes can be written to cData
00280
00281   Return Values:
00282     HTTP_READ_OK - name and value were successfully read
00283     HTTP_READ_TRUNCTATED - entire name and value could not fit in the buffer,
00284                             so input was truncated and data has been lost
00285     HTTP_READ_INCOMPLETE - entire name and value was not yet in the buffer,
00286                             so call this function again later to retrieve
00287
00288   Remarks:
00289     This function is aliased to HTTPReadPostValue, since they effectively
00290     perform the same task.  The name is provided only for completeness.
00291   ***************************************************************************/
00292 #define HTTPReadPostPair(cData, wLen) HTTPReadPostValue(cData, wLen)
00293
00294
00295 /****************************************************************************
00296   Section:
00297     User-Implemented Callback Function Prototypes
00298   ***************************************************************************/
00299
00300 /*****************************************************************************
00301   Function:
00302     HTTP_IO_RESULT HTTPExecuteGet(void)
00303
00304   Summary:
00305     Processes GET form field variables and cookies.
00306
00307   Description:
00308     This function is implemented by the application developer in
00309     CustomHTTPApp.c.  Its purpose is to parse the data received from
00310     URL parameters (GET method forms) and cookies and perform any
00311     application-specific tasks in response to these inputs.  Any
00312     required authentication has already been validated.
00313
00314     When this function is called, curHTTP.data contains sequential
00315     name/value pairs of strings representing the data received.  In this
00316     format, HTTPGetArg and HTTPGetROMArg can be used to search for
00317     specific variables in the input.  If data buffer space associated
00318     with this connection is required, curHTTP.data may be overwritten
00319     here once the application is done with the values.  Any data placed
00320     there will be available to future callbacks for this connection,
00321     including HTTPExecutePost and any HTTPPrint_varname dynamic
00322     substitutions.
00323
00324     This function may also issue redirections by setting curHTTP.data
00325     to the destination file name or URL, and curHTTP.httpStatus to
00326     HTTP_REDIRECT.
00327
00328     Finally, this function may set cookies.  Set curHTTP.data to a series
00329     of name/value string pairs (in the same format in which parameters
00330     arrive) and then set curHTTP.hasArgs equal to the number of cookie
00331     name/value pairs.  The cookies will be transmitted to the browser,
00332     and any future requests will have those values available in
00333     curHTTP.data.
00334
00335   Precondition:
00336     None
00337
00338   Parameters:
00339     None
00340
00341   Return Values:
00342     HTTP_IO_DONE - application is done processing
00343     HTTP_IO_NEED_DATA - this value may not be returned because more data
00344                         will not become available
00345     HTTP_IO_WAITING - the application is waiting for an asynchronous
00346                       process to complete, and this function should be
00347                       called again later
00348
00349   Remarks:
00350     This function is only called if variables are received via URL
00351     parameters or Cookie arguments.  This function may NOT write to the
00352     TCP buffer.
00353
00354     This function may service multiple HTTP requests simultaneously.
00355     Exercise caution when using global or static variables inside this
00356     routine.  Use curHTTP.callbackPos or curHTTP.data for storage associated
00357     with individual requests.
00358   ***************************************************************************/
00359 HTTP_IO_RESULT HTTPExecuteGet(void);
00360
00361 /*****************************************************************************
00362   Function:
00363     HTTP_IO_RESULT HTTPExecutePost(void)
00364
00365   Summary:
00366     Processes POST form variables and data.
00367
00368   Description:
00369     This function is implemented by the application developer in
00370     CustomHTTPApp.c.  Its purpose is to parse the data received from
00371     POST forms and perform any application-specific tasks in response
00372     to these inputs.  Any required authentication has already been
00373     validated before this function is called.
00374
00375     When this function is called, POST data will be waiting in the
00376     TCP buffer.  curHTTP.byteCount will indicate the number of bytes
00377     remaining to be received before the browser request is complete.
00378
00379     Since data is still in the TCP buffer, the application must call
00380     TCPGet or TCPGetArray in order to retrieve bytes.  When this is done,
00381     curHTTP.byteCount MUST be updated to reflect how many bytes now
00382     remain.  The functions TCPFind, TCPFindString, TCPFindROMString,
00383     TCPFindArray, and TCPFindROMArray may be helpful to locate data
00384     in the TCP buffer.
00385
00386     In general, data submitted from web forms via POST is URL encoded.
00387     The HTTPURLDecode function can be used to decode this information
00388     back to a standard string if required.  If data buffer space
00389     associated with this connection is required, curHTTP.data may be
00390     overwritten here once the application is done with the values.
00391     Any data placed there will be available to future callbacks for
00392     this connection,  including HTTPExecutePost and any
00393     HTTPPrint_varname dynamic substitutions.
00394
00395     Whenever a POST form is processed it is recommended to issue a
00396     redirect back to the browser, either to a status page or to
00397     the same form page that was posted.  This prevents accidental
00398     duplicate submissions (by clicking refresh or back/forward) and
00399     avoids browser warnings about "resubmitting form data".  Redirects
00400     may be issued to the browser by setting curHTTP.data to the
00401     destination file or URL, and curHTTP.httpStatus to HTTP_REDIRECT.
00402
00403     Finally, this function may set cookies.  Set curHTTP.data to a series
00404     of name/value string pairs (in the same format in which parameters
00405     arrive) and then set curHTTP.hasArgs equal to the number of cookie
00406     name/value pairs.  The cookies will be transmitted to the browser,
00407     and any future requests will have those values available in
00408     curHTTP.data.
00409
00410   Precondition:
00411     None
00412
00413   Parameters:
00414     None
00415
00416   Return Values:
00417     HTTP_IO_DONE - application is done processing
00418     HTTP_IO_NEED_DATA - more data is needed to continue, and this
00419                         function should be called again later
00420     HTTP_IO_WAITING - the application is waiting for an asynchronous
00421                       process to complete, and this function should
00422                       be called again later
00423
00424   Remarks:
00425     This function is only called when the request method is POST, and is
00426     only used when HTTP_USE_POST is defined.  This method may NOT write
00427     to the TCP buffer.
00428
00429     This function may service multiple HTTP requests simultaneously.
00430     Exercise caution when using global or static variables inside this
00431     routine.  Use curHTTP.callbackPos or curHTTP.data for storage associated
00432     with individual requests.
00433   ***************************************************************************/
00434 #if defined(HTTP_USE_POST)
00435 HTTP_IO_RESULT HTTPExecutePost(void);
00436 #endif
00437
00438 /*****************************************************************************
00439   Function:
00440     BYTE HTTPNeedsAuth(BYTE* cFile)
00441
00442   Summary:
00443     Determines if a given file name requires authentication
00444
00445   Description:
00446     This function is implemented by the application developer in
00447     CustomHTTPApp.c.  Its function is to determine if a file being
00448     requested requires authentication to view.  The user name and password,
00449     if supplied, will arrive later with the request headers, and will be
00450     processed at that time.
00451
00452     Return values 0x80 - 0xff indicate that authentication is not required,
00453     while values from 0x00 to 0x79 indicate that a user name and password
00454     are required before proceeding.  While most applications will only use a
00455     single value to grant access and another to require authorization, the
00456     range allows multiple "realms" or sets of pages to be protected, with
00457     different credential requirements for each.
00458
00459     The return value of this function is saved as curHTTP.isAuthorized, and
00460     will be available to future callbacks, including HTTPCheckAuth and any
00461     of the HTTPExecuteGet, HTTPExecutePost, or HTTPPrint_varname callbacks.
00462
00463   Precondition:
00464     None
00465
00466   Parameters:
00467     cFile - the name of the file being requested
00468
00469   Return Values:
00470     <= 0x79 - valid authentication is required
00471     >= 0x80 - access is granted for this connection
00472
00473   Remarks:
00474     This function may NOT write to the TCP buffer.
00475   ***************************************************************************/
00476 #if defined(HTTP_USE_AUTHENTICATION)
00477     BYTE HTTPNeedsAuth(BYTE* cFile);
00478 #endif
00479
00480 /*****************************************************************************
00481   Function:
00482     BYTE HTTPCheckAuth(BYTE* cUser, BYTE* cPass)
00483
00484   Summary:
00485     Performs validation on a specific user name and password.
00486
00487   Description:
00488     This function is implemented by the application developer in
00489     CustomHTTPApp.c.  Its function is to determine if the user name and
00490     password supplied by the client are acceptable for this resource.
00491
00492     The value of curHTTP.isAuthorized will be set to the previous return
00493     value of HTTPRequiresAuthorization.  This callback function can check
00494     this value to determine if only specific user names or passwords will
00495     be accepted for this resource.
00496
00497     Return values 0x80 - 0xff indicate that the credentials were accepted,
00498     while values from 0x00 to 0x79 indicate that authorization failed.
00499     While most applications will only use a single value to grant access,
00500     flexibility is provided to store multiple values in order to
00501     indicate which user (or user's group) logged in.
00502
00503     The return value of this function is saved as curHTTP.isAuthorized, and
00504     will be available to future callbacks, including any of the
00505     HTTPExecuteGet, HTTPExecutePost, or HTTPPrint_varname callbacks.
00506
00507   Precondition:
00508     None
00509
00510   Parameters:
00511     cUser - the user name supplied by the client
00512     cPass - the password supplied by the client
00513
00514   Return Values:
00515     <= 0x79 - the credentials were rejected
00516     >= 0x80 - access is granted for this connection
00517
00518   Remarks:
00519     This function is only called when an Authorization header is
00520     encountered.
00521
00522     This function may NOT write to the TCP buffer.
00523   ***************************************************************************/
00524 #if defined(HTTP_USE_AUTHENTICATION)
00525     BYTE HTTPCheckAuth(BYTE* cUser, BYTE* cPass);
00526 #endif
00527
00528 /*****************************************************************************
00529   Function:
00530     void HTTPPrint_varname(void)
00531     void HTTPPrint_varname(WORD wParam1)
00532     void HTTPPrint_varname(WORD wParam1, WORD wParam2, ...)
00533
00534   Summary:
00535     Inserts dynamic content into a web page
00536
00537   Description:
00538     Functions in this style are implemented by the application developer in
00539     CustomHTTPApp.c.  These functions generate dynamic content to be
00540     inserted into web pages and other files returned by the HTTP2 server.
00541
00542     Functions of this type are called when a dynamic variable is located
00543     in a web page.  (ie, ~varname~ )  The name between the tilde '~'
00544     characters is appended to the base function name.  In this example, the
00545     callback would be named HTTPPrint_varname.
00546
00547     The function prototype is located in your project's HTTPPrint.h, which
00548     is automatically generated by the MPFS2 Utility.  The prototype will
00549     have WORD parameters included for each parameter passed in the dynamic
00550     variable.  For example, the variable "~myArray(2,6)~" will generate the
00551     prototype "void HTTPPrint_varname(WORD, WORD);".
00552
00553     When called, this function should write its output directly to the TCP
00554     socket using any combination of TCPIsPutReady, TCPPut, TCPPutArray,
00555     TCPPutString, TCPPutROMArray, and TCPPutROMString.
00556
00557     Before calling, the HTTP2 server guarantees that at least
00558     HTTP_MIN_CALLBACK_FREE bytes (defaults to 16 bytes) are free in the
00559     output buffer.  If the function is writing less than this amount, it
00560     should simply write the data to the socket and return.
00561
00562     In situations where a function needs to write more this amount, it
00563     must manage its output state using curHTTP.callbackPos.  This value
00564     will be set to zero before the function is called.  If the function is
00565     managing its output state, it must set this to a non-zero value before
00566     returning.  Typically this is used to track how many bytes have been
00567     written, or how many remain to be written.  If curHTTP.callbackPos is
00568     non-zero, the function will be called again when more buffer space is
00569     available.  Once the callback completes, set this value back to zero
00570     to resume normal servicing of the request.
00571
00572   Precondition:
00573     None
00574
00575   Parameters:
00576     wParam1 - first parameter passed in the dynamic variable (if any)
00577     wParam2 - second parameter passed in the dynamic variable (if any)
00578     ... - additional parameters as necessary
00579
00580   Returns:
00581     None
00582
00583   Remarks:
00584     This function may service multiple HTTP requests simultaneously,
00585     especially when managing its output state.  Exercise caution when using
00586     global or static variables inside this routine.  Use curHTTP.callbackPos
00587     or curHTTP.data for storage associated with individual requests.
00588   ***************************************************************************/
00589 #if defined(DOCUMENTATION_ONLY)
00590     void HTTPPrint_varname(WORD wParam1, WORD wParam2, ...);
00591 #endif
00592
00593
00594 #endif
00595 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: Helpers.c Source File

Helpers.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00019 /*********************************************************************
00020  * Software License Agreement
00021  *
00022  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00023  * reserved.
00024  *
00025  * Microchip licenses to you the right to use, modify, copy, and
00026  * distribute:
00027  * (i)  the Software when embedded on a Microchip microcontroller or
00028  *      digital signal controller product ("Device") which is
00029  *      integrated into Licensee's product; or
00030  * (ii) ONLY the Software driver source files ENC28J60.c and
00031  *      ENC28J60.h ported to a non-Microchip device used in
00032  *      conjunction with a Microchip ethernet controller for the
00033  *      sole purpose of interfacing with the ethernet controller.
00034  *
00035  * You should refer to the license agreement accompanying this
00036  * Software for additional information regarding your rights and
00037  * obligations.
00038  *
00039  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00040  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00041  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00042  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00043  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00044  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00045  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00046  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00047  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00048  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00049  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00050  *
00051  *
00052  * Author               Date    Comment
00053  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00054  * Nilesh Rajbharti     5/17/01 Original        (Rev 1.0)
00055  * Nilesh Rajbharti     2/9/02  Cleanup
00056  * Nilesh Rajbharti     6/25/02 Rewritten CalcIPChecksum() to avoid
00057  *                              multi-byte shift operation.
00058  * Howard Schlunder     2/9/05  Added hexatob(), btohexa_high(), and
00059  *                              btohexa_low()
00060  * Howard Schlunder    10/10/06 Optimized swapl()
00061  * Elliott Wood        11/20/07 Added leftRotateDWORD()
00062  ********************************************************************/
00063 #define __HELPERS_C
00064
00065 #include "TCPIP.h"
00066
00067
00068 /*****************************************************************************
00069   Function:
00070     DWORD GenerateRandomDWORD(void)
00071
00072   Summary:
00073     Generates a random DWORD.
00074
00075   Description:
00076     This function generates a random 32-bit integer.  It collects
00077     randomness by comparing the A/D converter's internal R/C oscillator
00078     clock with our main system clock.  By passing collected entropy to the
00079     C rand()/srand() functions, the output is normalized to meet statistical
00080     randomness tests.
00081
00082   Precondition:
00083     None
00084
00085   Parameters:
00086     None
00087
00088   Returns:
00089     Random 32-bit number.
00090
00091   Side Effects:
00092     This function uses the A/D converter (and so you must disable
00093     interrupts if you use the A/D converted in your ISR).  The C rand()
00094     function will be reseeded, and Timer0 (PIC18) and Timer1 (PIC24,
00095     dsPIC, and PIC32) will be used.  TMR#H:TMR#L will have a new value.
00096     Note that this is the same timer used by the Tick module.
00097
00098   Remarks:
00099     This function times out after 1 second of attempting to generate the
00100     random DWORD.  In such a case, the output may not be truly random.
00101     Typically, this function executes in around 500,000 instruction cycles.
00102
00103     The intent of this function is to produce statistically random and
00104     cryptographically secure random number.  Whether or not this is true on
00105     all (or any) devices/voltages/temperatures is not tested.
00106   ***************************************************************************/
00107 DWORD GenerateRandomDWORD(void)
00108 {
00109     BYTE vBitCount;
00110     WORD w, wTime, wLastValue;
00111     DWORD dwTotalTime;
00112     DWORD dwRandomResult;
00113
00114 #if defined __18CXX
00115 {
00116     BYTE ADCON0Save, ADCON2Save;
00117     BYTE T0CONSave, TMR0HSave, TMR0LSave;
00118
00119     // TODO: Test if this works on the PIC18F87J50 family
00120     #if defined(__18F87J50) || defined(_18F87J50)
00121         #define ADCON2  ADCON1
00122     #endif
00123
00124     // Save hardware SFRs
00125     ADCON0Save = ADCON0;
00126     ADCON2Save = ADCON2;
00127     T0CONSave = T0CON;
00128     TMR0LSave = TMR0L;
00129     TMR0HSave = TMR0H;
00130
00131     // Set up Timer and A/D converter module
00132     ADCON0 = 0x01;  // Turn on the A/D module
00133     ADCON2 = 0x3F;  // 20 Tad acquisition, Frc A/D clock used for conversion
00134     T0CON = 0x88;   // TMR0ON = 1, no prescalar
00135     vBitCount = 0;
00136     dwTotalTime = 0;
00137     wLastValue = 0;
00138     dwRandomResult = rand();
00139     while(1)
00140     {
00141         // Time the duration of an A/D acquisition and conversion
00142         TMR0H = 0x00;
00143         TMR0L = 0x00;
00144         ADCON0bits.GO = 1;
00145         ClrWdt();
00146         while(ADCON0bits.GO);
00147         ((BYTE*)&wTime)[0] = TMR0L;
00148         ((BYTE*)&wTime)[1] = TMR0H;
00149         w = rand();
00150
00151         // Wait no longer than 1 second obtaining entropy
00152         dwTotalTime += wTime;
00153         if(dwTotalTime >= GetInstructionClock())
00154         {
00155             dwRandomResult ^= rand() | (((DWORD)rand())<<15ul) | (((DWORD)rand())<<30ul);
00156             break;
00157         }
00158
00159         // Keep sampling if minimal entropy was likely obtained this round
00160         if(wLastValue == wTime)
00161             continue;
00162
00163         // Add this entropy into the pseudo random number generator by reseeding
00164         srand(w + (wLastValue - wTime));
00165         wLastValue = wTime;
00166
00167         // Accumulate at least 32 bits of randomness over time
00168         dwRandomResult <<= 1;
00169         if(rand() >= 16384)
00170             dwRandomResult |= 0x1;
00171
00172         // See if we've collected a fair amount of entropy and can quit early
00173         if(++vBitCount == 0u)
00174             break;
00175     }
00176
00177     // Restore hardware SFRs
00178     ADCON0 = ADCON0Save;
00179     ADCON2 = ADCON2Save;
00180     TMR0H = TMR0HSave;
00181     TMR0L = TMR0LSave;
00182     T0CON = T0CONSave;
00183 }
00184 #else
00185 {
00186     WORD AD1CON1Save, AD1CON2Save, AD1CON3Save;
00187     WORD T1CONSave, PR1Save;
00188
00189     // Save hardware SFRs
00190     AD1CON1Save = AD1CON1;
00191     AD1CON2Save = AD1CON2;
00192     AD1CON3Save = AD1CON3;
00193     T1CONSave = T1CON;
00194     PR1Save = PR1;
00195
00196     // Set up Timer and A/D converter module
00197     AD1CON1 = 0x80E4;   // Turn on the A/D module, auto-convert
00198     AD1CON2 = 0x003F;   // Interrupt after every 16th sample/convert
00199     AD1CON3 = 0x9F00;   // Frc A/D clock, 31 Tad acquisition
00200     T1CON = 0x8000; // TON = 1, no prescalar
00201     PR1 = 0xFFFF;   // Don't clear timer early
00202     vBitCount = 0;
00203     dwTotalTime = 0;
00204     wLastValue = 0;
00205     dwRandomResult = rand();
00206     while(1)
00207     {
00208         ClrWdt();
00209         #if defined(__C30__)
00210             while(!IFS0bits.AD1IF);
00211         #else
00212             while(!IFS1bits.AD1IF);
00213         #endif
00214         wTime = TMR1;
00215         TMR1 = 0x0000;
00216
00217         #if defined(__C30__)
00218             IFS0bits.AD1IF = 0;
00219         #else
00220             IFS1bits.AD1IF = 0;
00221         #endif
00222         w = rand();
00223
00224         // Wait no longer than 1 second obtaining entropy
00225         dwTotalTime += wTime;
00226         if(dwTotalTime >= GetInstructionClock())
00227         {
00228             dwRandomResult ^= rand() | (((DWORD)rand())<<15) | (((DWORD)rand())<<30);
00229             break;
00230         }
00231
00232         // Keep sampling if minimal entropy was likely obtained this round
00233         if(wLastValue == wTime)
00234             continue;
00235
00236         // Add this entropy into the pseudo random number generator by reseeding
00237         srand(w + (wLastValue - wTime));
00238         wLastValue = wTime;
00239
00240         // Accumulate at least 32 bits of randomness over time
00241         dwRandomResult <<= 1;
00242         if(rand() >= 16384)
00243             dwRandomResult |= 0x1;
00244
00245         // See if we've collected a fair amount of entropy and can quit early
00246         if(++vBitCount == 0u)
00247             break;
00248     }
00249
00250
00251     // Restore hardware SFRs
00252     AD1CON1 = AD1CON1Save;
00253     AD1CON2 = AD1CON2Save;
00254     AD1CON3 = AD1CON3Save;
00255     T1CON = T1CONSave;
00256     PR1 = PR1Save;
00257 }
00258 #endif
00259
00260     return dwRandomResult;
00261 }
00262
00263
00264 #if defined(STACK_USE_HTTP_SERVER)
00265 /*****************************************************************************
00266   Function:
00267     void UnencodeURL(BYTE* URL)
00268
00269   Summary:
00270     Decodes a URL-encoded string.
00271
00272   Description:
00273     This function is deprecated except for use with HTTP Classic.  It
00274     attempts to decode a URL encoded string, converting all hex escape
00275     sequences into a literal byte.  However, it is inefficient over long
00276     strings and does not handle URL-encoded data strings ('&' and '=').
00277
00278   Precondition:
00279     None
00280
00281   Parameters:
00282     URL - the null-terminated string to decode
00283
00284   Returns:
00285     None
00286   ***************************************************************************/
00287 void UnencodeURL(BYTE* URL)
00288 {
00289     BYTE *Right, *Copy;
00290     WORD_VAL Number;
00291
00292     while((Right = (BYTE*)strchr((char*)URL, '%')))
00293     {
00294         // Make sure the string is long enough
00295         if(Right[1] == '\0')
00296             break;
00297         if(Right[2] == '\0')
00298             break;
00299
00300         // Update the string in place
00301         Number.v[0] = Right[2];
00302         Number.v[1] = Right[1];
00303         *Right++ = hexatob(Number);
00304         URL = Right;
00305
00306         // Remove two blank spots by shifting all remaining characters right two
00307         Copy = Right + 2;
00308         while((*Right++ = *Copy++));
00309     }
00310 }
00311 #endif
00312
00313
00314 /*****************************************************************************
00315   Function:
00316     BOOL StringToIPAddress(BYTE* str, IP_ADDR* IPAddress)
00317
00318   Summary:
00319     Converts a string to an IP address
00320
00321   Description:
00322     This function parses a dotted-quad decimal IP address string into an
00323     IP_ADDR struct.  The output result is big-endian.
00324
00325   Precondition:
00326     None
00327
00328   Parameters:
00329     str - Pointer to a dotted-quad IP address string
00330     IPAddress - Pointer to IP_ADDR in which to store the result
00331
00332   Return Values:
00333     TRUE - an IP address was successfully decoded
00334     FALSE - no IP address could be found, or the format was incorrect
00335   ***************************************************************************/
00336 BOOL StringToIPAddress(BYTE* str, IP_ADDR* IPAddress)
00337 {
00338     DWORD_VAL dwVal;
00339     BYTE i, charLen, currentOctet;
00340
00341     charLen = 0;
00342     currentOctet = 0;
00343     dwVal.Val = 0;
00344     while((i = *str++))
00345     {
00346         if(currentOctet > 3u)
00347             break;
00348
00349         i -= '0';
00350
00351
00352         // Validate the character is a numerical digit or dot, depending on location
00353         if(charLen == 0u)
00354         {
00355             if(i > 9u)
00356                 return FALSE;
00357         }
00358         else if(charLen == 3u)
00359         {
00360             if(i != (BYTE)('.' - '0'))
00361                 return FALSE;
00362
00363             if(dwVal.Val > 0x00020505ul)
00364                 return FALSE;
00365
00366             IPAddress->v[currentOctet++] = dwVal.v[2]*((BYTE)100) + dwVal.v[1]*((BYTE)10) + dwVal.v[0];
00367             charLen = 0;
00368             dwVal.Val = 0;
00369             continue;
00370         }
00371         else
00372         {
00373             if(i == (BYTE)('.' - '0'))
00374             {
00375                 if(dwVal.Val > 0x00020505ul)
00376                     return FALSE;
00377
00378                 IPAddress->v[currentOctet++] = dwVal.v[2]*((BYTE)100) + dwVal.v[1]*((BYTE)10) + dwVal.v[0];
00379                 charLen = 0;
00380                 dwVal.Val = 0;
00381                 continue;
00382             }
00383             if(i > 9u)
00384                 return FALSE;
00385         }
00386
00387         charLen++;
00388         dwVal.Val <<= 8;
00389         dwVal.v[0] = i;
00390     }
00391
00392     // Make sure the very last character is a valid termination character
00393     // (i.e., not more hostname, which could be legal and not an IP
00394     // address as in "10.5.13.233.picsaregood.com"
00395     if(i != 0u && i != '/' && i != '\r' && i != '\n' && i != ' ' && i != '\t')
00396         return FALSE;
00397
00398     // Verify and convert the last octet and return the result
00399     if(dwVal.Val > 0x00020505ul)
00400         return FALSE;
00401
00402     IPAddress->v[3] = dwVal.v[2]*((BYTE)100) + dwVal.v[1]*((BYTE)10) + dwVal.v[0];
00403
00404     return TRUE;
00405 }
00406
00407 /*****************************************************************************
00408   Function:
00409     BOOL ROMStringToIPAddress(ROM BYTE* str, IP_ADDR* IPAddress)
00410
00411   Summary:
00412     Converts a string to an IP address
00413
00414   Description:
00415     This function parses a dotted-quad decimal IP address string into an
00416     IP_ADDR struct.  The output result is big-endian.
00417
00418   Precondition:
00419     None
00420
00421   Parameters:
00422     str - Pointer to a dotted-quad IP address string
00423     IPAddress - Pointer to IP_ADDR in which to store the result
00424
00425   Return Values:
00426     TRUE - an IP address was successfully decoded
00427     FALSE - no IP address could be found, or the format was incorrect
00428
00429   Remarks:
00430     This function is aliased to StringToIPAddress on non-PIC18 platforms.
00431   ***************************************************************************/
00432 // MODIFIX: Do not compile!
00433 #if 0
00434 BOOL ROMStringToIPAddress(ROM BYTE* str, IP_ADDR* IPAddress)
00435 {
00436     DWORD_VAL dwVal;
00437     BYTE i, charLen, currentOctet;
00438
00439     charLen = 0;
00440     currentOctet = 0;
00441     dwVal.Val = 0;
00442     while(i = *str++)
00443     {
00444         if(currentOctet > 3u)
00445             break;
00446
00447         i -= '0';
00448
00449
00450         // Validate the character is a numerical digit or dot, depending on location
00451         if(charLen == 0u)
00452         {
00453             if(i > 9u)
00454                 return FALSE;
00455         }
00456         else if(charLen == 3u)
00457         {
00458             if(i != (BYTE)('.' - '0'))
00459                 return FALSE;
00460
00461             if(dwVal.Val > 0x00020505ul)
00462                 return FALSE;
00463
00464             IPAddress->v[currentOctet++] = dwVal.v[2]*((BYTE)100) + dwVal.v[1]*((BYTE)10) + dwVal.v[0];
00465             charLen = 0;
00466             dwVal.Val = 0;
00467             continue;
00468         }
00469         else
00470         {
00471             if(i == (BYTE)('.' - '0'))
00472             {
00473                 if(dwVal.Val > 0x00020505ul)
00474                     return FALSE;
00475
00476                 IPAddress->v[currentOctet++] = dwVal.v[2]*((BYTE)100) + dwVal.v[1]*((BYTE)10) + dwVal.v[0];
00477                 charLen = 0;
00478                 dwVal.Val = 0;
00479                 continue;
00480             }
00481             if(i > 9u)
00482                 return FALSE;
00483         }
00484
00485         charLen++;
00486         dwVal.Val <<= 8;
00487         dwVal.v[0] = i;
00488     }
00489
00490     // Make sure the very last character is a valid termination character
00491     // (i.e., not more hostname, which could be legal and not an IP
00492     // address as in "10.5.13.233.picsaregood.com"
00493     if(i != 0u && i != '/' && i != '\r' && i != '\n' && i != ' ' && i != '\t')
00494         return FALSE;
00495
00496     // Verify and convert the last octet and return the result
00497     if(dwVal.Val > 0x00020505ul)
00498         return FALSE;
00499
00500     IPAddress->v[3] = dwVal.v[2]*((BYTE)100) + dwVal.v[1]*((BYTE)10) + dwVal.v[0];
00501
00502     return TRUE;
00503 }
00504 #endif
00505
00506
00507
00508 /*****************************************************************************
00509   Function:
00510     WORD Base64Decode(BYTE* cSourceData, WORD wSourceLen,
00511                         BYTE* cDestData, WORD wDestLen)
00512
00513   Description:
00514     Decodes a Base-64 array to its literal representation.
00515
00516   Precondition:
00517     None
00518
00519   Parameters:
00520     cSourceData - Pointer to a string of Base-64 encoded data
00521     wSourceLen  - Length of the Base-64 source data
00522     cDestData   - Pointer to write the decoded data
00523     wSourceLen  - Maximum length that can be written to cDestData
00524
00525   Returns:
00526     Number of decoded bytes written to cDestData.
00527
00528   Remarks:
00529     This function is binary safe and will ignore invalid characters (CR, LF,
00530     etc).  If cSourceData is equal to cDestData, the data will be converted
00531     in-place.  If cSourceData is not equal to cDestData, but the regions
00532     overlap, the behavior is undefined.
00533
00534     Decoded data is always at least 1/4 smaller than the source data.
00535   ***************************************************************************/
00536 #if defined(STACK_USE_BASE64_DECODE)
00537 WORD Base64Decode(BYTE* cSourceData, WORD wSourceLen, BYTE* cDestData, WORD wDestLen)
00538 {
00539     BYTE i;
00540     BYTE vByteNumber;
00541     BOOL bPad;
00542     WORD wBytesOutput;
00543
00544     vByteNumber = 0;
00545     wBytesOutput = 0;
00546
00547     // Loop over all provided bytes
00548     while(wSourceLen--)
00549     {
00550         // Fetch a Base64 byte and decode it to the original 6 bits
00551         i = *cSourceData++;
00552         bPad = (i == '=');
00553         if(i >= 'A' && i <= 'Z')    // Regular data
00554             i -= 'A' - 0;
00555         else if(i >= 'a' && i <= 'z')
00556             i -= 'a' - 26;
00557         else if(i >= '0' && i <= '9')
00558             i -= '0' - 52;
00559         else if(i == '+' || i == '-')
00560             i = 62;
00561         else if(i == '/' || i == '_')
00562             i = 63;
00563         else                        // Skip all padding (=) and non-Base64 characters
00564             continue;
00565
00566
00567         // Write the 6 bits to the correct destination location(s)
00568         if(vByteNumber == 0u)
00569         {
00570             if(bPad)                // Padding here would be illegal, treat it as a non-Base64 chacter and just skip over it
00571                 continue;
00572             vByteNumber++;
00573             if(wBytesOutput >= wDestLen)
00574                 break;
00575             wBytesOutput++;
00576             *cDestData = i << 2;
00577         }
00578         else if(vByteNumber == 1u)
00579         {
00580             vByteNumber++;
00581             *cDestData++ |= i >> 4;
00582             if(wBytesOutput >= wDestLen)
00583                 break;
00584             if(bPad)
00585                 continue;
00586             wBytesOutput++;
00587             *cDestData = i << 4;
00588         }
00589         else if(vByteNumber == 2u)
00590         {
00591             vByteNumber++;
00592             *cDestData++ |= i >> 2;
00593             if(wBytesOutput >= wDestLen)
00594                 break;
00595             if(bPad)
00596                 continue;
00597             wBytesOutput++;
00598             *cDestData = i << 6;
00599         }
00600         else if(vByteNumber == 3u)
00601         {
00602             vByteNumber = 0;
00603             *cDestData++ |= i;
00604         }
00605     }
00606
00607     return wBytesOutput;
00608 }
00609 #endif  // #if defined(STACK_USE_BASE64_DECODE)
00610
00611
00612 /*****************************************************************************
00613   Function:
00614     WORD Base64Encode(BYTE* cSourceData, WORD wSourceLen,
00615                         BYTE* cDestData, WORD wDestLen)
00616
00617   Description:
00618     Encodes a binary array to Base-64.
00619
00620   Precondition:
00621     None
00622
00623   Parameters:
00624     cSourceData - Pointer to a string of binary data
00625     wSourceLen  - Length of the binary source data
00626     cDestData   - Pointer to write the Base-64 encoded data
00627     wSourceLen  - Maximum length that can be written to cDestData
00628
00629   Returns:
00630     Number of encoded bytes written to cDestData.  This will always be
00631     a multiple of 4.
00632
00633   Remarks:
00634     Encoding cannot be performed in-place.  If cSourceData overlaps with
00635     cDestData, the behavior is undefined.
00636
00637     Encoded data is always at least 1/3 larger than the source data.  It may
00638     be 1 or 2 bytes larger than that.
00639   ***************************************************************************/
00640 #if defined(STACK_USE_BASE64_ENCODE) || defined(STACK_USE_SMTP_CLIENT) || defined(STACK_USE_DYNAMICDNS_CLIENT)
00641 WORD Base64Encode(BYTE* cSourceData, WORD wSourceLen, BYTE* cDestData, WORD wDestLen)
00642 {
00643     BYTE i, j;
00644     BYTE vOutput[4];
00645     WORD wOutputLen;
00646
00647     wOutputLen = 0;
00648     while(wDestLen >= 4u)
00649     {
00650         // Start out treating the output as all padding
00651         vOutput[0] = 0xFF;
00652         vOutput[1] = 0xFF;
00653         vOutput[2] = 0xFF;
00654         vOutput[3] = 0xFF;
00655
00656         // Get 3 input octets and split them into 4 output hextets (6-bits each)
00657         if(wSourceLen == 0u)
00658             break;
00659         i = *cSourceData++;
00660         wSourceLen--;
00661         vOutput[0] = (i & 0xFC)>>2;
00662         vOutput[1] = (i & 0x03)<<4;
00663         if(wSourceLen)
00664         {
00665             i = *cSourceData++;
00666             wSourceLen--;
00667             vOutput[1] |= (i & 0xF0)>>4;
00668             vOutput[2] = (i & 0x0F)<<2;
00669             if(wSourceLen)
00670             {
00671                 i = *cSourceData++;
00672                 wSourceLen--;
00673                 vOutput[2] |= (i & 0xC0)>>6;
00674                 vOutput[3] = i & 0x3F;
00675             }
00676         }
00677
00678         // Convert hextets into Base 64 alphabet and store result
00679         for(i = 0; i < 4u; i++)
00680         {
00681             j = vOutput[i];
00682
00683             if(j <= 25u)
00684                 j += 'A' - 0;
00685             else if(j <= 51u)
00686                 j += 'a' - 26;
00687             else if(j <= 61u)
00688                 j += '0' - 52;
00689             else if(j == 62u)
00690                 j = '+';
00691             else if(j == 63u)
00692                 j = '/';
00693             else                // Padding
00694                 j = '=';
00695
00696             *cDestData++ = j;
00697         }
00698
00699         // Update counters
00700         wDestLen -= 4;
00701         wOutputLen += 4;
00702     }
00703
00704     return wOutputLen;
00705 }
00706 #endif // #if defined(STACK_USE_BASE64_ENCODE) || defined(STACK_USE_SMTP) || defined(STACK_USE_DYNAMICDNS_CLIENT)
00707
00708
00709 /*****************************************************************************
00710   Function:
00711     void uitoa(WORD Value, BYTE* Buffer)
00712
00713   Summary:
00714     Converts an unsigned integer to a decimal string.
00715
00716   Description:
00717     Converts a 16-bit unsigned integer to a null-terminated decimal string.
00718
00719   Precondition:
00720     None
00721
00722   Parameters:
00723     Value   - The number to be converted
00724     Buffer  - Pointer in which to store the converted string
00725
00726   Returns:
00727     None
00728   ***************************************************************************/
00729
00730 // MODIFIX: Do not compile!
00731 #if 0
00732 void uitoa(WORD Value, BYTE* Buffer)
00733 {
00734     BYTE i;
00735     WORD Digit;
00736     WORD Divisor;
00737     BOOL Printed = FALSE;
00738
00739     if(Value)
00740     {
00741         for(i = 0, Divisor = 10000; i < 5u; i++)
00742         {
00743             Digit = Value/Divisor;
00744             if(Digit || Printed)
00745             {
00746                 *Buffer++ = '0' + Digit;
00747                 Value -= Digit*Divisor;
00748                 Printed = TRUE;
00749             }
00750             Divisor /= 10;
00751         }
00752     }
00753     else
00754     {
00755         *Buffer++ = '0';
00756     }
00757
00758     *Buffer = '\0';
00759 }
00760 #endif
00761
00762 /*****************************************************************************
00763   Function:
00764     void ultoa(DWORD Value, BYTE* Buffer)
00765
00766   Summary:
00767     Converts an unsigned integer to a decimal string.
00768
00769   Description:
00770     Converts a 32-bit unsigned integer to a null-terminated decimal string.
00771
00772   Precondition:
00773     None
00774
00775   Parameters:
00776     Value   - The number to be converted
00777     Buffer  - Pointer in which to store the converted string
00778
00779   Returns:
00780     None
00781   ***************************************************************************/
00782 #if !defined(__18CXX) || defined(HI_TECH_C)
00783 void ultoa(DWORD Value, BYTE* Buffer)
00784 {
00785     BYTE i;
00786     DWORD Digit;
00787     DWORD Divisor;
00788     BOOL Printed = FALSE;
00789
00790     if(Value)
00791     {
00792         for(i = 0, Divisor = 1000000000; i < 10; i++)
00793         {
00794             Digit = Value/Divisor;
00795             if(Digit || Printed)
00796             {
00797                 *Buffer++ = '0' + Digit;
00798                 Value -= Digit*Divisor;
00799                 Printed = TRUE;
00800             }
00801             Divisor /= 10;
00802         }
00803     }
00804     else
00805     {
00806         *Buffer++ = '0';
00807     }
00808
00809     *Buffer = '\0';
00810 }
00811 #endif
00812
00813 /*****************************************************************************
00814   Function:
00815     BYTE hexatob(WORD_VAL AsciiChars)
00816
00817   Summary:
00818     Converts a hex string to a single byte.
00819
00820   Description:
00821     Converts a two-character ASCII hex string to a single packed byte.
00822
00823   Precondition:
00824     None
00825
00826   Parameters:
00827     AsciiChars - WORD_VAL where .v[0] is the ASCII value for the lower nibble
00828                     and .v[1] is the ASCII value for the upper nibble.  Each
00829                     must range from '0'-'9', 'A'-'F', or 'a'-'f'.
00830
00831   Returns:
00832     Resulting packed byte 0x00 - 0xFF.
00833   ***************************************************************************/
00834 BYTE hexatob(WORD_VAL AsciiChars)
00835 {
00836     // Convert lowercase to uppercase
00837     if(AsciiChars.v[1] > 'F')
00838         AsciiChars.v[1] -= 'a'-'A';
00839     if(AsciiChars.v[0] > 'F')
00840         AsciiChars.v[0] -= 'a'-'A';
00841
00842     // Convert 0-9, A-F to 0x0-0xF
00843     if(AsciiChars.v[1] > '9')
00844         AsciiChars.v[1] -= 'A' - 10;
00845     else
00846         AsciiChars.v[1] -= '0';
00847
00848     if(AsciiChars.v[0] > '9')
00849         AsciiChars.v[0] -= 'A' - 10;
00850     else
00851         AsciiChars.v[0] -= '0';
00852
00853     // Concatenate
00854     return (AsciiChars.v[1]<<4) |  AsciiChars.v[0];
00855 }
00856
00857 /*****************************************************************************
00858   Function:
00859     BYTE btohexa_high(BYTE b)
00860
00861   Summary:
00862     Converts the upper nibble of a binary value to a hexadecimal ASCII byte.
00863
00864   Description:
00865     Converts the upper nibble of a binary value to a hexadecimal ASCII byte.
00866     For example, btohexa_high(0xAE) will return 'A'.
00867
00868   Precondition:
00869     None
00870
00871   Parameters:
00872     b - the byte to convert
00873
00874   Returns:
00875     The upper hexadecimal ASCII byte '0'-'9' or 'A'-'F'.
00876   ***************************************************************************/
00877 BYTE btohexa_high(BYTE b)
00878 {
00879     b >>= 4;
00880     return (b>0x9u) ? b+'A'-10:b+'0';
00881 }
00882
00883 /*****************************************************************************
00884   Function:
00885     BYTE btohexa_high(BYTE b)
00886
00887   Summary:
00888     Converts the lower nibble of a binary value to a hexadecimal ASCII byte.
00889
00890   Description:
00891     Converts the lower nibble of a binary value to a hexadecimal ASCII byte.
00892     For example, btohexa_high(0xAE) will return 'E'.
00893
00894   Precondition:
00895     None
00896
00897   Parameters:
00898     b - the byte to convert
00899
00900   Returns:
00901     The lower hexadecimal ASCII byte '0'-'9' or 'A'-'F'.
00902   ***************************************************************************/
00903 BYTE btohexa_low(BYTE b)
00904 {
00905     b &= 0x0F;
00906     return (b>9u) ? b+'A'-10:b+'0';
00907 }
00908
00909 /*****************************************************************************
00910   Function:
00911     signed char stricmppgm2ram(BYTE* a, ROM BYTE* b)
00912
00913   Summary:
00914     Case-insensitive comparison of a string in RAM to a string in ROM.
00915
00916   Description:
00917     Performs a case-insensitive comparison of a string in RAM to a string
00918     in ROM.  This function performs identically to strcmppgm2ram, except that
00919     the comparison is not case-sensitive.
00920
00921   Precondition:
00922     None
00923
00924   Parameters:
00925     a - Pinter to tring in RAM
00926     b - Pointer to string in ROM
00927
00928   Return Values:
00929     \-1 - a < b
00930     0   - a = b
00931     1   - a > b
00932   ***************************************************************************/
00933 signed char stricmppgm2ram(BYTE* a, ROM BYTE* b)
00934 {
00935     BYTE cA, cB;
00936
00937     // Load first two characters
00938     cA = *a;
00939     cB = *b;
00940
00941     // Loop until one string terminates
00942     while(cA != '\0' && cB != '\0')
00943     {
00944         // Shift case if necessary
00945         if(cA >= 'a' && cA <= 'z')
00946             cA -= 'a' - 'A';
00947         if(cB >= 'a' && cB <= 'z')
00948             cB -= 'a' - 'A';
00949
00950         // Compare
00951         if(cA > cB)
00952             return 1;
00953         if(cA < cB)
00954             return -1;
00955
00956         // Characters matched, so continue
00957         a++;
00958         b++;
00959         cA = *a;
00960         cB = *b;
00961     }
00962
00963     // See if one string terminated first
00964     if(cA > cB)
00965         return 1;
00966     if(cA < cB)
00967         return -1;
00968
00969     // Strings match
00970     return 0;
00971 }
00972
00973 /*****************************************************************************
00974   Function:
00975     WORD swaps(WORD v)
00976
00977   Description:
00978     Swaps the endian-ness of a WORD.
00979
00980   Precondition:
00981     None
00982
00983   Parameters:
00984     v - the WORD to swap
00985
00986   Returns:
00987     The swapped version of v.
00988   ***************************************************************************/
00989 WORD swaps(WORD v)
00990 {
00991     WORD_VAL t;
00992     BYTE b;
00993
00994     t.Val   = v;
00995     b       = t.v[1];
00996     t.v[1]  = t.v[0];
00997     t.v[0]  = b;
00998
00999     return t.Val;
01000 }
01001
01002 /*****************************************************************************
01003   Function:
01004     DWORD swapl(DWORD v)
01005
01006   Description:
01007     Swaps the endian-ness of a DWORD.
01008
01009   Precondition:
01010     None
01011
01012   Parameters:
01013     v - the DWORD to swap
01014
01015   Returns:
01016     The swapped version of v.
01017   ***************************************************************************/
01018 DWORD swapl(DWORD v)
01019 {
01020     // Swap bytes 0 and 3
01021     ((DWORD_VAL*)&v)->v[0] ^= ((DWORD_VAL*)&v)->v[3];
01022     ((DWORD_VAL*)&v)->v[3] ^= ((DWORD_VAL*)&v)->v[0];
01023     ((DWORD_VAL*)&v)->v[0] ^= ((DWORD_VAL*)&v)->v[3];
01024
01025     // Swap bytes 1 and 2
01026     ((DWORD_VAL*)&v)->v[1] ^= ((DWORD_VAL*)&v)->v[2];
01027     ((DWORD_VAL*)&v)->v[2] ^= ((DWORD_VAL*)&v)->v[1];
01028     ((DWORD_VAL*)&v)->v[1] ^= ((DWORD_VAL*)&v)->v[2];
01029
01030     return v;
01031 }
01032
01033
01034 /*****************************************************************************
01035   Function:
01036     WORD CalcIPChecksum(BYTE* buffer, WORD count)
01037
01038   Summary:
01039     Calculates an IP checksum value.
01040
01041   Description:
01042     This function calculates an IP checksum over an array of input data.  The
01043     checksum is the 16-bit one's complement of one's complement sum of all
01044     words in the data (with zero-padding if an odd number of bytes are
01045     summed).  This checksum is defined in RFC 793.
01046
01047   Precondition:
01048     buffer is WORD aligned (even memory address) on 16- and 32-bit PICs.
01049
01050   Parameters:
01051     buffer - pointer to the data to be checksummed
01052     count  - number of bytes to be checksummed
01053
01054   Returns:
01055     The calculated checksum.
01056
01057   Internal:
01058     This function could be improved to do 32-bit sums on PIC32 platforms.
01059   ***************************************************************************/
01060 WORD CalcIPChecksum(BYTE* buffer, WORD count)
01061 {
01062     WORD i;
01063     WORD *val;
01064     DWORD_VAL sum = {0x00000000ul};
01065
01066     i = count >> 1;
01067     val = (WORD*)buffer;
01068
01069     // Calculate the sum of all words
01070     while(i--)
01071         sum.Val += (DWORD)*val++;
01072
01073     // Add in the sum of the remaining byte, if present
01074     if(((WORD_VAL*)&count)->bits.b0)
01075         sum.Val += (DWORD)*(BYTE*)val;
01076
01077     // Do an end-around carry (one's complement arrithmatic)
01078     sum.Val = (DWORD)sum.w[0] + (DWORD)sum.w[1];
01079
01080     // Do another end-around carry in case if the prior add
01081     // caused a carry out
01082     sum.w[0] += sum.w[1];
01083
01084     // Return the resulting checksum
01085     return ~sum.w[0];
01086 }
01087
01088
01089 /*****************************************************************************
01090   Function:
01091     WORD CalcIPBufferChecksum(WORD len)
01092
01093   Summary:
01094     Calculates an IP checksum in the MAC buffer itself.
01095
01096   Description:
01097     This function calculates an IP checksum over an array of input data
01098     existing in the MAC buffer.  The checksum is the 16-bit one's complement
01099     of one's complement sum of all words in the data (with zero-padding if
01100     an odd number of bytes are summed).  This checksum is defined in RFC 793.
01101
01102   Precondition:
01103     TCP is initialized and the MAC buffer pointer is set to the start of
01104     the buffer.
01105
01106   Parameters:
01107     len - number of bytes to be checksummed
01108
01109   Returns:
01110     The calculated checksum.
01111
01112   Remarks:
01113     All Microchip MACs should perform this function in hardware.
01114   ***************************************************************************/
01115 #if defined(NON_MCHP_MAC)
01116 WORD CalcIPBufferChecksum(WORD len)
01117 {
01118     DWORD_VAL Checksum = {0x00000000ul};
01119     WORD ChunkLen;
01120     BYTE DataBuffer[20];    // Must be an even size
01121     WORD *DataPtr;
01122
01123     while(len)
01124     {
01125         // Obtain a chunk of data (less SPI overhead compared
01126         // to requesting one byte at a time)
01127         ChunkLen = len > sizeof(DataBuffer) ? sizeof(DataBuffer) : len;
01128         MACGetArray(DataBuffer, ChunkLen);
01129         len -= ChunkLen;
01130
01131         // Take care of a last odd numbered data byte
01132         if(((WORD_VAL*)&ChunkLen)->bits.b0)
01133         {
01134             DataBuffer[ChunkLen] = 0x00;
01135             ChunkLen++;
01136         }
01137
01138         // Calculate the checksum over this chunk
01139         DataPtr = (WORD*)&DataBuffer[0];
01140         while(ChunkLen)
01141         {
01142             Checksum.Val += *DataPtr++;
01143             ChunkLen -= 2;
01144         }
01145     }
01146
01147     // Do an end-around carry (one's complement arrithmatic)
01148     Checksum.Val = (DWORD)Checksum.w[0] + (DWORD)Checksum.w[1];
01149
01150     // Do another end-around carry in case if the prior add
01151     // caused a carry out
01152     Checksum.w[0] += Checksum.w[1];
01153
01154     // Return the resulting checksum
01155     return ~Checksum.w[0];
01156 }
01157 #endif
01158
01159 /*****************************************************************************
01160   Function:
01161     char* strupr(char* s)
01162
01163   Summary:
01164     Converts a string to uppercase.
01165
01166   Description:
01167     This function converts strings to uppercase on platforms that do not
01168     already have this function defined.  All lower-case characters are
01169     converted, an characters not included in 'a'-'z' are left as-is.
01170
01171   Precondition:
01172     None
01173
01174   Parameters:
01175     s - the null-terminated string to be converted.
01176
01177   Returns:
01178     Pointer to the initial string.
01179   ***************************************************************************/
01180 #if !defined(__18CXX) || defined(HI_TECH_C)
01181 char* strupr(char* s)
01182 {
01183     char c;
01184     char *t;
01185
01186     t = s;
01187     while( (c = *t) )
01188     {
01189         if(c >= 'a' && c <= 'z')
01190         {
01191             *t -= ('a' - 'A');
01192         }
01193         t++;
01194     }
01195     return s;
01196 }
01197 #endif
01198
01199 #if defined(__18CXX)
01200 // Make this variable global for the following function.
01201 // Hi-Tech PICC18 cannot access local function variables from inline asm.
01202 DWORD_VAL toRotate;
01203 #endif
01204
01205 /*****************************************************************************
01206   Function:
01207     DWORD leftRotateDWORD(DWORD val, BYTE bits)
01208
01209   Summary:
01210     Left-rotates a DWORD.
01211
01212   Description:
01213     This function rotates the bits in a 32-bit DWORD left by a specific
01214     number of bits.
01215
01216   Precondition:
01217     None
01218
01219   Parameters:
01220     val     - the DWORD to be rotated
01221     bits    - the number of bits by which to shift
01222
01223   Returns:
01224     Rotated DWORD value.
01225
01226   Remarks:
01227     This function is only implemented on 8-bit platforms for now.  The
01228     8-bit compilers generate excessive code for this function, while C30
01229     and C32 already generate compact code.  Those compilers are served
01230     by a macro defined in Helpers.h.
01231   ***************************************************************************/
01232 // MODIFIX: Do not compile!
01233 #if 0
01234 DWORD leftRotateDWORD(DWORD val, BYTE bits)
01235 {
01236     BYTE i, t;
01237     //DWORD_VAL toRotate;
01238     toRotate.Val = val;
01239
01240     for(i = bits; i >= 8u; i -= 8)
01241     {
01242         t = toRotate.v[3];
01243         toRotate.v[3] = toRotate.v[2];
01244         toRotate.v[2] = toRotate.v[1];
01245         toRotate.v[1] = toRotate.v[0];
01246         toRotate.v[0] = t;
01247     }
01248
01249
01250     #if defined(HI_TECH_C)
01251     for(; i != 0; i--)
01252     {
01253         asm("movlb (_toRotate)>>8");
01254         asm("bcf _STATUS,0,C");
01255         asm("btfsc (_toRotate)&0ffh+3,7,B");
01256         asm("bsf _STATUS,0,C");
01257         asm("rlcf (_toRotate)&0ffh+0,F,B");
01258         asm("rlcf (_toRotate)&0ffh+1,F,B");
01259         asm("rlcf (_toRotate)&0ffh+2,F,B");
01260         asm("rlcf (_toRotate)&0ffh+3,F,B");
01261     }
01262     #else
01263     for(; i != 0u; i--)
01264     {
01265         _asm
01266         movlb toRotate
01267         bcf STATUS,0,0
01268         btfsc toRotate+3,7,1
01269         bsf STATUS,0,0
01270         rlcf toRotate+0,1,1
01271         rlcf toRotate+1,1,1
01272         rlcf toRotate+2,1,1
01273         rlcf toRotate+3,1,1
01274         _endasm
01275     }
01276     #endif
01277
01278     return toRotate.Val;
01279 }
01280 #endif
01281
01282 /*****************************************************************************
01283   Function:
01284     void FormatNetBIOSName(BYTE Name[])
01285
01286   Summary:
01287     Formats a string to a valid NetBIOS name.
01288
01289   Description:
01290     This function formats a string to a valid NetBIOS name.  Names will be
01291     exactly 16 characters, as defined by the NetBIOS spec.  The 16th
01292     character will be a 0x00 byte, while the other 15 will be the
01293     provided string, padded with spaces as necessary.
01294
01295   Precondition:
01296     None
01297
01298   Parameters:
01299     Name - the string to format as a NetBIOS name.  This parameter must have
01300       at least 16 bytes allocated.
01301
01302   Returns:
01303     None
01304   ***************************************************************************/
01305
01306 // MODIFIX: Do not compile!
01307 #if 0
01308 void FormatNetBIOSName(BYTE Name[])
01309 {
01310     BYTE i;
01311
01312     Name[15] = '\0';
01313     strupr((char*)Name);
01314     i = 0;
01315     while(i < 15u)
01316     {
01317         if(Name[i] == '\0')
01318         {
01319             while(i < 15u)
01320             {
01321                 Name[i++] = ' ';
01322             }
01323             break;
01324         }
01325         i++;
01326     }
01327 }
01328 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: Helpers.h Source File

Helpers.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00019 /*********************************************************************
00020  * Software License Agreement
00021  *
00022  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00023  * reserved.
00024  *
00025  * Microchip licenses to you the right to use, modify, copy, and
00026  * distribute:
00027  * (i)  the Software when embedded on a Microchip microcontroller or
00028  *      digital signal controller product ("Device") which is
00029  *      integrated into Licensee's product; or
00030  * (ii) ONLY the Software driver source files ENC28J60.c and
00031  *      ENC28J60.h ported to a non-Microchip device used in
00032  *      conjunction with a Microchip ethernet controller for the
00033  *      sole purpose of interfacing with the ethernet controller.
00034  *
00035  * You should refer to the license agreement accompanying this
00036  * Software for additional information regarding your rights and
00037  * obligations.
00038  *
00039  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00040  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00041  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00042  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00043  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00044  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00045  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00046  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00047  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00048  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00049  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00050  *
00051  *
00052  * Author               Date    Comment
00053  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00054  * Nilesh Rajbharti     5/17/01 Original        (Rev 1.0)
00055  * Nilesh Rajbharti     2/9/02  Cleanup
00056  ********************************************************************/
00057 #ifndef __HELPERS_H
00058 #define __HELPERS_H
00059
00060
00061 #if !defined(__18CXX) || defined(HI_TECH_C)
00062     char *strupr(char* s);
00063     void ultoa(DWORD Value, BYTE* Buffer);
00064 #endif
00065
00066 #if defined(__DEBUG)
00067     #define DebugPrint(a)   {putrsUART(a);}
00068 #else
00069     #define DebugPrint(a)
00070 #endif
00071
00072 DWORD   GenerateRandomDWORD(void);
00073 void    uitoa(WORD Value, BYTE* Buffer);
00074 void    UnencodeURL(BYTE* URL);
00075 WORD    Base64Decode(BYTE* cSourceData, WORD wSourceLen, BYTE* cDestData, WORD wDestLen);
00076 WORD    Base64Encode(BYTE* cSourceData, WORD wSourceLen, BYTE* cDestData, WORD wDestLen);
00077 BOOL    StringToIPAddress(BYTE* str, IP_ADDR* IPAddress);
00078 BYTE    ReadStringUART(BYTE* Dest, BYTE BufferLen);
00079 BYTE    hexatob(WORD_VAL AsciiChars);
00080 BYTE    btohexa_high(BYTE b);
00081 BYTE    btohexa_low(BYTE b);
00082 signed char stricmppgm2ram(BYTE* a, ROM BYTE* b);
00083
00084 // MODIFIX: Commented out!
00085 #if 0
00086 #if defined(__18CXX)
00087     BOOL    ROMStringToIPAddress(ROM BYTE* str, IP_ADDR* IPAddress);
00088 #else
00089     // Non-ROM variant for C30 and C32
00090     #define ROMStringToIPAddress(a,b)   StringToIPAddress((BYTE*)a,b)
00091 #endif
00092 #endif
00093
00094 WORD    swaps(WORD v);
00095 DWORD   swapl(DWORD v);
00096
00097 WORD    CalcIPChecksum(BYTE* buffer, WORD len);
00098 WORD    CalcIPBufferChecksum(WORD len);
00099
00100 #if defined(__18CXX)
00101     DWORD leftRotateDWORD(DWORD val, BYTE bits);
00102 #else
00103     // Rotations are more efficient in C30 and C32
00104     #define leftRotateDWORD(x, n) (((x) << (n)) | ((x) >> (32-(n))))
00105 #endif
00106
00107 void FormatNetBIOSName(BYTE Name[16]);
00108
00109 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: ICMP.c Source File

ICMP.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00026 /*********************************************************************
00027  * Software License Agreement
00028  *
00029  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00030  * reserved.
00031  *
00032  * Microchip licenses to you the right to use, modify, copy, and
00033  * distribute:
00034  * (i)  the Software when embedded on a Microchip microcontroller or
00035  *      digital signal controller product ("Device") which is
00036  *      integrated into Licensee's product; or
00037  * (ii) ONLY the Software driver source files ENC28J60.c and
00038  *      ENC28J60.h ported to a non-Microchip device used in
00039  *      conjunction with a Microchip ethernet controller for the
00040  *      sole purpose of interfacing with the ethernet controller.
00041  *
00042  * You should refer to the license agreement accompanying this
00043  * Software for additional information regarding your rights and
00044  * obligations.
00045  *
00046  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00047  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00048  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00049  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00050  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00051  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00052  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00053  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00054  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00055  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00056  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00057  *
00058  *
00059  * Author               Date        Comment
00060  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00061  * Howard Schlunder     03/16/07    Original
00062  ********************************************************************/
00063 #define __ICMP_C
00064
00065 #include "TCPIP.h"
00066
00067 /*********************************************************************
00068  * Function:        void ICMPProcess(void)
00069  *
00070  * PreCondition:    MAC buffer contains ICMP type packet.
00071  *
00072  * Input:           *remote: Pointer to a NODE_INFO structure of the
00073  *                  ping requester
00074  *                  len: Count of how many bytes the ping header and
00075  *                  payload are in this IP packet
00076  *
00077  * Output:          Generates an echo reply, if requested
00078  *                  Validates and sets ICMPFlags.bReplyValid if a
00079  *                  correct ping response to one of ours is received.
00080  *
00081  * Side Effects:    None
00082  *
00083  * Overview:        None
00084  *
00085  * Note:            None
00086  ********************************************************************/
00087 void ICMPProcess(NODE_INFO *remote, WORD len)
00088 {
00089     DWORD_VAL dwVal;
00090
00091     // Obtain the ICMP header Type, Code, and Checksum fields
00092     MACGetArray((BYTE*)&dwVal, sizeof(dwVal));
00093
00094     // See if this is an ICMP echo (ping) request
00095     if(dwVal.w[0] == 0x0008u)
00096     {
00097         // Validate the checksum using the Microchip MAC's DMA module
00098         // The checksum data includes the precomputed checksum in the
00099         // header, so a valid packet will always have a checksum of
00100         // 0x0000 if the packet is not disturbed.
00101         if(MACCalcRxChecksum(0+sizeof(IP_HEADER), len))
00102             return;
00103
00104         // Calculate new Type, Code, and Checksum values
00105         dwVal.v[0] = 0x00;  // Type: 0 (ICMP echo/ping reply)
00106         dwVal.v[2] += 8;    // Subtract 0x0800 from the checksum
00107         if(dwVal.v[2] < 8u)
00108         {
00109             dwVal.v[3]++;
00110             if(dwVal.v[3] == 0u)
00111                 dwVal.v[2]++;
00112         }
00113
00114         // Position the write pointer for the next IPPutHeader operation
00115         MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
00116
00117         // Wait for TX hardware to become available (finish transmitting
00118         // any previous packet)
00119         while(!IPIsTxReady());
00120
00121         // Create IP header in TX memory
00122         IPPutHeader(remote, IP_PROT_ICMP, len);
00123
00124         // Copy ICMP response into the TX memory
00125         MACPutArray((BYTE*)&dwVal, sizeof(dwVal));
00126         MACMemCopyAsync(-1, -1, len-4);
00127         while(!MACIsMemCopyDone());
00128
00129         // Transmit the echo reply packet
00130         MACFlush();
00131     }
00132 }
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: ICMP.h Source File

ICMP.h

Go to the documentation of this file.
00001
00002
00003
00029 /*********************************************************************
00030  * Software License Agreement
00031  *
00032  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00033  * reserved.
00034  *
00035  * Microchip licenses to you the right to use, modify, copy, and
00036  * distribute:
00037  * (i)  the Software when embedded on a Microchip microcontroller or
00038  *      digital signal controller product ("Device") which is
00039  *      integrated into Licensee's product; or
00040  * (ii) ONLY the Software driver source files ENC28J60.c and
00041  *      ENC28J60.h ported to a non-Microchip device used in
00042  *      conjunction with a Microchip ethernet controller for the
00043  *      sole purpose of interfacing with the ethernet controller.
00044  *
00045  * You should refer to the license agreement accompanying this
00046  * Software for additional information regarding your rights and
00047  * obligations.
00048  *
00049  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00050  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00051  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00052  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00053  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00054  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00055  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00056  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00057  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00058  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00059  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00060  *
00061  *
00062  * Author               Date        Comment
00063  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00064  * Howard Schlunder     03/16/07    Original
00065  ********************************************************************/
00066 #ifndef __ICMP_H
00067 #define __ICMP_H
00068
00069 void ICMPProcess(NODE_INFO *remote, WORD len);
00070
00071 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: IP.c Source File

IP.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00028 /*********************************************************************
00029  * Software License Agreement
00030  *
00031  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00032  * reserved.
00033  *
00034  * Microchip licenses to you the right to use, modify, copy, and
00035  * distribute:
00036  * (i)  the Software when embedded on a Microchip microcontroller or
00037  *      digital signal controller product ("Device") which is
00038  *      integrated into Licensee's product; or
00039  * (ii) ONLY the Software driver source files ENC28J60.c and
00040  *      ENC28J60.h ported to a non-Microchip device used in
00041  *      conjunction with a Microchip ethernet controller for the
00042  *      sole purpose of interfacing with the ethernet controller.
00043  *
00044  * You should refer to the license agreement accompanying this
00045  * Software for additional information regarding your rights and
00046  * obligations.
00047  *
00048  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00049  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00050  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00051  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00052  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00053  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00054  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00055  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00056  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00057  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00058  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00059  *
00060  *
00061  * Author               Date    Comment
00062  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00063  * Nilesh Rajbharti     4/27/01 Original        (Rev 1.0)
00064  * Nilesh Rajbharti     2/9/02  Cleanup
00065  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
00066  * Howard Schlunder     8/31/04 Beta Rev 0.9 (See version.log for detail)
00067  * Howard Schlunder     1/5/06  Improved DMA checksum efficiency
00068  * Darren Rook          9/21/06 Corrected IPHeaderLen not being
00069  *                              initialized when NON_MCHP_MAC defined.
00070  ********************************************************************/
00071 #define __IP_C
00072
00073 #include "TCPIP.h"
00074
00075 // This is left shifted by 4.  Actual value is 0x04.
00076 #define IPv4                (0x40u)
00077 #define IP_VERSION          IPv4
00078
00079 // IHL (Internet Header Length) is # of DWORDs in a header.
00080 // Since, we do not support options, our IP header length will be
00081 // minimum i.e. 20 bytes : IHL = 20 / 4 = 5.
00082 #define IP_IHL              (0x05)
00083
00084 #define IP_SERVICE_NW_CTRL  (0x07)
00085 #define IP_SERVICE_IN_CTRL  (0x06)
00086 #define IP_SERVICE_ECP      (0x05)
00087 #define IP_SERVICE_OVR      (0x04)
00088 #define IP_SERVICE_FLASH    (0x03)
00089 #define IP_SERVICE_IMM      (0x02)
00090 #define IP_SERVICE_PRIOR    (0x01)
00091 #define IP_SERVICE_ROUTINE  (0x00)
00092
00093 #define IP_SERVICE_N_DELAY  (0x00)
00094 #define IP_SERCICE_L_DELAY  (0x08)
00095 #define IP_SERVICE_N_THRPT  (0x00)
00096 #define IP_SERVICE_H_THRPT  (0x10)
00097 #define IP_SERVICE_N_RELIB  (0x00)
00098 #define IP_SERVICE_H_RELIB  (0x20)
00099
00100 #define IP_SERVICE          (IP_SERVICE_ROUTINE | IP_SERVICE_N_DELAY)
00101
00102 #define MY_IP_TTL           (255)  // Time-To-Live in hops
00103
00104
00105
00106
00107 static WORD _Identifier = 0;
00108 static BYTE IPHeaderLen;
00109
00110
00111 static void SwapIPHeader(IP_HEADER* h);
00112
00113
00114
00115
00116 /*********************************************************************
00117  * Function:        BOOL IPGetHeader( IP_ADDR    *localIP,
00118  *                                    NODE_INFO  *remote,
00119  *                                    BYTE        *Protocol,
00120  *                                    WORD        *len)
00121  *
00122  * PreCondition:    MACGetHeader() == TRUE
00123  *
00124  * Input:           localIP     - Local node IP Address as received
00125  *                                in current IP header.
00126  *                                If this information is not required
00127  *                                caller may pass NULL value.
00128  *                  remote      - Remote node info
00129  *                  Protocol    - Current packet protocol
00130  *                  len         - Current packet data length
00131  *
00132  * Output:          TRUE, if valid packet was received
00133  *                  FALSE otherwise
00134  *
00135  * Side Effects:    None
00136  *
00137  * Note:            Only one IP message can be received.
00138  *                  Caller may not transmit and receive a message
00139  *                  at the same time.
00140  *
00141  ********************************************************************/
00142 BOOL IPGetHeader(IP_ADDR *localIP,
00143                  NODE_INFO *remote,
00144                  BYTE *protocol,
00145                  WORD *len)
00146 {
00147     WORD_VAL    CalcChecksum;
00148     IP_HEADER   header;
00149
00150 #if defined(NON_MCHP_MAC)
00151     WORD_VAL    ReceivedChecksum;
00152     WORD        checksums[2];
00153     BYTE        optionsLen;
00154     #define MAX_OPTIONS_LEN     (40)            // As per RFC 791.
00155     BYTE        options[MAX_OPTIONS_LEN];
00156 #endif
00157
00158     // Read IP header.
00159     MACGetArray((BYTE*)&header, sizeof(header));
00160
00161     // Make sure that this is an IPv4 packet.
00162     if ( (header.VersionIHL & 0xf0) != IP_VERSION )
00163         return FALSE;
00164
00165     // Throw this packet away if it is a fragment.
00166     // We don't have enough RAM for IP fragment reconstruction.
00167     if(header.FragmentInfo & 0xFF1F)
00168         return FALSE;
00169
00170     IPHeaderLen = (header.VersionIHL & 0x0f) << 2;
00171
00172 #if !defined(NON_MCHP_MAC)
00173     // Validate the IP header.  If it is correct, the checksum
00174     // will come out to 0x0000 (because the header contains a
00175     // precomputed checksum).  A corrupt header will have a
00176     // nonzero checksum.
00177     CalcChecksum.Val = MACCalcRxChecksum(0, IPHeaderLen);
00178
00179     // Seek to the end of the IP header
00180     MACSetReadPtrInRx(IPHeaderLen);
00181
00182     if(CalcChecksum.Val)
00183 #else
00184     // Calculate options length in this header, if there is any.
00185     // IHL is in terms of numbers of 32-bit DWORDs; i.e. actual
00186     // length is 4 times IHL.
00187     optionsLen = IPHeaderLen - sizeof(header);
00188
00189     // If there is any option(s), read it so that we can include them
00190     // in checksum calculation.
00191     if ( optionsLen > MAX_OPTIONS_LEN )
00192         return FALSE;
00193
00194     if ( optionsLen > 0 )
00195         MACGetArray(options, optionsLen);
00196
00197     // Save header checksum; clear it and recalculate it ourselves.
00198     ReceivedChecksum.Val = header.HeaderChecksum;
00199     header.HeaderChecksum = 0;
00200
00201     // Calculate checksum of header including options bytes.
00202     checksums[0] = ~CalcIPChecksum((BYTE*)&header, sizeof(header));
00203
00204     // Calculate Options checksum too, if they are present.
00205     if ( optionsLen > 0 )
00206         checksums[1] = ~CalcIPChecksum((BYTE*)options, optionsLen);
00207     else
00208         checksums[1] = 0;
00209
00210     CalcChecksum.Val  = CalcIPChecksum((BYTE*)checksums,
00211                                             2 * sizeof(WORD));
00212
00213     // Make sure that checksum is correct
00214     if ( ReceivedChecksum.Val != CalcChecksum.Val )
00215 #endif
00216     {
00217         // Bad packet. The function caller will be notified by means of the FALSE
00218         // return value and it should discard the packet.
00219         return FALSE;
00220     }
00221
00222     // Network to host conversion.
00223     SwapIPHeader(&header);
00224
00225     // If caller is interested, return destination IP address
00226     // as seen in this IP header.
00227     if (localIP)
00228         localIP->Val    = header.DestAddress.Val;
00229
00230     remote->IPAddr.Val  = header.SourceAddress.Val;
00231     *protocol           = header.Protocol;
00232     *len                = header.TotalLength - IPHeaderLen;
00233
00234     return TRUE;
00235 }
00236
00237
00238
00239
00240 /*********************************************************************
00241  * Function: WORD IPPutHeader(NODE_INFO *remote,
00242  *                            BYTE protocol,
00243  *                            WORD len)
00244  *
00245  * PreCondition:    IPIsTxReady() == TRUE
00246  *
00247  * Input:           *remote     - Destination node address
00248  *                  protocol    - Current packet protocol
00249  *                  len         - Current packet data length
00250  *
00251  * Output:          (WORD)0
00252  *
00253  * Side Effects:    None
00254  *
00255  * Note:            Only one IP message can be transmitted at any
00256  *                  time.
00257  ********************************************************************/
00258 WORD IPPutHeader(NODE_INFO *remote,
00259                  BYTE protocol,
00260                  WORD len)
00261 {
00262     IP_HEADER   header;
00263
00264     IPHeaderLen = sizeof(IP_HEADER);
00265
00266     header.VersionIHL       = IP_VERSION | IP_IHL;
00267     header.TypeOfService    = IP_SERVICE;
00268     header.TotalLength      = sizeof(header) + len;
00269     header.Identification   = ++_Identifier;
00270     header.FragmentInfo     = 0;
00271     header.TimeToLive       = MY_IP_TTL;
00272     header.Protocol         = protocol;
00273     header.HeaderChecksum   = 0;
00274 // MODIFIX: Use the eWicht structure sIPConfig instead of AppConfig
00275     header.SourceAddress    = sIPConfig.MyIPAddr;
00276
00277     header.DestAddress.Val = remote->IPAddr.Val;
00278
00279     SwapIPHeader(&header);
00280
00281     header.HeaderChecksum   = CalcIPChecksum((BYTE*)&header, sizeof(header));
00282
00283     MACPutHeader(&remote->MACAddr, MAC_IP, (sizeof(header)+len));
00284     MACPutArray((BYTE*)&header, sizeof(header));
00285
00286     return 0x0000;
00287
00288 }
00289
00290 /*********************************************************************
00291  * Function:        IPSetRxBuffer(WORD Offset)
00292  *
00293  * PreCondition:    IPHeaderLen must have been intialized by
00294  *                  IPGetHeader() or IPPutHeader()
00295  *
00296  * Input:           Offset from beginning of IP data field
00297  *
00298  * Output:          Next Read/Write access to receive buffer is
00299  *                  set to Offset
00300  *
00301  * Side Effects:    None
00302  *
00303  * Note:            None
00304  *
00305  ********************************************************************/
00306 void IPSetRxBuffer(WORD Offset)
00307 {
00308     MACSetReadPtrInRx(Offset+IPHeaderLen);
00309 }
00310
00311
00312
00313 static void SwapIPHeader(IP_HEADER* h)
00314 {
00315     h->TotalLength      = swaps(h->TotalLength);
00316     h->Identification   = swaps(h->Identification);
00317     h->HeaderChecksum   = swaps(h->HeaderChecksum);
00318 }
00319
00320 // MODIFIX: Added the following functions.
00321 DWORD IPConvertSubnetToMask(BYTE Subnet)
00322 {
00323     int i = 0;
00324     DWORD mask = 0x80000000ul;
00325     for (i = 1; i < Subnet; i++)
00326     {
00327         mask |= mask >> 1;
00328     }
00329
00330     mask = swapl(mask);
00331     return mask;
00332 }
00333
00334 BYTE IPConvertMaskToSubnet(BYTE * MaskArray)
00335 {
00336     BYTE subnet = 0;
00337
00338     DWORD mask = swapl(*((DWORD *)MaskArray));
00339     while(mask & 0x80000000ul)
00340     {
00341         mask = mask << 1;
00342         subnet++;
00343     }
00344
00345     return subnet;
00346 }
00347
00348 // MODIFIX: END
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: IP.h Source File

IP.h

Go to the documentation of this file.
00001
00002
00028 /*********************************************************************
00029  * Software License Agreement
00030  *
00031  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00032  * reserved.
00033  *
00034  * Microchip licenses to you the right to use, modify, copy, and
00035  * distribute:
00036  * (i)  the Software when embedded on a Microchip microcontroller or
00037  *      digital signal controller product ("Device") which is
00038  *      integrated into Licensee's product; or
00039  * (ii) ONLY the Software driver source files ENC28J60.c and
00040  *      ENC28J60.h ported to a non-Microchip device used in
00041  *      conjunction with a Microchip ethernet controller for the
00042  *      sole purpose of interfacing with the ethernet controller.
00043  *
00044  * You should refer to the license agreement accompanying this
00045  * Software for additional information regarding your rights and
00046  * obligations.
00047  *
00048  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00049  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00050  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00051  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00052  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00053  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00054  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00055  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00056  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00057  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00058  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00059  *
00060  *
00061  * Author               Date    Comment
00062  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00063  * Nilesh Rajbharti     4/27/01 Original        (Rev 1.0)
00064  * Nilesh Rajbharti     2/9/02  Cleanup
00065  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
00066  ********************************************************************/
00067 #ifndef __IP_H
00068 #define __IP_H
00069
00070
00071 #define IP_PROT_ICMP    (1u)
00072 #define IP_PROT_TCP     (6u)
00073 #define IP_PROT_UDP     (17u)
00074
00075
00076 // IP packet header definition
00077 typedef struct _IP_HEADER
00078 {
00079     BYTE    VersionIHL;
00080     BYTE    TypeOfService;
00081     WORD    TotalLength;
00082     WORD    Identification;
00083     WORD    FragmentInfo;
00084     BYTE    TimeToLive;
00085     BYTE    Protocol;
00086     WORD    HeaderChecksum;
00087     IP_ADDR SourceAddress;
00088     IP_ADDR DestAddress;
00089 } IP_HEADER;
00090
00091 // IP Pseudo header as defined by RFC 793 (needed for TCP and UDP
00092 // checksum calculations/verification)
00093 typedef struct _PSEUDO_HEADER
00094 {
00095     IP_ADDR SourceAddress;
00096     IP_ADDR DestAddress;
00097     BYTE Zero;
00098     BYTE Protocol;
00099     WORD Length;
00100 } PSEUDO_HEADER;
00101
00102 #define SwapPseudoHeader(h)  (h.Length = swaps(h.Length))
00103
00104
00105 /*********************************************************************
00106  * Function:        BOOL IPIsTxReady(BOOL HighPriority)
00107  *
00108  * PreCondition:    None
00109  *
00110  * Input:           None
00111  *
00112  * Output:          TRUE if transmit buffer is empty
00113  *                  FALSE if transmit buffer is not empty
00114  *
00115  * Side Effects:    None
00116  *
00117  * Note:            None
00118  *
00119  ********************************************************************/
00120 #define IPIsTxReady()       MACIsTxReady()
00121
00122
00123 /*********************************************************************
00124  * Macro:           IPSetTxBuffer(a, b)
00125  *
00126  * PreCondition:    None
00127  *
00128  * Input:           a       - Buffer identifier
00129  *                  b       - Offset
00130  *
00131  * Output:          Next Read/Write access to transmit buffer 'a'
00132  *                  set to offset 'b'
00133  *
00134  * Side Effects:    None
00135  *
00136  * Note:            None
00137  *
00138  ********************************************************************/
00139 #define IPSetTxBuffer(b) MACSetWritePtr(b + BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER))
00140
00141
00142
00143 /*********************************************************************
00144  * Function:        WORD IPPutHeader(   IP_ADDR *Dest,
00145  *                                      BYTE    Protocol,
00146  *                                      WORD    Identifier,
00147  *                                      WORD    DataLen)
00148  *
00149  * PreCondition:    IPIsTxReady() == TRUE
00150  *
00151  * Input:           Src         - Destination node address
00152  *                  Protocol    - Current packet protocol
00153  *                  Identifier  - Current packet identifier
00154  *                  DataLen     - Current packet data length
00155  *
00156  * Output:          Handle to current packet - For use by
00157  *                  IPSendByte() function.
00158  *
00159  * Side Effects:    None
00160  *
00161  * Note:            Only one IP message can be transmitted at any
00162  *                  time.
00163  *                  Caller may not transmit and receive a message
00164  *                  at the same time.
00165  *
00166  ********************************************************************/
00167 WORD    IPPutHeader(NODE_INFO *remote,
00168                     BYTE protocol,
00169                     WORD len);
00170
00171
00172 /*********************************************************************
00173  * Function:        BOOL IPGetHeader( IP_ADDR    *localIP,
00174  *                                    NODE_INFO  *remote,
00175  *                                    BYTE        *Protocol,
00176  *                                    WORD        *len)
00177  *
00178  * PreCondition:    MACGetHeader() == TRUE
00179  *
00180  * Input:           localIP     - Local node IP Address as received
00181  *                                in current IP header.
00182  *                                If this information is not required
00183  *                                caller may pass NULL value.
00184  *                  remote      - Remote node info
00185  *                  Protocol    - Current packet protocol
00186  *                  len         - Current packet data length
00187  *
00188  * Output:          TRUE, if valid packet was received
00189  *                  FALSE otherwise
00190  *
00191  * Side Effects:    None
00192  *
00193  * Note:            Only one IP message can be received.
00194  *                  Caller may not transmit and receive a message
00195  *                  at the same time.
00196  *
00197  ********************************************************************/
00198 BOOL IPGetHeader(IP_ADDR *localIP,
00199                  NODE_INFO *remote,
00200                  BYTE *protocol,
00201                  WORD *len);
00202
00203
00204 /*********************************************************************
00205  * Macro:           IPDiscard()
00206  *
00207  * PreCondition:    MACGetHeader() == TRUE
00208  *
00209  * Input:           None
00210  *
00211  * Output:          Current packet is discarded and buffer is
00212  *                  freed-up
00213  *
00214  * Side Effects:    None
00215  *
00216  * Note:            None
00217  *
00218  ********************************************************************/
00219 #define IPDiscard()         MACDiscard()
00220
00221
00222
00223 /*********************************************************************
00224  * Macro:           IPGetArray(a, b)
00225  *
00226  * PreCondition:    MACGetHeader() == TRUE
00227  *
00228  * Input:           a       - Data buffer
00229  *                  b       - Buffer length
00230  *
00231  * Output:          None
00232  *
00233  * Side Effects:    None
00234  *
00235  * Note:            Data is copied from IP data to given buffer
00236  *
00237  ********************************************************************/
00238 #define IPGetArray(a, b)    MACGetArray(a, b)
00239
00240
00241
00242
00243 /*********************************************************************
00244  * Function:        IPSetRxBuffer(WORD Offset)
00245  *
00246  * PreCondition:    IPHeaderLen must have been intialized by
00247  *                  IPGetHeader() or IPPutHeader()
00248  *
00249  * Input:           Offset from beginning of IP data field
00250  *
00251  * Output:          Next Read/Write access to receive buffer is
00252  *                  set to Offset
00253  *
00254  * Side Effects:    None
00255  *
00256  * Note:            None
00257  *
00258  ********************************************************************/
00259 void IPSetRxBuffer(WORD Offset);
00260
00261
00262
00263 // MODIFIX: Added this both functions.
00265
00284 DWORD IPConvertSubnetToMask(BYTE Subnet);
00285
00286
00288
00308 BYTE IPConvertMaskToSubnet(BYTE * MaskArray);
00309
00310 #endif
00311
00312
00313
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: MAC.h Source File

MAC.h

Go to the documentation of this file.
00001
00002
00003
00031 /*********************************************************************
00032  * Software License Agreement
00033  *
00034  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00035  * reserved.
00036  *
00037  * Microchip licenses to you the right to use, modify, copy, and
00038  * distribute:
00039  * (i)  the Software when embedded on a Microchip microcontroller or
00040  *      digital signal controller product ("Device") which is
00041  *      integrated into Licensee's product; or
00042  * (ii) ONLY the Software driver source files ENC28J60.c and
00043  *      ENC28J60.h ported to a non-Microchip device used in
00044  *      conjunction with a Microchip ethernet controller for the
00045  *      sole purpose of interfacing with the ethernet controller.
00046  *
00047  * You should refer to the license agreement accompanying this
00048  * Software for additional information regarding your rights and
00049  * obligations.
00050  *
00051  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00052  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00053  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00054  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00055  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00056  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00057  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00058  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00059  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00060  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00061  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00062  *
00063  *
00064  * Author               Date        Comment
00065  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00066  * Nilesh Rajbharti     4/27/01     Original        (Rev 1.0)
00067  * Nilesh Rajbharti     11/27/01    Added SLIP
00068  * Nilesh Rajbharti     2/9/02      Cleanup
00069  * Nilesh Rajbharti     5/22/02     Rev 2.0 (See version.log for detail)
00070  * Howard Schlunder     6/28/04     Added ENC28J60 specific features
00071  * Howard Schlunder     11/29/04    Added Get/SetLEDConfig macros
00072  ********************************************************************/
00073 #ifndef __MAC_H
00074 #define __MAC_H
00075
00076
00077 // MODIFIX: Removed support for ENC28J60
00078 #include "ETH97J60.h"
00079
00080 // MODIFIX: Added MAC address which is located in flash (bootloader).
00081 #ifdef __ETH97J60_C
00082
00083     #ifdef __DEBUG
00084         ROM BYTE cau8Mac[6] = {0x00,0x50,0xc2,0x7c,0x40,0x00};
00085         ROM BYTE * pu8MAC = (ROM BYTE *)cau8Mac;
00086     #else
00087         ROM BYTE * pu8MAC = (ROM BYTE *)0x1FBFAul;
00088     #endif
00089 #else
00090     extern ROM BYTE * pu8MAC;
00091 #endif
00092
00093
00094 #define MAC_TX_BUFFER_SIZE          (1500ul)
00095
00096 // A generic structure representing the Ethernet header starting all Ethernet
00097 // frames
00098 typedef struct  __attribute__((aligned(2), packed))
00099 {
00100     MAC_ADDR        DestMACAddr;
00101     MAC_ADDR        SourceMACAddr;
00102     WORD_VAL        Type;
00103 } ETHER_HEADER;
00104
00105
00106 #define MAC_IP          (0x00u)
00107 #define MAC_ARP         (0x06u)
00108 #define MAC_UNKNOWN     (0xFFu)
00109
00110 /*
00111  * Microchip Ethernet controller specific MAC items
00112  */
00113 #if !defined(STACK_USE_HTTP2_SERVER)
00114     #define RESERVED_HTTP_MEMORY 0ul
00115 #endif
00116
00117 #if !defined(STACK_USE_SSL)
00118     #define RESERVED_SSL_MEMORY 0ul
00119 #endif
00120
00121 // MAC RAM definitions
00122 #define RAMSIZE 8192ul
00123 #define TXSTART (RAMSIZE - (1ul+1514ul+7ul) - TCP_ETH_RAM_SIZE - RESERVED_HTTP_MEMORY - RESERVED_SSL_MEMORY)
00124 #define RXSTART (0ul)                       // Should be an even memory address; must be 0 for errata
00125 #define RXSTOP  ((TXSTART-2ul) | 0x0001ul)  // Odd for errata workaround
00126 #define RXSIZE  (RXSTOP-RXSTART+1ul)
00127
00128 #define BASE_TX_ADDR    (TXSTART + 1ul)
00129 #define BASE_TCB_ADDR   (BASE_TX_ADDR + (1514ul+7ul))
00130 #define BASE_HTTPB_ADDR (BASE_TCB_ADDR + TCP_ETH_RAM_SIZE)
00131 #define BASE_SSLB_ADDR  (BASE_HTTPB_ADDR + RESERVED_HTTP_MEMORY)
00132
00133 #if (RXSIZE < 1400) || (RXSIZE > RAMSIZE)
00134     #error Warning, Ethernet RX buffer is tiny.  Reduce TCP socket count, the size of each TCP socket, or move sockets to a different RAM
00135 #endif
00136
00137 WORD    MACCalcRxChecksum(WORD offset, WORD len);
00138 WORD    CalcIPBufferChecksum(WORD len);
00139
00140 void    MACPowerDown(void);
00141 void    MACPowerUp(void);
00142 void    WritePHYReg(BYTE Register, WORD Data);
00143 PHYREG  ReadPHYReg(BYTE Register);
00144 void    SetRXHashTableEntry(MAC_ADDR DestMACAddr);
00145
00146 // MODIFIX: Removed ENC28J60 specific function prototypes SetCLKOUT and
00147 // GetCLKOUT.
00148
00149 /******************************************************************************
00150  * Macro:           void SetLEDConfig(WORD NewConfig)
00151  *
00152  * PreCondition:    SPI bus must be initialized (done in MACInit()).
00153  *
00154  * Input:           NewConfig - xxx0: Pulse stretching disabled
00155  *                              xxx2: Pulse stretch to 40ms (default)
00156  *                              xxx6: Pulse stretch to 73ms
00157  *                              xxxA: Pulse stretch to 139ms
00158  *
00159  *                              xx1x: LEDB - TX
00160  *                              xx2x: LEDB - RX (default)
00161  *                              xx3x: LEDB - collisions
00162  *                              xx4x: LEDB - link
00163  *                              xx5x: LEDB - duplex
00164  *                              xx7x: LEDB - TX and RX
00165  *                              xx8x: LEDB - on
00166  *                              xx9x: LEDB - off
00167  *                              xxAx: LEDB - blink fast
00168  *                              xxBx: LEDB - blink slow
00169  *                              xxCx: LEDB - link and RX
00170  *                              xxDx: LEDB - link and TX and RX
00171  *                              xxEx: LEDB - duplex and collisions
00172  *
00173  *                              x1xx: LEDA - TX
00174  *                              x2xx: LEDA - RX
00175  *                              x3xx: LEDA - collisions
00176  *                              x4xx: LEDA - link (default)
00177  *                              x5xx: LEDA - duplex
00178  *                              x7xx: LEDA - TX and RX
00179  *                              x8xx: LEDA - on
00180  *                              x9xx: LEDA - off
00181  *                              xAxx: LEDA - blink fast
00182  *                              xBxx: LEDA - blink slow
00183  *                              xCxx: LEDA - link and RX
00184  *                              xDxx: LEDA - link and TX and RX
00185  *                              xExx: LEDA - duplex and collisions
00186  *
00187  * Output:          None
00188  *
00189  * Side Effects:    None
00190  *
00191  * Overview:        Writes the value of NewConfig into the PHLCON PHY register.
00192  *                  The LED pins will beginning outputting the new
00193  *                  configuration immediately.
00194  *
00195  * Note:
00196  *****************************************************************************/
00197 #define SetLEDConfig(NewConfig)     WritePHYReg(PHLCON, NewConfig)
00198
00199
00200 /******************************************************************************
00201  * Macro:           WORD GetLEDConfig(void)
00202  *
00203  * PreCondition:    SPI bus must be initialized (done in MACInit()).
00204  *
00205  * Input:           None
00206  *
00207  * Output:          WORD -  xxx0: Pulse stretching disabled
00208  *                          xxx2: Pulse stretch to 40ms (default)
00209  *                          xxx6: Pulse stretch to 73ms
00210  *                          xxxA: Pulse stretch to 139ms
00211  *
00212  *                          xx1x: LEDB - TX
00213  *                          xx2x: LEDB - RX (default)
00214  *                          xx3x: LEDB - collisions
00215  *                          xx4x: LEDB - link
00216  *                          xx5x: LEDB - duplex
00217  *                          xx7x: LEDB - TX and RX
00218  *                          xx8x: LEDB - on
00219  *                          xx9x: LEDB - off
00220  *                          xxAx: LEDB - blink fast
00221  *                          xxBx: LEDB - blink slow
00222  *                          xxCx: LEDB - link and RX
00223  *                          xxDx: LEDB - link and TX and RX
00224  *                          xxEx: LEDB - duplex and collisions
00225  *
00226  *                          x1xx: LEDA - TX
00227  *                          x2xx: LEDA - RX
00228  *                          x3xx: LEDA - collisions
00229  *                          x4xx: LEDA - link (default)
00230  *                          x5xx: LEDA - duplex
00231  *                          x7xx: LEDA - TX and RX
00232  *                          x8xx: LEDA - on
00233  *                          x9xx: LEDA - off
00234  *                          xAxx: LEDA - blink fast
00235  *                          xBxx: LEDA - blink slow
00236  *                          xCxx: LEDA - link and RX
00237  *                          xDxx: LEDA - link and TX and RX
00238  *                          xExx: LEDA - duplex and collisions
00239  *
00240  * Side Effects:    None
00241  *
00242  * Overview:        Returns the current value of the PHLCON register.
00243  *
00244  * Note:            None
00245  *****************************************************************************/
00246 #define GetLEDConfig()      ReadPHYReg(PHLCON).Val
00247
00248
00249 void MACInit(void);
00250
00251
00253
00269 BOOL MACIsLinked(void);
00270
00271 BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type);
00272 void MACSetReadPtrInRx(WORD offset);
00273 WORD MACSetWritePtr(WORD address);
00274 WORD MACSetReadPtr(WORD address);
00275 BYTE MACGet(void);
00276 WORD MACGetArray(BYTE *val, WORD len);
00277 void MACDiscardRx(void);
00278 WORD MACGetFreeRxSize(void);
00279 void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len);
00280 BOOL MACIsMemCopyDone(void);
00281
00282 void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen);
00283 BOOL MACIsTxReady(void);
00284 void MACPut(BYTE val);
00285 void MACPutArray(BYTE *val, WORD len);
00286 void MACFlush(void);
00287
00288 // ROM function variants for PIC18
00289 #if defined(__18CXX)
00290     void MACPutROMArray(ROM BYTE *val, WORD len);
00291 #else
00292     #define MACPutROMArray(a,b) MACPutArray((BYTE*)a,b)
00293 #endif
00294
00295
00296 WORD_VAL u16MACGetCurrentReadPtrPos(void);
00297 void MACSetCurrentReadPtrPos(WORD_VAL u16Pos);
00298
00299 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: MPFS2.c Source File

MPFS2.c

Go to the documentation of this file.
00001
00002
00003
00023 /*********************************************************************
00024  * Software License Agreement
00025  *
00026  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00027  * reserved.
00028  *
00029  * Microchip licenses to you the right to use, modify, copy, and
00030  * distribute:
00031  * (i)  the Software when embedded on a Microchip microcontroller or
00032  *      digital signal controller product ("Device") which is
00033  *      integrated into Licensee's product; or
00034  * (ii) ONLY the Software driver source files ENC28J60.c and
00035  *      ENC28J60.h ported to a non-Microchip device used in
00036  *      conjunction with a Microchip ethernet controller for the
00037  *      sole purpose of interfacing with the ethernet controller.
00038  *
00039  * You should refer to the license agreement accompanying this
00040  * Software for additional information regarding your rights and
00041  * obligations.
00042  *
00043  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00044  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00045  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00046  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00047  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00048  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00049  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00050  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00051  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00052  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00053  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00054  *
00055  *
00056  * Author               Date        Comment
00057  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00058  * Elliott Wood         07/2007     Complete rewrite as MPFS2
00059  * E. Wood              04/2008     Updated as MPFS2.1
00060  ********************************************************************/
00061 #define __MPFS2_C
00062
00063 #include "TCPIP.h"
00064
00065 #if defined(STACK_USE_MPFS2)
00066
00067 // MODIFIX: Added inlude for huffman decoding support:
00068 #include "huffman.h"
00069
00070
00071 //Supports long file names to 64 characters
00072 #define MAX_FILE_NAME_LEN   (64u)
00073
00074 /*
00075  * MPFS Structure:
00076  *     [M][P][F][S]
00077  *     [BYTE Ver Hi][BYTE Ver Lo][WORD Number of Files]
00078  *     [Name Hash 0][Name Hash 1]...[Name Hash N]
00079  *     [File Record 0][File Record 1]...[File Record N]
00080  *     [String 0][String 1]...[String N]
00081  *     [File Data 0][File Data 1]...[File Data N]
00082  *
00083  * Name Hash (2 bytes):
00084  *     hash = 0
00085  *     for each(byte in name)
00086  *         hash += byte
00087  *         hash <<= 1
00088  *
00089  *     Technically this means the hash only includes the
00090  *     final 15 characters of a name.
00091  *
00092  * File Record Structure (22 bytes):
00093  *     [DWORD String Ptr][DWORD Data Ptr]
00094  *     [DWORD Len][DWORD Timestamp][DWORD Microtime]
00095  *     [WORD Flags]
00096  *
00097  *     Pointers are absolute addresses within the MPFS image.
00098  *     Timestamp is the UNIX timestamp
00099  *     Microtime is currently unimplemented
00100  *
00101  * String Structure (1 to 64 bytes):
00102  *     ["path/to/file.ext"][0x00]
00103  *
00104  * File Data Structure (arbitrary length):
00105  *      [File Data]
00106  *
00107  * Unlike previous versions, there are no delimiters.
00108  *
00109  * Name hash is calculated as follows:
00110  *      hash = 0
00111  *      for each(byte in name)
00112  *          hash += byte, hash <<= 1
00113  *
00114  * When a file has an index, that index file has no file name,
00115  * but is accessible as the file immediately following in the image.
00116  *
00117  * Current version is 2.1
00118  */
00119
00120 /****************************************************************************
00121   Section:
00122     Module-Only Globals and Functions
00123   ***************************************************************************/
00124
00125 // Track the MPFS File Handles
00126 // MPFSStubs[0] is reserved for internal use (FAT access)
00127 static MPFS_STUB MPFSStubs[MAX_MPFS_HANDLES+1];
00128
00129 // Allows the MPFS to be locked, preventing access during updates
00130 static BOOL isMPFSLocked;
00131
00132 // FAT record cache
00133 static MPFS_FAT_RECORD fatCache;
00134
00135 // ID of currently loaded fatCache
00136 static WORD fatCacheID;
00137
00138 // Number of files in this MPFS image
00139 static WORD numFiles;
00140
00141
00142 static void _LoadFATRecord(WORD fatID);
00143 static void _Validate(void);
00144
00145 /****************************************************************************
00146   Section:
00147     EEPROM vs Flash Storage Settings
00148   ***************************************************************************/
00149
00150 #if defined(MPFS_USE_EEPROM)
00151
00152     // Beginning address of MPFS Image
00153     #define MPFS_HEAD       MPFS_RESERVE_BLOCK
00154
00155     // Track the last read address to prevent unnecessary
00156     // data overhead to switch locations.
00157     MPFS_PTR lastRead;
00158
00159
00160 #elif defined(MPFS_USE_SPI_FLASH)
00161
00162     // Beginning address of MPFS Image
00163     #define MPFS_HEAD       MPFS_RESERVE_BLOCK
00164
00165 #else
00166
00167     // An address where MPFS data starts in program memory.
00168     #if defined(__18CXX) || defined(__C32__)
00169         extern ROM BYTE MPFS_Start[];
00170         #define MPFS_HEAD       ((DWORD)(&MPFS_Start[0]))
00171     #else
00172         extern DWORD MPFS_Start;
00173         #define MPFS_HEAD       MPFS_Start;
00174     #endif
00175
00176 #endif
00177
00178 /****************************************************************************
00179   Section:
00180     Stack-Level Functions
00181   ***************************************************************************/
00182
00183 /*****************************************************************************
00184   Function:
00185     void MPFSInit(void)
00186
00187   Summary:
00188     Initializes the MPFS module.
00189
00190   Description:
00191     Sets all MPFS handles to closed, and initializes access to the EEPROM
00192     if necessary.
00193
00194   Precondition:
00195     None
00196
00197   Parameters:
00198     None
00199
00200   Returns:
00201     None
00202
00203   Remarks:
00204     This function is called only one during lifetime of the application.
00205   ***************************************************************************/
00206 void MPFSInit(void)
00207 {
00208     BYTE i;
00209
00210     for(i = 1; i <= MAX_MPFS_HANDLES; i++)
00211     {
00212         MPFSStubs[i].addr = MPFS_INVALID;
00213     }
00214
00215     #if defined(MPFS_USE_EEPROM)
00216     // Initialize the EEPROM access routines.
00217     XEEInit();
00218     lastRead = MPFS_INVALID;
00219     #endif
00220
00221     #if defined(MPFS_USE_SPI_FLASH)
00222     // Initialize SPI Flash access routines.
00223     SPIFlashInit();
00224     #endif
00225
00226     // Validate the image and load numFiles
00227     _Validate();
00228
00229     isMPFSLocked = FALSE;
00230
00231 }
00232
00233 /****************************************************************************
00234   Section:
00235     Handle Management Functions
00236   ***************************************************************************/
00237
00238 /*****************************************************************************
00239   Function:
00240     MPFS_HANDLE MPFSOpen(BYTE* cFile)
00241
00242   Description:
00243     Opens a file in the MPFS2 file system.
00244
00245   Precondition:
00246     None
00247
00248   Parameters:
00249     cFile - a null terminated file name to open
00250
00251   Returns:
00252     An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE
00253     if the file could not be found or no free handles exist.
00254   ***************************************************************************/
00255 MPFS_HANDLE MPFSOpen(BYTE* cFile)
00256 {
00257     MPFS_HANDLE hMPFS;
00258     WORD nameHash, i;
00259     WORD hashCache[8];
00260     BYTE *ptr, c;
00261
00262     // Initialize c to avoid "may be used uninitialized" compiler warning
00263     c = 0;
00264
00265     // Make sure MPFS is unlocked and we got a filename
00266     if(*cFile == '\0' || isMPFSLocked == TRUE)
00267         return MPFS_INVALID_HANDLE;
00268
00269     // Calculate the name hash to speed up searching
00270     for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++)
00271     {
00272         nameHash += *ptr;
00273         nameHash <<= 1;
00274     }
00275
00276     // Find a free file handle to use
00277     for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++)
00278         if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
00279             break;
00280     if(hMPFS == MAX_MPFS_HANDLES)
00281         return MPFS_INVALID_HANDLE;
00282
00283     // Read in hashes, and check remainder on a match.  Store 8 in cache for performance
00284     for(i = 0; i < numFiles; i++)
00285     {
00286         // For new block of 8, read in data
00287         if((i & 0x07) == 0)
00288         {
00289             MPFSStubs[0].addr = 8 + i*2;
00290             MPFSStubs[0].bytesRem = 16;
00291             MPFSGetArray(0, (BYTE*)hashCache, 16);
00292         }
00293
00294         // If the hash matches, compare the full filename
00295         if(hashCache[i&0x07] == nameHash)
00296         {
00297             _LoadFATRecord(i);
00298             MPFSStubs[hMPFS].addr = fatCache.string;
00299             MPFSStubs[hMPFS].bytesRem = 255;
00300             MPFSStubs[hMPFS].offset = 0;    // MODIFIX: Added for huffman decoding.
00301
00302             // Loop over filename to perform comparison
00303             for(ptr = cFile; *ptr != '\0'; ptr++)
00304             {
00305                 MPFSGet(hMPFS, &c);
00306                 if(*ptr != c)
00307                     break;
00308             }
00309
00310             MPFSGet(hMPFS, &c);
00311
00312             if(c == '\0' && *ptr == '\0')
00313             {// Filename matches, so return true
00314                 MPFSStubs[hMPFS].addr = fatCache.data;
00315                 MPFSStubs[hMPFS].bytesRem = fatCache.len;
00316                 MPFSStubs[hMPFS].fatID = i;
00317
00318                 // MODIFIX: Added the following lines for huffman encoding support.
00319                 if (fatCache.flags & MPFS2_FLAG_ISCOMPRESSED)
00320                 {
00321                     MPFSStubs[hMPFS].offset = 0x01;
00322                 }
00323                 else
00324                 {
00325                     MPFSStubs[hMPFS].offset = 0;
00326                 }
00327                 // MODIFIX: END
00328
00329                 return hMPFS;
00330             }
00331         }
00332     }
00333
00334     // No file name matched, so return nothing
00335     return MPFS_INVALID_HANDLE;
00336 }
00337
00338 /*****************************************************************************
00339   Function:
00340     MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile)
00341
00342   Description:
00343     Opens a file in the MPFS2 file system.
00344
00345   Precondition:
00346     None
00347
00348   Parameters:
00349     cFile - a null terminated file name to open
00350
00351   Returns:
00352     An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE
00353     if the file could not be found or no free handles exist.
00354
00355   Remarks:
00356     This function is aliased to MPFSOpen on non-PIC18 platforms.
00357   ***************************************************************************/
00358 #if defined(__18CXX)
00359 MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile)
00360 {
00361     MPFS_HANDLE hMPFS;
00362     WORD nameHash, i;
00363     WORD hashCache[8];
00364     ROM BYTE *ptr;
00365     BYTE c;
00366
00367     // Make sure MPFS is unlocked and we got a filename
00368     if(*cFile == '\0' || isMPFSLocked == TRUE)
00369         return MPFS_INVALID_HANDLE;
00370
00371     // Calculate the name hash to speed up searching
00372     for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++)
00373     {
00374         nameHash += *ptr;
00375         nameHash <<= 1;
00376     }
00377
00378     // Find a free file handle to use
00379     for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++)
00380         if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
00381             break;
00382     if(hMPFS == MAX_MPFS_HANDLES)
00383         return MPFS_INVALID_HANDLE;
00384
00385     // Read in hashes, and check remainder on a match.  Store 8 in cache for performance
00386     for(i = 0; i < numFiles; i++)
00387     {
00388         // For new block of 8, read in data
00389         if((i & 0x07) == 0)
00390         {
00391             MPFSStubs[0].addr = 8 + i*2;
00392             MPFSStubs[0].bytesRem = 16;
00393             MPFSGetArray(0, (BYTE*)hashCache, 16);
00394         }
00395
00396         // If the hash matches, compare the full filename
00397         if(hashCache[i&0x07] == nameHash)
00398         {
00399             _LoadFATRecord(i);
00400             MPFSStubs[hMPFS].addr = fatCache.string;
00401             MPFSStubs[hMPFS].bytesRem = 255;
00402             MPFSStubs[hMPFS].offset = 0;    // MODIFIX: Added for huffman decoding.
00403
00404             // Loop over filename to perform comparison
00405             for(ptr = cFile; *ptr != '\0'; ptr++)
00406             {
00407                 MPFSGet(hMPFS, &c);
00408                 if(*ptr != c)
00409                     break;
00410             }
00411
00412             MPFSGet(hMPFS, &c);
00413
00414             if(c == '\0' && *ptr == '\0')
00415             {// Filename matches, so return true
00416                 MPFSStubs[hMPFS].addr = fatCache.data;
00417                 MPFSStubs[hMPFS].bytesRem = fatCache.len;
00418                 MPFSStubs[hMPFS].fatID = i;
00419
00420                 // MODIFIX: Added the following lines for huffman encoding support.
00421                 if (fatCache.flags & MPFS2_FLAG_HASINDEX)
00422                 {
00423                     MPFSStubs[hMPFS].offset = 0x01;
00424                 }
00425                 else
00426                 {
00427                     MPFSStubs[hMPFS].offset = 0;
00428                 }
00429                 // MODIFIX: END
00430
00431                 return hMPFS;
00432             }
00433         }
00434     }
00435
00436     // No file name matched, so return nothing
00437     return MPFS_INVALID_HANDLE;
00438 }
00439 #endif
00440
00441 /*****************************************************************************
00442   Function:
00443     MPFS_HANDLE MPFSOpenID(WORD hFatID)
00444
00445   Summary:
00446     Quickly re-opens a file.
00447
00448   Description:
00449     Quickly re-opens a file in the MPFS2 file system.  Use this function
00450     along with MPFSGetID() to quickly re-open a file without tying up
00451     a permanent MPFSStub.
00452
00453   Precondition:
00454     None
00455
00456   Parameters:
00457     hFatID - the ID of a previous opened file in the FAT
00458
00459   Returns:
00460     An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE
00461     if the file could not be found or no free handles exist.
00462   ***************************************************************************/
00463 MPFS_HANDLE MPFSOpenID(WORD hFatID)
00464 {
00465     MPFS_HANDLE hMPFS;
00466
00467     // Make sure MPFS is unlocked and we got a valid id
00468     if(isMPFSLocked == TRUE || hFatID > numFiles)
00469         return MPFS_INVALID_HANDLE;
00470
00471     // Find a free file handle to use
00472     for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++)
00473         if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
00474             break;
00475     if(hMPFS == MAX_MPFS_HANDLES)
00476         return MPFS_INVALID_HANDLE;
00477
00478     // Load the FAT record
00479     _LoadFATRecord(hFatID);
00480
00481     // Set up the file handle
00482     MPFSStubs[hMPFS].fatID = hFatID;
00483     MPFSStubs[hMPFS].addr = fatCache.data;
00484     MPFSStubs[hMPFS].bytesRem = fatCache.len;
00485
00486
00487     // MODIFIX: Added the following lines for huffman encoding support.
00488     if (fatCache.flags & MPFS2_FLAG_HASINDEX)
00489     {
00490         MPFSStubs[hMPFS].offset = 0x01;
00491     }
00492     else
00493     {
00494         MPFSStubs[hMPFS].offset = 0;
00495     }
00496     // MODIFIX: END
00497
00498
00499     return hMPFS;
00500 }
00501
00502 /*****************************************************************************
00503   Function:
00504     void MPFSClose(MPFS_HANDLE hMPFS)
00505
00506   Summary:
00507     Closes a file.
00508
00509   Description:
00510     Closes a file and releases its stub back to the pool of available
00511     handles.
00512
00513   Precondition:
00514     None
00515
00516   Parameters:
00517     hMPFS - the file handle to be closed
00518
00519   Returns:
00520     None
00521   ***************************************************************************/
00522 void MPFSClose(MPFS_HANDLE hMPFS)
00523 {
00524     if(hMPFS != 0u && hMPFS <= MAX_MPFS_HANDLES)
00525         MPFSStubs[hMPFS].addr = MPFS_INVALID;
00526 }
00527
00528
00529 /****************************************************************************
00530   Section:
00531     Data Reading Functions
00532   ***************************************************************************/
00533
00534 // MODIFIX: Added the following function!
00535 void MPFSGetArrayHuffman(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen)
00536 {
00537     BYTE currentValue;
00538     BYTE offset = MPFSStubs[hMPFS].offset;
00539     ROM BYTE* addr;
00540     BYTE bytesRead = 0;
00541
00542     MPFSStubs[hMPFS].bytesRem -= wLen;
00543     addr = (ROM BYTE*)(MPFSStubs[hMPFS].addr + MPFS_HEAD);
00544     currentValue = *addr;
00545
00546     while(wLen)
00547     {
00548         HUFFMAN_CODE_TYPE mask = MAX_HUFFMAN_CODE_MASK;
00549         HUFFMAN_CODE_TYPE code = 0;
00550         BYTE codeLength = 1;
00551         BYTE codeIndex = 0;
00552
00553         while(1)
00554         {
00555             if (offset & currentValue)
00556             {
00557                 code |= mask;
00558             }
00559
00560             offset = offset << 1;
00561             if (offset == 0)
00562             {
00563                 addr++;
00564                 currentValue = *addr;
00565                 bytesRead++;
00566                 offset = 0x01;
00567             }
00568
00569
00570             if (HuffmanCode[codeIndex].CodeLength == codeLength)
00571             {
00572                 if (HuffmanCode[codeIndex].StartCode <= code)
00573                 {
00574                     break;
00575                 }
00576
00577                 codeIndex++;
00578             }
00579
00580
00581             codeLength++;
00582             mask = mask >> 1;
00583         }
00584
00585
00586         if (cData)
00587         {
00588             // Fetch the character from the table:
00589             BYTE index = HuffmanCode[codeIndex].CharacterIndex;
00590             code = (code - HuffmanCode[codeIndex].StartCode);
00591
00592             while(code)
00593             {
00594                 code -= mask;
00595                 index++;
00596             }
00597
00598             *cData = HuffmanCharacter[index];
00599             cData++;
00600         }
00601
00602         wLen--;
00603     }
00604
00605
00606     MPFSStubs[hMPFS].offset = offset;
00607     MPFSStubs[hMPFS].addr += bytesRead;
00608 }
00609 // MODIFIX: END
00610
00611
00612 /*****************************************************************************
00613   Function:
00614     BOOL MPFSGet(MPFS_HANDLE hMPFS, BYTE* c)
00615
00616   Description:
00617     Reads a byte from a file.
00618
00619   Precondition:
00620     The file handle referenced by hMPFS is already open.
00621
00622   Parameters:
00623     hMPFS - the file handle from which to read
00624     c - Where to store the byte that was read
00625
00626   Return Values:
00627     TRUE - The byte was successfully read
00628     FALSE - No byte was read because either the handle was invalid or
00629             the end of the file has been reached.
00630   ***************************************************************************/
00631 BOOL MPFSGet(MPFS_HANDLE hMPFS, BYTE* c)
00632 {
00633     // Make sure we're reading a valid address
00634     if(hMPFS > MAX_MPFS_HANDLES)
00635         return FALSE;
00636     if( MPFSStubs[hMPFS].addr == MPFS_INVALID ||
00637         MPFSStubs[hMPFS].bytesRem == 0u)
00638         return FALSE;
00639
00640     // MODIFIX: Added the following lines for huffman decoding support:
00641     if (MPFSStubs[hMPFS].offset)
00642     {
00643         MPFSGetArrayHuffman(hMPFS, c, 1);
00644         return TRUE;
00645     }
00646     // MODIFIX: END
00647
00648     if(c == NULL)
00649     {
00650         MPFSStubs[hMPFS].addr++;
00651         MPFSStubs[hMPFS].bytesRem--;
00652         return TRUE;
00653     }
00654
00655
00656     // Read function for EEPROM
00657     #if defined(MPFS_USE_EEPROM)
00658         // For performance, cache the last read address
00659         if(MPFSStubs[hMPFS].addr != lastRead+1)
00660             XEEBeginRead(MPFSStubs[hMPFS].addr + MPFS_HEAD);
00661         *c = XEERead();
00662         lastRead = MPFSStubs[hMPFS].addr;
00663         MPFSStubs[hMPFS].addr++;
00664     #elif defined(MPFS_USE_SPI_FLASH)
00665         SPIFlashReadArray(MPFSStubs[hMPFS].addr + MPFS_HEAD, c, 1);
00666         MPFSStubs[hMPFS].addr++;
00667     #else
00668         #if defined(__C30__)
00669         {
00670             DWORD addr;
00671             DWORD_VAL read;
00672             BYTE i;
00673
00674             // MPFS Images are addressed by the byte; Program memory by the word.
00675             //
00676             // Flash program memory is 24 bits wide and only even words are
00677             // implemented.  The upper byte of the upper word is read as 0x00.
00678             // Address in program memory of any given byte is (MPFSAddr * 2) / 3
00679             //
00680             // We will read 24 bits at a time, but need to support using only
00681             // fractions of the first and last byte.
00682
00683             // Find the beginning address in program memory.
00684             addr = (MPFSStubs[hMPFS].addr / 3) << 1;
00685
00686             // Find where to start in that first 3 bytes
00687             read.Val = (addr * 3) >> 1;
00688             if(read.Val == MPFSStubs[hMPFS].addr)
00689                 i = 0;
00690             else if(read.Val+1 == MPFSStubs[hMPFS].addr)
00691                 i = 1;
00692             else
00693                 i = 2;
00694
00695             // Add in the MPFS starting address offset
00696             addr += MPFS_HEAD;
00697
00698             // Update the MPFS Handle
00699             MPFSStubs[hMPFS].addr++;
00700
00701             // Read the DWORD
00702             read.Val = ReadProgramMemory(addr & 0x00FFFFFF);
00703             *c = read.v[i];
00704
00705         }
00706         #else
00707         {
00708             DWORD dwHITECHWorkaround = MPFS_HEAD;
00709         *c = *((ROM BYTE*)(MPFSStubs[hMPFS].addr+dwHITECHWorkaround));
00710             MPFSStubs[hMPFS].addr++;
00711         }
00712         #endif
00713     #endif
00714
00715     MPFSStubs[hMPFS].bytesRem--;
00716     return TRUE;
00717 }
00718
00719 /*****************************************************************************
00720   Function:
00721     WORD MPFSGetArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen)
00722
00723   Description:
00724     Reads a series of bytes from a file.
00725
00726   Precondition:
00727     The file handle referenced by hMPFS is already open.
00728
00729   Parameters:
00730     hMPFS - the file handle from which to read
00731     cData - where to store the bytes that were read
00732     wLen - how many bytes to read
00733
00734   Returns:
00735     The number of bytes successfully read.  If this is less than wLen,
00736     an EOF occurred while attempting to read.
00737   ***************************************************************************/
00738 WORD MPFSGetArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen)
00739 {
00740     // Make sure we're reading a valid address
00741     if(hMPFS > MAX_MPFS_HANDLES)
00742         return 0;
00743
00744     // Determine how many we can actually read
00745     if(wLen > MPFSStubs[hMPFS].bytesRem)
00746         wLen = MPFSStubs[hMPFS].bytesRem;
00747
00748     // Make sure we're reading a valid address
00749     if(MPFSStubs[hMPFS].addr == MPFS_INVALID || wLen == 0)
00750         return 0;
00751
00752     // MODIFIX: Added the following lines for huffman decoding support:
00753     if (MPFSStubs[hMPFS].offset)
00754     {
00755         MPFSGetArrayHuffman(hMPFS, cData, wLen);
00756         return wLen;
00757     }
00758     // MODIFIX: END
00759
00760
00761     if(cData == NULL)
00762     {
00763         MPFSStubs[hMPFS].addr += wLen;
00764         MPFSStubs[hMPFS].bytesRem -= wLen;
00765         return wLen;
00766     }
00767
00768     // Read the data
00769     #if defined(MPFS_USE_EEPROM)
00770         XEEReadArray(MPFSStubs[hMPFS].addr+MPFS_HEAD, cData, wLen);
00771         MPFSStubs[hMPFS].addr += wLen;
00772         MPFSStubs[hMPFS].bytesRem -= wLen;
00773         lastRead = MPFS_INVALID;
00774     #elif defined(MPFS_USE_SPI_FLASH)
00775         SPIFlashReadArray(MPFSStubs[hMPFS].addr+MPFS_HEAD, cData, wLen);
00776         MPFSStubs[hMPFS].addr += wLen;
00777         MPFSStubs[hMPFS].bytesRem -= wLen;
00778     #else
00779         #if defined(__C30__)
00780         {
00781             DWORD addr;
00782             DWORD_VAL read;
00783             WORD count;
00784             BYTE i;
00785
00786             // MPFS Images are addressed by the byte; Program memory by the word.
00787             //
00788             // Flash program memory is 24 bits wide and only even words are
00789             // implemented.  The upper byte of the upper word is read as 0x00.
00790             // Address in program memory of any given byte is (MPFSAddr * 2) / 3
00791             //
00792             // We will read 24 bits at a time, but need to support using only
00793             // fractions of the first and last byte.
00794
00795             // Find the beginning address in program memory.
00796             addr = (MPFSStubs[hMPFS].addr / 3) << 1;
00797
00798             // Find where to start in that first 3 bytes
00799             read.Val = (addr * 3) >> 1;
00800             if(read.Val == MPFSStubs[hMPFS].addr)
00801                 i = 0;
00802             else if(read.Val+1 == MPFSStubs[hMPFS].addr)
00803                 i = 1;
00804             else
00805                 i = 2;
00806
00807             // Add in the MPFS starting address offset
00808             addr += MPFS_HEAD;
00809
00810             // Update the MPFS Handle
00811             MPFSStubs[hMPFS].addr += wLen;
00812             MPFSStubs[hMPFS].bytesRem -= wLen;
00813
00814             // Read the first DWORD
00815             read.Val = ReadProgramMemory(addr & 0x00FFFFFF);
00816             addr += 2;
00817
00818             // Copy values as needed
00819             for(count = wLen; count > 0; cData++, count--)
00820             {
00821                 // Copy the next value in
00822                 *cData = read.v[i++];
00823
00824                 // Check if a new DWORD is needed
00825                 if(i == 3 && count != 1)
00826                 {// Read in a new DWORD
00827                     read.Val = ReadProgramMemory(addr & 0x00FFFFFF);
00828                     addr += 2;
00829                     i = 0;
00830                 }
00831             }
00832
00833         }
00834         #else
00835         {
00836             DWORD dwHITECHWorkaround = MPFS_HEAD;
00837             memcpypgm2ram(cData, (ROM void*)(MPFSStubs[hMPFS].addr + dwHITECHWorkaround), wLen);
00838             MPFSStubs[hMPFS].addr += wLen;
00839             MPFSStubs[hMPFS].bytesRem -= wLen;
00840         }
00841         #endif
00842     #endif
00843
00844     return wLen;
00845 }
00846
00847 /*****************************************************************************
00848   Function:
00849     BOOL MPFSGetLong(MPFS_HANDLE hMPFS, DWORD* ul)
00850
00851   Description:
00852     Reads a DWORD or Long value from the MPFS.
00853
00854   Precondition:
00855     The file handle referenced by hMPFS is already open.
00856
00857   Parameters:
00858     hMPFS - the file handle from which to read
00859     ul - where to store the DWORD or long value that was read
00860
00861   Returns:
00862     TRUE - The byte was successfully read
00863     FALSE - No byte was read because either the handle was invalid or
00864             the end of the file has been reached.
00865   ***************************************************************************/
00866 BOOL MPFSGetLong(MPFS_HANDLE hMPFS, DWORD* ul)
00867 {
00868     return ( MPFSGetArray(hMPFS, (BYTE*)ul, 4) == 4 );
00869 }
00870
00871 /*****************************************************************************
00872   Function:
00873     BOOL MPFSSeek(MPFS_HANDLE hMPFS, DWORD dwOffset, MPFS_SEEK_MODE tMode)
00874
00875   Description:
00876     Moves the current read pointer to a new location.
00877
00878   Precondition:
00879     The file handle referenced by hMPFS is already open.
00880
00881   Parameters:
00882     hMPFS - the file handle to seek with
00883     dwOffset - offset from the specified position in the specified direction
00884     tMode - one of the MPFS_SEEK_MODE constants
00885
00886   Returns:
00887     TRUE - the seek was successful
00888     FALSE - either the new location or the handle itself was invalid
00889   ***************************************************************************/
00890 BOOL MPFSSeek(MPFS_HANDLE hMPFS, DWORD dwOffset, MPFS_SEEK_MODE tMode)
00891 {
00892     DWORD temp;
00893
00894     // Make sure a valid file is open
00895     if(hMPFS > MAX_MPFS_HANDLES)
00896         return FALSE;
00897     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
00898         return FALSE;
00899
00900     switch(tMode)
00901     {
00902         // Seek offset bytes from start
00903         case MPFS_SEEK_START:
00904             temp = MPFSGetSize(hMPFS);
00905             if(dwOffset > temp)
00906                 return FALSE;
00907
00908             MPFSStubs[hMPFS].addr = MPFSGetStartAddr(hMPFS) + dwOffset;
00909             MPFSStubs[hMPFS].bytesRem = temp - dwOffset;
00910             return TRUE;
00911
00912         // Seek forwards offset bytes
00913         case MPFS_SEEK_FORWARD:
00914             if(dwOffset > MPFSStubs[hMPFS].bytesRem)
00915                 return FALSE;
00916
00917             MPFSStubs[hMPFS].addr += dwOffset;
00918             MPFSStubs[hMPFS].bytesRem -= dwOffset;
00919             return TRUE;
00920
00921         // Seek backwards offset bytes
00922         case MPFS_SEEK_REWIND:
00923             temp = MPFSGetStartAddr(hMPFS);
00924             if(MPFSStubs[hMPFS].addr < temp + dwOffset)
00925                 return FALSE;
00926
00927             MPFSStubs[hMPFS].addr -= dwOffset;
00928             MPFSStubs[hMPFS].bytesRem += dwOffset;
00929             return TRUE;
00930
00931         // Seek so that offset bytes remain in file
00932         case MPFS_SEEK_END:
00933             temp = MPFSGetSize(hMPFS);
00934             if(dwOffset > temp)
00935                 return FALSE;
00936
00937             MPFSStubs[hMPFS].addr = MPFSGetEndAddr(hMPFS) - dwOffset;
00938             MPFSStubs[hMPFS].bytesRem = dwOffset;
00939             return TRUE;
00940
00941         default:
00942             return FALSE;
00943     }
00944 }
00945
00946
00947 /****************************************************************************
00948   Section:
00949     Data Writing Functions
00950   ***************************************************************************/
00951
00952 /*****************************************************************************
00953   Function:
00954     MPFS_HANDLE MPFSFormat(void)
00955
00956   Summary:
00957     Prepares the MPFS image for writing.
00958
00959   Description:
00960     Prepares the MPFS image for writing and locks the image so that other
00961     processes may not access it.
00962
00963   Precondition:
00964     None
00965
00966   Parameters:
00967     None
00968
00969   Returns:
00970     An MPFS handle that can be used for MPFSPut commands, or
00971     MPFS_INVALID_HANDLE when the EEPROM failed to initialize for writing.
00972
00973   Remarks:
00974     In order to prevent misreads, the MPFS will be inaccessible until
00975     MPFSClose is called.  This function is not available when the MPFS
00976     is stored in internal Flash program memory.
00977   ***************************************************************************/
00978 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH)
00979 MPFS_HANDLE MPFSFormat(void)
00980 {
00981
00982     BYTE i;
00983
00984     // Close all files
00985     for(i = 0; i < MAX_MPFS_HANDLES; i++)
00986         MPFSStubs[i].addr = MPFS_INVALID;
00987
00988     // Lock the image
00989     isMPFSLocked = TRUE;
00990
00991     #if defined(MPFS_USE_EEPROM)
00992         // Set FAT ptr for writing
00993         MPFSStubs[0].addr = 0;
00994         MPFSStubs[0].fatID = 0xffff;
00995         MPFSStubs[0].bytesRem = MPFS_WRITE_PAGE_SIZE - ( ((BYTE)MPFSStubs[0].addr+MPFS_HEAD) & (MPFS_WRITE_PAGE_SIZE-1) );
00996
00997         // Set up EEPROM for writing
00998         if( XEEBeginWrite(MPFSStubs[0].addr+MPFS_HEAD) == XEE_SUCCESS )
00999             return 0x00;
01000
01001         return MPFS_INVALID_HANDLE;
01002     #else
01003         // Set up SPI Flash for writing
01004         SPIFlashBeginWrite(MPFS_HEAD);
01005         return 0x00;
01006     #endif
01007 }
01008 #endif
01009
01010 /*****************************************************************************
01011   Function:
01012     WORD MPFSPutArray(MPFS_HANDLE hMPFS, BYTE *cData, WORD wLen)
01013
01014   Description:
01015     Writes an array of data to the MPFS image.
01016
01017   Precondition:
01018     MPFSFormat was sucessfully called.
01019
01020   Parameters:
01021     hMPFS - the file handle for writing
01022     cData - the array of bytes to write
01023     wLen - how many bytes to write
01024
01025   Returns:
01026     The number of bytes successfully written.
01027
01028   Remarks:
01029     For EEPROM, the actual write may not initialize until the internal write
01030     page is full.  To ensure that previously written data gets stored,
01031     MPFSPutEnd must be called after the last call to MPFSPutArray.
01032   ***************************************************************************/
01033 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH)
01034 WORD MPFSPutArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen)
01035 {
01036     #if defined(MPFS_USE_EEPROM)
01037         // Write to the EEPROM
01038         WORD count;
01039
01040         for(count = 0; count < wLen; count++)
01041         {
01042             XEEWrite(cData[count]);
01043
01044             MPFSStubs[hMPFS].addr++;
01045             MPFSStubs[hMPFS].bytesRem--;
01046
01047             if(MPFSStubs[hMPFS].bytesRem == 0)
01048             {
01049                 MPFSPutEnd(FALSE);
01050                 isMPFSLocked = TRUE;
01051                 XEEBeginWrite(MPFSStubs[hMPFS].addr+MPFS_HEAD);
01052                 MPFSStubs[hMPFS].bytesRem = MPFS_WRITE_PAGE_SIZE;
01053             }
01054         }
01055
01056         return count;
01057
01058     #else
01059         // Write to the SPI Flash
01060         SPIFlashWriteArray(cData, wLen);
01061     #endif
01062 }
01063 #endif
01064
01065 /*****************************************************************************
01066   Function:
01067     void MPFSPutEnd(void)
01068
01069   Description:
01070     Finalizes an MPFS writing operation.
01071
01072   Precondition:
01073     MPFSFormat and MPFSPutArray were sucessfully called.
01074
01075   Parameters:
01076     final - TRUE if the application is done writing, FALSE if MPFS2 called
01077         this function locally.
01078
01079   Returns:
01080     None
01081   ***************************************************************************/
01082 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH)
01083 void MPFSPutEnd(BOOL final)
01084 {
01085     isMPFSLocked = FALSE;
01086
01087     #if defined(MPFS_USE_EEPROM)
01088         XEEEndWrite();
01089         while(XEEIsBusy());
01090     #endif
01091
01092     if(final)
01093         _Validate();
01094 }
01095 #endif
01096
01097
01098 /****************************************************************************
01099   Section:
01100     Meta Data Accessors
01101   ***************************************************************************/
01102
01103 /*****************************************************************************
01104   Function:
01105     static void _LoadFATRecord(WORD fatID)
01106
01107   Description:
01108     Loads the FAT record for a specified handle.
01109
01110   Precondition:
01111     None
01112
01113   Parameters:
01114     fatID - the ID of the file whose FAT is to be loaded
01115
01116   Returns:
01117     None
01118
01119   Remarks:
01120     The FAT record will be stored in fatCache.
01121   ***************************************************************************/
01122 static void _LoadFATRecord(WORD fatID)
01123 {
01124     if(fatID == fatCacheID || fatID >= numFiles)
01125         return;
01126
01127     // Read the FAT record to the cache
01128     MPFSStubs[0].bytesRem = 22;
01129     MPFSStubs[0].addr = 8 + numFiles*2 + fatID*22;
01130     MPFSStubs[0].offset = 0;    // MODIFIX: Added this line for initialize.
01131     MPFSGetArray(0, (BYTE*)&fatCache, 22);
01132     fatCacheID = fatID;
01133 }
01134
01135 /*****************************************************************************
01136   Function:
01137     DWORD MPFSGetTimestamp(MPFS_HANDLE hMPFS)
01138
01139   Description:
01140     Reads the timestamp for the specified file.
01141
01142   Precondition:
01143     The file handle referenced by hMPFS is already open.
01144
01145   Parameters:
01146     hMPFS - the file handle from which to read the metadata
01147
01148   Returns:
01149     The timestamp that was read as a DWORD
01150   ***************************************************************************/
01151 DWORD MPFSGetTimestamp(MPFS_HANDLE hMPFS)
01152 {
01153     // Make sure a valid file is open
01154     if(hMPFS > MAX_MPFS_HANDLES)
01155         return 0x00000000;
01156     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01157         return 0x00000000;
01158
01159     // Move to the point for reading
01160     _LoadFATRecord(MPFSStubs[hMPFS].fatID);
01161     return fatCache.timestamp;
01162 }
01163
01164 /*****************************************************************************
01165   Function:
01166     DWORD MPFSGetMicrotime(MPFS_HANDLE hMPFS)
01167
01168   Description:
01169     Reads the microtime portion of a file's timestamp.
01170
01171   Precondition:
01172     The file handle referenced by hMPFS is already open.
01173
01174   Parameters:
01175     hMPFS - the file handle from which to read the metadata
01176
01177   Returns:
01178     The microtime that was read as a DWORD
01179   ***************************************************************************/
01180 DWORD MPFSGetMicrotime(MPFS_HANDLE hMPFS)
01181 {
01182     // Make sure a valid file is open
01183     if(hMPFS > MAX_MPFS_HANDLES)
01184         return 0x00000000;
01185     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01186         return 0x00000000;
01187
01188     // Move to the point for reading
01189     _LoadFATRecord(MPFSStubs[hMPFS].fatID);
01190     return fatCache.microtime;
01191 }
01192
01193 /*****************************************************************************
01194   Function:
01195     WORD MPFSGetFlags(MPFS_HANDLE hMPFS)
01196
01197   Description:
01198     Reads a file's flags.
01199
01200   Precondition:
01201     The file handle referenced by hMPFS is already open.
01202
01203   Parameters:
01204     hMPFS - the file handle from which to read the metadata
01205
01206   Returns:
01207     The flags that were associated with the file
01208   ***************************************************************************/
01209 WORD MPFSGetFlags(MPFS_HANDLE hMPFS)
01210 {
01211     // Make sure a valid file is open
01212     if(hMPFS > MAX_MPFS_HANDLES)
01213         return 0x0000;
01214     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01215         return 0x0000;
01216
01217     //move to the point for reading
01218     _LoadFATRecord(MPFSStubs[hMPFS].fatID);
01219     return fatCache.flags;
01220 }
01221
01222 /*****************************************************************************
01223   Function:
01224     DWORD MPFSGetSize(MPFS_HANDLE hMPFS)
01225
01226   Description:
01227     Reads the size of a file.
01228
01229   Precondition:
01230     The file handle referenced by hMPFS is already open.
01231
01232   Parameters:
01233     hMPFS - the file handle from which to read the metadata
01234
01235   Returns:
01236     The size that was read as a DWORD
01237   ***************************************************************************/
01238 DWORD MPFSGetSize(MPFS_HANDLE hMPFS)
01239 {
01240     // Make sure a valid file is open
01241     if(hMPFS > MAX_MPFS_HANDLES)
01242         return 0x00000000;
01243     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01244         return 0x00000000;
01245
01246     // Move to the point for reading
01247     _LoadFATRecord(MPFSStubs[hMPFS].fatID);
01248     return fatCache.len;
01249 }
01250
01251 /*****************************************************************************
01252   Function:
01253     DWORD MPFSGetBytesRem(MPFS_HANDLE hMPFS)
01254
01255   Description:
01256     Determines how many bytes remain to be read.
01257
01258   Precondition:
01259     The file handle referenced by hMPFS is already open.
01260
01261   Parameters:
01262     hMPFS - the file handle from which to read the metadata
01263
01264   Returns:
01265     The number of bytes remaining in the file as a DWORD
01266   ***************************************************************************/
01267 #if 0
01268 DWORD MPFSGetBytesRem(MPFS_HANDLE hMPFS)
01269 {
01270     // Make sure a valid file is open
01271     if(hMPFS > MAX_MPFS_HANDLES)
01272         return 0x00000000;
01273     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01274         return 0x00000000;
01275
01276     return MPFSStubs[hMPFS].bytesRem;
01277 }
01278 #endif
01279
01280 /*****************************************************************************
01281   Function:
01282     MPFS_PTR MPFSGetStartAddr(MPFS_HANDLE hMPFS)
01283
01284   Description:
01285     Reads the starting address of a file.
01286
01287   Precondition:
01288     The file handle referenced by hMPFS is already open.
01289
01290   Parameters:
01291     hMPFS - the file handle from which to read the metadata
01292
01293   Returns:
01294     The starting address of the file in the MPFS image
01295   ***************************************************************************/
01296 MPFS_PTR MPFSGetStartAddr(MPFS_HANDLE hMPFS)
01297 {
01298     // Make sure a valid file is open
01299     if(hMPFS > MAX_MPFS_HANDLES)
01300         return 0;
01301     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01302         return MPFS_INVALID;
01303
01304     // Move to the point for reading
01305     _LoadFATRecord(MPFSStubs[hMPFS].fatID);
01306     return fatCache.data;
01307 }
01308
01309 /*****************************************************************************
01310   Function:
01311     MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS)
01312
01313   Description:
01314     Determines the ending address of a file.
01315
01316   Precondition:
01317     The file handle referenced by hMPFS is already open.
01318
01319   Parameters:
01320     hMPFS - the file handle from which to read the metadata
01321
01322   Returns:
01323     The address just after the file ends (start address of next file)
01324   ***************************************************************************/
01325 MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS)
01326 {
01327     // Make sure a valid file is open
01328     if(hMPFS > MAX_MPFS_HANDLES)
01329         return MPFS_INVALID;
01330     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01331         return MPFS_INVALID;
01332
01333     // Move to the point for reading
01334     _LoadFATRecord(MPFSStubs[hMPFS].fatID);
01335     return fatCache.data + fatCache.len;
01336 }
01337
01338 /*****************************************************************************
01339   Function:
01340     BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen)
01341
01342   Description:
01343     Reads the file name of a file that is already open.
01344
01345   Precondition:
01346     The file handle referenced by hMPFS is already open.
01347
01348   Parameters:
01349     hMPFS - the file handle from which to determine the file name
01350     cName - where to store the name of the file
01351     wLen - the maximum length of data to store in cName
01352
01353   Return Values:
01354     TRUE - the file name was successfully located
01355     FALSE - the file handle provided is not currently open
01356   ***************************************************************************/
01357 BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen)
01358 {
01359     DWORD addr;
01360
01361     // Make sure a valid file is open
01362     if(hMPFS > MAX_MPFS_HANDLES)
01363         return FALSE;
01364     if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
01365         return FALSE;
01366
01367     // Move to the point for reading
01368     _LoadFATRecord(MPFSStubs[hMPFS].fatID);
01369     addr = fatCache.string;
01370     MPFSStubs[0].addr = addr;
01371     MPFSStubs[0].bytesRem = 255;
01372
01373     // Read the value and return
01374     MPFSGetArray(0, cName, wLen);
01375     return TRUE;
01376 }
01377
01378 /*****************************************************************************
01379   Function:
01380     DWORD MPFSGetPosition(MPFS_HANDLE hMPFS)
01381
01382   Description:
01383     Determines the current position in the file
01384
01385   Precondition:
01386     The file handle referenced by hMPFS is already open.
01387
01388   Parameters:
01389     hMPFS - the file handle for which to determine position
01390
01391   Returns:
01392     The position in the file as a DWORD (or MPFS_PTR)
01393
01394   Remarks:
01395     Calling MPFSSeek(hMPFS, pos, MPFS_SEEK_START) will return the pointer
01396     to this position at a later time.  (Where pos is the value returned by
01397     this function.)
01398   ***************************************************************************/
01399 DWORD MPFSGetPosition(MPFS_HANDLE hMPFS)
01400 {
01401     return MPFSStubs[hMPFS].addr - MPFSGetStartAddr(hMPFS);
01402 }
01403
01404 /*****************************************************************************
01405   Function:
01406     WORD MPFSGetID(MPFS_HANDLE hMPFS)
01407
01408   Description:
01409     Determines the ID in the FAT for a file.
01410
01411   Precondition:
01412     The file handle referenced by hMPFS is already open.
01413
01414   Parameters:
01415     hMPFS - the file handle from which to read the metadata
01416
01417   Returns:
01418     The ID in the FAT for this file
01419
01420   Remarks:
01421     Use this function in association with MPFSOpenID to quickly access file
01422     without permanently reserving a file handle.
01423   ***************************************************************************/
01424 WORD MPFSGetID(MPFS_HANDLE hMPFS)
01425 {
01426     return MPFSStubs[hMPFS].fatID;
01427 }
01428
01429
01430 /****************************************************************************
01431   Section:
01432     Utility Functions
01433   ***************************************************************************/
01434
01435 /*****************************************************************************
01436   Function:
01437     void _Validate(void)
01438
01439   Summary:
01440     Validates the MPFS Image
01441
01442   Description:
01443     Verifies that the MPFS image is valid, and reads the number of
01444     available files from the image header.  This function is called on
01445     boot, and again after any image is written.
01446
01447   Precondition:
01448     None
01449
01450   Parameters:
01451     None
01452
01453   Returns:
01454     None
01455   ***************************************************************************/
01456 static void _Validate(void)
01457 {
01458     // Validate the image and update numFiles
01459     MPFSStubs[0].addr = 0;
01460     MPFSStubs[0].bytesRem = 8;
01461     MPFSStubs[0].offset = 0;    // MODIFIX: Added this line for huffman decoding.
01462     MPFSGetArray(0, (BYTE*)&fatCache, 6);
01463     if(!memcmppgm2ram((void*)&fatCache, (ROM void*)"MPFS\x02\x01", 6))
01464         MPFSGetArray(0, (BYTE*)&numFiles, 2);
01465     else
01466         numFiles = 0;
01467     fatCacheID = MPFS_INVALID_FAT;
01468 }
01469 #endif //#if defined(STACK_USE_MPFS2)
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: MPFS2.h Source File

MPFS2.h

Go to the documentation of this file.
00001
00002
00003
00030 /*********************************************************************
00031  * Software License Agreement
00032  *
00033  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00034  * reserved.
00035  *
00036  * Microchip licenses to you the right to use, modify, copy, and
00037  * distribute:
00038  * (i)  the Software when embedded on a Microchip microcontroller or
00039  *      digital signal controller product ("Device") which is
00040  *      integrated into Licensee's product; or
00041  * (ii) ONLY the Software driver source files ENC28J60.c and
00042  *      ENC28J60.h ported to a non-Microchip device used in
00043  *      conjunction with a Microchip ethernet controller for the
00044  *      sole purpose of interfacing with the ethernet controller.
00045  *
00046  * You should refer to the license agreement accompanying this
00047  * Software for additional information regarding your rights and
00048  * obligations.
00049  *
00050  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00051  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00052  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00053  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00054  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00055  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00056  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00057  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00058  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00059  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00060  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00061  *
00062  *
00063  * Author               Date        Comment
00064  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00065  * Elliott Wood         07/2007     Complete rewrite as MPFS2
00066  * E. Wood              04/2008     Updated as MPFS2.1
00067  ********************************************************************/
00068
00069 #ifndef __MPFS2_H
00070 #define __MPFS2_H
00071
00072
00073 /****************************************************************************
00074   Section:
00075     Storage Type Configurations
00076   ***************************************************************************/
00077     #if defined(STACK_USE_MPFS) && defined(STACK_USE_MPFS2)
00078         #error Both MPFS and MPFS2 are included
00079     #endif
00080
00081     #if defined(MPFS_USE_EEPROM)
00082         #if defined(USE_EEPROM_25LC1024)
00083             #define MPFS_WRITE_PAGE_SIZE        (256u)  // Defines the size of a page in EEPROM
00084         #else
00085             #define MPFS_WRITE_PAGE_SIZE        (64u)   // Defines the size of a page in EEPROM
00086         #endif
00087     #endif
00088
00089 /****************************************************************************
00090   Section:
00091     Type Definitions
00092   ***************************************************************************/
00093     #define MPFS2_FLAG_ISZIPPED     ((WORD)0x0001)  // Indicates a file is compressed with GZIP compression
00094     #define MPFS2_FLAG_HASINDEX     ((WORD)0x0002)  // Indicates a file has an associated index of dynamic variables
00095     // MODIFIX: Added the following macro:
00096     #define MPFS2_FLAG_ISCOMPRESSED ((WORD)0x0004)  // Indicates a file is compressed with huffman compression
00097     #define MPFS_INVALID            (0xffffffffu)   // Indicates a position pointer is invalid
00098     #define MPFS_INVALID_FAT        (0xffffu)       // Indicates an invalid FAT cache
00099     #define MPFS_INVALID_HANDLE     (0xffu)         // Indicates that a handle is not valid
00100     typedef DWORD MPFS_PTR;                         // MPFS Pointers are currently DWORDs
00101     typedef BYTE MPFS_HANDLE;                       // MPFS Handles are currently stored as BYTEs
00102
00103
00104     // Stores each file handle's information
00105     // Handles are free when addr = MPFS_INVALID
00106     typedef struct
00107     {
00108         MPFS_PTR addr;      // Current address in the file system
00109         DWORD bytesRem;     // How many bytes remain in this file
00110         WORD fatID;         // ID of which file in the FAT was accessed
00111         BYTE offset;        // MODIFIX: Added this field for bit position in huffman encoded files.
00112     } MPFS_STUB;
00113
00114     // Indicates the method for MPFSSeek
00115     typedef enum
00116     {
00117         MPFS_SEEK_START     = 0u,   // Seek forwards from the front of the file
00118         MPFS_SEEK_END,              // Seek backwards from the end of the file
00119         MPFS_SEEK_FORWARD,          // Seek forward from the current position
00120         MPFS_SEEK_REWIND            // See backwards from the current position
00121     } MPFS_SEEK_MODE;
00122
00123     // Stores the data for an MPFS2 FAT record
00124     typedef struct
00125     {
00126         DWORD string;       // Pointer to the file name
00127         DWORD data;         // Address of the file data
00128         DWORD len;          // Length of file data
00129         DWORD timestamp;    // Timestamp of file
00130         DWORD microtime;    // Microtime stamp of file
00131         WORD flags;         // Flags for this file
00132     } MPFS_FAT_RECORD;
00133
00134 /****************************************************************************
00135   Section:
00136     Function Definitions
00137   ***************************************************************************/
00138
00139 void MPFSInit(void);
00140
00141 MPFS_HANDLE MPFSOpen(BYTE* cFile);
00142 #if defined(__18CXX)
00143     MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile);
00144 #else
00145     // Non-ROM variant for C30 / C32
00146     #define MPFSOpenROM(a)  MPFSOpen((BYTE*) a);
00147 #endif
00148 MPFS_HANDLE MPFSOpenID(WORD hFatID);
00149 void MPFSClose(MPFS_HANDLE hMPFS);
00150
00151 BOOL MPFSGet(MPFS_HANDLE hMPFS, BYTE* c);
00152 WORD MPFSGetArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen);
00153 BOOL MPFSGetLong(MPFS_HANDLE hMPFS, DWORD* ul);
00154 BOOL MPFSSeek(MPFS_HANDLE hMPFS, DWORD dwOffset, MPFS_SEEK_MODE tMode);
00155 #if defined(__C30__)
00156     // Assembly function to read all three bytes of program memory for 16-bit parts
00157     extern DWORD ReadProgramMemory(DWORD address);
00158 #endif
00159
00160 MPFS_HANDLE MPFSFormat(void);
00161 void MPFSPutEnd(BOOL final);
00162 WORD MPFSPutArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen);
00163
00164 DWORD MPFSGetTimestamp(MPFS_HANDLE hMPFS);
00165 DWORD MPFSGetMicrotime(MPFS_HANDLE hMPFS);
00166 WORD MPFSGetFlags(MPFS_HANDLE hMPFS);
00167 DWORD MPFSGetSize(MPFS_HANDLE hMPFS);
00168 DWORD MPFSGetBytesRem(MPFS_HANDLE hMPFS);
00169 MPFS_PTR MPFSGetStartAddr(MPFS_HANDLE hMPFS);
00170 MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS);
00171 BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen);
00172 DWORD MPFSGetPosition(MPFS_HANDLE hMPFS);
00173 WORD MPFSGetID(MPFS_HANDLE hMPFS);
00174
00175 // Alias of MPFSGetPosition
00176 #define MPFSTell(a) MPFSGetPosition(a)
00177
00178 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: Reboot.c Source File

Reboot.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00026 /*********************************************************************
00027  * Software License Agreement
00028  *
00029  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00030  * reserved.
00031  *
00032  * Microchip licenses to you the right to use, modify, copy, and
00033  * distribute:
00034  * (i)  the Software when embedded on a Microchip microcontroller or
00035  *      digital signal controller product ("Device") which is
00036  *      integrated into Licensee's product; or
00037  * (ii) ONLY the Software driver source files ENC28J60.c and
00038  *      ENC28J60.h ported to a non-Microchip device used in
00039  *      conjunction with a Microchip ethernet controller for the
00040  *      sole purpose of interfacing with the ethernet controller.
00041  *
00042  * You should refer to the license agreement accompanying this
00043  * Software for additional information regarding your rights and
00044  * obligations.
00045  *
00046  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00047  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00048  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00049  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00050  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00051  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00052  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00053  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00054  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00055  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00056  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00057  *
00058  *
00059  * Author               Date        Comment
00060  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00061  * Howard Schlunder     02/22/07    Original
00062  ********************************************************************/
00063 #define __REBOOT_C
00064
00065 #include "TCPIP.h"
00066
00067 #define REBOOT_PORT     69  // UDP TFTP port
00068
00069
00070 // For improved security, you might want to limit reboot capabilities
00071 // to only users on the same IP subnet.  Define REBOOT_SAME_SUBNET_ONLY
00072 // to enable this access restriction.
00073 #define REBOOT_SAME_SUBNET_ONLY
00074
00075
00076 /*********************************************************************
00077  * Function:        void RebootTask(void)
00078  *
00079  * PreCondition:    Stack is initialized()
00080  *
00081  * Input:           None
00082  *
00083  * Output:          None
00084  *
00085  * Side Effects:    None
00086  *
00087  * Overview:        Checks for incomming traffic on port 69.
00088  *
00089  * Note:            This module is primarily for use with the
00090  *                  Ethernet bootloader.  By resetting, the Ethernet
00091  *                  bootloader can take control for a second and let
00092  *                  a firmware upgrade take place.
00093  ********************************************************************/
00094 void RebootTask(void)
00095 {
00096     static UDP_SOCKET   MySocket = INVALID_UDP_SOCKET;
00097
00098     if(MySocket == INVALID_UDP_SOCKET)
00099         MySocket = UDPOpen(REBOOT_PORT, NULL, INVALID_UDP_PORT);
00100
00101     if(MySocket == INVALID_UDP_SOCKET)
00102         return;
00103
00104     // Do nothing if no data is waiting
00105     if(!UDPIsGetReady(MySocket))
00106     {
00107         return;
00108     }
00109
00110     u16GlobalFlags |= BOOTLOADER_MASK;
00111     ApplRestart(FALSE);
00112 }
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: Reboot.h Source File

Reboot.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00030 /*********************************************************************
00031  * Software License Agreement
00032  *
00033  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00034  * reserved.
00035  *
00036  * Microchip licenses to you the right to use, modify, copy, and
00037  * distribute:
00038  * (i)  the Software when embedded on a Microchip microcontroller or
00039  *      digital signal controller product ("Device") which is
00040  *      integrated into Licensee's product; or
00041  * (ii) ONLY the Software driver source files ENC28J60.c and
00042  *      ENC28J60.h ported to a non-Microchip device used in
00043  *      conjunction with a Microchip ethernet controller for the
00044  *      sole purpose of interfacing with the ethernet controller.
00045  *
00046  * You should refer to the license agreement accompanying this
00047  * Software for additional information regarding your rights and
00048  * obligations.
00049  *
00050  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00051  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00052  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00053  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00054  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00055  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00056  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00057  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00058  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00059  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00060  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00061  *
00062  *
00063  * Author               Date        Comment
00064  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00065  * Howard Schlunder     02/26/07    Original
00066  ********************************************************************/
00067 #ifndef __REBOOT_H
00068 #define __REBOOT_H
00069
00070 void RebootTask(void);
00071
00072 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: SPIEEPROM.c Source File

SPIEEPROM.c

Go to the documentation of this file.
00001
00002
00003
00015 /*********************************************************************
00016  * Software License Agreement
00017  *
00018  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00019  * reserved.
00020  *
00021  * Microchip licenses to you the right to use, modify, copy, and
00022  * distribute:
00023  * (i)  the Software when embedded on a Microchip microcontroller or
00024  *      digital signal controller product ("Device") which is
00025  *      integrated into Licensee's product; or
00026  * (ii) ONLY the Software driver source files ENC28J60.c and
00027  *      ENC28J60.h ported to a non-Microchip device used in
00028  *      conjunction with a Microchip ethernet controller for the
00029  *      sole purpose of interfacing with the ethernet controller.
00030  *
00031  * You should refer to the license agreement accompanying this
00032  * Software for additional information regarding your rights and
00033  * obligations.
00034  *
00035  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00036  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00037  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00038  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00039  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00040  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00041  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00042  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00043  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00044  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00045  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00046  *
00047  *
00048  * Author               Date        Comment
00049  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00050  * Nilesh Rajbharti     5/20/02     Original (Rev. 1.0)
00051  * Howard Schlunder     9/01/04     Rewritten for SPI EEPROMs
00052  * Howard Schlunder     8/10/06     Modified to control SPI module
00053  *                                  frequency whenever EEPROM accessed
00054  *                                  to allow bus sharing with different
00055  *                                  frequencies.
00056 ********************************************************************/
00057 #define __SPIEEPROM_C
00058
00059 #include "TCPIP.h"
00060
00062 // Local Defines
00064
00065 // SPI Serial EEPROM buffer size.  To enhance performance while
00066 // cooperatively sharing the SPI bus with other peripherals, bytes
00067 // read and written to the memory are locally buffered. Legal
00068 // sizes are 1 to the EEPROM page size.
00069 #define EEPROM_BUFFER_SIZE              (32)
00070
00071 // EEPROM SPI opcodes
00072 #define READ    0x03    // Read data from memory array beginning at selected address
00073 #define WRITE   0x02    // Write data to memory array beginning at selected address
00074 #define WRDI    0x04    // Reset the write enable latch (disable write operations)
00075 #define WREN    0x06    // Set the write enable latch (enable write operations)
00076 #define RDSR    0x05    // Read Status register
00077 #define WRSR    0x01    // Write Status register
00078
00079 #define EEPROM_CS_IO    (LATFbits.LATF5)
00080
00081
00083 // Local function prototypes
00085
00086 static void DoWrite(void);
00087 // MODIFIX: Moved the following prototypes from the header file to this
00088 // location and made them static.
00089 static XEE_RESULT XEEBeginWrite(XEE_ADDR address);
00090 static XEE_RESULT XEEWrite(unsigned char val);
00091 static XEE_RESULT XEEEndWrite(void);
00092 static BOOL XEEIsBusy(void);
00093
00094
00096 // Local Variables
00098
00099 static XEE_ADDR EEPROMAddress;
00100 static BYTE EEPROMBuffer[EEPROM_BUFFER_SIZE];
00101 static BYTE EEPROMBytesToWrite;
00102 static BYTE EEPROMPageSpace;
00103
00104
00105 // MODIFIX: Removed the functions XEEInit, XEEBeginRead, XEERead and
00106 // XEEEndRead.
00107
00108 /*********************************************************************
00109  * Function:        XEE_RESULT XEEReadArray(XEE_ADDR address,
00110  *                                          BYTE *buffer,
00111  *                                          BYTE length)
00112  *
00113  * PreCondition:    None.
00114  *
00115  * Input:           address     - Address from where array is to be read
00116  *                  buffer      - Caller supplied buffer to hold the data
00117  *                  length      - Number of bytes to read.
00118  *
00119  * Output:          XEE_SUCCESS
00120  *
00121  * Side Effects:    None
00122  *
00123  * Overview:        Reads desired number of bytes in sequential mode.
00124  *                  This function performs all necessary steps
00125  *                  and releases the bus when finished.
00126  *
00127  * Note:            None
00128  ********************************************************************/
00129
00130 void _startReading(XEE_ADDR Address)
00131 {
00132     BYTE tmp;
00133
00134     // SPI-Configuration for EEPROM:
00135     // SPI Master / Clock = Fosc/16 / Enable / Clock idle state is low
00136     SSP1CON1 = 0x21;
00137     SSP1STAT = 0x40;    // CKE = 1
00138
00139     // Send READ opcode
00140     PIR1bits.SSP1IF = 0;
00141     EEPROM_CS_IO = 0;
00142     SSPBUF = READ;
00143     while(PIR1bits.SSP1IF == 0);
00144     tmp = SSPBUF;
00145
00146     // Send address (WORD)
00147     PIR1bits.SSP1IF = 0;
00148     SSPBUF = ((WORD_VAL*)&Address)->v[1];
00149     while( PIR1bits.SSP1IF == 0 );
00150     tmp = SSPBUF;
00151     PIR1bits.SSP1IF = 0;
00152     SSPBUF = ((WORD_VAL*)&Address)->v[0];
00153     while( PIR1bits.SSP1IF == 0 );
00154     tmp = SSPBUF;
00155 }
00156
00159
00160
00161 XEE_RESULT XEEReadArray(XEE_ADDR address, BYTE *buffer, BYTE length)
00162 {
00163     BYTE Dummy;
00164     BYTE len = length;
00165     BYTE * pBuf = buffer;
00166
00167     _startReading(address);
00168
00169     while(len--)
00170     {
00171         PIR1bits.SSP1IF = 0;
00172         SSPBUF = 0;
00173         while(PIR1bits.SSP1IF == 0);
00174         *pBuf++ = SSPBUF;
00175     }
00176
00177     EEPROM_CS_IO = 1;
00178
00179     return XEE_SUCCESS;
00180 }
00181
00182
00183 /*********************************************************************
00184  * Function:        XEE_RESULT XEEBeginWrite(XEE_ADDR address)
00185  *
00186  * PreCondition:    None (MODIFIX)
00187  *
00188  * Input:           address     - address to be set for writing
00189  *
00190  * Output:          XEE_SUCCESS
00191  *
00192  * Side Effects:    None
00193  *
00194  * Overview:        Starts the writing of content to EEPROM to the
00195  *                  given address.
00196  *
00197  ********************************************************************/
00198 XEE_RESULT XEEBeginWrite(XEE_ADDR address)
00199 {
00200     EEPROMAddress = address;
00201     EEPROMBytesToWrite = 0;
00202     EEPROMPageSpace = EEPROM_BUFFER_SIZE-(address % EEPROM_BUFFER_SIZE);
00203     return XEE_SUCCESS;
00204 }
00205
00206
00207 /*********************************************************************
00208  * Function:        XEE_RESULT XEEWrite(BYTE val)
00209  *
00210  * PreCondition:    XEEBeginWrite() are already called.
00211  *
00212  * Input:           val - Byte to be written
00213  *
00214  * Output:          XEE_SUCCESS
00215  *
00216  * Side Effects:    None
00217  *
00218  * Overview:        Adds a byte to the current page to be writen when
00219  *                  XEEEndWrite() is called.
00220  *
00221  * Note:            Page boundary cannot be exceeded or the byte
00222  *                  to be written will be looped back to the
00223  *                  beginning of the page.
00224  ********************************************************************/
00225 XEE_RESULT XEEWrite(BYTE val)
00226 {
00227     EEPROMBuffer[EEPROMBytesToWrite++] = val;
00228     EEPROMPageSpace--;
00229
00230     if(EEPROMPageSpace==0)
00231         DoWrite();
00232
00233     return XEE_SUCCESS;
00234 }
00235
00236
00237 /*********************************************************************
00238  * Function:        XEE_RESULT XEEEndWrite(void)
00239  *
00240  * PreCondition:    XEEBeginWrite() is already called.
00241  *
00242  * Input:           None
00243  *
00244  * Output:          XEE_SUCCESS if successful
00245  *                  other value if failed.
00246  *
00247  * Side Effects:    None
00248  *
00249  * Overview:        Instructs EEPROM to begin write cycle.
00250  *
00251  * Note:            Call this function after either page full of bytes
00252  *                  written or no more bytes are left to load.
00253  *                  This function initiates the write cycle.
00254  *                  User must call for XEEIsBusy() to ensure that write
00255  *                  cycle is finished before calling any other
00256  *                  routine.
00257  ********************************************************************/
00258 XEE_RESULT XEEEndWrite(void)
00259 {
00260     if(EEPROMBytesToWrite)
00261         DoWrite();
00262
00263     return XEE_SUCCESS;
00264 }
00265
00266 static void DoWrite(void)
00267 {
00268     BYTE Dummy;
00269     BYTE i;
00270
00271     // SPI-Configuration for EEPROM:
00272     // SPI Master / Clock = Fosc/16 / Enable / Clock idle state is low (CKP=0)
00273     SSP1CON1 = 0x21;
00274     SSP1STAT = 0x40;    // CKE = 1
00275
00276     // Set the Write Enable latch
00277     PIR1bits.SSP1IF = 0;
00278     EEPROM_CS_IO = 0;
00279     SSPBUF = WREN;
00280     while( PIR1bits.SSP1IF == 0 );
00281     Dummy = SSPBUF;
00282     EEPROM_CS_IO = 1;
00283
00284     // Send WRITE opcode
00285     EEPROM_CS_IO = 0;
00286     PIR1bits.SSP1IF = 0;
00287     SSPBUF = WRITE;
00288     while(PIR1bits.SSP1IF == 0);
00289     Dummy = SSPBUF;
00290
00291     // Send address (WORD)
00292     PIR1bits.SSP1IF = 0;
00293     SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[1];
00294     while(PIR1bits.SSP1IF == 0);
00295     Dummy = SSPBUF;
00296     PIR1bits.SSP1IF = 0;
00297     SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[0];
00298     while(PIR1bits.SSP1IF == 0);
00299     Dummy = SSPBUF;
00300
00301     EEPROMAddress += EEPROMBytesToWrite;
00302
00303     for (i=0; i<EEPROMBytesToWrite;i++)
00304     {
00305         // Send the byte to write
00306         PIR1bits.SSP1IF = 0;
00307         SSPBUF = EEPROMBuffer[i];
00308         while(PIR1bits.SSP1IF == 0);
00309         Dummy = SSPBUF;
00310     }
00311
00312     // Begin the write
00313     EEPROM_CS_IO = 1;
00314
00315     EEPROMBytesToWrite = 0;
00316     EEPROMPageSpace = EEPROM_BUFFER_SIZE;
00317
00318
00319     // Wait for write to complete
00320     while( XEEIsBusy() );
00321 }
00322
00323
00324 /*********************************************************************
00325  * Function:        BOOL XEEIsBusy(void)
00326  *
00327  * PreCondition:    None.
00328  *
00329  * Input:           None
00330  *
00331  * Output:          FALSE if EEPROM is not busy
00332  *                  TRUE if EEPROM is busy
00333  *
00334  * Side Effects:    None
00335  *
00336  * Overview:        Reads the status register
00337  *
00338  * Note:            None
00339  ********************************************************************/
00340 static BOOL XEEIsBusy(void)
00341 {
00342     BYTE_VAL result;
00343
00344     // SPI-Configuration for EEPROM:
00345     // SPI Master / Clock = Fosc/16 / Enable / Clock idle state is low
00346     SSP1CON1 = 0x21;
00347     SSP1STAT = 0x40;    // CKE = 1
00348
00349     PIR1bits.SSP1IF = 0;
00350     EEPROM_CS_IO = 0;
00351     // Send RDSR - Read Status Register opcode
00352     SSPBUF = RDSR;
00353     while(PIR1bits.SSP1IF == 0);
00354     result.Val = SSPBUF;
00355
00356     // Get register contents
00357     PIR1bits.SSP1IF = 0;
00358     SSPBUF = 0;
00359     while(PIR1bits.SSP1IF == 0);
00360     result.Val = SSPBUF;
00361     EEPROM_CS_IO = 1;
00362
00363     return result.bits.b0;
00364 }
00365
00368
00369 void XEEEraseEEPROM(void)
00370 {
00371     int i = 0;
00372     XEEBeginWrite(0);
00373
00374     for (; i < EEPROM_SIZE; i++)
00375     {
00376         XEEWrite(0xFF);
00377     }
00378
00379     XEEEndWrite();
00380 }
00381
00384
00385 void XEEWriteArray(WORD address, BYTE * pData, BYTE len)
00386 {
00387     BYTE i;
00388
00389     XEEBeginWrite(address);
00390
00391     for (i = 0; i < len; i++)
00392         XEEWrite(pData[i]);
00393
00394     XEEEndWrite();
00395 }
00396
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: StackTsk.c Source File

StackTsk.c

Go to the documentation of this file.
00001
00002
00003
00025 /*********************************************************************
00026  * Software License Agreement
00027  *
00028  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00029  * reserved.
00030  *
00031  * Microchip licenses to you the right to use, modify, copy, and
00032  * distribute:
00033  * (i)  the Software when embedded on a Microchip microcontroller or
00034  *      digital signal controller product ("Device") which is
00035  *      integrated into Licensee's product; or
00036  * (ii) ONLY the Software driver source files ENC28J60.c and
00037  *      ENC28J60.h ported to a non-Microchip device used in
00038  *      conjunction with a Microchip ethernet controller for the
00039  *      sole purpose of interfacing with the ethernet controller.
00040  *
00041  * You should refer to the license agreement accompanying this
00042  * Software for additional information regarding your rights and
00043  * obligations.
00044  *
00045  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00046  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00047  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00048  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00049  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00050  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00051  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00052  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00053  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00054  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00055  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00056  *
00057  *
00058  * Author               Date        Comment
00059  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00060  * Nilesh Rajbharti     8/14/01     Original (Rev. 1.0)
00061  * Nilesh Rajbharti     2/9/02      Cleanup
00062  * Nilesh Rajbharti     5/22/02     Rev 2.0 (See version.log for detail)
00063  * Nilesh Rajbharti     12/5/02     Modified UDPProcess() and TCPProcess()
00064  *                                  to include localIP as third param.
00065  *                                  This was done to allow these functions
00066  *                                  to calculate checksum correctly.
00067  * Nilesh Rajbharti     7/26/04     Added code in StackTask() to not
00068  *                                  clear statically IP address if link is
00069  *                                  removed and DHCP module is disabled
00070  *                                  at runtime.
00071  * Howard Schlunder     03/16/07    Rewrote stack manager to be linear
00072 ********************************************************************/
00073 #define __STACKTSK_C
00074
00075 #include "TCPIP.h"
00076 #include "Reboot.h" // MODIFIX: added this include.
00077
00078 // MODIFIX: Removed external symbol "myDHCPBindCount"
00079
00080 // Stack FSM states.
00081 typedef enum _SM_STACK
00082 {
00083     SM_STACK_IDLE,
00084     SM_STACK_MAC,
00085     SM_STACK_IP,
00086     SM_STACK_ARP,
00087     SM_STACK_TCP,
00088     SM_STACK_UDP
00089 } SM_STACK;
00090 static SM_STACK smStack;
00091
00092 NODE_INFO remoteNode;
00093
00094
00095
00096 /*********************************************************************
00097  * Function:        void StackInit(void)
00098  *
00099  * PreCondition:    None
00100  *
00101  * Input:           None
00102  *
00103  * Output:          Stack and its componets are initialized
00104  *
00105  * Side Effects:    None
00106  *
00107  * Note:            This function must be called before any of the
00108  *                  stack or its component routines are used.
00109  *
00110  ********************************************************************/
00111 void StackInit(void)
00112 {
00113     smStack = SM_STACK_IDLE;
00114
00115     // MODIFIX: Removed IP gleaning functionality.
00116
00117     // Seed the rand() function
00118     srand(GenerateRandomDWORD());
00119
00120 //    MACInit();
00121
00122     ARPInit();
00123
00124     UDPInit();
00125
00126     TCPInit();
00127
00128     // MODIFIX: Removed Berkeley handling.
00129
00130     // Initialize the HTTP module for the eWicht Webpage.
00131     HTTPInit();
00132
00133     // MODIFIX: Removed DHCP handling because its handled completely from
00134     //          the eWicht application.
00135
00136     // MODIFIX: Removed all other parts not used by the eWicht application.
00137 }
00138
00139
00140 /*********************************************************************
00141  * Function:        void StackTask(void)
00142  *
00143  * PreCondition:    StackInit() is already called.
00144  *
00145  * Input:           None
00146  *
00147  * Output:          Stack FSM is executed.
00148  *
00149  * Side Effects:    None
00150  *
00151  * Note:            This FSM checks for new incoming packets,
00152  *                  and routes it to appropriate stack components.
00153  *                  It also performs timed operations.
00154  *
00155  *                  This function must be called periodically to
00156  *                  ensure timely responses.
00157  *
00158  ********************************************************************/
00159 void StackTask(void)
00160 {
00161     WORD dataCount;
00162     IP_ADDR tempLocalIP;
00163     BYTE cFrameType;
00164     BYTE cIPFrameType;
00165
00166     // MODIFIX: Modified DHCP handling because its handled from the eWicht
00167     //          application.
00168     if(sPCommonConfig.Flags.bIsDHCPEnabled)
00169     {
00170         // DHCP must be called all the time even after IP configuration is
00171         // discovered.
00172         // DHCP has to account lease expiration time and renew the configuration
00173         // time.
00174         DHCPTask();
00175     }
00176
00177
00178     // Perform all TCP time related tasks (retransmit, send acknowledge, close connection, etc)
00179     TCPTick();
00180
00181     UDPTask();
00182
00183     // Process as many incomming packets as we can
00184     while(1)
00185     {
00186         // MODIFIX: Removed the STACK_USE_RANDOM functionality.
00187
00188         // We are about to fetch a new packet, make sure that the
00189         // UDP module knows that any old RX data it has laying
00190         // around will now be gone.
00191         UDPDiscard();
00192
00193         // Fetch a packet (throws old one away, if not thrown away
00194         // yet)
00195         if(!MACGetHeader(&remoteNode.MACAddr, &cFrameType))
00196             break;
00197
00198         // Dispatch the packet to the appropriate handler
00199         switch(cFrameType)
00200         {
00201             case MAC_ARP:
00202                 ARPProcess();
00203                 break;
00204
00205             case MAC_IP:
00206                 if(!IPGetHeader(&tempLocalIP, &remoteNode, &cIPFrameType, &dataCount))
00207                     break;
00208
00209                 if(cIPFrameType == IP_PROT_ICMP)
00210                 {
00211                     // MODIFIX: Removed IP gleaning functionality.
00212
00213                     // Process this ICMP packet if it the destination IP address matches our address or one of the broadcast IP addressees
00214                     // MODIFIX: Use the eWicht structure sIPConfig (4 times)
00215                     if( (tempLocalIP.Val == sIPConfig.MyIPAddr.Val) ||
00216                         (tempLocalIP.Val == 0xFFFFFFFF) ||
00217                         (tempLocalIP.Val == ((sIPConfig.MyIPAddr.Val & sIPConfig.MyMask.Val) | ~sIPConfig.MyMask.Val)))
00218                     {
00219                         ICMPProcess(&remoteNode, dataCount);
00220                     }
00221                     break;
00222                 }
00223
00224                 if(cIPFrameType == IP_PROT_TCP)
00225                 {
00226                     TCPProcess(&remoteNode, &tempLocalIP, dataCount);
00227                     break;
00228                 }
00229
00230                 if(cIPFrameType == IP_PROT_UDP)
00231                 {
00232                     // Stop processing packets if we came upon a UDP frame with application data in it
00233                     if (UDPProcess(&remoteNode, &tempLocalIP, dataCount))
00234                         return;
00235                 }
00236
00237                 break;
00238         }
00239     }
00240 }
00241
00242 /*********************************************************************
00243  * Function:        void StackApplications(void)
00244  *
00245  * PreCondition:    StackInit() is already called.
00246  *
00247  * Input:           None
00248  *
00249  * Output:          Calls all loaded application modules.
00250  *
00251  * Side Effects:    None
00252  *
00253  * Note:            This function must be called periodically to
00254  *                  ensure timely responses.
00255  *
00256  ********************************************************************/
00257 void StackApplications(void)
00258 {
00259     HTTPServer();
00260
00261     RebootTask();
00262
00263     // MODIFIX: Removed unneeded parts.
00264 }
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: StackTsk.h Source File

StackTsk.h

Go to the documentation of this file.
00001
00002
00029 /*********************************************************************
00030  * Software License Agreement
00031  *
00032  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00033  * reserved.
00034  *
00035  * Microchip licenses to you the right to use, modify, copy, and
00036  * distribute:
00037  * (i)  the Software when embedded on a Microchip microcontroller or
00038  *      digital signal controller product ("Device") which is
00039  *      integrated into Licensee's product; or
00040  * (ii) ONLY the Software driver source files ENC28J60.c and
00041  *      ENC28J60.h ported to a non-Microchip device used in
00042  *      conjunction with a Microchip ethernet controller for the
00043  *      sole purpose of interfacing with the ethernet controller.
00044  *
00045  * You should refer to the license agreement accompanying this
00046  * Software for additional information regarding your rights and
00047  * obligations.
00048  *
00049  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00050  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00051  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00052  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00053  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00054  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00055  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00056  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00057  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00058  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00059  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00060  *
00061  *
00062  * Author               Date    Comment
00063  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00064  * Nilesh Rajbharti     8/10/01 Original        (Rev 1.0)
00065  * Nilesh Rajbharti     2/9/02  Cleanup
00066  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
00067  * Nilesh Rajbharti     8/7/03  Rev 2.21 - TFTP Client addition
00068  * Howard Schlunder     9/30/04 Added MCHP_MAC, MAC_POWER_ON_TEST,
00069                                 EEPROM_BUFFER_SIZE, USE_LCD
00070  * Howard Schlunder     8/09/06 Removed MCHP_MAC, added STACK_USE_NBNS,
00071  *                              STACK_USE_DNS, and STACK_USE_GENERIC_TCP_EXAMPLE
00072  ********************************************************************/
00073 #ifndef __STACK_TSK_H
00074 #define __STACK_TSK_H
00075
00076
00077 // Check for potential configuration errors in "TCPIPConfig.h"
00078 #if (MAX_UDP_SOCKETS <= 0 || MAX_UDP_SOCKETS > 255 )
00079 #error Invalid MAX_UDP_SOCKETS value specified
00080 #endif
00081
00082 // Check for potential configuration errors in "TCPIPConfig.h"
00083 #if (MAX_HTTP_CONNECTIONS <= 0 || MAX_HTTP_CONNECTIONS > 255 )
00084 #error Invalid MAX_HTTP_CONNECTIONS value specified.
00085 #endif
00086
00092 typedef struct __attribute__((__packed__)) _MAC_ADDR
00093 {
00094     BYTE v[6];
00095 } MAC_ADDR;
00096
00097 #define IP_ADDR     DWORD_VAL
00098
00104 typedef struct __attribute__((__packed__)) _NODE_INFO
00105 {
00106     MAC_ADDR    MACAddr;
00107     IP_ADDR     IPAddr;
00108 } NODE_INFO;
00109
00110 // MODIFIX: Removed typedef struct and definition of APP_CONFIG as replaced by
00111 // other eWicht structures.
00112
00113
00115
00126 void StackInit(void);
00127
00128
00130
00142 void StackTask(void);
00143
00144
00146
00156 void StackApplications(void);
00157
00158 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCP.c Source File

TCP.c

Go to the documentation of this file.
00001
00002
00003
00029 /*********************************************************************
00030  * Software License Agreement
00031  *
00032  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00033  * reserved.
00034  *
00035  * Microchip licenses to you the right to use, modify, copy, and
00036  * distribute:
00037  * (i)  the Software when embedded on a Microchip microcontroller or
00038  *      digital signal controller product ("Device") which is
00039  *      integrated into Licensee's product; or
00040  * (ii) ONLY the Software driver source files ENC28J60.c and
00041  *      ENC28J60.h ported to a non-Microchip device used in
00042  *      conjunction with a Microchip ethernet controller for the
00043  *      sole purpose of interfacing with the ethernet controller.
00044  *
00045  * You should refer to the license agreement accompanying this
00046  * Software for additional information regarding your rights and
00047  * obligations.
00048  *
00049  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00050  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00051  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00052  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00053  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00054  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00055  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00056  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00057  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00058  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00059  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00060  *
00061  *
00062  * Author               Date        Comment
00063  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00064  * Nilesh Rajbharti     5/8/01      Original        (Rev 1.0)
00065  * Howard Schlunder     12/11/06    Changed almost everything to
00066  *                                  better meet RFC 793.
00067  ********************************************************************/
00068 #define __TCP_C
00069
00070 #include "TCPIP.h"
00071
00072 /****************************************************************************
00073   Section:
00074     Configuration Parameters
00075   ***************************************************************************/
00076
00077 // Starting port for client sockets
00078 #define LOCAL_PORT_START_NUMBER (1024u)
00079 // End port for client sockets
00080 #define LOCAL_PORT_END_NUMBER   (5000u)
00081
00082 // For debugging only.  Normal applications should never enable these
00083 //#define DEBUG_GENERATE_TX_LOSS        31129
00084 //#define DEBUG_GENERATE_RX_LOSS        32113
00085
00086 // A lot of pointer dereference code can be removed if you
00087 // locally copy TCBStubs to an absolute memory location.
00088 // If you define TCP_OPTIMIZE_FOR_SIZE, local caching will
00089 // occur and will substantially decrease the entire TCP ROM
00090 // footprint (up to 35%).  If you leave TCP_OPTIMIZE_FOR_SIZE
00091 // undefined, the local caching will be disabled.  On PIC18
00092 // products, this will improve TCP performance/throughput by
00093 // approximately 15%.
00094 #define TCP_OPTIMIZE_FOR_SIZE
00095
00096 // For smallest size and best throughput, TCP_OPTIMIZE_FOR_SIZE
00097 // should always be enabled on PIC24/dsPIC products.  On PIC32
00098 // products there is very little difference and depnds on compiler
00099 // optimization level
00100 #if defined(__C30__) && !defined(TCP_OPTIMIZE_FOR_SIZE)
00101     #define TCP_OPTIMIZE_FOR_SIZE
00102 #elif defined(__C32__) && defined(TCP_OPTIMIZE_FOR_SIZE)
00103     #undef TCP_OPTIMIZE_FOR_SIZE
00104 #endif
00105
00106 // TCP Maximum Segment Size (TX and RX)
00107 #define TCP_MAX_SEG_SIZE            (536u)
00108
00109 // TCP Timeout and retransmit numbers
00110 #define TCP_START_TIMEOUT_VAL       ((TICK)TICK_SECOND*1)   // Timeout to retransmit unacked data
00111 #define TCP_DELAYED_ACK_TIMEOUT     ((TICK)TICK_SECOND/10)  // Timeout for delayed-acknowledgement algorithm
00112 #define TCP_FIN_WAIT_2_TIMEOUT      ((TICK)TICK_SECOND*5)   // Timeout for FIN WAIT 2 state
00113 #define TCP_KEEP_ALIVE_TIMEOUT      ((TICK)TICK_SECOND*10)  // Timeout for keep-alive messages when no traffic is sent
00114 #define TCP_CLOSE_WAIT_TIMEOUT      ((TICK)TICK_SECOND/5)   // Timeout for the CLOSE_WAIT state
00115 #define TCP_MAX_RETRIES             (5u)                    // Maximum number of retransmission attempts
00116 #define TCP_MAX_UNACKED_KEEP_ALIVES (6u)                    // Maximum number of keep-alive messages that can be sent without receiving a response before automatically closing the connection
00117 #define TCP_MAX_SYN_RETRIES         (2u)    // Smaller than all other retries to reduce SYN flood DoS duration
00118
00119 #define TCP_AUTO_TRANSMIT_TIMEOUT_VAL   (TICK_SECOND/25ull) // Timeout before automatically tranmitting unflushed data
00120
00121 #define TCP_SYN_QUEUE_MAX_ENTRIES   (3u)                    // Number of TCP RX SYN packets to save if they cannot be serviced immediately
00122 #define TCP_SYN_QUEUE_TIMEOUT       ((TICK)TICK_SECOND*3)   // Timeout for when SYN queue entries are deleted if unserviceable
00123
00124 /****************************************************************************
00125   Section:
00126     TCP Header Data Types
00127   ***************************************************************************/
00128
00129 #define FIN     (0x01)      // FIN Flag as defined in RFC
00130 #define SYN     (0x02)      // SYN Flag as defined in RFC
00131 #define RST     (0x04)      // Reset Flag as defined in RFC
00132 #define PSH     (0x08)      // Push Flag as defined in RFC
00133 #define ACK     (0x10)      // Acknowledge Flag as defined in RFC
00134 #define URG     (0x20)      // Urgent Flag as defined in RFC
00135
00136 // TCP Header Data Structure
00137 typedef struct _TCP_HEADER
00138 {
00139     WORD    SourcePort;     // Local port number
00140     WORD    DestPort;       // Remote port number
00141     DWORD   SeqNumber;      // Local sequence number
00142     DWORD   AckNumber;      // Acknowledging remote sequence number
00143
00144     struct
00145     {
00146         unsigned char Reserved3      : 4;
00147         unsigned char Val            : 4;
00148     } DataOffset;           // Data offset flags nibble
00149
00150     union
00151     {
00152         struct
00153         {
00154             unsigned char flagFIN    : 1;
00155             unsigned char flagSYN    : 1;
00156             unsigned char flagRST    : 1;
00157             unsigned char flagPSH    : 1;
00158             unsigned char flagACK    : 1;
00159             unsigned char flagURG    : 1;
00160             unsigned char Reserved2  : 2;
00161         } bits;
00162         BYTE byte;
00163     } Flags;                // TCP Flags as defined in RFC
00164
00165     WORD    Window;         // Local free RX buffer window
00166     WORD    Checksum;       // Data payload checksum
00167     WORD    UrgentPointer;  // Urgent pointer
00168 } TCP_HEADER;
00169
00170 #define TCP_OPTIONS_END_OF_LIST     (0x00u)     // End of List TCP Option Flag
00171 #define TCP_OPTIONS_NO_OP           (0x01u)     // No Op TCP Option
00172 #define TCP_OPTIONS_MAX_SEG_SIZE    (0x02u)     // Maximum segment size TCP flag
00173 typedef struct _TCP_OPTIONS
00174 {
00175     BYTE        Kind;                           // Type of option
00176     BYTE        Length;                         // Length
00177     WORD_VAL    MaxSegSize;                     // Maximum segment size
00178 } TCP_OPTIONS;                                  // TCP Options data structure
00179
00180 // Structure containing all the important elements of an incomming
00181 // SYN packet in order to establish a connection at a future time
00182 // if all sockets on the listening port are already connected to
00183 // someone
00184 typedef struct
00185 {
00186     NODE_INFO   niSourceAddress;// Remote IP address and MAC address
00187     WORD        wSourcePort;    // Remote TCP port number that the response SYN needs to be sent to
00188     DWORD       dwSourceSEQ;    // Remote TCP SEQuence number that must be ACKnowledged when we send our response SYN
00189     WORD        wDestPort;      // Local TCP port which the original SYN was destined for
00190     WORD        wTimestamp;     // Timer to expire old SYN packets that can't be serviced at all
00191 } TCP_SYN_QUEUE;
00192
00193
00194 #if defined(STACK_CLIENT_MODE)
00195 static WORD NextPort __attribute__((persistent));   // Tracking variable for next local client port number
00196 #endif
00197
00198 /****************************************************************************
00199   Section:
00200     TCB Definitions
00201   ***************************************************************************/
00202
00203 // Determines the number of defined TCP sockets
00204 #define TCP_SOCKET_COUNT    (sizeof(TCPSocketInitializer)/sizeof(TCPSocketInitializer[0]))
00205
00206
00207 #if defined(HI_TECH_C)
00208     // The initializer forces this large array out of the bss section
00209     // so we can link correctly.
00210     #pragma psect bigdata=TCB_uRAM_BIG
00211     #pragma psect data=TCB_uRAM
00212     static TCB_STUB TCBStubs[TCP_SOCKET_COUNT] = {'\0'};
00213     #pragma psect data=ordinary_data_sect
00214     #pragma psect bigdata=ordinary_data_sect_big
00215 #else
00216     // The TCB array is very large.  With the C18 compiler, one must
00217     // modify the linker script to make an array that spans more than
00218     // one memory bank.  To do this, make the necessary changes to your
00219     // processor's linker script (.lkr).  Here is an example showing
00220     // gpr11 and 128 bytes of gpr12 being combined into one 384 byte
00221     // block used exclusively by the TCB_uRAM data section:
00222     // ...
00223     // //DATABANK   NAME=gpr11      START=0xB00          END=0xBFF
00224     // //DATABANK   NAME=gpr12      START=0xC00          END=0xCFF
00225     // DATABANK   NAME=gpr11b     START=0xB00          END=0xC7F           PROTECTED
00226     // DATABANK   NAME=gpr12      START=0xC80          END=0xCFF
00227     // ...
00228     // SECTION    NAME=TCB_uRAM    RAM=gpr11b
00229     // ...
00230     #pragma udata TCB_uRAM
00231     static TCB_STUB TCBStubs[TCP_SOCKET_COUNT];
00232     #pragma udata                   // Return to any other RAM section
00233 #endif
00234
00235 static TCB MyTCB;                                   // Currently loaded TCB
00236 static TCP_SOCKET hCurrentTCP = INVALID_SOCKET;     // Current TCP socket
00237 #if TCP_SYN_QUEUE_MAX_ENTRIES
00238     #pragma udata SYN_QUEUE_RAM_SECT
00239     static TCP_SYN_QUEUE SYNQueue[TCP_SYN_QUEUE_MAX_ENTRIES];   // Array of saved incoming SYN requests that need to be serviced later
00240     #pragma udata
00241 #endif
00242
00243 /****************************************************************************
00244   Section:
00245     Function Prototypes
00246   ***************************************************************************/
00247
00248 static void TCPRAMCopy(PTR_BASE wDest, BYTE vDestType, PTR_BASE wSource, BYTE vSourceType, WORD wLength);
00249
00250 #if defined(__18CXX)
00251     static void TCPRAMCopyROM(PTR_BASE wDest, BYTE wDestType, ROM BYTE* wSource, WORD wLength);
00252 #else
00253     #define TCPRAMCopyROM(a,b,c,d)  TCPRAMCopy(a,b,c,TCP_PIC_RAM,d)
00254 #endif
00255
00256 static void SendTCP(BYTE vTCPFlags, BYTE vSendFlags);
00257 static void HandleTCPSeg(TCP_HEADER* h, WORD len);
00258 static BOOL FindMatchingSocket(TCP_HEADER* h, NODE_INFO* remote);
00259 static void SwapTCPHeader(TCP_HEADER* header);
00260 static void CloseSocket(void);
00261 static void SyncTCB(void);
00262
00263 // Indicates if this packet is a retransmission (no reset) or a new packet (reset required)
00264 #define SENDTCP_RESET_TIMERS    0x01
00265 // Instead of transmitting normal data, a garbage octet is transmitted according to RFC 1122 section 4.2.3.6
00266 #define SENDTCP_KEEP_ALIVE      0x02
00267
00268
00269 /****************************************************************************
00270   Section:
00271     TCB Optimization Configuration
00272   ***************************************************************************/
00273
00274 #if defined(TCP_OPTIMIZE_FOR_SIZE)
00275     static TCB_STUB MyTCBStub;
00276
00277     // Flushes MyTCBStub cache and loads up the specified TCB_STUB.
00278     // Does nothing on cache hit.
00279     static void SyncTCBStub(TCP_SOCKET hTCP)
00280     {
00281         if(hCurrentTCP == hTCP)
00282             return;
00283
00284         if(hCurrentTCP != INVALID_SOCKET)
00285         {
00286             // Save the current TCB stub
00287             memcpy((void*)&TCBStubs[hCurrentTCP], (void*)&MyTCBStub, sizeof(MyTCBStub));
00288         }
00289
00290         hCurrentTCP = hTCP;
00291
00292         if(hTCP == INVALID_SOCKET)
00293             return;
00294
00295         // Load up the new TCB stub
00296         memcpy((void*)&MyTCBStub, (void*)&TCBStubs[hTCP], sizeof(MyTCBStub));
00297     }
00298 #else
00299     // Flushes MyTCBStub cache and loads up the specified TCB_STUB.
00300     // Does nothing on cache hit.
00301     #define SyncTCBStub(a)  hCurrentTCP = a
00302     // Alias to current TCP stub.
00303     #define MyTCBStub       TCBStubs[hCurrentTCP]
00304 #endif
00305
00306
00307
00308 // Flushes MyTCB cache and loads up the specified TCB.
00309 // Does nothing on cache hit.
00310 static void SyncTCB(void)
00311 {
00312     static TCP_SOCKET hLastTCB = INVALID_SOCKET;
00313
00314     if(hLastTCB == hCurrentTCP)
00315         return;
00316
00317     if(hLastTCB != INVALID_SOCKET)
00318     {
00319         // Save the current TCB
00320         TCPRAMCopy(TCBStubs[hLastTCB].bufferTxStart - sizeof(MyTCB), TCBStubs[hLastTCB].vMemoryMedium, (PTR_BASE)&MyTCB, TCP_PIC_RAM, sizeof(MyTCB));
00321     }
00322
00323     // Load up the new TCB
00324     hLastTCB = hCurrentTCP;
00325     TCPRAMCopy((PTR_BASE)&MyTCB, TCP_PIC_RAM, TCBStubs[hCurrentTCP].bufferTxStart - sizeof(MyTCB), TCBStubs[hLastTCB].vMemoryMedium, sizeof(MyTCB));
00326 }
00327
00328
00329 /*****************************************************************************
00330   Function:
00331     void TCPInit(void)
00332
00333   Summary:
00334     Initializes the TCP module.
00335
00336   Description:
00337     Initializes the TCP module.  This function sets up the TCP buffers
00338     in memory and initializes each socket to the CLOSED state.  If
00339     insufficient memory was allocated for the TCP sockets, the function
00340     will hang here to be captured by the debugger.
00341
00342   Precondition:
00343     None
00344
00345   Parameters:
00346     None
00347
00348   Returns:
00349     None
00350
00351   Remarks:
00352     This function is called only one during lifetime of the application.
00353   ***************************************************************************/
00354 void TCPInit(void)
00355 {
00356     BYTE i;
00357     BYTE vSocketsAllocated;
00358     WORD wTXSize, wRXSize;
00359     PTR_BASE ptrBaseAddress;
00360     BYTE vMedium;
00361     #if TCP_ETH_RAM_SIZE > 0
00362     WORD wCurrentETHAddress = TCP_ETH_RAM_BASE_ADDRESS;
00363     #endif
00364     #if TCP_PIC_RAM_SIZE > 0
00365     PTR_BASE ptrCurrentPICAddress = TCP_PIC_RAM_BASE_ADDRESS;
00366     #endif
00367     #if TCP_SPI_RAM_SIZE > 0
00368     WORD wCurrentSPIAddress = TCP_SPI_RAM_BASE_ADDRESS;
00369     #endif
00370
00371     // Mark all SYN Queue entries as invalid by zeroing the memory
00372     #if TCP_SYN_QUEUE_MAX_ENTRIES
00373         memset((void*)SYNQueue, 0x00, sizeof(SYNQueue));
00374     #endif
00375
00376     // Allocate all socket FIFO addresses
00377     vSocketsAllocated = 0;
00378     for(i = 0; i < TCP_SOCKET_COUNT; i++)
00379     {
00380         // Generate all needed sockets of each type (TCP_PURPOSE_*)
00381         SyncTCBStub(i);
00382         SyncTCB();
00383
00384         vMedium = TCPSocketInitializer[i].vMemoryMedium;
00385         wTXSize = TCPSocketInitializer[i].wTXBufferSize;
00386         wRXSize = TCPSocketInitializer[i].wRXBufferSize;
00387
00388         switch(vMedium)
00389         {
00390             #if TCP_ETH_RAM_SIZE > 0
00391             case TCP_ETH_RAM:
00392                 ptrBaseAddress = wCurrentETHAddress;
00393                 wCurrentETHAddress += sizeof(TCB) + wTXSize+1 + wRXSize+1;
00394                 // Do a sanity check to ensure that we aren't going to use memory that hasn't been allocated to us.
00395                 // If your code locks up right here, it means you've incorrectly allocated your TCP socket buffers in TCPIPConfig.h.  See the TCP memory allocation section.  More RAM needs to be allocated to the base memory mediums, or the individual sockets TX and RX FIFOS and socket quantiy needs to be shrunken.
00396                 while(wCurrentETHAddress > TCP_ETH_RAM_BASE_ADDRESS + TCP_ETH_RAM_SIZE);
00397                 break;
00398             #endif
00399
00400             #if TCP_PIC_RAM_SIZE > 0
00401             case TCP_PIC_RAM:
00402                 ptrBaseAddress = ptrCurrentPICAddress;
00403                 ptrCurrentPICAddress += sizeof(TCB) + wTXSize+1 + wRXSize+1;
00404                 // Do a sanity check to ensure that we aren't going to use memory that hasn't been allocated to us.
00405                 // If your code locks up right here, it means you've incorrectly allocated your TCP socket buffers in TCPIPConfig.h.  See the TCP memory allocation section.  More RAM needs to be allocated to the base memory mediums, or the individual sockets TX and RX FIFOS and socket quantiy needs to be shrunken.
00406                 while(ptrCurrentPICAddress > TCP_PIC_RAM_BASE_ADDRESS + TCP_PIC_RAM_SIZE);
00407                 break;
00408             #endif
00409
00410             #if TCP_SPI_RAM_SIZE > 0
00411             case TCP_SPI_RAM:
00412                 ptrBaseAddress = wCurrentSPIAddress;
00413                 wCurrentSPIAddress += sizeof(TCB) + wTXSize+1 + wRXSize+1;
00414                 // Do a sanity check to ensure that we aren't going to use memory that hasn't been allocated to us.
00415                 // If your code locks up right here, it means you've incorrectly allocated your TCP socket buffers in TCPIPConfig.h.  See the TCP memory allocation section.  More RAM needs to be allocated to the base memory mediums, or the individual sockets TX and RX FIFOS and socket quantiy needs to be shrunken.
00416                 while(wCurrentSPIAddress > TCP_SPI_RAM_BASE_ADDRESS + TCP_SPI_RAM_SIZE);
00417                 break;
00418             #endif
00419
00420             default:
00421                 while(1); // Undefined allocation medium.  Go fix your TCPIPConfig.h TCP memory allocations.
00422         }
00423
00424         MyTCB.vSocketPurpose = TCPSocketInitializer[i].vSocketPurpose;
00425
00426         MyTCBStub.vMemoryMedium = vMedium;
00427         MyTCBStub.bufferTxStart = ptrBaseAddress + sizeof(TCB);
00428         MyTCBStub.bufferRxStart = MyTCBStub.bufferTxStart + wTXSize + 1;
00429         MyTCBStub.bufferEnd     = MyTCBStub.bufferRxStart + wRXSize;
00430         MyTCBStub.smState       = TCP_CLOSED;
00431         MyTCBStub.Flags.bServer = FALSE;
00432         #if defined(STACK_USE_SSL)
00433         MyTCBStub.sslStubID = SSL_INVALID_ID;
00434         #endif
00435
00436         CloseSocket();
00437     }
00438 }
00439
00440 /****************************************************************************
00441   Section:
00442     Connection Management Functions
00443   ***************************************************************************/
00444
00445
00446 /****************************************************************************
00447   Function:
00448       TCP_SOCKET TCPOpen(DWORD dwRemoteHost,
00449                           BYTE vRemoteHostType,
00450                           WORD wPort,
00451                           BYTE vSocketPurpose)
00452
00453   Summary:
00454     Opens a TCP socket for listening or as a client.
00455
00456   Description:
00457     Provides a unified method for opening TCP sockets. This function can
00458     open both client and server sockets. For client sockets, it can accept
00459     host name string to query in DNS, and IP address as a string, an IP
00460     address in binary form, or a previously resolved NODE_INFO structure.
00461     When a host name or IP address only is provided, the TCP module will
00462     internally perform the necessary DNS and/or ARP resolution steps before
00463     reporting that the TCP socket is connected (via a call to
00464     TCPISConnected returning TRUE). Server sockets ignore this destination
00465     parameter and listen only on the indicated port.
00466
00467     The vSocketPurpose field allows sockets to be opened with varying
00468     buffer size parameters and memory storage mediums. This field
00469     corresponds to pre-defined sockets types in TCPIPConfig.h or the
00470     TCPIPConfig utility.
00471
00472     Sockets are statically allocated on boot, but can be claimed with this
00473     \function and freed using TCPDisconnect (for client sockets). Server
00474     sockets are opened permanently for the duration of the application.
00475     Calls to TCPDisconnect will only release the socket to the listening
00476     state.
00477
00478   Conditions:
00479     TCP is initialized.
00480
00481   Input:
00482     dwRemoteHost -     For client sockets only. Provide a pointer to a
00483                        null\-terminated string of the remote host name (ex\:
00484                        "www.microchip.com" or "192.168.1.123"), a literal
00485                        destination IP address (ex\: 0x7B01A8C0 or an IP_ADDR
00486                        data type), or a pointer to a NODE_INFO structure
00487                        with the remote IP address and remote node or gateway
00488                        MAC address specified. If a string is provided, note
00489                        that it must be statically allocated in memory and
00490                        cannot be modified or deallocated until
00491                        TCPIsConnected returns TRUE. This parameter is
00492                        ignored for server sockets.
00493     vRemoteHostType -  TCP_OPEN_SERVER, TCP_OPEN_RAM_HOST,
00494                        TCP_OPEN_ROM_HOST, TCP_OPEN_IP_ADDRESS, or
00495                        TCP_OPEN_NODE_INFO.
00496     wPort -            For client sockets, the remote TCP port to which a
00497                        connection should be made. For server sockets, the
00498                        local TCP port on which to listen for connections.
00499     vSocketPurpose -   Any of the TCP_PURPOSE_* constants defined in
00500                        TCPIPConfig.h or the TCPIPConfig utility.
00501
00502   Return Values:
00503     INVALID_SOCKET -  No sockets of the specified type were available to be
00504                       opened.
00505     Otherwise -       A TCP_SOCKET handle. Save this handle and use it when
00506                       calling all other TCP APIs.
00507
00508   Remarks:
00509     This function replaces the old TCPConnect and TCPListen functions.
00510
00511     If TCP_OPEN_RAM_HOST or TCP_OPEN_ROM_HOST are used for the destination
00512     type, the DNS client module must also be enabled.
00513
00514   Example:
00515     <code>
00516     // Open a server socket
00517     skt = TCPOpen(NULL, TCP_OPEN_SERVER, HTTP_PORT, TCP_PURPOSE_HTTP_SERVER);
00518
00519     // Open a client socket to www.microchip.com
00520     // The double cast here prevents compiler warnings
00521     skt = TCPOpen((DWORD)(PTR_BASE)"www.microchip.com",
00522                     TCP_OPEN_ROM_HOST, 80, TCP_PURPOSE_DEFAULT);
00523
00524     // Reopen a client socket without repeating DNS or ARP
00525     SOCKET_INFO cache = TCPGetSocketInfo(skt);  // Call with the old socket
00526     skt = TCPOpen((DWORD)(PTR_BASE)&cache.remote, TCP_OPEN_NODE_INFO,
00527                     cache.remotePort.Val, TCP_PURPOSE_DEFAULT);
00528     </code>
00529   ****************************************************************************/
00530 TCP_SOCKET TCPOpen(DWORD dwRemoteHost, BYTE vRemoteHostType, WORD wPort, BYTE vSocketPurpose)
00531 {
00532     TCP_SOCKET hTCP;
00533
00534     // Find an available socket that matches the specified socket type
00535     for(hTCP = 0; hTCP < TCP_SOCKET_COUNT; hTCP++)
00536     {
00537         SyncTCBStub(hTCP);
00538
00539         // Sockets that are in use will be in a non-closed state
00540         if(MyTCBStub.smState != TCP_CLOSED)
00541             continue;
00542
00543         SyncTCB();
00544
00545         // See if this socket matches the desired type
00546         if(MyTCB.vSocketPurpose != vSocketPurpose)
00547             continue;
00548
00549         // See if this is a server socket
00550         if(vRemoteHostType == TCP_OPEN_SERVER)
00551         {
00552             MyTCB.localPort.Val = wPort;
00553             MyTCBStub.Flags.bServer = TRUE;
00554             MyTCBStub.smState = TCP_LISTEN;
00555             MyTCBStub.remoteHash.Val = wPort;
00556             #if defined(STACK_USE_SSL_SERVER)
00557             MyTCB.localSSLPort.Val = 0;
00558             #endif
00559         }
00560         // Handle all the client mode socket types
00561         else
00562         {
00563             #if defined(STACK_CLIENT_MODE)
00564             {
00565                 // Each new socket that is opened by this node, gets the
00566                 // next sequential local port number.
00567                 if(NextPort < LOCAL_PORT_START_NUMBER || NextPort > LOCAL_PORT_END_NUMBER)
00568                     NextPort = LOCAL_PORT_START_NUMBER;
00569
00570                 // Set the non-zero TCB fields
00571                 MyTCB.localPort.Val = NextPort++;
00572                 MyTCB.remotePort.Val = wPort;
00573
00574                 // Flag to start the DNS, ARP, SYN processes
00575                 MyTCBStub.eventTime = TickGet();
00576                 MyTCBStub.Flags.bTimerEnabled = 1;
00577                 MyTCBStub.Flags.bSocketReset = 0;
00578
00579                 switch(vRemoteHostType)
00580                 {
00581                     #if defined(STACK_USE_DNS)
00582                     case TCP_OPEN_RAM_HOST:
00583                     case TCP_OPEN_ROM_HOST:
00584                         MyTCB.remote.dwRemoteHost = dwRemoteHost;
00585                         MyTCB.flags.bRemoteHostIsROM = (vRemoteHostType == TCP_OPEN_ROM_HOST);
00586                         MyTCBStub.smState = TCP_GET_DNS_MODULE;
00587                         break;
00588                     #endif
00589
00590                     case TCP_OPEN_IP_ADDRESS:
00591                         // dwRemoteHost is a literal IP address.  This
00592                         // doesn't need DNS and can skip directly to the
00593                         // Gateway ARPing step.
00594                         MyTCBStub.remoteHash.Val = (((DWORD_VAL*)&dwRemoteHost)->w[1]+((DWORD_VAL*)&dwRemoteHost)->w[0] + wPort) ^ MyTCB.localPort.Val;
00595                         MyTCB.remote.niRemoteMACIP.IPAddr.Val = dwRemoteHost;
00596                         MyTCB.retryCount = 0;
00597                         MyTCB.retryInterval = (TICK_SECOND/4)/256;
00598                         MyTCBStub.smState = TCP_GATEWAY_SEND_ARP;
00599                         break;
00600
00601                     case TCP_OPEN_NODE_INFO:
00602                         MyTCBStub.remoteHash.Val = (((NODE_INFO*)(PTR_BASE)dwRemoteHost)->IPAddr.w[1]+((NODE_INFO*)(PTR_BASE)dwRemoteHost)->IPAddr.w[0] + wPort) ^ MyTCB.localPort.Val;
00603                         memcpy((void*)(BYTE*)&MyTCB.remote, (void*)(BYTE*)(PTR_BASE)dwRemoteHost, sizeof(NODE_INFO));
00604                         MyTCBStub.smState = TCP_SYN_SENT;
00605                         SendTCP(SYN, SENDTCP_RESET_TIMERS);
00606                         break;
00607                 }
00608             }
00609             #else
00610             {
00611                 return INVALID_SOCKET;
00612             }
00613             #endif
00614         }
00615
00616         return hTCP;
00617     }
00618
00619     // If there is no socket available, return error.
00620     return INVALID_SOCKET;
00621 }
00622
00623
00624 /*****************************************************************************
00625   Function:
00626     BOOL TCPWasReset(TCP_SOCKET hTCP)
00627
00628   Summary:
00629     Self-clearing semaphore inidicating socket reset.
00630
00631   Description:
00632     This function is a self-clearing semaphore indicating whether or not
00633     a socket has been disconnected since the previous call.  This function
00634     works for all possible disconnections: a call to TCPDisconnect, a FIN
00635     from the remote node, or an acknowledgement timeout caused by the loss
00636     of a network link.  It also returns TRUE after the first call to TCPInit.
00637     Applications should use this function to reset their state machines.
00638
00639     This function was added due to the possibility of an error when relying
00640     on TCPIsConnected returing FALSE to check for a condition requiring a
00641     state machine reset.  If a socket is closed (due to a FIN ACK) and then
00642     immediately reopened (due to a the arrival of a new SYN) in the same
00643     cycle of the stack, calls to TCPIsConnected by the application will
00644     never return FALSE even though the socket has been disconnected.  This
00645     can cause errors for protocols such as HTTP in which a client will
00646     immediately open a new connection upon closing of a prior one.  Relying
00647     on this function instead allows applications to trap those conditions
00648     and properly reset their internal state for the new connection.
00649
00650   Precondition:
00651     TCP is initialized.
00652
00653   Parameters:
00654     hTCP - The socket to check.
00655
00656   Return Values:
00657     TRUE - The socket has been disconnected since the previous call.
00658     FALSE - The socket has not been disconnected since the previous call.
00659   ***************************************************************************/
00660 BOOL TCPWasReset(TCP_SOCKET hTCP)
00661 {
00662     SyncTCBStub(hTCP);
00663
00664     if(MyTCBStub.Flags.bSocketReset)
00665     {
00666         MyTCBStub.Flags.bSocketReset = 0;
00667         return TRUE;
00668     }
00669
00670     return FALSE;
00671 }
00672
00673
00674 /*****************************************************************************
00675   Function:
00676     BOOL TCPIsConnected(TCP_SOCKET hTCP)
00677
00678   Summary:
00679     Determines if a socket has an established connection.
00680
00681   Description:
00682     This function determines if a socket has an established connection to
00683     a remote node.  Call this function after calling TCPOpen to determine
00684     when the connection is set up and ready for use.  This function was
00685     historically used to check for disconnections, but TCPWasReset is now a
00686     more appropriate solution.
00687
00688   Precondition:
00689     TCP is initialized.
00690
00691   Parameters:
00692     hTCP - The socket to check.
00693
00694   Return Values:
00695     TRUE - The socket has an established connection to a remote node.
00696     FALSE - The socket is not currently connected.
00697
00698   Remarks:
00699     A socket is said to be connected only if it is in the TCP_ESTABLISHED
00700     state.  Sockets in the process of opening or closing will return FALSE.
00701   ***************************************************************************/
00702 BOOL TCPIsConnected(TCP_SOCKET hTCP)
00703 {
00704     SyncTCBStub(hTCP);
00705     return (MyTCBStub.smState == TCP_ESTABLISHED);
00706 }
00707
00708
00709 /*****************************************************************************
00710   Function:
00711     void TCPDisconnect(TCP_SOCKET hTCP)
00712
00713   Summary:
00714     Disconnects an open socket.
00715
00716   Description:
00717     This function closes a connection to a remote node by sending a FIN.
00718     The function can be called a second time to force a socket closed by
00719     sending a RST packet.  This is useful when the application knows that
00720     the remote node will not send an ACK (if it has crashed or lost its link),
00721     or when the application needs to reuse the socket immediately regardless
00722     of whether or not the remote node would like to transmit more data before
00723     closing.
00724
00725   Precondition:
00726     TCP is initialized.
00727
00728   Parameters:
00729     hTCP - The socket to check.
00730
00731   Returns:
00732     None
00733
00734   Remarks:
00735     This function does nothing if the socket is not already connected.
00736
00737     If the socket is using SSL, a CLOSE_NOTIFY record will be transmitted
00738     first to allow the SSL session to be resumed at a later time.
00739   ***************************************************************************/
00740 void TCPDisconnect(TCP_SOCKET hTCP)
00741 {
00742     SyncTCBStub(hTCP);
00743
00744     // Delete all data in the RX FIFO
00745     // In this stack's API, the application TCP handle is
00746     // immediately invalid after calling this function, so there
00747     // is no longer any way to receive data from the TCP RX FIFO,
00748     // even though the data is still there.  Leaving the data there
00749     // could interfere with the remote node sending us a FIN if our
00750     // RX window is zero
00751     MyTCBStub.rxTail = MyTCBStub.rxHead;
00752
00753     switch(MyTCBStub.smState)
00754     {
00755         #if defined(STACK_CLIENT_MODE) && defined(STACK_USE_DNS)
00756         case TCP_DNS_RESOLVE:
00757             DNSEndUsage();  // Release the DNS module, since the user is aborting
00758             CloseSocket();
00759             break;
00760         #endif
00761
00762         case TCP_SYN_SENT:
00763             CloseSocket();
00764             break;
00765
00766         case TCP_SYN_RECEIVED:
00767         case TCP_ESTABLISHED:
00768             #if defined(STACK_USE_SSL)
00769             // When disconnecting SSL sockets, send a close_notify so we can resume later
00770             if(MyTCBStub.sslStubID != SSL_INVALID_ID)
00771             {
00772                 // Flush pending data and send close_notify
00773                 SSLTxRecord(hTCP, MyTCBStub.sslStubID, SSL_APPLICATION);
00774                 SSLTxMessage(hTCP, MyTCBStub.sslStubID, SSL_ALERT_CLOSE_NOTIFY);
00775             }
00776             #endif
00777
00778             // Send the FIN
00779             SendTCP(FIN | ACK, SENDTCP_RESET_TIMERS);
00780             MyTCBStub.smState = TCP_FIN_WAIT_1;
00781             break;
00782
00783         case TCP_CLOSE_WAIT:
00784             // Send the FIN
00785             SendTCP(FIN | ACK, SENDTCP_RESET_TIMERS);
00786             MyTCBStub.smState = TCP_LAST_ACK;
00787             break;
00788
00789         // These states are all already closed or don't need explicit disconnecting -- they will disconnect by themselves after a while
00790         //case TCP_CLOSED:
00791         //case TCP_LISTEN:
00792         //case TCP_CLOSING:
00793         //case TCP_TIME_WAIT:
00794         //  return;
00795
00796         case TCP_CLOSED_BUT_RESERVED:
00797             MyTCBStub.smState = TCP_CLOSED;
00798             break;
00799
00800         // This state will close itself after some delay, however,
00801         // this is handled so that the user can call TCPDisconnect()
00802         // twice to immediately close a socket (using an RST) without
00803         // having to get an ACK back from the remote node.  This is
00804         // great for instance when the application determines that
00805         // the remote node has been physically disconnected and
00806         // already knows that no ACK will be returned.  Alternatively,
00807         // if the application needs to immediately reuse the socket
00808         // regardless of what the other node's state is in (half open).
00809         case TCP_FIN_WAIT_1:
00810         case TCP_FIN_WAIT_2:
00811         case TCP_LAST_ACK:
00812         default:
00813             SendTCP(RST | ACK, 0);
00814             CloseSocket();
00815             break;
00816     }
00817 }
00818
00819
00820 /*****************************************************************************
00821   Function:
00822     SOCKET_INFO* TCPGetRemoteInfo(TCP_SOCKET hTCP)
00823
00824   Summary:
00825     Obtains information about a currently open socket.
00826
00827   Description:
00828     Returns the SOCKET_INFO structure associated with this socket.  This
00829     contains the NODE_INFO structure with IP and MAC address (or gateway
00830     MAC) and the remote port.
00831
00832   Precondition:
00833     TCP is initialized and the socket is connected.
00834
00835   Parameters:
00836     hTCP - The socket to check.
00837
00838   Returns:
00839     The SOCKET_INFO structure associated with this socket.  This structure is
00840     allocated statically by the function and is valid only until the next
00841     time TCPGetRemoteInfo() is called.
00842   ***************************************************************************/
00843 SOCKET_INFO* TCPGetRemoteInfo(TCP_SOCKET hTCP)
00844 {
00845     static SOCKET_INFO  RemoteInfo;
00846
00847     SyncTCB();
00848     memcpy((void*)&RemoteInfo.remote, (void*)&MyTCB.remote, sizeof(NODE_INFO));
00849     RemoteInfo.remotePort.Val = MyTCB.remotePort.Val;
00850
00851     return &RemoteInfo;
00852 }
00853
00854
00855
00856 /****************************************************************************
00857   Section:
00858     Transmit Functions
00859   ***************************************************************************/
00860
00861 /*****************************************************************************
00862   Function:
00863     void TCPFlush(TCP_SOCKET hTCP)
00864
00865   Summary:
00866     Immediately transmits all pending TX data.
00867
00868   Description:
00869     This function immediately transmits all pending TX data with a PSH
00870     flag.  If this function is not called, data will automatically be sent
00871     when either a) the TX buffer is half full or b) the
00872     TCP_AUTO_TRANSMIT_TIMEOUT_VAL (default: 40ms) has elapsed.
00873
00874   Precondition:
00875     TCP is initialized and the socket is connected.
00876
00877   Parameters:
00878     hTCP - The socket whose data is to be transmitted.
00879
00880   Returns:
00881     None
00882
00883   Remarks:
00884     SSL application data is automatically flushed, so this function has
00885     no effect for SSL sockets.
00886   ***************************************************************************/
00887 void TCPFlush(TCP_SOCKET hTCP)
00888 {
00889     SyncTCBStub(hTCP);
00890     SyncTCB();
00891
00892     // NOTE: Pending SSL data will NOT be transferred here
00893
00894     if(MyTCBStub.txHead != MyTCB.txUnackedTail)
00895     {
00896         // Send the TCP segment with all unacked bytes
00897         SendTCP(ACK, SENDTCP_RESET_TIMERS);
00898     }
00899 }
00900
00901
00902 /*****************************************************************************
00903   Function:
00904     void WORD TCPIsPutReady(TCP_SOCKET hTCP)
00905
00906   Summary:
00907     Determines how much free space is available in the TCP TX buffer.
00908
00909   Description:
00910     Call this function to determine how many bytes can be written to the
00911     TCP TX buffer.  If this function returns zero, the application must
00912     return to the main stack loop before continuing in order to transmit
00913     more data.
00914
00915   Precondition:
00916     TCP is initialized.
00917
00918   Parameters:
00919     hTCP - The socket to check.
00920
00921   Returns:
00922     The number of bytes available to be written in the TCP TX buffer.
00923   ***************************************************************************/
00924 WORD TCPIsPutReady(TCP_SOCKET hTCP)
00925 {
00926     BYTE i;
00927
00928     SyncTCBStub(hTCP);
00929
00930     i = MyTCBStub.smState;
00931
00932     // Unconnected sockets shouldn't be transmitting anything.
00933     if(!( (i == TCP_ESTABLISHED) || (i == TCP_CLOSE_WAIT) ))
00934         return 0;
00935
00936     // Calculate the free space in this socket's TX FIFO
00937     #if defined(STACK_USE_SSL)
00938     if(MyTCBStub.sslStubID != SSL_INVALID_ID)
00939     {// Use sslTxHead as the head pointer when SSL is active
00940         WORD rem;
00941
00942         // Find out raw free space
00943         if(MyTCBStub.sslTxHead >= MyTCBStub.txTail)
00944             rem = (MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart - 1) - (MyTCBStub.sslTxHead - MyTCBStub.txTail);
00945         else
00946             rem = MyTCBStub.txTail - MyTCBStub.sslTxHead - 1;
00947
00948         // Reserve space for a new MAC and header
00949         if(rem > 22)
00950             return rem - 22;
00951         else
00952             return 0;
00953     }
00954     #endif
00955
00956     if(MyTCBStub.txHead >= MyTCBStub.txTail)
00957         return (MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart - 1) - (MyTCBStub.txHead - MyTCBStub.txTail);
00958     else
00959         return MyTCBStub.txTail - MyTCBStub.txHead - 1;
00960 }
00961
00962
00963 /*****************************************************************************
00964   Function:
00965     BOOL TCPPut(TCP_SOCKET hTCP, BYTE byte)
00966
00967   Description:
00968     Writes a single byte to a TCP socket.
00969
00970   Precondition:
00971     TCP is initialized.
00972
00973   Parameters:
00974     hTCP - The socket to which data is to be written.
00975     byte - The byte to write.
00976
00977   Return Values:
00978     TRUE - The byte was written to the transmit buffer.
00979     FALSE - The transmit buffer was full, or the socket is not connected.
00980   ***************************************************************************/
00981 BOOL TCPPut(TCP_SOCKET hTCP, BYTE byte)
00982 {
00983     WORD wFreeTXSpace;
00984
00985     SyncTCBStub(hTCP);
00986
00987     wFreeTXSpace = TCPIsPutReady(hTCP);
00988     if(wFreeTXSpace == 0u)
00989         return FALSE;
00990     else if(wFreeTXSpace == 1u) // About to run out of space, lets transmit so the remote node might send an ACK back faster
00991         TCPFlush(hTCP);
00992
00993     // Send all current bytes if we are crossing half full
00994     // This is required to improve performance with the delayed
00995     // acknowledgement algorithm
00996     if((!MyTCBStub.Flags.bHalfFullFlush) && (wFreeTXSpace <= ((MyTCBStub.bufferRxStart-MyTCBStub.bufferTxStart)>>1)))
00997     {
00998         TCPFlush(hTCP);
00999         MyTCBStub.Flags.bHalfFullFlush = TRUE;
01000     }
01001
01002     #if defined(STACK_USE_SSL)
01003     if(MyTCBStub.sslStubID != SSL_INVALID_ID)
01004     {
01005         TCPRAMCopy(MyTCBStub.sslTxHead, MyTCBStub.vMemoryMedium, (PTR_BASE)&byte, TCP_PIC_RAM, sizeof(byte));
01006         if(++MyTCBStub.sslTxHead >= MyTCBStub.bufferRxStart)
01007             MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
01008     }
01009     else
01010     {
01011         TCPRAMCopy(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, (PTR_BASE)&byte, TCP_PIC_RAM, sizeof(byte));
01012         if(++MyTCBStub.txHead >= MyTCBStub.bufferRxStart)
01013             MyTCBStub.txHead = MyTCBStub.bufferTxStart;
01014     }
01015     #else
01016     TCPRAMCopy(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, (PTR_BASE)&byte, TCP_PIC_RAM, sizeof(byte));
01017     if(++MyTCBStub.txHead >= MyTCBStub.bufferRxStart)
01018         MyTCBStub.txHead = MyTCBStub.bufferTxStart;
01019     #endif
01020
01021
01022     // Send the last byte as a separate packet (likely will make the remote node send back ACK faster)
01023     if(wFreeTXSpace == 1u)
01024     {
01025         TCPFlush(hTCP);
01026     }
01027     // If not already enabled, start a timer so this data will
01028     // eventually get sent even if the application doens't call
01029     // TCPFlush()
01030     else if(!MyTCBStub.Flags.bTimer2Enabled)
01031     {
01032         MyTCBStub.Flags.bTimer2Enabled = TRUE;
01033         MyTCBStub.eventTime2 = (WORD)TickGetDiv256() + TCP_AUTO_TRANSMIT_TIMEOUT_VAL/256ull;
01034     }
01035
01036     return TRUE;
01037 }
01038
01039 /*****************************************************************************
01040   Function:
01041     WORD TCPPutArray(TCP_SOCKET hTCP, BYTE* data, WORD len)
01042
01043   Description:
01044     Writes an array from RAM to a TCP socket.
01045
01046   Precondition:
01047     TCP is initialized.
01048
01049   Parameters:
01050     hTCP - The socket to which data is to be written.
01051     data - Pointer to the array to be written.
01052     len  - Number of bytes to be written.
01053
01054   Returns:
01055     The number of bytes written to the socket.  If less than len, the
01056     buffer became full or the socket is not conected.
01057   ***************************************************************************/
01058 WORD TCPPutArray(TCP_SOCKET hTCP, BYTE* data, WORD len)
01059 {
01060     WORD wActualLen;
01061     WORD wFreeTXSpace;
01062     WORD wRightLen = 0;
01063
01064     SyncTCBStub(hTCP);
01065
01066     wFreeTXSpace = TCPIsPutReady(hTCP);
01067     if(wFreeTXSpace == 0u)
01068     {
01069         TCPFlush(hTCP);
01070         return 0;
01071     }
01072
01073     wActualLen = wFreeTXSpace;
01074     if(wFreeTXSpace > len)
01075         wActualLen = len;
01076
01077     // Send all current bytes if we are crossing half full
01078     // This is required to improve performance with the delayed
01079     // acknowledgement algorithm
01080     if((!MyTCBStub.Flags.bHalfFullFlush) && (wFreeTXSpace <= ((MyTCBStub.bufferRxStart-MyTCBStub.bufferTxStart)>>1)))
01081     {
01082         TCPFlush(hTCP);
01083         MyTCBStub.Flags.bHalfFullFlush = TRUE;
01084     }
01085
01086     #if defined(STACK_USE_SSL)
01087     if(MyTCBStub.sslStubID != SSL_INVALID_ID)
01088     {
01089         // See if we need a two part put
01090         if(MyTCBStub.sslTxHead + wActualLen >= MyTCBStub.bufferRxStart)
01091         {
01092             wRightLen = MyTCBStub.bufferRxStart-MyTCBStub.sslTxHead;
01093             TCPRAMCopy(MyTCBStub.sslTxHead, MyTCBStub.vMemoryMedium, (PTR_BASE)data, TCP_PIC_RAM, wRightLen);
01094             data += wRightLen;
01095             wActualLen -= wRightLen;
01096             MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
01097         }
01098
01099         TCPRAMCopy(MyTCBStub.sslTxHead, MyTCBStub.vMemoryMedium, (PTR_BASE)data, TCP_PIC_RAM, wActualLen);
01100         MyTCBStub.sslTxHead += wActualLen;
01101     }
01102     else
01103     {
01104         // See if we need a two part put
01105         if(MyTCBStub.txHead + wActualLen >= MyTCBStub.bufferRxStart)
01106         {
01107             wRightLen = MyTCBStub.bufferRxStart-MyTCBStub.txHead;
01108             TCPRAMCopy(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, (PTR_BASE)data, TCP_PIC_RAM, wRightLen);
01109             data += wRightLen;
01110             wActualLen -= wRightLen;
01111             MyTCBStub.txHead = MyTCBStub.bufferTxStart;
01112         }
01113
01114         TCPRAMCopy(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, (PTR_BASE)data, TCP_PIC_RAM, wActualLen);
01115         MyTCBStub.txHead += wActualLen;
01116     }
01117     #else
01118     // See if we need a two part put
01119     if(MyTCBStub.txHead + wActualLen >= MyTCBStub.bufferRxStart)
01120     {
01121         wRightLen = MyTCBStub.bufferRxStart-MyTCBStub.txHead;
01122         TCPRAMCopy(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, (PTR_BASE)data, TCP_PIC_RAM, wRightLen);
01123         data += wRightLen;
01124         wActualLen -= wRightLen;
01125         MyTCBStub.txHead = MyTCBStub.bufferTxStart;
01126     }
01127
01128     TCPRAMCopy(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, (PTR_BASE)data, TCP_PIC_RAM, wActualLen);
01129     MyTCBStub.txHead += wActualLen;
01130     #endif
01131
01132     // Send these bytes right now if we are out of TX buffer space
01133     if(wFreeTXSpace <= len)
01134     {
01135         TCPFlush(hTCP);
01136     }
01137     // If not already enabled, start a timer so this data will
01138     // eventually get sent even if the application doens't call
01139     // TCPFlush()
01140     else if(!MyTCBStub.Flags.bTimer2Enabled)
01141     {
01142         MyTCBStub.Flags.bTimer2Enabled = TRUE;
01143         MyTCBStub.eventTime2 = (WORD)TickGetDiv256() + TCP_AUTO_TRANSMIT_TIMEOUT_VAL/256ull;
01144     }
01145
01146     return wActualLen + wRightLen;
01147 }
01148
01149 /*****************************************************************************
01150   Function:
01151     WORD TCPPutROMArray(TCP_SOCKET hTCP, ROM BYTE* data, WORD len)
01152
01153   Description:
01154     Writes an array from ROM to a TCP socket.
01155
01156   Precondition:
01157     TCP is initialized.
01158
01159   Parameters:
01160     hTCP - The socket to which data is to be written.
01161     data - Pointer to the array to be written.
01162     len  - Number of bytes to be written.
01163
01164   Returns:
01165     The number of bytes written to the socket.  If less than len, the
01166     buffer became full or the socket is not conected.
01167
01168   Remarks:
01169     This function is aliased to TCPPutArray on non-PIC18 platforms.
01170   ***************************************************************************/
01171 #if defined(__18CXX)
01172 WORD TCPPutROMArray(TCP_SOCKET hTCP, ROM BYTE* data, WORD len)
01173 {
01174     WORD wActualLen;
01175     WORD wFreeTXSpace;
01176     WORD wRightLen = 0;
01177
01178     SyncTCBStub(hTCP);
01179
01180     wFreeTXSpace = TCPIsPutReady(hTCP);
01181     if(wFreeTXSpace == 0u)
01182     {
01183         TCPFlush(hTCP);
01184         return 0;
01185     }
01186
01187     // Send all current bytes if we are crossing half full
01188     // This is required to improve performance with the delayed
01189     // acknowledgement algorithm
01190     if((!MyTCBStub.Flags.bHalfFullFlush) && (wFreeTXSpace <= ((MyTCBStub.bufferRxStart-MyTCBStub.bufferTxStart)>>1)))
01191     {
01192         TCPFlush(hTCP);
01193         MyTCBStub.Flags.bHalfFullFlush = TRUE;
01194     }
01195
01196     wActualLen = wFreeTXSpace;
01197     if(wFreeTXSpace > len)
01198         wActualLen = len;
01199
01200     #if defined(STACK_USE_SSL)
01201     if(MyTCBStub.sslStubID != SSL_INVALID_ID)
01202     {
01203         // See if we need a two part put
01204         if(MyTCBStub.sslTxHead + wActualLen >= MyTCBStub.bufferRxStart)
01205         {
01206             wRightLen = MyTCBStub.bufferRxStart-MyTCBStub.sslTxHead;
01207             TCPRAMCopyROM(MyTCBStub.sslTxHead, MyTCBStub.vMemoryMedium, data, wRightLen);
01208             data += wRightLen;
01209             wActualLen -= wRightLen;
01210             MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
01211         }
01212
01213         TCPRAMCopyROM(MyTCBStub.sslTxHead, MyTCBStub.vMemoryMedium, data, wActualLen);
01214         MyTCBStub.sslTxHead += wActualLen;
01215     }
01216     else
01217     {
01218         // See if we need a two part put
01219         if(MyTCBStub.txHead + wActualLen >= MyTCBStub.bufferRxStart)
01220         {
01221             wRightLen = MyTCBStub.bufferRxStart-MyTCBStub.txHead;
01222             TCPRAMCopyROM(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, data, wRightLen);
01223             data += wRightLen;
01224             wActualLen -= wRightLen;
01225             MyTCBStub.txHead = MyTCBStub.bufferTxStart;
01226         }
01227
01228         TCPRAMCopyROM(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, data, wActualLen);
01229         MyTCBStub.txHead += wActualLen;
01230     }
01231     #else
01232     // See if we need a two part put
01233     if(MyTCBStub.txHead + wActualLen >= MyTCBStub.bufferRxStart)
01234     {
01235         wRightLen = MyTCBStub.bufferRxStart-MyTCBStub.txHead;
01236         TCPRAMCopyROM(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, data, wRightLen);
01237         data += wRightLen;
01238         wActualLen -= wRightLen;
01239         MyTCBStub.txHead = MyTCBStub.bufferTxStart;
01240     }
01241
01242     TCPRAMCopyROM(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, data, wActualLen);
01243     MyTCBStub.txHead += wActualLen;
01244     #endif
01245
01246     // Send these bytes right now if we are out of TX buffer space
01247     if(wFreeTXSpace <= len)
01248     {
01249         TCPFlush(hTCP);
01250     }
01251     // If not already enabled, start a timer so this data will
01252     // eventually get sent even if the application doens't call
01253     // TCPFlush()
01254     else if(!MyTCBStub.Flags.bTimer2Enabled)
01255     {
01256         MyTCBStub.Flags.bTimer2Enabled = TRUE;
01257         MyTCBStub.eventTime2 = (WORD)TickGetDiv256() + TCP_AUTO_TRANSMIT_TIMEOUT_VAL/256ull;
01258     }
01259
01260     return wActualLen + wRightLen;
01261 }
01262 #endif
01263
01264 /*****************************************************************************
01265   Function:
01266     BYTE* TCPPutString(TCP_SOCKET hTCP, BYTE* data)
01267
01268   Description:
01269     Writes a null-terminated string from RAM to a TCP socket.  The
01270     null-terminator is not copied to the socket.
01271
01272   Precondition:
01273     TCP is initialized.
01274
01275   Parameters:
01276     hTCP - The socket to which data is to be written.
01277     data - Pointer to the string to be written.
01278
01279   Returns:
01280     Pointer to the byte following the last byte written to the socket.  If
01281     this pointer does not dereference to a NUL byte, the buffer became full
01282     or the socket is not connected.
01283
01284   Remarks:
01285     The return value of this function differs from that of TCPPutArray.  To
01286     write long strings in a single state, initialize the *data pointer to the
01287     first byte, then call this function repeatedly (breaking to the main
01288     stack loop after each call) until the return value dereferences to a NUL
01289     byte.  Save the return value as the new starting *data pointer otherwise.
01290   ***************************************************************************/
01291 BYTE* TCPPutString(TCP_SOCKET hTCP, BYTE* data)
01292 {
01293     return data + TCPPutArray(hTCP, data, strlen((char*)data));
01294 }
01295
01296 /*****************************************************************************
01297   Function:
01298     BYTE* TCPPutROMString(TCP_SOCKET hTCP, ROM BYTE* data)
01299
01300   Description:
01301     Writes a null-terminated string from ROM to a TCP socket.  The
01302     null-terminator is not copied to the socket.
01303
01304   Precondition:
01305     TCP is initialized.
01306
01307   Parameters:
01308     hTCP - The socket to which data is to be written.
01309     data - Pointer to the string to be written.
01310
01311   Returns:
01312     Pointer to the byte following the last byte written to the socket.  If
01313     this pointer does not dereference to a NUL byte, the buffer became full
01314     or the socket is not connected.
01315
01316   Remarks:
01317     The return value of this function differs from that of TCPPutArray.  To
01318     write long strings in a single state, initialize the *data pointer to the
01319     first byte, then call this function repeatedly (breaking to the main
01320     stack loop after each call) until the return value dereferences to a NUL
01321     byte.  Save the return value as the new starting *data pointer otherwise.
01322
01323     This function is aliased to TCPPutString on non-PIC18 platforms.
01324   ***************************************************************************/
01325 #if defined(__18CXX)
01326 ROM BYTE* TCPPutROMString(TCP_SOCKET hTCP, ROM BYTE* data)
01327 {
01328     return data + TCPPutROMArray(hTCP, data, strlenpgm((ROM char*)data));
01329 }
01330 #endif
01331
01332 /*****************************************************************************
01333   Function:
01334     WORD TCPGetTxFIFOFull(TCP_SOCKET hTCP)
01335
01336   Description:
01337     Determines how many bytes are pending in the TCP TX FIFO.
01338
01339   Precondition:
01340     TCP is initialized.
01341
01342   Parameters:
01343     hTCP - The socket to check.
01344
01345   Returns:
01346     Number of bytes pending to be flushed in the TCP TX FIFO.
01347   ***************************************************************************/
01348 WORD TCPGetTxFIFOFull(TCP_SOCKET hTCP)
01349 {
01350     WORD wDataLen;
01351     WORD wFIFOSize;
01352
01353     SyncTCBStub(hTCP);
01354
01355     // Calculate total usable FIFO size
01356     wFIFOSize = MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart - 1;
01357
01358     // Find out how many data bytes are free in the TX FIFO
01359     wDataLen = TCPIsPutReady(hTCP);
01360
01361     return wFIFOSize - wDataLen;
01362 }
01363
01364
01365
01366 /****************************************************************************
01367   Section:
01368     Receive Functions
01369   ***************************************************************************/
01370
01371 /*****************************************************************************
01372   Function:
01373     void TCPDiscard(TCP_SOCKET hTCP)
01374
01375   Description:
01376     Discards any pending data in the TCP RX FIFO.
01377
01378   Precondition:
01379     TCP is initialized.
01380
01381   Parameters:
01382     hTCP - The socket whose RX FIFO is to be cleared.
01383
01384   Returns:
01385     None
01386   ***************************************************************************/
01387 void TCPDiscard(TCP_SOCKET hTCP)
01388 {
01389     if(TCPIsGetReady(hTCP))
01390     {
01391         SyncTCBStub(hTCP);
01392
01393         // Delete all data in the RX buffer
01394         MyTCBStub.rxTail = MyTCBStub.rxHead;
01395
01396         // Send a Window update message to the remote node
01397         SendTCP(ACK, SENDTCP_RESET_TIMERS);
01398     }
01399 }
01400
01401
01402 /*****************************************************************************
01403   Function:
01404     void WORD TCPIsGetReady(TCP_SOCKET hTCP)
01405
01406   Summary:
01407     Determines how many bytes can be read from the TCP RX buffer.
01408
01409   Description:
01410     Call this function to determine how many bytes can be read from the
01411     TCP RX buffer.  If this function returns zero, the application must
01412     return to the main stack loop before continuing in order to wait for
01413     more data to arrive.
01414
01415   Precondition:
01416     TCP is initialized.
01417
01418   Parameters:
01419     hTCP - The socket to check.
01420
01421   Returns:
01422     The number of bytes available to be read from the TCP RX buffer.
01423   ***************************************************************************/
01424 WORD TCPIsGetReady(TCP_SOCKET hTCP)
01425 {
01426     SyncTCBStub(hTCP);
01427
01428     if(MyTCBStub.rxHead >= MyTCBStub.rxTail)
01429         return MyTCBStub.rxHead - MyTCBStub.rxTail;
01430     else
01431         return (MyTCBStub.bufferEnd - MyTCBStub.rxTail + 1) + (MyTCBStub.rxHead - MyTCBStub.bufferRxStart);
01432 }
01433
01434
01435 /*****************************************************************************
01436   Function:
01437     BOOL TCPGet(TCP_SOCKET hTCP, BYTE* byte)
01438
01439   Description:
01440     Retrieves a single byte to a TCP socket.
01441
01442   Precondition:
01443     TCP is initialized.
01444
01445   Parameters:
01446     hTCP - The socket from which to read.
01447     byte - Pointer to location in which the read byte should be stored.
01448
01449   Return Values:
01450     TRUE - A byte was read from the buffer.
01451     FALSE - The buffer was empty, or the socket is not connected.
01452   ***************************************************************************/
01453 BOOL TCPGet(TCP_SOCKET hTCP, BYTE* byte)
01454 {
01455     WORD wGetReadyCount;
01456
01457     // See if there is any data which can be read
01458     wGetReadyCount = TCPIsGetReady(hTCP);
01459     if(wGetReadyCount == 0u)
01460         return FALSE;
01461
01462     SyncTCBStub(hTCP);
01463
01464     if(byte)
01465         TCPRAMCopy((PTR_BASE)byte, TCP_PIC_RAM, MyTCBStub.rxTail, MyTCBStub.vMemoryMedium, 1);
01466     if(++MyTCBStub.rxTail > MyTCBStub.bufferEnd)
01467         MyTCBStub.rxTail = MyTCBStub.bufferRxStart;
01468
01469     // Send a window update if we've run out of data
01470     if(wGetReadyCount == 1u)
01471     {
01472         MyTCBStub.Flags.bTXASAPWithoutTimerReset = 1;
01473     }
01474     // If not already enabled, start a timer so a window
01475     // update will get sent to the remote node at some point
01476     else if(!MyTCBStub.Flags.bTimer2Enabled)
01477     {
01478         MyTCBStub.Flags.bTimer2Enabled = TRUE;
01479         MyTCBStub.eventTime2 = (WORD)TickGetDiv256() + TCP_AUTO_TRANSMIT_TIMEOUT_VAL/256ull;
01480     }
01481
01482
01483     return TRUE;
01484 }
01485
01486
01487 /*****************************************************************************
01488   Function:
01489     WORD TCPGetArray(TCP_SOCKET hTCP, BYTE* data, WORD len)
01490
01491   Description:
01492     Reads an array from a TCP socket.
01493
01494   Precondition:
01495     TCP is initialized.
01496
01497   Parameters:
01498     hTCP - The socket from which data is to be read.
01499     data - Pointer to the array to store data that was read.
01500     len  - Number of bytes to be read.
01501
01502   Returns:
01503     The number of bytes read from the socket.  If less than len, the
01504     buffer became empty or the socket is not conected.
01505   ***************************************************************************/
01506 WORD TCPGetArray(TCP_SOCKET hTCP, BYTE* buffer, WORD len)
01507 {
01508     WORD wGetReadyCount;
01509     WORD RightLen = 0;
01510
01511     // See if there is any data which can be read
01512     wGetReadyCount = TCPIsGetReady(hTCP);
01513     if(wGetReadyCount == 0u)
01514         return 0x0000u;
01515
01516     SyncTCBStub(hTCP);
01517
01518     // Make sure we don't try to read more data than is available
01519     if(len > wGetReadyCount)
01520         len = wGetReadyCount;
01521
01522     // See if we need a two part get
01523     if(MyTCBStub.rxTail + len > MyTCBStub.bufferEnd)
01524     {
01525         RightLen = MyTCBStub.bufferEnd - MyTCBStub.rxTail + 1;
01526         if(buffer)
01527         {
01528             TCPRAMCopy((PTR_BASE)buffer, TCP_PIC_RAM, MyTCBStub.rxTail, MyTCBStub.vMemoryMedium, RightLen);
01529             buffer += RightLen;
01530         }
01531         len -= RightLen;
01532         MyTCBStub.rxTail = MyTCBStub.bufferRxStart;
01533     }
01534
01535     if(buffer)
01536         TCPRAMCopy((PTR_BASE)buffer, TCP_PIC_RAM, MyTCBStub.rxTail, MyTCBStub.vMemoryMedium, len);
01537     MyTCBStub.rxTail += len;
01538     len += RightLen;
01539
01540     // Send a window update if we've run low on data
01541     if(wGetReadyCount - len <= len)
01542     {
01543         MyTCBStub.Flags.bTXASAPWithoutTimerReset = 1;
01544     }
01545     else if(!MyTCBStub.Flags.bTimer2Enabled)
01546     // If not already enabled, start a timer so a window
01547     // update will get sent to the remote node at some point
01548     {
01549         MyTCBStub.Flags.bTimer2Enabled = TRUE;
01550         MyTCBStub.eventTime2 = (WORD)TickGetDiv256() + TCP_AUTO_TRANSMIT_TIMEOUT_VAL/256ull;
01551     }
01552
01553     return len;
01554 }
01555
01556
01557 /*****************************************************************************
01558   Function:
01559     WORD TCPGetRxFIFOFree(TCP_SOCKET hTCP)
01560
01561   Description:
01562     Determines how many bytes are free in the RX FIFO.
01563
01564   Precondition:
01565     TCP is initialized.
01566
01567   Parameters:
01568     hTCP - The socket to check.
01569
01570   Returns:
01571     The number of bytes free in the TCP RX FIFO.  If zero, no additional
01572     data can be received until the application removes some data using one
01573     of the TCPGet family functions.
01574   ***************************************************************************/
01575 WORD TCPGetRxFIFOFree(TCP_SOCKET hTCP)
01576 {
01577     WORD wDataLen;
01578     WORD wFIFOSize;
01579
01580     SyncTCBStub(hTCP);
01581
01582     // Calculate total usable FIFO size
01583     wFIFOSize = MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart;
01584
01585     #if defined(STACK_USE_SSL)
01586     {
01587         PTR_BASE SSLtemp = MyTCBStub.rxHead;
01588
01589         // Move SSL pointer to determine full buffer size
01590         if(MyTCBStub.sslStubID != SSL_INVALID_ID)
01591             MyTCBStub.rxHead = MyTCBStub.sslRxHead;
01592
01593         // Find out how many data bytes are actually in the RX FIFO
01594         wDataLen = TCPIsGetReady(hTCP);
01595
01596         // Move SSL pointer back to proper location (if we changed it)
01597         MyTCBStub.rxHead = SSLtemp;
01598     }
01599     #else
01600     {
01601         // Find out how many data bytes are actually in the RX FIFO
01602         wDataLen = TCPIsGetReady(hTCP);
01603     }
01604     #endif
01605
01606     // Perform the calculation
01607     return wFIFOSize - wDataLen;
01608 }
01609
01610
01611
01612 /****************************************************************************
01613   Section:
01614     Search Functions
01615   ***************************************************************************/
01616
01617 /*****************************************************************************
01618   Function:
01619     WORD TCPFindArrayEx(TCP_SOCKET hTCP, BYTE* cFindArray, WORD wLen,
01620                         WORD wStart, WORD wSearchLen, BOOL bTextCompare)
01621
01622   Summary:
01623     Searches for a string in the TCP RX buffer.
01624
01625   Description:
01626     This function finds the first occurrance of an array of bytes in the
01627     TCP RX buffer.  It can be used by an application to abstract searches
01628     out of their own application code.  For increased efficiency, the
01629     function is capable of limiting the scope of search to a specific
01630     range of bytes.  It can also perform a case-insensitive search if
01631     required.
01632
01633     For example, if the buffer contains "I love PIC MCUs!" and the search
01634     array is "love" with a length of 4, a value of 2 will be returned.
01635
01636   Precondition:
01637     TCP is initialized.
01638
01639   Parameters:
01640     hTCP - The socket to search within.
01641     cFindArray - The array of bytes to find in the buffer.
01642     wLen - Length of cFindArray.
01643     wStart - Zero-indexed starting position within the buffer.
01644     wSearchLen - Length from wStart to search in the buffer.
01645     bTextCompare - TRUE for case-insensitive text search, FALSE for binary search
01646
01647   Return Values:
01648     0xFFFF - Search array not found
01649     Otherwise - Zero-indexed position of the first occurrance
01650
01651   Remarks:
01652     Since this function usually must transfer data from external storage
01653     to internal RAM for comparison, its performance degrades significantly
01654     when the buffer is full and the array is not found.  For better
01655     performance, try to search for characters that are expected to exist or
01656     limit the scope of the search as much as possible.  The HTTP2 module,
01657     for example, uses this function to parse headers.  However, it searches
01658     for newlines, then the separating colon, then reads the header name to
01659     RAM for final comparison.  This has proven to be significantly faster
01660     than searching for full header name strings outright.
01661   ***************************************************************************/
01662 WORD TCPFindArrayEx(TCP_SOCKET hTCP, BYTE* cFindArray, WORD wLen, WORD wStart, WORD wSearchLen, BOOL bTextCompare)
01663 {
01664     PTR_BASE ptrRead;
01665     WORD wDataLen;
01666     WORD wBytesUntilWrap;
01667     PTR_BASE ptrLocation;
01668     WORD wLenStart;
01669     BYTE *cFindArrayStart;
01670     BYTE i, j, k;
01671     BOOL isFinding;
01672     BYTE buffer[32];
01673
01674     if(wLen == 0u)
01675         return 0u;
01676
01677     SyncTCBStub(hTCP);
01678
01679     // Find out how many bytes are in the RX FIFO and return
01680     // immediately if we won't possibly find a match
01681     wDataLen = TCPIsGetReady(hTCP) - wStart;
01682     if(wDataLen < wLen)
01683         return 0xFFFFu;
01684     if(wSearchLen && wDataLen > wSearchLen)
01685         wDataLen = wSearchLen;
01686
01687     ptrLocation = MyTCBStub.rxTail + wStart;
01688     if(ptrLocation > MyTCBStub.bufferEnd)
01689         ptrLocation -= MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart + 1;
01690     ptrRead = ptrLocation;
01691     wBytesUntilWrap = MyTCBStub.bufferEnd - ptrLocation + 1;
01692     ptrLocation = wStart;
01693     wLenStart = wLen;
01694     cFindArrayStart = cFindArray;
01695     j = *cFindArray++;
01696     isFinding = FALSE;
01697     if(bTextCompare)
01698     {
01699         if(j >= 'a' && j <= 'z')
01700             j += 'A'-'a';
01701     }
01702
01703     // Search for the array
01704     while(1)
01705     {
01706         // Figure out how big of a chunk to read
01707         k = sizeof(buffer);
01708         if(k > wBytesUntilWrap)
01709             k = wBytesUntilWrap;
01710         if((WORD)k > wDataLen)
01711             k = wDataLen;
01712
01713         // Read a chunk of data into the buffer
01714         TCPRAMCopy((PTR_BASE)buffer, TCP_PIC_RAM, ptrRead, MyTCBStub.vMemoryMedium, (WORD)k);
01715         ptrRead += k;
01716         wBytesUntilWrap -= k;
01717
01718         if(wBytesUntilWrap == 0u)
01719         {
01720             ptrRead = MyTCBStub.bufferRxStart;
01721             wBytesUntilWrap = 0xFFFFu;
01722         }
01723
01724         // Convert everything to uppercase
01725         if(bTextCompare)
01726         {
01727             for(i = 0; i < k; i++)
01728             {
01729                 if(buffer[i] >= 'a' && buffer[i] <= 'z')
01730                     buffer[i] += 'A'-'a';
01731
01732                 if(j == buffer[i])
01733                 {
01734                     if(--wLen == 0u)
01735                         return ptrLocation-wLenStart + i + 1;
01736                     j = *cFindArray++;
01737                     isFinding = TRUE;
01738                     if(j >= 'a' && j <= 'z')
01739                         j += 'A'-'a';
01740                 }
01741                 else
01742                 {
01743                     wLen = wLenStart;
01744                     if(isFinding)
01745                     {
01746                         cFindArray = cFindArrayStart;
01747                         j = *cFindArray++;
01748                         if(j >= 'a' && j <= 'z')
01749                             j += 'A'-'a';
01750                         isFinding = FALSE;
01751                     }
01752                 }
01753             }
01754         }
01755         else    // Compare as is
01756         {
01757             for(i = 0; i < k; i++)
01758             {
01759                 if(j == buffer[i])
01760                 {
01761                     if(--wLen == 0)
01762                         return ptrLocation-wLenStart + i + 1;
01763                     j = *cFindArray++;
01764                     isFinding = TRUE;
01765                 }
01766                 else
01767                 {
01768                     wLen = wLenStart;
01769                     if(isFinding)
01770                     {
01771                         cFindArray = cFindArrayStart;
01772                         j = *cFindArray++;
01773                         isFinding = FALSE;
01774                     }
01775                 }
01776             }
01777         }
01778
01779         // Check to see if it is impossible to find a match
01780         wDataLen -= k;
01781         if(wDataLen < wLen)
01782             return 0xFFFFu;
01783
01784         ptrLocation += k;
01785     }
01786 }
01787
01788 /*****************************************************************************
01789   Function:
01790     WORD TCPFindROMArrayEx(TCP_SOCKET hTCP, BYTE* cFindArray, WORD wLen,
01791                         WORD wStart, WORD wSearchLen, BOOL bTextCompare)
01792
01793   Summary:
01794     Searches for a ROM string in the TCP RX buffer.
01795
01796   Description:
01797     This function finds the first occurrance of an array of bytes in the
01798     TCP RX buffer.  It can be used by an application to abstract searches
01799     out of their own application code.  For increased efficiency, the
01800     function is capable of limiting the scope of search to a specific
01801     range of bytes.  It can also perform a case-insensitive search if
01802     required.
01803
01804     For example, if the buffer contains "I love PIC MCUs!" and the search
01805     array is "love" with a length of 4, a value of 2 will be returned.
01806
01807   Precondition:
01808     TCP is initialized.
01809
01810   Parameters:
01811     hTCP - The socket to search within.
01812     cFindArray - The array of bytes to find in the buffer.
01813     wLen - Length of cFindArray.
01814     wStart - Zero-indexed starting position within the buffer.
01815     wSearchLen - Length from wStart to search in the buffer.
01816     bTextCompare - TRUE for case-insensitive text search, FALSE for binary search
01817
01818   Return Values:
01819     0xFFFF - Search array not found
01820     Otherwise - Zero-indexed position of the first occurrance
01821
01822   Remarks:
01823     Since this function usually must transfer data from external storage
01824     to internal RAM for comparison, its performance degrades significantly
01825     when the buffer is full and the array is not found.  For better
01826     performance, try to search for characters that are expected to exist or
01827     limit the scope of the search as much as possible.  The HTTP2 module,
01828     for example, uses this function to parse headers.  However, it searches
01829     for newlines, then the separating colon, then reads the header name to
01830     RAM for final comparison.  This has proven to be significantly faster
01831     than searching for full header name strings outright.
01832
01833     This function is aliased to TCPFindArrayEx on non-PIC18 platforms.
01834   ***************************************************************************/
01835 #if defined(__18CXX)
01836 WORD TCPFindROMArrayEx(TCP_SOCKET hTCP, ROM BYTE* cFindArray, WORD wLen, WORD wStart, WORD wSearchLen, BOOL bTextCompare)
01837 {
01838     PTR_BASE ptrRead;
01839     WORD wDataLen;
01840     WORD wBytesUntilWrap;
01841     PTR_BASE ptrLocation;
01842     WORD wLenStart;
01843     ROM BYTE *cFindArrayStart;
01844     BYTE i, j, k;
01845     BOOL isFinding;
01846     BYTE buffer[32];
01847
01848     if(wLen == 0u)
01849         return 0u;
01850
01851     SyncTCBStub(hTCP);
01852
01853     // Find out how many bytes are in the RX FIFO and return
01854     // immediately if we won't possibly find a match
01855     wDataLen = TCPIsGetReady(hTCP) - wStart;
01856     if(wDataLen < wLen)
01857         return 0xFFFFu;
01858     if(wSearchLen && wDataLen > wSearchLen)
01859         wDataLen = wSearchLen;
01860
01861     ptrLocation = MyTCBStub.rxTail + wStart;
01862     if(ptrLocation > MyTCBStub.bufferEnd)
01863         ptrLocation -= MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart + 1;
01864     ptrRead = ptrLocation;
01865     wBytesUntilWrap = MyTCBStub.bufferEnd - ptrLocation + 1;
01866     ptrLocation = wStart;
01867     wLenStart = wLen;
01868     cFindArrayStart = cFindArray;
01869     j = *cFindArray++;
01870     isFinding = FALSE;
01871     if(bTextCompare)
01872     {
01873         if(j >= 'a' && j <= 'z')
01874             j += 'A'-'a';
01875     }
01876
01877     // Search for the array
01878     while(1)
01879     {
01880         // Figure out how big of a chunk to read
01881         k = sizeof(buffer);
01882         if(k > wBytesUntilWrap)
01883             k = wBytesUntilWrap;
01884         if((WORD)k > wDataLen)
01885             k = wDataLen;
01886
01887         // Read a chunk of data into the buffer
01888         TCPRAMCopy((PTR_BASE)buffer, TCP_PIC_RAM, ptrRead, MyTCBStub.vMemoryMedium, (WORD)k);
01889         ptrRead += k;
01890         wBytesUntilWrap -= k;
01891
01892         if(wBytesUntilWrap == 0)
01893         {
01894             ptrRead = MyTCBStub.bufferRxStart;
01895             wBytesUntilWrap = 0xFFFFu;
01896         }
01897
01898         // Convert everything to uppercase
01899         if(bTextCompare)
01900         {
01901             for(i = 0; i < k; i++)
01902             {
01903                 if(buffer[i] >= 'a' && buffer[i] <= 'z')
01904                     buffer[i] += 'A'-'a';
01905
01906                 if(j == buffer[i])
01907                 {
01908                     if(--wLen == 0u)
01909                         return ptrLocation-wLenStart + i + 1;
01910                     j = *cFindArray++;
01911                     isFinding = TRUE;
01912                     if(j >= 'a' && j <= 'z')
01913                         j += 'A'-'a';
01914                 }
01915                 else
01916                 {
01917                     wLen = wLenStart;
01918                     if(isFinding)
01919                     {
01920                         cFindArray = cFindArrayStart;
01921                         j = *cFindArray++;
01922                         if(j >= 'a' && j <= 'z')
01923                             j += 'A'-'a';
01924                         isFinding = FALSE;
01925                     }
01926                 }
01927             }
01928         }
01929         else    // Compare as is
01930         {
01931             for(i = 0; i < k; i++)
01932             {
01933                 if(j == buffer[i])
01934                 {
01935                     if(--wLen == 0)
01936                         return ptrLocation-wLenStart + i + 1;
01937                     j = *cFindArray++;
01938                     isFinding = TRUE;
01939                 }
01940                 else
01941                 {
01942                     wLen = wLenStart;
01943                     if(isFinding)
01944                     {
01945                         cFindArray = cFindArrayStart;
01946                         j = *cFindArray++;
01947                         isFinding = FALSE;
01948                     }
01949                 }
01950             }
01951         }
01952
01953         // Check to see if it is impossible to find a match
01954         wDataLen -= k;
01955         if(wDataLen < wLen)
01956             return 0xFFFFu;
01957
01958         ptrLocation += k;
01959     }
01960 }
01961 #endif
01962
01963
01964 /*****************************************************************************
01965   Function:
01966     WORD TCPFindEx(TCP_SOCKET hTCP, BYTE cFind,
01967                         WORD wStart, WORD wSearchLen, BOOL bTextCompare)
01968
01969   Summary:
01970     Searches for a byte in the TCP RX buffer.
01971
01972   Description:
01973     This function finds the first occurrance of a byte in the TCP RX
01974     buffer.  It can be used by an application to abstract searches
01975     out of their own application code.  For increased efficiency, the
01976     function is capable of limiting the scope of search to a specific
01977     range of bytes.  It can also perform a case-insensitive search if
01978     required.
01979
01980     For example, if the buffer contains "I love PIC MCUs!" and the cFind
01981     byte is ' ', a value of 1 will be returned.
01982
01983   Precondition:
01984     TCP is initialized.
01985
01986   Parameters:
01987     hTCP - The socket to search within.
01988     cFind - The byte to find in the buffer.
01989     wStart - Zero-indexed starting position within the buffer.
01990     wSearchLen - Length from wStart to search in the buffer.
01991     bTextCompare - TRUE for case-insensitive text search, FALSE for binary search
01992
01993   Return Values:
01994     0xFFFF - Search array not found
01995     Otherwise - Zero-indexed position of the first occurrance
01996
01997   Remarks:
01998     Since this function usually must transfer data from external storage
01999     to internal RAM for comparison, its performance degrades significantly
02000     when the buffer is full and the array is not found.  For better
02001     performance, try to search for characters that are expected to exist or
02002     limit the scope of the search as much as possible.  The HTTP2 module,
02003     for example, uses this function to parse headers.  However, it searches
02004     for newlines, then the separating colon, then reads the header name to
02005     RAM for final comparison.  This has proven to be significantly faster
02006     than searching for full header name strings outright.
02007   ***************************************************************************/
02008 WORD TCPFindEx(TCP_SOCKET hTCP, BYTE cFind, WORD wStart, WORD wSearchLen, BOOL bTextCompare)
02009 {
02010     return TCPFindArrayEx(hTCP, &cFind, sizeof(cFind), wStart, wSearchLen, bTextCompare);
02011 }
02012
02013
02014
02015 /****************************************************************************
02016   Section:
02017     Data Processing Functions
02018   ***************************************************************************/
02019
02020 /*****************************************************************************
02021   Function:
02022     void TCPTick(void)
02023
02024   Summary:
02025     Performs periodic TCP tasks.
02026
02027   Description:
02028     This function performs any required periodic TCP tasks.  Each
02029     socket's state machine is checked, and any elapsed timeout periods
02030     are handled.
02031
02032   Precondition:
02033     TCP is initialized.
02034
02035   Parameters:
02036     None
02037
02038   Returns:
02039     None
02040   ***************************************************************************/
02041 void TCPTick(void)
02042 {
02043     TCP_SOCKET hTCP;
02044     BOOL bRetransmit;
02045     BOOL bCloseSocket;
02046     BYTE vFlags;
02047     WORD w;
02048
02049     // Periodically all "not closed" sockets must perform timed operations
02050     for(hTCP = 0; hTCP < TCP_SOCKET_COUNT; hTCP++)
02051     {
02052         SyncTCBStub(hTCP);
02053
02054         // Handle any SSL Processing and Message Transmission
02055         #if defined(STACK_USE_SSL)
02056         if(MyTCBStub.sslStubID != SSL_INVALID_ID)
02057         {
02058             // Handle any periodic tasks, such as RSA operations
02059             SSLPeriodic(hTCP, MyTCBStub.sslStubID);
02060
02061             // If unsent data is waiting, transmit it as an application record
02062             if(MyTCBStub.sslTxHead != MyTCBStub.txHead && TCPSSLGetPendingTxSize(hTCP) != 0)
02063                 SSLTxRecord(hTCP, MyTCBStub.sslStubID, SSL_APPLICATION);
02064
02065             // If an SSL message is requested, send it now
02066             if(MyTCBStub.sslReqMessage != SSL_NO_MESSAGE)
02067                 SSLTxMessage(hTCP, MyTCBStub.sslStubID, MyTCBStub.sslReqMessage);
02068         }
02069         #endif
02070
02071         vFlags = 0x00;
02072         bRetransmit = FALSE;
02073         bCloseSocket = FALSE;
02074
02075         // Transmit ASAP data if the medium is available
02076         if(MyTCBStub.Flags.bTXASAP || MyTCBStub.Flags.bTXASAPWithoutTimerReset)
02077         {
02078             if(MACIsTxReady())
02079             {
02080                 vFlags = ACK;
02081                 bRetransmit = MyTCBStub.Flags.bTXASAPWithoutTimerReset;
02082             }
02083         }
02084
02085         // Perform any needed window updates and data transmissions
02086         if(MyTCBStub.Flags.bTimer2Enabled)
02087         {
02088             // See if the timeout has occured, and we need to send a new window update and pending data
02089             if((SHORT)(MyTCBStub.eventTime2 - (WORD)TickGetDiv256()) <= (SHORT)0)
02090                 vFlags = ACK;
02091         }
02092
02093         // Process Delayed ACKnowledgement timer
02094         if(MyTCBStub.Flags.bDelayedACKTimerEnabled)
02095         {
02096             // See if the timeout has occured and delayed ACK needs to be sent
02097             if((SHORT)(MyTCBStub.OverlappedTimers.delayedACKTime - (WORD)TickGetDiv256()) <= (SHORT)0)
02098                 vFlags = ACK;
02099         }
02100
02101         // Process TCP_CLOSE_WAIT timer
02102         if(MyTCBStub.smState == TCP_CLOSE_WAIT)
02103         {
02104             // Automatically close the socket on our end if the application
02105             // fails to call TCPDisconnect() is a reasonable amount of time.
02106             if((SHORT)(MyTCBStub.OverlappedTimers.closeWaitTime - (WORD)TickGetDiv256()) <= (SHORT)0)
02107             {
02108                 vFlags = FIN | ACK;
02109                 MyTCBStub.smState = TCP_LAST_ACK;
02110             }
02111         }
02112
02113         // Process listening server sockets that might have a SYN waiting in the SYNQueue[]
02114         #if TCP_SYN_QUEUE_MAX_ENTRIES
02115             if(MyTCBStub.smState == TCP_LISTEN)
02116             {
02117                 for(w = 0; w < TCP_SYN_QUEUE_MAX_ENTRIES; w++)
02118                 {
02119                     // Abort search if there are no more valid records
02120                     if(SYNQueue[w].wDestPort == 0u)
02121                         break;
02122
02123                     // Stop searching if this SYN queue entry can be used by this socket
02124                     #if defined(STACK_USE_SSL_SERVER)
02125                     if(SYNQueue[w].wDestPort == MyTCBStub.remoteHash.Val || SYNQueue[w].wDestPort == MyTCBStub.sslTxHead)
02126                     #else
02127                     if(SYNQueue[w].wDestPort == MyTCBStub.remoteHash.Val)
02128                     #endif
02129                     {
02130                         // Set up our socket and generate a reponse SYN+ACK packet
02131                         SyncTCB();
02132
02133                         #if defined(STACK_USE_SSL_SERVER)
02134                         // If this matches the SSL port, make sure that can be configured
02135                         // before continuing.  If not, break and leave this in the queue
02136                         if(SYNQueue[w].wDestPort == MyTCBStub.sslTxHead && !TCPStartSSLServer(hTCP))
02137                             break;
02138                         #endif
02139
02140                         memcpy((void*)&MyTCB.remote.niRemoteMACIP, (void*)&SYNQueue[w].niSourceAddress, sizeof(NODE_INFO));
02141                         MyTCB.remotePort.Val = SYNQueue[w].wSourcePort;
02142                         MyTCB.RemoteSEQ = SYNQueue[w].dwSourceSEQ + 1;
02143                         MyTCBStub.remoteHash.Val = (MyTCB.remote.niRemoteMACIP.IPAddr.w[1] + MyTCB.remote.niRemoteMACIP.IPAddr.w[0] + MyTCB.remotePort.Val) ^ MyTCB.localPort.Val;
02144                         vFlags = SYN | ACK;
02145                         MyTCBStub.smState = TCP_SYN_RECEIVED;
02146
02147                         // Delete this SYN from the SYNQueue and compact the SYNQueue[] array
02148                         TCPRAMCopy((PTR_BASE)&SYNQueue[w], TCP_PIC_RAM, (PTR_BASE)&SYNQueue[w+1], TCP_PIC_RAM, (TCP_SYN_QUEUE_MAX_ENTRIES-1u-w)*sizeof(TCP_SYN_QUEUE));
02149                         SYNQueue[TCP_SYN_QUEUE_MAX_ENTRIES-1].wDestPort = 0u;
02150
02151                         break;
02152                     }
02153                 }
02154             }
02155         #endif
02156
02157         if(vFlags)
02158             SendTCP(vFlags, bRetransmit ? 0 : SENDTCP_RESET_TIMERS);
02159
02160         // The TCP_CLOSED, TCP_LISTEN, and sometimes the TCP_ESTABLISHED
02161         // state don't need any timeout events, so see if the timer is enabled
02162         if(!MyTCBStub.Flags.bTimerEnabled)
02163         {
02164             #if defined(TCP_KEEP_ALIVE_TIMEOUT)
02165                 // Only the established state has any use for keep-alives
02166                 if(MyTCBStub.smState == TCP_ESTABLISHED)
02167                 {
02168                     // If timeout has not occured, do not do anything.
02169                     if((LONG)(TickGet() - MyTCBStub.eventTime) < (LONG)0)
02170                         continue;
02171
02172                     // If timeout has occured and the connection appears to be dead (no
02173                     // responses from remote node at all), close the connection so the
02174                     // application doesn't sit around indefinitely with a useless socket
02175                     // that it thinks is still open
02176                     if(MyTCBStub.Flags.vUnackedKeepalives == TCP_MAX_UNACKED_KEEP_ALIVES)
02177                     {
02178                         vFlags = MyTCBStub.Flags.bServer;
02179
02180                         // Force an immediate FIN and RST transmission
02181                         // Double calling TCPDisconnect() will also place us
02182                         // back in the listening state immediately if a server socket.
02183                         TCPDisconnect(hTCP);
02184                         TCPDisconnect(hTCP);
02185
02186                         // Prevent client mode sockets from getting reused by other applications.
02187                         // The application must call TCPDisconnect() with the handle to free this
02188                         // socket (and the handle associated with it)
02189                         if(!vFlags)
02190                             MyTCBStub.smState = TCP_CLOSED_BUT_RESERVED;
02191
02192                         continue;
02193                     }
02194
02195                     // Otherwise, if a timeout occured, simply send a keep-alive packet
02196                     SyncTCB();
02197                     SendTCP(ACK, SENDTCP_KEEP_ALIVE);
02198                     MyTCBStub.eventTime = TickGet() + TCP_KEEP_ALIVE_TIMEOUT;
02199                 }
02200             #endif
02201             continue;
02202         }
02203
02204         // If timeout has not occured, do not do anything.
02205         if((LONG)(TickGet() - MyTCBStub.eventTime) < (LONG)0)
02206             continue;
02207
02208         // Load up extended TCB information
02209         SyncTCB();
02210
02211         // A timeout has occured.  Respond to this timeout condition
02212         // depending on what state this socket is in.
02213         switch(MyTCBStub.smState)
02214         {
02215             #if defined(STACK_CLIENT_MODE)
02216             #if defined(STACK_USE_DNS)
02217             case TCP_GET_DNS_MODULE:
02218                 if(DNSBeginUsage())
02219                 {
02220                     MyTCBStub.smState = TCP_DNS_RESOLVE;
02221                     #if defined(__C30__)
02222                         DNSResolve((BYTE*)(WORD)MyTCB.remote.dwRemoteHost, DNS_TYPE_A);
02223                     #else
02224                         if(MyTCB.flags.bRemoteHostIsROM)
02225                             DNSResolveROM((ROM BYTE*)MyTCB.remote.dwRemoteHost, DNS_TYPE_A);
02226                         else
02227                             DNSResolve((BYTE*)MyTCB.remote.dwRemoteHost, DNS_TYPE_A);
02228                     #endif
02229                 }
02230                 break;
02231
02232             case TCP_DNS_RESOLVE:
02233                 if(DNSIsResolved(&MyTCB.remote.niRemoteMACIP.IPAddr))
02234                 {
02235                     if(DNSEndUsage())
02236                     {
02237                         MyTCBStub.smState = TCP_GATEWAY_SEND_ARP;
02238                         MyTCBStub.remoteHash.Val = (MyTCB.remote.niRemoteMACIP.IPAddr.w[1]+MyTCB.remote.niRemoteMACIP.IPAddr.w[0] + MyTCB.remotePort.Val) ^ MyTCB.localPort.Val;
02239                         MyTCB.retryCount = 0;
02240                         MyTCB.retryInterval = (TICK_SECOND/4)/256;
02241                     }
02242                     else
02243                     {
02244                         MyTCBStub.eventTime = TickGet() + 10*TICK_SECOND;
02245                         MyTCBStub.smState = TCP_GET_DNS_MODULE;
02246                     }
02247                 }
02248                 break;
02249             #endif // #if defined(STACK_USE_DNS)
02250
02251             case TCP_GATEWAY_SEND_ARP:
02252                 // Obtain the MAC address associated with the server's IP address (either direct MAC address on same subnet, or the MAC address of the Gateway machine)
02253                 MyTCBStub.eventTime2 = TickGetDiv256();
02254                 ARPResolve(&MyTCB.remote.niRemoteMACIP.IPAddr);
02255                 MyTCBStub.smState = TCP_GATEWAY_GET_ARP;
02256                 break;
02257
02258             case TCP_GATEWAY_GET_ARP:
02259                 // Wait for the MAC address to finish being obtained
02260                 if(!ARPIsResolved(&MyTCB.remote.niRemoteMACIP.IPAddr, &MyTCB.remote.niRemoteMACIP.MACAddr))
02261                 {
02262                     // Time out if too much time is spent in this state
02263                     // Note that this will continuously send out ARP
02264                     // requests for an infinite time if the Gateway
02265                     // never responds
02266                     if(TickGetDiv256() - MyTCBStub.eventTime2 > MyTCB.retryInterval)
02267                     {
02268                         // Exponentially increase timeout until we reach 6 attempts then stay constant
02269                         if(MyTCB.retryCount < 6)
02270                         {
02271                             MyTCB.retryCount++;
02272                             MyTCB.retryInterval <<= 1;
02273                         }
02274
02275                         // Retransmit ARP request
02276                         MyTCBStub.smState = TCP_GATEWAY_SEND_ARP;
02277                     }
02278                     break;
02279                 }
02280
02281                 // Send out SYN connection request to remote node
02282                 // This automatically disables the Timer from
02283                 // continuously firing for this socket
02284                 vFlags = SYN;
02285                 bRetransmit = FALSE;
02286                 MyTCBStub.smState = TCP_SYN_SENT;
02287                 break;
02288             #endif // #if defined(STACK_CLIENT_MODE)
02289
02290             case TCP_SYN_SENT:
02291                 // Keep sending SYN until we hear from remote node.
02292                 // This may be for infinite time, in that case
02293                 // caller must detect it and do something.
02294                 vFlags = SYN;
02295                 bRetransmit = TRUE;
02296                 break;
02297
02298             case TCP_SYN_RECEIVED:
02299                 // We must receive ACK before timeout expires.
02300                 // If not, resend SYN+ACK.
02301                 // Abort, if maximum attempts counts are reached.
02302                 if(MyTCB.retryCount < TCP_MAX_SYN_RETRIES)
02303                 {
02304                     vFlags = SYN | ACK;
02305                     bRetransmit = TRUE;
02306                 }
02307                 else
02308                 {
02309                     if(MyTCBStub.Flags.bServer)
02310                     {
02311                         vFlags = RST | ACK;
02312                         bCloseSocket = TRUE;
02313                     }
02314                     else
02315                     {
02316                         vFlags = SYN;
02317                     }
02318                 }
02319                 break;
02320
02321             case TCP_ESTABLISHED:
02322             case TCP_CLOSE_WAIT:
02323                 // Retransmit any unacknowledged data
02324                 if(MyTCB.retryCount < TCP_MAX_RETRIES)
02325                 {
02326                     vFlags = ACK;
02327                     bRetransmit = TRUE;
02328                 }
02329                 else
02330                 {
02331                     // No response back for too long, close connection
02332                     // This could happen, for instance, if the communication
02333                     // medium was lost
02334                     MyTCBStub.smState = TCP_FIN_WAIT_1;
02335                     vFlags = FIN | ACK;
02336                 }
02337                 break;
02338
02339             case TCP_FIN_WAIT_1:
02340                 if(MyTCB.retryCount < TCP_MAX_RETRIES)
02341                 {
02342                     // Send another FIN
02343                     vFlags = FIN | ACK;
02344                     bRetransmit = TRUE;
02345                 }
02346                 else
02347                 {
02348                     // Close on our own, we can't seem to communicate
02349                     // with the remote node anymore
02350                     vFlags = RST | ACK;
02351                     bCloseSocket = TRUE;
02352                 }
02353                 break;
02354
02355             case TCP_FIN_WAIT_2:
02356                 // Close on our own, we can't seem to communicate
02357                 // with the remote node anymore
02358                 vFlags = RST | ACK;
02359                 bCloseSocket = TRUE;
02360                 break;
02361
02362             case TCP_CLOSING:
02363                 if(MyTCB.retryCount < TCP_MAX_RETRIES)
02364                 {
02365                     // Send another ACK+FIN (the FIN is retransmitted
02366                     // automatically since it hasn't been acknowledged by
02367                     // the remote node yet)
02368                     vFlags = ACK;
02369                     bRetransmit = TRUE;
02370                 }
02371                 else
02372                 {
02373                     // Close on our own, we can't seem to communicate
02374                     // with the remote node anymore
02375                     vFlags = RST | ACK;
02376                     bCloseSocket = TRUE;
02377                 }
02378                 break;
02379
02380 //          case TCP_TIME_WAIT:
02381 //              // Wait around for a while (2MSL) and then goto closed state
02382 //              bCloseSocket = TRUE;
02383 //              break;
02384 //
02385
02386             case TCP_LAST_ACK:
02387                 // Send some more FINs or close anyway
02388                 if(MyTCB.retryCount < TCP_MAX_RETRIES)
02389                 {
02390                     vFlags = FIN | ACK;
02391                     bRetransmit = TRUE;
02392                 }
02393                 else
02394                 {
02395                     vFlags = RST | ACK;
02396                     bCloseSocket = TRUE;
02397                 }
02398                 break;
02399
02400             default:
02401                 break;
02402         }
02403
02404         if(vFlags)
02405         {
02406             if(bRetransmit)
02407             {
02408                 // Set the appropriate retry time
02409                 MyTCB.retryCount++;
02410                 MyTCB.retryInterval <<= 1;
02411
02412                 // Transmit all unacknowledged data over again
02413                 // Roll back unacknowledged TX tail pointer to cause retransmit to occur
02414                 MyTCB.MySEQ -= (LONG)(SHORT)(MyTCB.txUnackedTail - MyTCBStub.txTail);
02415                 if(MyTCB.txUnackedTail < MyTCBStub.txTail)
02416                     MyTCB.MySEQ -= (LONG)(SHORT)(MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart);
02417                 MyTCB.txUnackedTail = MyTCBStub.txTail;
02418                 SendTCP(vFlags, 0);
02419             }
02420             else
02421                 SendTCP(vFlags, SENDTCP_RESET_TIMERS);
02422
02423         }
02424
02425         if(bCloseSocket)
02426             CloseSocket();
02427     }
02428
02429
02430     #if TCP_SYN_QUEUE_MAX_ENTRIES
02431         // Process SYN Queue entry timeouts
02432         for(w = 0; w < TCP_SYN_QUEUE_MAX_ENTRIES; w++)
02433         {
02434             // Abort search if there are no more valid records
02435             if(SYNQueue[w].wDestPort == 0u)
02436                 break;
02437
02438             // See if this SYN has timed out
02439             if((WORD)TickGetDiv256() - SYNQueue[w].wTimestamp > (WORD)(TCP_SYN_QUEUE_TIMEOUT/256ull))
02440             {
02441                 // Delete this SYN from the SYNQueue and compact the SYNQueue[] array
02442                 TCPRAMCopy((PTR_BASE)&SYNQueue[w], TCP_PIC_RAM, (PTR_BASE)&SYNQueue[w+1], TCP_PIC_RAM, (TCP_SYN_QUEUE_MAX_ENTRIES-1u-w)*sizeof(TCP_SYN_QUEUE));
02443                 SYNQueue[TCP_SYN_QUEUE_MAX_ENTRIES-1].wDestPort = 0u;
02444
02445                 // Since we deleted an entry, we need to roll back one
02446                 // index so next loop will process the correct record
02447                 w--;
02448             }
02449         }
02450     #endif
02451 }
02452
02453
02454 /*****************************************************************************
02455   Function:
02456     BOOL TCPProcess(NODE_INFO* remote, IP_ADDR* localIP, WORD len)
02457
02458   Summary:
02459     Handles incoming TCP segments.
02460
02461   Description:
02462     This function handles incoming TCP segments.  When a segment arrives, it
02463     is compared to open sockets using a hash of the remote port and IP.
02464     On a match, the data is passed to HandleTCPSeg for further processing.
02465
02466   Precondition:
02467     TCP is initialized and a TCP segment is ready in the MAC buffer.
02468
02469   Parameters:
02470     remote - Remote NODE_INFO structure
02471     localIP - This stack's IP address (for header checking)
02472     len - Total length of the waiting TCP segment
02473
02474   Return Values:
02475     TRUE - the segment was properly handled.
02476     FALSE - otherwise
02477   ***************************************************************************/
02478 BOOL TCPProcess(NODE_INFO* remote, IP_ADDR* localIP, WORD len)
02479 {
02480     TCP_HEADER      TCPHeader;
02481     PSEUDO_HEADER   pseudoHeader;
02482     WORD_VAL        checksum1;
02483     WORD_VAL        checksum2;
02484     BYTE            optionsSize;
02485
02486     // Calculate IP pseudoheader checksum.
02487     pseudoHeader.SourceAddress      = remote->IPAddr;
02488     pseudoHeader.DestAddress        = *localIP;
02489     pseudoHeader.Zero               = 0x0;
02490     pseudoHeader.Protocol           = IP_PROT_TCP;
02491     pseudoHeader.Length             = len;
02492
02493     SwapPseudoHeader(pseudoHeader);
02494
02495     checksum1.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader,
02496         sizeof(pseudoHeader));
02497
02498     // Now calculate TCP packet checksum in NIC RAM - should match
02499     // pesudo header checksum
02500     checksum2.Val = CalcIPBufferChecksum(len);
02501
02502     // Compare checksums.
02503     if(checksum1.Val != checksum2.Val)
02504     {
02505         MACDiscardRx();
02506         return TRUE;
02507     }
02508
02509 #if defined(DEBUG_GENERATE_RX_LOSS)
02510     // Throw RX packets away randomly
02511     if(rand() > DEBUG_GENERATE_RX_LOSS)
02512     {
02513         MACDiscardRx();
02514         return TRUE;
02515     }
02516 #endif
02517
02518     // Retrieve TCP header.
02519     IPSetRxBuffer(0);
02520     MACGetArray((BYTE*)&TCPHeader, sizeof(TCPHeader));
02521     SwapTCPHeader(&TCPHeader);
02522
02523
02524     // Skip over options to retrieve data bytes
02525     optionsSize = (BYTE)((TCPHeader.DataOffset.Val << 2)-
02526         sizeof(TCPHeader));
02527     len = len - optionsSize - sizeof(TCPHeader);
02528
02529     // Find matching socket.
02530     if(FindMatchingSocket(&TCPHeader, remote))
02531     {
02532         #if defined(STACK_USE_SSL)
02533         PTR_BASE prevRxHead = 0;
02534         // For SSL connections, show HandleTCPSeg() the full data buffer
02535         if(MyTCBStub.sslStubID != SSL_INVALID_ID)
02536         {
02537             prevRxHead = MyTCBStub.rxHead;
02538             MyTCBStub.rxHead = MyTCBStub.sslRxHead;
02539         }
02540         #endif
02541
02542         HandleTCPSeg(&TCPHeader, len);
02543
02544         #if defined(STACK_USE_SSL)
02545         if(MyTCBStub.sslStubID != SSL_INVALID_ID)
02546         {
02547             // Restore the buffer state
02548             MyTCBStub.sslRxHead = MyTCBStub.rxHead;
02549             MyTCBStub.rxHead = prevRxHead;
02550
02551             // Process the new SSL data, using the currently loaded stub
02552             TCPSSLHandleIncoming(hCurrentTCP);
02553         }
02554         #endif
02555     }
02556 //  else
02557 //  {
02558 //      // \TODO: RFC 793 specifies that if the socket is closed
02559 //      // and a segment arrives, we should send back a RST if
02560 //      // the RST bit in the incoming packet is not set.  The
02561 //      // code to respond with the RST packet and believable SEQ
02562 //      // and ACK numbers needs to be implemented.
02563 //      //if(!TCPHeader.Flags.bits.flagRST)
02564 //      //  SendTCP(RST, SENDTCP_RESET_TIMERS);
02565 //  }
02566
02567     // Finished with this packet, discard it and free the Ethernet RAM for new packets
02568     MACDiscardRx();
02569
02570     return TRUE;
02571 }
02572
02573
02574 /*****************************************************************************
02575   Function:
02576     static void SendTCP(BYTE vTCPFlags, BYTE vSendFlags)
02577
02578   Summary:
02579     Transmits a TPC segment.
02580
02581   Description:
02582     This function assembles and transmits a TCP segment, including any
02583     pending data.  It also supports retransmissions, keep-alives, and
02584     other packet types.
02585
02586   Precondition:
02587     TCP is initialized.
02588
02589   Parameters:
02590     vTCPFlags - Additional TCP flags to include
02591     vSendFlags - Any combinations of SENDTCP_* constants to modify the
02592                  transmit behavior or contents.
02593
02594   Returns:
02595     None
02596   ***************************************************************************/
02597 static void SendTCP(BYTE vTCPFlags, BYTE vSendFlags)
02598 {
02599     WORD_VAL        wVal;
02600     TCP_HEADER      header;
02601     TCP_OPTIONS     options;
02602     PSEUDO_HEADER   pseudoHeader;
02603     WORD            len;
02604     WORD            wEffectiveWindow;
02605
02606     SyncTCB();
02607
02608     // FINs must be handled specially
02609     if(vTCPFlags & FIN)
02610     {
02611         MyTCBStub.Flags.bTXFIN = 1;
02612         vTCPFlags &= ~FIN;
02613     }
02614
02615     // Status will now be synched, disable automatic future
02616     // status transmissions
02617     MyTCBStub.Flags.bTimer2Enabled = 0;
02618     MyTCBStub.Flags.bDelayedACKTimerEnabled = 0;
02619     MyTCBStub.Flags.bOneSegmentReceived = 0;
02620     MyTCBStub.Flags.bTXASAP = 0;
02621     MyTCBStub.Flags.bTXASAPWithoutTimerReset = 0;
02622     MyTCBStub.Flags.bHalfFullFlush = 0;
02623
02624     //  Make sure that we can write to the MAC transmit area
02625     while(!IPIsTxReady());
02626
02627     // Put all socket application data in the TX space
02628     if(vTCPFlags & (SYN | RST))
02629     {
02630         // Don't put any data in SYN and RST messages
02631         len = 0;
02632     }
02633     else
02634     {
02635         // Begin copying any application data over to the TX space
02636         if(MyTCBStub.txHead == MyTCB.txUnackedTail)
02637         {
02638             // All caught up on data TX, no real data for this packet
02639             len = 0;
02640
02641             // If we are to transmit a FIN, make sure we can put one in this packet
02642             if(MyTCBStub.Flags.bTXFIN)
02643             {
02644                 if(MyTCB.remoteWindow)
02645                     vTCPFlags |= FIN;
02646             }
02647         }
02648         else if(MyTCBStub.txHead > MyTCB.txUnackedTail)
02649         {
02650             len = MyTCBStub.txHead - MyTCB.txUnackedTail;
02651             wEffectiveWindow = MyTCB.remoteWindow;
02652             if(MyTCB.txUnackedTail >= MyTCBStub.txTail)
02653                 wEffectiveWindow -= MyTCB.txUnackedTail - MyTCBStub.txTail;
02654             else
02655                 wEffectiveWindow -= (MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart) - (MyTCBStub.txTail - MyTCB.txUnackedTail);
02656
02657             if(len > wEffectiveWindow)
02658                 len = wEffectiveWindow;
02659
02660             if(len > TCP_MAX_SEG_SIZE)
02661             {
02662                 len = TCP_MAX_SEG_SIZE;
02663                 MyTCBStub.Flags.bTXASAPWithoutTimerReset = 1;
02664             }
02665
02666             // If we are to transmit a FIN, make sure we can put one in this packet
02667             if(MyTCBStub.Flags.bTXFIN)
02668             {
02669                 if((len != wEffectiveWindow) && (len != TCP_MAX_SEG_SIZE))
02670                     vTCPFlags |= FIN;
02671             }
02672
02673             // Copy application data into the raw TX buffer
02674             TCPRAMCopy(BASE_TX_ADDR+sizeof(ETHER_HEADER)+sizeof(IP_HEADER)+sizeof(TCP_HEADER), TCP_ETH_RAM, MyTCB.txUnackedTail, MyTCBStub.vMemoryMedium, len);
02675             MyTCB.txUnackedTail += len;
02676         }
02677         else
02678         {
02679             pseudoHeader.Length = MyTCBStub.bufferRxStart - MyTCB.txUnackedTail;
02680             len = pseudoHeader.Length + MyTCBStub.txHead - MyTCBStub.bufferTxStart;
02681
02682             wEffectiveWindow = MyTCB.remoteWindow;
02683             if(MyTCB.txUnackedTail >= MyTCBStub.txTail)
02684                 wEffectiveWindow -= MyTCB.txUnackedTail - MyTCBStub.txTail;
02685             else
02686                 wEffectiveWindow -= (MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart) - (MyTCBStub.txTail - MyTCB.txUnackedTail);
02687
02688             if(len > wEffectiveWindow)
02689                 len = wEffectiveWindow;
02690
02691             if(len > TCP_MAX_SEG_SIZE)
02692             {
02693                 len = TCP_MAX_SEG_SIZE;
02694                 MyTCBStub.Flags.bTXASAPWithoutTimerReset = 1;
02695             }
02696
02697             // If we are to transmit a FIN, make sure we can put one in this packet
02698             if(MyTCBStub.Flags.bTXFIN)
02699             {
02700                 if((len != wEffectiveWindow) && (len != TCP_MAX_SEG_SIZE))
02701                     vTCPFlags |= FIN;
02702             }
02703
02704             if(pseudoHeader.Length > len)
02705                 pseudoHeader.Length = len;
02706
02707             // Copy application data into the raw TX buffer
02708             TCPRAMCopy(BASE_TX_ADDR+sizeof(ETHER_HEADER)+sizeof(IP_HEADER)+sizeof(TCP_HEADER), TCP_ETH_RAM, MyTCB.txUnackedTail, MyTCBStub.vMemoryMedium, pseudoHeader.Length);
02709             pseudoHeader.Length = len - pseudoHeader.Length;
02710
02711             // Copy any left over chunks of application data over
02712             if(pseudoHeader.Length)
02713             {
02714                 TCPRAMCopy(BASE_TX_ADDR+sizeof(ETHER_HEADER)+sizeof(IP_HEADER)+sizeof(TCP_HEADER)+(MyTCBStub.bufferRxStart-MyTCB.txUnackedTail), TCP_ETH_RAM, MyTCBStub.bufferTxStart, MyTCBStub.vMemoryMedium, pseudoHeader.Length);
02715             }
02716
02717             MyTCB.txUnackedTail += len;
02718             if(MyTCB.txUnackedTail >= MyTCBStub.bufferRxStart)
02719                 MyTCB.txUnackedTail -= MyTCBStub.bufferRxStart-MyTCBStub.bufferTxStart;
02720         }
02721     }
02722
02723     // Ensure that all packets with data of some kind are
02724     // retransmitted by TCPTick() until acknowledged
02725     // Pure ACK packets with no data are not ACKed back in TCP
02726     if(len || (vTCPFlags & (SYN | FIN)))
02727     {
02728         // Push (PSH) all data for enhanced responsiveness on
02729         // the remote end, especially with GUIs
02730         if(len)
02731             vTCPFlags |= PSH;
02732
02733         if(vSendFlags & SENDTCP_RESET_TIMERS)
02734         {
02735             MyTCB.retryCount = 0;
02736             MyTCB.retryInterval = TCP_START_TIMEOUT_VAL;
02737         }
02738
02739         MyTCBStub.eventTime = TickGet() + MyTCB.retryInterval;
02740         MyTCBStub.Flags.bTimerEnabled = 1;
02741     }
02742     else if(vSendFlags & SENDTCP_KEEP_ALIVE)
02743     {
02744         // Increment Keep Alive TX counter to handle disconnection if not response is returned
02745         MyTCBStub.Flags.vUnackedKeepalives++;
02746
02747         // Generate a dummy byte
02748         MyTCB.MySEQ -= 1;
02749         len = 1;
02750     }
02751     else if(MyTCBStub.Flags.bTimerEnabled)
02752     {
02753         // If we have data to transmit, but the remote RX window is zero,
02754         // so we aren't transmitting any right now then make sure to not
02755         // extend the retry counter or timer.  This will stall our TX
02756         // with a periodic ACK sent to the remote node.
02757         if(!(vSendFlags & SENDTCP_RESET_TIMERS))
02758         {
02759             // Roll back retry counters since we can't send anything
02760             MyTCB.retryCount--;
02761             MyTCB.retryInterval >>= 1;
02762         }
02763
02764         MyTCBStub.eventTime = TickGet() + MyTCB.retryInterval;
02765     }
02766
02767
02768     header.SourcePort           = MyTCB.localPort.Val;
02769     header.DestPort             = MyTCB.remotePort.Val;
02770     header.SeqNumber            = MyTCB.MySEQ;
02771     header.AckNumber            = MyTCB.RemoteSEQ;
02772     header.Flags.bits.Reserved2 = 0;
02773     header.DataOffset.Reserved3 = 0;
02774     header.Flags.byte           = vTCPFlags;
02775     header.UrgentPointer        = 0;
02776
02777     // Update our send sequence number and ensure retransmissions
02778     // of SYNs and FINs use the right sequence number
02779     MyTCB.MySEQ += (DWORD)len;
02780     if(vTCPFlags & SYN)
02781     {
02782         if(MyTCB.flags.bSYNSent)
02783             header.SeqNumber--;
02784         else
02785         {
02786             MyTCB.MySEQ++;
02787             MyTCB.flags.bSYNSent = 1;
02788         }
02789     }
02790     if(vTCPFlags & FIN)
02791     {
02792         if(MyTCB.flags.bFINSent)
02793             header.SeqNumber--;
02794         else
02795         {
02796             MyTCB.MySEQ++;
02797             MyTCB.flags.bFINSent = 1;
02798         }
02799     }
02800
02801     // Calculate the amount of free space in the RX buffer area of this socket
02802     if(MyTCBStub.rxHead >= MyTCBStub.rxTail)
02803         header.Window = (MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart) - (MyTCBStub.rxHead - MyTCBStub.rxTail);
02804     else
02805         header.Window = MyTCBStub.rxTail - MyTCBStub.rxHead - 1;
02806
02807     // Calculate the amount of free space in the MAC RX buffer area and adjust window if needed
02808     wVal.Val = MACGetFreeRxSize()-64;
02809     if((SHORT)wVal.Val < (SHORT)0)
02810         wVal.Val = 0;
02811     // Force the remote node to throttle back if we are running low on general RX buffer space
02812     if(header.Window > wVal.Val)
02813         header.Window = wVal.Val;
02814
02815     SwapTCPHeader(&header);
02816
02817
02818     len += sizeof(header);
02819     header.DataOffset.Val   = sizeof(header) >> 2;
02820
02821     // Insert the MSS (Maximum Segment Size) TCP option if this is SYN packet
02822     if(vTCPFlags & SYN)
02823     {
02824         len += sizeof(options);
02825         options.Kind = TCP_OPTIONS_MAX_SEG_SIZE;
02826         options.Length = 0x04;
02827
02828         // Load MSS and swap to big endian
02829         options.MaxSegSize.Val = (((TCP_MAX_SEG_SIZE-4)&0x00FF)<<8) | (((TCP_MAX_SEG_SIZE-4)&0xFF00)>>8);
02830
02831         header.DataOffset.Val   += sizeof(options) >> 2;
02832     }
02833
02834     // Calculate IP pseudoheader checksum.
02835     // MODIFIX: Use the eWicht structure sIPConfig.
02836     pseudoHeader.SourceAddress  = sIPConfig.MyIPAddr;
02837     pseudoHeader.DestAddress    = MyTCB.remote.niRemoteMACIP.IPAddr;
02838     pseudoHeader.Zero           = 0x0;
02839     pseudoHeader.Protocol       = IP_PROT_TCP;
02840     pseudoHeader.Length         = len;
02841     SwapPseudoHeader(pseudoHeader);
02842     header.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader));
02843
02844     // Write IP header
02845     MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
02846     IPPutHeader(&MyTCB.remote.niRemoteMACIP, IP_PROT_TCP, len);
02847     MACPutArray((BYTE*)&header, sizeof(header));
02848     if(vTCPFlags & SYN)
02849         MACPutArray((BYTE*)&options, sizeof(options));
02850
02851     // Update the TCP checksum
02852     MACSetReadPtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER));
02853     wVal.Val = CalcIPBufferChecksum(len);
02854 #if defined(DEBUG_GENERATE_TX_LOSS)
02855     // Damage TCP checksums on TX packets randomly
02856     if(rand() > DEBUG_GENERATE_TX_LOSS)
02857     {
02858         wVal.Val++;
02859     }
02860 #endif
02861     MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + 16);
02862     MACPutArray((BYTE*)&wVal, sizeof(WORD));
02863
02864     // Physically start the packet transmission over the network
02865     MACFlush();
02866 }
02867
02868 /*****************************************************************************
02869   Function:
02870     static BOOL FindMatchingSocket(TCP_HEADER* h, NODE_INFO* remote)
02871
02872   Summary:
02873     Finds a suitable socket for a TCP segment.
02874
02875   Description:
02876     This function searches through the sockets and attempts to match one with
02877     a given TCP header and NODE_INFO structure.  If a socket is found, its
02878     index is saved in hCurrentTCP and the associated MyTCBStub and MyTCB are
02879     loaded. Otherwise, INVALID_SOCKET is placed in hCurrentTCP.
02880
02881   Precondition:
02882     TCP is initialized.
02883
02884   Parameters:
02885     h - TCP header to be matched against
02886     remote - The remote node who sent this header
02887
02888   Return Values:
02889     TRUE - A match was found and is loaded in hCurrentTCP
02890     FALSE - No suitable socket was found and hCurrentTCP is INVALID_SOCKET
02891   ***************************************************************************/
02892 static BOOL FindMatchingSocket(TCP_HEADER* h, NODE_INFO* remote)
02893 {
02894     TCP_SOCKET hTCP;
02895     TCP_SOCKET partialMatch;
02896     WORD hash;
02897
02898     // Prevent connections on invalid port 0
02899     if(h->DestPort == 0)
02900         return FALSE;
02901
02902     partialMatch = INVALID_SOCKET;
02903     hash = (remote->IPAddr.w[1]+remote->IPAddr.w[0] + h->SourcePort) ^ h->DestPort;
02904
02905     // Loop through all sockets looking for a socket that is expecting this
02906     // packet or can handle it.
02907     for(hTCP = 0; hTCP < TCP_SOCKET_COUNT; hTCP++ )
02908     {
02909         SyncTCBStub(hTCP);
02910
02911         if(MyTCBStub.smState == TCP_CLOSED)
02912         {
02913             continue;
02914         }
02915         else if(MyTCBStub.smState == TCP_LISTEN)
02916         {// For listening ports, check if this is the correct port
02917             if(MyTCBStub.remoteHash.Val == h->DestPort)
02918                 partialMatch = hTCP;
02919
02920             #if defined(STACK_USE_SSL_SERVER)
02921             // Check the SSL port as well for SSL Servers
02922             // 0 is defined as an invalid port number
02923             if(MyTCBStub.sslTxHead == h->DestPort)
02924                 partialMatch = hTCP;
02925             #endif
02926
02927             continue;
02928         }
02929         else if(MyTCBStub.remoteHash.Val != hash)
02930         {// Ignore if the hash doesn't match
02931             continue;
02932         }
02933
02934         SyncTCB();
02935         if( h->DestPort == MyTCB.localPort.Val &&
02936             h->SourcePort == MyTCB.remotePort.Val &&
02937             remote->IPAddr.Val == MyTCB.remote.niRemoteMACIP.IPAddr.Val)
02938         {
02939             return TRUE;
02940         }
02941     }
02942
02943
02944     // If there is a partial match, then a listening socket is currently
02945     // available.  Set up the extended TCB with the info needed
02946     // to establish a connection and return this socket to the
02947     // caller.
02948     if(partialMatch != INVALID_SOCKET)
02949     {
02950         SyncTCBStub(partialMatch);
02951         SyncTCB();
02952
02953         // For SSL ports, begin the SSL Handshake
02954         #if defined(STACK_USE_SSL_SERVER)
02955         if(MyTCBStub.sslTxHead == h->DestPort)
02956         {
02957             // Try to start an SSL session.  If no stubs are available,
02958             // we can't service this request right now, so ignore it.
02959             if(!TCPStartSSLServer(partialMatch))
02960                 partialMatch = INVALID_SOCKET;
02961         }
02962         #endif
02963
02964         // Make sure the above check didn't fail (this is unfortunately
02965         // redundant for non-SSL sockets).  Otherwise, fall out to below
02966         // and add to the SYN queue.
02967         if(partialMatch != INVALID_SOCKET)
02968         {
02969             MyTCBStub.remoteHash.Val = hash;
02970
02971             memcpy((void*)&MyTCB.remote, (void*)remote, sizeof(NODE_INFO));
02972             MyTCB.remotePort.Val = h->SourcePort;
02973             MyTCB.localPort.Val = h->DestPort;
02974             MyTCB.txUnackedTail = MyTCBStub.bufferTxStart;
02975
02976             // All done, and we have a match
02977             return TRUE;
02978         }
02979     }
02980
02981     // No available sockets are listening on this port.  (Or, for
02982     // SSL requests, perhaps no SSL sessions were available.  However,
02983     // there may be a server socket which is currently busy but
02984     // could handle this packet, so we should check.
02985     #if TCP_SYN_QUEUE_MAX_ENTRIES
02986     {
02987         WORD wQueueInsertPos;
02988
02989         // See if this is a SYN packet
02990         if(!h->Flags.bits.flagSYN)
02991             return FALSE;
02992
02993         // See if there is space in our SYN queue
02994         if(SYNQueue[TCP_SYN_QUEUE_MAX_ENTRIES-1].wDestPort)
02995             return FALSE;
02996
02997         // See if we have this SYN already in our SYN queue.
02998         // If not already in the queue, find out where we
02999         // should insert this SYN to the queue
03000         for(wQueueInsertPos = 0; wQueueInsertPos < TCP_SYN_QUEUE_MAX_ENTRIES; wQueueInsertPos++)
03001         {
03002             // Exit loop if we found a free record
03003             if(SYNQueue[wQueueInsertPos].wDestPort == 0u)
03004                 break;
03005
03006             // Check if this SYN packet is already in the SYN queue
03007             if(SYNQueue[wQueueInsertPos].wDestPort != h->DestPort)
03008                 continue;
03009             if(SYNQueue[wQueueInsertPos].wSourcePort != h->SourcePort)
03010                 continue;
03011             if(SYNQueue[wQueueInsertPos].niSourceAddress.IPAddr.Val != remote->IPAddr.Val)
03012                 continue;
03013
03014             // SYN matches SYN queue entry.  Update timestamp and do nothing.
03015             SYNQueue[wQueueInsertPos].wTimestamp = TickGetDiv256();
03016             return FALSE;
03017         }
03018
03019         // Check to see if we have any server sockets which
03020         // are currently connected, but could handle this SYN
03021         // request at a later time if the client disconnects.
03022         for(hTCP = 0; hTCP < TCP_SOCKET_COUNT; hTCP++)
03023         {
03024             SyncTCBStub(hTCP);
03025             if(!MyTCBStub.Flags.bServer)
03026                 continue;
03027
03028             SyncTCB();
03029             #if defined(STACK_USE_SSL_SERVER)
03030             if((MyTCB.localPort.Val != h->DestPort) && (MyTCB.localSSLPort.Val != h->DestPort))
03031             #else
03032             if(MyTCB.localPort.Val != h->DestPort)
03033             #endif
03034                 continue;
03035
03036             // Generate the SYN queue entry
03037             memcpy((void*)&SYNQueue[wQueueInsertPos].niSourceAddress, (void*)remote, sizeof(NODE_INFO));
03038             SYNQueue[wQueueInsertPos].wSourcePort = h->SourcePort;
03039             SYNQueue[wQueueInsertPos].dwSourceSEQ = h->SeqNumber;
03040             SYNQueue[wQueueInsertPos].wDestPort = h->DestPort;
03041             SYNQueue[wQueueInsertPos].wTimestamp = TickGetDiv256();
03042
03043             return FALSE;
03044         }
03045     }
03046     #endif
03047
03048     return FALSE;
03049
03050 }
03051
03052
03053
03054 /*****************************************************************************
03055   Function:
03056     static void SwapTCPHeader(TCP_HEADER* header)
03057
03058   Summary:
03059     Swaps endian-ness of a TCP header.
03060
03061   Description:
03062     This function swaps the endian-ness of a given TCP header for comparison.
03063
03064   Precondition:
03065     None
03066
03067   Parameters:
03068     header - The TCP header that is to be swapped
03069
03070   Returns:
03071     None
03072   ***************************************************************************/
03073 static void SwapTCPHeader(TCP_HEADER* header)
03074 {
03075     header->SourcePort      = swaps(header->SourcePort);
03076     header->DestPort        = swaps(header->DestPort);
03077     header->SeqNumber       = swapl(header->SeqNumber);
03078     header->AckNumber       = swapl(header->AckNumber);
03079     header->Window          = swaps(header->Window);
03080     header->Checksum        = swaps(header->Checksum);
03081     header->UrgentPointer   = swaps(header->UrgentPointer);
03082 }
03083
03084
03085
03086 /*****************************************************************************
03087   Function:
03088     static void CloseSocket(void)
03089
03090   Summary:
03091     Closes a TCP socket.
03092
03093   Description:
03094     This function closes a TCP socket.  All socket state information is
03095     reset, and any buffered bytes are discarded.  The socket is no longer
03096     accessible by the application after this point.
03097
03098   Precondition:
03099     The TCPStub corresponding to the socket to be closed is synced.
03100
03101   Parameters:
03102     None
03103
03104   Returns:
03105     None
03106   ***************************************************************************/
03107 static void CloseSocket(void)
03108 {
03109     SyncTCB();
03110
03111     MyTCBStub.remoteHash.Val = MyTCB.localPort.Val;
03112     MyTCBStub.txHead = MyTCBStub.bufferTxStart;
03113     MyTCBStub.txTail = MyTCBStub.bufferTxStart;
03114     MyTCBStub.rxHead = MyTCBStub.bufferRxStart;
03115     MyTCBStub.rxTail = MyTCBStub.bufferRxStart;
03116     MyTCBStub.smState = MyTCBStub.Flags.bServer ? TCP_LISTEN : TCP_CLOSED;
03117     MyTCBStub.Flags.vUnackedKeepalives = 0;
03118     MyTCBStub.Flags.bTimerEnabled = 0;
03119     MyTCBStub.Flags.bTimer2Enabled = 0;
03120     MyTCBStub.Flags.bDelayedACKTimerEnabled = 0;
03121     MyTCBStub.Flags.bOneSegmentReceived = 0;
03122     MyTCBStub.Flags.bHalfFullFlush = 0;
03123     MyTCBStub.Flags.bTXASAP = 0;
03124     MyTCBStub.Flags.bTXASAPWithoutTimerReset = 0;
03125     MyTCBStub.Flags.bTXFIN = 0;
03126     MyTCBStub.Flags.bSocketReset = 1;
03127
03128     #if defined(STACK_USE_SSL)
03129     // If SSL is active, then we need to close it
03130     if(MyTCBStub.sslStubID != SSL_INVALID_ID)
03131     {
03132         SSLTerminate(MyTCBStub.sslStubID);
03133         MyTCBStub.sslStubID = SSL_INVALID_ID;
03134
03135         // Swap the SSL port and local port back to proper values
03136         MyTCBStub.remoteHash.Val = MyTCB.localSSLPort.Val;
03137         MyTCB.localSSLPort.Val = MyTCB.localPort.Val;
03138         MyTCB.localPort.Val = MyTCBStub.remoteHash.Val;
03139     }
03140
03141     // Reset the SSL buffer pointers
03142     MyTCBStub.sslRxHead = MyTCBStub.bufferRxStart;
03143     MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
03144     #endif
03145
03146     #if defined(STACK_USE_SSL_SERVER)
03147     MyTCBStub.sslTxHead = MyTCB.localSSLPort.Val;
03148     #endif
03149
03150     MyTCB.flags.bFINSent = 0;
03151     MyTCB.flags.bSYNSent = 0;
03152     MyTCB.flags.bRXNoneACKed1 = 0;
03153     MyTCB.flags.bRXNoneACKed2 = 0;
03154     MyTCB.txUnackedTail = MyTCBStub.bufferTxStart;
03155     ((DWORD_VAL*)(&MyTCB.MySEQ))->w[0] = rand();
03156     ((DWORD_VAL*)(&MyTCB.MySEQ))->w[1] = rand();
03157     MyTCB.sHoleSize = -1;
03158     MyTCB.remoteWindow = 1;
03159 }
03160
03161
03162
03163 /*****************************************************************************
03164   Function:
03165     static void HandleTCPSeg(TCP_HEADER* h, WORD len)
03166
03167   Summary:
03168     Processes an incoming TCP segment.
03169
03170   Description:
03171     Once an incoming segment has been matched to a socket, this function
03172     performs the necessary processing with the data.  Depending on the
03173     segment and the state, this may include copying data to the TCP buffer,
03174     re-assembling out-of order packets, continuing an initialization or
03175     closing handshake, or closing the socket altogether.
03176
03177   Precondition:
03178     TCP is initialized and the current TCP stub is already synced.
03179
03180   Parameters:
03181     h - The TCP header for this packet
03182     len - The total buffer length of this segment
03183
03184   Returns:
03185     None
03186   ***************************************************************************/
03187 static void HandleTCPSeg(TCP_HEADER* h, WORD len)
03188 {
03189     DWORD dwTemp;
03190     PTR_BASE wTemp;
03191     LONG lMissingBytes;
03192     WORD wMissingBytes;
03193     WORD wFreeSpace;
03194     BYTE localHeaderFlags;
03195     DWORD localAckNumber;
03196     DWORD localSeqNumber;
03197     WORD wSegmentLength;
03198     BOOL bSegmentAcceptable;
03199
03200     // Cache a few variables in local RAM.
03201     // PIC18s take a fair amount of code and execution time to
03202     // dereference pointers frequently.
03203     localHeaderFlags = h->Flags.byte;
03204     localAckNumber = h->AckNumber;
03205     localSeqNumber = h->SeqNumber;
03206
03207     // We received a packet, reset the keep alive timer and count
03208     #if defined(TCP_KEEP_ALIVE_TIMEOUT)
03209         MyTCBStub.Flags.vUnackedKeepalives = 0;
03210         if(!MyTCBStub.Flags.bTimerEnabled)
03211             MyTCBStub.eventTime = TickGet() + TCP_KEEP_ALIVE_TIMEOUT;
03212     #endif
03213
03214     // Handle TCP_LISTEN and TCP_SYN_SENT states
03215     // Both of these states will return, so code following this
03216     // state machine need not check explicitly for these two
03217     // states.
03218     switch(MyTCBStub.smState)
03219     {
03220         case TCP_LISTEN:
03221             // First: check RST flag
03222             if(localHeaderFlags & RST)
03223             {
03224                 CloseSocket();  // Unbind remote IP address/port info
03225                 return;
03226             }
03227
03228             // Second: check ACK flag, which would be invalid
03229             if(localHeaderFlags & ACK)
03230             {
03231                 // Use a believable sequence number and reset the remote node
03232                 MyTCB.MySEQ = localAckNumber;
03233                 SendTCP(RST, 0);
03234                 CloseSocket();  // Unbind remote IP address/port info
03235                 return;
03236             }
03237
03238             // Third: check for SYN flag, which is what we're looking for
03239             if(localHeaderFlags & SYN)
03240             {
03241                 // We now have a sequence number for the remote node
03242                 MyTCB.RemoteSEQ = localSeqNumber + 1;
03243
03244                 // Set Initial Send Sequence (ISS) number
03245                 // Nothing to do on this step... ISS already set in CloseSocket()
03246
03247                 // Respond with SYN + ACK
03248                 SendTCP(SYN | ACK, SENDTCP_RESET_TIMERS);
03249                 MyTCBStub.smState = TCP_SYN_RECEIVED;
03250             }
03251             else
03252             {
03253                 CloseSocket();  // Unbind remote IP address/port info
03254             }
03255
03256             // Fourth: check for other text and control
03257             // Nothing to do since we don't support this
03258             return;
03259
03260         case TCP_SYN_SENT:
03261             // Second: check the RST bit
03262             // This is out of order because this stack has no API for
03263             // notifying the application that the connection seems to
03264             // be failing.  Instead, the application must time out and
03265             // the stack will just keep trying in the mean time.
03266             if(localHeaderFlags & RST)
03267                 return;
03268
03269             // First: check ACK bit
03270             if(localHeaderFlags & ACK)
03271             {
03272                 if(localAckNumber != MyTCB.MySEQ)
03273                 {
03274                     // Send a RST packet with SEQ = SEG.ACK, but retain our SEQ
03275                     // number for arivial of any other SYN+ACK packets
03276                     localSeqNumber = MyTCB.MySEQ;   // Save our original SEQ number
03277                     MyTCB.MySEQ = localAckNumber;   // Set SEQ = SEG.ACK
03278                     SendTCP(RST, SENDTCP_RESET_TIMERS);     // Send the RST
03279                     MyTCB.MySEQ = localSeqNumber;   // Restore original SEQ number
03280                     return;
03281                 }
03282             }
03283
03284             // Third: check the security and precedence
03285             // No such feature in this stack.  We want to accept all connections.
03286
03287             // Fourth: check the SYN bit
03288             if(localHeaderFlags & SYN)
03289             {
03290                 // We now have an initial sequence number and window size
03291                 MyTCB.RemoteSEQ = localSeqNumber + 1;
03292                 MyTCB.remoteWindow = h->Window;
03293
03294                 if(localHeaderFlags & ACK)
03295                 {
03296                     SendTCP(ACK, SENDTCP_RESET_TIMERS);
03297                     MyTCBStub.smState = TCP_ESTABLISHED;
03298                     MyTCBStub.Flags.bTimerEnabled = 0;
03299                 }
03300                 else
03301                 {
03302                     SendTCP(SYN | ACK, SENDTCP_RESET_TIMERS);
03303                     MyTCBStub.smState = TCP_SYN_RECEIVED;
03304                 }
03305             }
03306
03307             // Fifth: drop the segment if neither SYN or RST is set
03308             return;
03309
03310         default:
03311             break;
03312     }
03313
03314     //
03315     // First: check the sequence number
03316     //
03317     wSegmentLength = len;
03318     if(localHeaderFlags & FIN)
03319         wSegmentLength++;
03320     if(localHeaderFlags & SYN)
03321         wSegmentLength++;
03322
03323     // Calculate the RX FIFO space
03324     if(MyTCBStub.rxHead >= MyTCBStub.rxTail)
03325         wFreeSpace = (MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart) - (MyTCBStub.rxHead - MyTCBStub.rxTail);
03326     else
03327         wFreeSpace = MyTCBStub.rxTail - MyTCBStub.rxHead - 1;
03328
03329     // Calculate the number of bytes ahead of our head pointer this segment skips
03330     lMissingBytes = localSeqNumber - MyTCB.RemoteSEQ;
03331     wMissingBytes = (WORD)lMissingBytes;
03332
03333     // Run TCP acceptability tests to verify that this packet has a valid sequence number
03334     bSegmentAcceptable = FALSE;
03335     if(wSegmentLength)
03336     {
03337         // Check to see if we have free space, and if so, if any of the data falls within the freespace
03338         if(wFreeSpace)
03339         {
03340             // RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
03341             if((lMissingBytes >= (LONG)0) && (wFreeSpace > lMissingBytes))
03342                 bSegmentAcceptable = TRUE;
03343             else
03344             {
03345                 // RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
03346                 if((lMissingBytes + (LONG)wSegmentLength > (LONG)0) && (lMissingBytes <= (LONG)(SHORT)(wFreeSpace - wSegmentLength)))
03347                     bSegmentAcceptable = TRUE;
03348             }
03349
03350             if((lMissingBytes < (LONG)wFreeSpace) && ((SHORT)wMissingBytes + (SHORT)wSegmentLength > (SHORT)0))
03351                 bSegmentAcceptable = TRUE;
03352         }
03353         // Segments with data are not acceptable if we have no free space
03354     }
03355     else
03356     {
03357         // Zero length packets are acceptable if they fall within our free space window
03358         // SEG.SEQ = RCV.NXT
03359         if(lMissingBytes == 0)
03360         {
03361             bSegmentAcceptable = TRUE;
03362         }
03363         else
03364         {
03365             // RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
03366             if((lMissingBytes >= (LONG)0) && (wFreeSpace > lMissingBytes))
03367                 bSegmentAcceptable = TRUE;
03368         }
03369     }
03370
03371     if(!bSegmentAcceptable)
03372     {
03373         // Unacceptable segment, drop it and respond appropriately
03374         if(!(localHeaderFlags & RST))
03375             SendTCP(ACK, SENDTCP_RESET_TIMERS);
03376         return;
03377     }
03378
03379
03380     //
03381     // Second: check the RST bit
03382     //
03383     //
03384     // Fourth: check the SYN bit
03385     //
03386     // Note, that since the third step is not implemented, we can
03387     // combine this second and fourth step into a single operation.
03388     if(localHeaderFlags & (RST | SYN))
03389     {
03390         CloseSocket();
03391         return;
03392     }
03393
03394     //
03395     // Third: check the security and precedence
03396     //
03397     // Feature not supported.  Let's process this segment.
03398
03399     //
03400     // Fifth: check the ACK bit
03401     //
03402     if(!(localHeaderFlags & ACK))
03403         return;
03404
03405     switch(MyTCBStub.smState)
03406     {
03407         case TCP_SYN_RECEIVED:
03408             if(localAckNumber != MyTCB.MySEQ)
03409             {
03410                 // Send a RST packet with SEQ = SEG.ACK, but retain our SEQ
03411                 // number for arivial of any other correct packets
03412                 localSeqNumber = MyTCB.MySEQ;   // Save our original SEQ number
03413                 MyTCB.MySEQ = localAckNumber;   // Set SEQ = SEG.ACK
03414                 SendTCP(RST, SENDTCP_RESET_TIMERS);     // Send the RST
03415                 MyTCB.MySEQ = localSeqNumber;   // Restore original SEQ number
03416                 return;
03417             }
03418             MyTCBStub.smState = TCP_ESTABLISHED;
03419             // No break
03420
03421         case TCP_ESTABLISHED:
03422         case TCP_FIN_WAIT_1:
03423         case TCP_FIN_WAIT_2:
03424         case TCP_CLOSE_WAIT:
03425         case TCP_CLOSING:
03426             // Calculate what the highest possible SEQ number in our TX FIFO is
03427             wTemp = MyTCBStub.txHead - MyTCB.txUnackedTail;
03428             if((SHORT)wTemp < (SHORT)0)
03429                 wTemp += MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart;
03430             dwTemp = MyTCB.MySEQ + (DWORD)wTemp;
03431
03432             // Drop the packet if it ACKs something we haven't sent
03433             if((LONG)(dwTemp - localAckNumber) < (LONG)0)
03434             {
03435                 SendTCP(ACK, 0);
03436                 return;
03437             }
03438
03439             // Throw away all ACKnowledged TX data:
03440             // Calculate what the last acknowledged sequence number was (ignoring any FINs we sent)
03441             dwTemp = MyTCB.MySEQ - (LONG)(SHORT)(MyTCB.txUnackedTail - MyTCBStub.txTail);
03442             if(MyTCB.txUnackedTail < MyTCBStub.txTail)
03443                 dwTemp -= MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart;
03444
03445             // Calcluate how many bytes were ACKed with this packet
03446             dwTemp = localAckNumber - dwTemp;
03447             if(((LONG)(dwTemp) > (LONG)0) && (dwTemp <= MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart))
03448             {
03449                 MyTCB.flags.bRXNoneACKed1 = 0;
03450                 MyTCB.flags.bRXNoneACKed2 = 0;
03451                 MyTCBStub.Flags.bHalfFullFlush = FALSE;
03452
03453                 // Bytes ACKed, free up the TX FIFO space
03454                 wTemp = MyTCBStub.txTail;
03455                 MyTCBStub.txTail += dwTemp;
03456                 if(MyTCB.txUnackedTail >= wTemp)
03457                 {
03458                     if(MyTCB.txUnackedTail < MyTCBStub.txTail)
03459                     {
03460                         MyTCB.MySEQ += MyTCBStub.txTail - MyTCB.txUnackedTail;
03461                         MyTCB.txUnackedTail = MyTCBStub.txTail;
03462                     }
03463                 }
03464                 else
03465                 {
03466                     wTemp = MyTCB.txUnackedTail + (MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart);
03467                     if(wTemp < MyTCBStub.txTail)
03468                     {
03469                         MyTCB.MySEQ += MyTCBStub.txTail - wTemp;
03470                         MyTCB.txUnackedTail = MyTCBStub.txTail;
03471                     }
03472                 }
03473                 if(MyTCBStub.txTail >= MyTCBStub.bufferRxStart)
03474                     MyTCBStub.txTail -= MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart;
03475                 if(MyTCB.txUnackedTail >= MyTCBStub.bufferRxStart)
03476                     MyTCB.txUnackedTail -= MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart;
03477             }
03478             else
03479             {
03480                 // See if we have outstanding TX data that is waiting for an ACK
03481                 if(MyTCBStub.txTail != MyTCB.txUnackedTail)
03482                 {
03483                     if(MyTCB.flags.bRXNoneACKed1)
03484                     {
03485                         if(MyTCB.flags.bRXNoneACKed2)
03486                         {
03487                             // Set up to perform a fast retransmission
03488                             // Roll back unacknowledged TX tail pointer to cause retransmit to occur
03489                             MyTCB.MySEQ -= (LONG)(SHORT)(MyTCB.txUnackedTail - MyTCBStub.txTail);
03490                             if(MyTCB.txUnackedTail < MyTCBStub.txTail)
03491                                 MyTCB.MySEQ -= (LONG)(SHORT)(MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart);
03492                             MyTCB.txUnackedTail = MyTCBStub.txTail;
03493                             MyTCBStub.Flags.bTXASAPWithoutTimerReset = 1;
03494                         }
03495                         MyTCB.flags.bRXNoneACKed2 = 1;
03496                     }
03497                     MyTCB.flags.bRXNoneACKed1 = 1;
03498                 }
03499             }
03500
03501             // No need to keep our retransmit timer going if we have nothing that needs ACKing anymore
03502             if(MyTCBStub.txTail == MyTCBStub.txHead)
03503             {
03504                 // Make sure there isn't a "FIN byte in our TX FIFO"
03505                 if(MyTCBStub.Flags.bTXFIN == 0)
03506                 {
03507                     MyTCBStub.Flags.bTimerEnabled = 0;
03508                 }
03509                 else
03510                 {
03511                     // "Throw away" FIN byte from our TX FIFO if it has been ACKed
03512                     if(MyTCB.MySEQ == localAckNumber)
03513                     {
03514                         MyTCBStub.Flags.bTimerEnabled = 0;
03515                         MyTCBStub.Flags.bTXFIN = 0;
03516                         MyTCB.flags.bFINSent = 0;
03517                     }
03518                 }
03519             }
03520
03521             // Update the local stored copy of the RemoteWindow
03522             // If previously we had a zero window, and now we don't
03523             // immediately send whatever was pending
03524             if((MyTCB.remoteWindow == 0u) && h->Window)
03525                 MyTCBStub.Flags.bTXASAP = 1;
03526             MyTCB.remoteWindow = h->Window;
03527
03528             // A couple of states must do all of the TCP_ESTABLISHED stuff, but also a little more
03529             if(MyTCBStub.smState == TCP_FIN_WAIT_1)
03530             {
03531                 // Check to see if our FIN has been ACKnowledged
03532                 if(MyTCB.MySEQ == localAckNumber)
03533                 {
03534                     // Reset our timer for forced closure if the remote node
03535                     // doesn't send us a FIN in a timely manner.
03536                     MyTCBStub.eventTime = TickGet() + TCP_FIN_WAIT_2_TIMEOUT;
03537                     MyTCBStub.Flags.bTimerEnabled = 1;
03538                     MyTCBStub.smState = TCP_FIN_WAIT_2;
03539                 }
03540             }
03541             else if(MyTCBStub.smState == TCP_FIN_WAIT_2)
03542             {
03543                 // RFC noncompliance:
03544                 // The remote node should not keep sending us data
03545                 // indefinitely after we send a FIN to it.
03546                 // However, some bad stacks may still keep sending
03547                 // us data indefinitely after ACKing our FIN.  To
03548                 // prevent this from locking up our socket, let's
03549                 // send a RST right now and close forcefully on
03550                 // our side.
03551                 if(!(localHeaderFlags & FIN))
03552                 {
03553                     MyTCB.MySEQ = localAckNumber;   // Set SEQ = SEG.ACK
03554                     SendTCP(RST | ACK, 0);
03555                     CloseSocket();
03556                     return;
03557                 }
03558             }
03559             else if(MyTCBStub.smState == TCP_CLOSING)
03560             {
03561                 // Check to see if our FIN has been ACKnowledged
03562                 if(MyTCB.MySEQ == localAckNumber)
03563                 {
03564                     // RFC not recommended: We should be going to
03565                     // the TCP_TIME_WAIT state right here and
03566                     // starting a 2MSL timer, but since we have so
03567                     // few precious sockets, we can't afford to
03568                     // leave a socket waiting around doing nothing
03569                     // for a long time.  If the remote node does
03570                     // not recieve this ACK, it'll have to figure
03571                     // out on it's own that the connection is now
03572                     // closed.
03573                     CloseSocket();
03574                 }
03575
03576                 return;
03577             }
03578
03579             break;
03580
03581         case TCP_LAST_ACK:
03582             // Check to see if our FIN has been ACKnowledged
03583             if(MyTCB.MySEQ == localAckNumber)
03584                 CloseSocket();
03585             return;
03586
03587 //      case TCP_TIME_WAIT:
03588 //          // Nothing is supposed to arrive here.  If it does, reset the quiet timer.
03589 //          SendTCP(ACK, SENDTCP_RESET_TIMERS);
03590 //          return;
03591
03592         default:
03593             break;
03594     }
03595
03596     //
03597     // Sixth: Check the URG bit
03598     //
03599     // Urgent packets are not supported in this stack, so we
03600     // will throw them away instead
03601     if(localHeaderFlags & URG)
03602         return;
03603
03604     //
03605     // Seventh: Process the segment text
03606     //
03607     // Throw data away if in a state that doesn't accept data
03608     if(MyTCBStub.smState == TCP_CLOSE_WAIT)
03609         return;
03610     if(MyTCBStub.smState == TCP_CLOSING)
03611         return;
03612     if(MyTCBStub.smState == TCP_LAST_ACK)
03613         return;
03614 //  if(MyTCBStub.smState == TCP_TIME_WAIT)
03615 //      return;
03616
03617     // Copy any valid segment data into our RX FIFO, if any
03618     if(len)
03619     {
03620         // See if there are bytes we must skip
03621         if((SHORT)wMissingBytes <= 0)
03622         {
03623             // Position packet read pointer to start of useful data area.
03624             IPSetRxBuffer((h->DataOffset.Val << 2) - wMissingBytes);
03625             len += wMissingBytes;
03626
03627             // Truncate packets that would overflow our TCP RX FIFO
03628             // and request a retransmit by sending a duplicate ACK
03629             if(len > wFreeSpace)
03630                 len = wFreeSpace;
03631
03632             MyTCB.RemoteSEQ += (DWORD)len;
03633
03634             // Copy the application data from the packet into the socket RX FIFO
03635             // See if we need a two part copy (spans bufferEnd->bufferRxStart)
03636             if(MyTCBStub.rxHead + len > MyTCBStub.bufferEnd)
03637             {
03638                 wTemp = MyTCBStub.bufferEnd - MyTCBStub.rxHead + 1;
03639                 TCPRAMCopy(MyTCBStub.rxHead, MyTCBStub.vMemoryMedium, (PTR_BASE)-1, TCP_ETH_RAM, wTemp);
03640                 TCPRAMCopy(MyTCBStub.bufferRxStart, MyTCBStub.vMemoryMedium, (PTR_BASE)-1, TCP_ETH_RAM, len - wTemp);
03641                 MyTCBStub.rxHead = MyTCBStub.bufferRxStart + (len - wTemp);
03642             }
03643             else
03644             {
03645                 TCPRAMCopy(MyTCBStub.rxHead, MyTCBStub.vMemoryMedium, (PTR_BASE)-1, TCP_ETH_RAM, len);
03646                 MyTCBStub.rxHead += len;
03647             }
03648
03649             // See if we have a hole and other data waiting already in the RX FIFO
03650             if(MyTCB.sHoleSize != -1)
03651             {
03652                 MyTCB.sHoleSize -= len;
03653                 wTemp = MyTCB.wFutureDataSize + MyTCB.sHoleSize;
03654
03655                 // See if we just closed up a hole, and if so, advance head pointer
03656                 if((SHORT)wTemp < (SHORT)0)
03657                 {
03658                     MyTCB.sHoleSize = -1;
03659                 }
03660                 else if(MyTCB.sHoleSize <= 0)
03661                 {
03662                     MyTCB.RemoteSEQ += wTemp;
03663                     MyTCBStub.rxHead += wTemp;
03664                     if(MyTCBStub.rxHead > MyTCBStub.bufferEnd)
03665                         MyTCBStub.rxHead -= MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart + 1;
03666                     MyTCB.sHoleSize = -1;
03667                 }
03668             }
03669         } // This packet is out of order or we lost a packet, see if we can generate a hole to accomodate it
03670         else if((SHORT)wMissingBytes > 0)
03671         {
03672             // Truncate packets that would overflow our TCP RX FIFO
03673             if(len + wMissingBytes > wFreeSpace)
03674                 len = wFreeSpace - wMissingBytes;
03675
03676             // Position packet read pointer to start of useful data area.
03677             IPSetRxBuffer(h->DataOffset.Val << 2);
03678
03679             // See if we need a two part copy (spans bufferEnd->bufferRxStart)
03680             if(MyTCBStub.rxHead + wMissingBytes + len > MyTCBStub.bufferEnd)
03681             {
03682                 // Calculate number of data bytes to copy before wraparound
03683                 wTemp = MyTCBStub.bufferEnd - MyTCBStub.rxHead + 1 - wMissingBytes;
03684                 if((SHORT)wTemp >= 0)
03685                 {
03686                     TCPRAMCopy(MyTCBStub.rxHead + wMissingBytes, MyTCBStub.vMemoryMedium, (PTR_BASE)-1, TCP_ETH_RAM, wTemp);
03687                     TCPRAMCopy(MyTCBStub.bufferRxStart, MyTCBStub.vMemoryMedium, (PTR_BASE)-1, TCP_ETH_RAM, len - wTemp);
03688                 }
03689                 else
03690                 {
03691                     TCPRAMCopy(MyTCBStub.rxHead + wMissingBytes - (MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart + 1), MyTCBStub.vMemoryMedium, (PTR_BASE)-1, TCP_ETH_RAM, len);
03692                 }
03693             }
03694             else
03695             {
03696                 TCPRAMCopy(MyTCBStub.rxHead + wMissingBytes, MyTCBStub.vMemoryMedium, (PTR_BASE)-1, TCP_ETH_RAM, len);
03697             }
03698
03699             // Record the hole is here
03700             if(MyTCB.sHoleSize == -1)
03701             {
03702                 MyTCB.sHoleSize = wMissingBytes;
03703                 MyTCB.wFutureDataSize = len;
03704             }
03705             else
03706             {
03707                 // We already have a hole, see if we can shrink the hole
03708                 // or extend the future data size
03709                 if(wMissingBytes < (WORD)MyTCB.sHoleSize)
03710                 {
03711                     if((wMissingBytes + len > (WORD)MyTCB.sHoleSize + MyTCB.wFutureDataSize) || (wMissingBytes + len < (WORD)MyTCB.sHoleSize))
03712                         MyTCB.wFutureDataSize = len;
03713                     else
03714                         MyTCB.wFutureDataSize = (WORD)MyTCB.sHoleSize + MyTCB.wFutureDataSize - wMissingBytes;
03715                     MyTCB.sHoleSize = wMissingBytes;
03716                 }
03717                 else if(wMissingBytes + len > (WORD)MyTCB.sHoleSize + MyTCB.wFutureDataSize)
03718                 {
03719                     // Make sure that there isn't a second hole between
03720                     // our future data and this TCP segment's future data
03721                     if(wMissingBytes <= (WORD)MyTCB.sHoleSize + MyTCB.wFutureDataSize)
03722                         MyTCB.wFutureDataSize += wMissingBytes + len - (WORD)MyTCB.sHoleSize - MyTCB.wFutureDataSize;
03723                 }
03724
03725             }
03726         }
03727     }
03728
03729     // Send back an ACK of the data (+SYN | FIN) we just received,
03730     // if any.  To minimize bandwidth waste, we are implementing
03731     // the delayed acknowledgement algorithm here, only sending
03732     // back an immediate ACK if this is the second segment received.
03733     // Otherwise, a 200ms timer will cause the ACK to be transmitted.
03734     if(wSegmentLength)
03735     {
03736         // For non-established sockets, let's delete all data in
03737         // the RX buffer immediately after receiving it.  This is
03738         // not really how TCP was intended to operate since a
03739         // socket cannot receive any response after it sends a FIN,
03740         // but our TCP application API doesn't readily accomodate
03741         // receiving data after calling TCPDisconnect(), which
03742         // invalidates the application TCP handle.  By deleting all
03743         // data, we'll ensure that the RX window is nonzero and
03744         // the remote node will be able to send us a FIN response,
03745         // which needs an RX window of at least 1.
03746         if(MyTCBStub.smState != TCP_ESTABLISHED)
03747             MyTCBStub.rxTail = MyTCBStub.rxHead;
03748
03749         if(MyTCBStub.Flags.bOneSegmentReceived)
03750         {
03751             SendTCP(ACK, SENDTCP_RESET_TIMERS);
03752             SyncTCB();
03753             // bOneSegmentReceived is cleared in SendTCP(), so no need here
03754         }
03755         else
03756         {
03757             MyTCBStub.Flags.bOneSegmentReceived = TRUE;
03758
03759             // Do not send an ACK immediately back.  Instead, we will
03760             // perform delayed acknowledgements.  To do this, we will
03761             // just start a timer
03762             if(!MyTCBStub.Flags.bDelayedACKTimerEnabled)
03763             {
03764                 MyTCBStub.Flags.bDelayedACKTimerEnabled = 1;
03765                 MyTCBStub.OverlappedTimers.delayedACKTime = (WORD)TickGetDiv256() + (WORD)((TCP_DELAYED_ACK_TIMEOUT)>>8);
03766             }
03767         }
03768     }
03769
03770     //
03771     // Eighth: check the FIN bit
03772     //
03773     if(localHeaderFlags & FIN)
03774     {
03775         // Note: Since we don't have a good means of storing "FIN bytes"
03776         // in our TCP RX FIFO, we must ensure that FINs are processed
03777         // in-order.
03778         if(MyTCB.RemoteSEQ + 1 == localSeqNumber + (DWORD)wSegmentLength)
03779         {
03780             // FINs are treated as one byte of data for ACK sequencing
03781             MyTCB.RemoteSEQ++;
03782
03783             switch(MyTCBStub.smState)
03784             {
03785                 case TCP_SYN_RECEIVED:
03786                     // RFC in exact: Our API has no need for the user
03787                     // to explicitly close a socket that never really
03788                     // got opened fully in the first place, so just
03789                     // transmit a FIN automatically and jump to
03790                     // TCP_LAST_ACK
03791                     MyTCBStub.smState = TCP_LAST_ACK;
03792                     SendTCP(FIN | ACK, SENDTCP_RESET_TIMERS);
03793                     return;
03794
03795                 case TCP_ESTABLISHED:
03796                     // Go to TCP_CLOSE_WAIT state
03797                     MyTCBStub.smState = TCP_CLOSE_WAIT;
03798
03799                     // For legacy applications that don't call
03800                     // TCPDisconnect() as needed and expect the TCP/IP
03801                     // Stack to automatically close sockets when the
03802                     // remote node sends a FIN, let's start a timer so
03803                     // that we will eventually close the socket automatically
03804                     MyTCBStub.OverlappedTimers.closeWaitTime = (WORD)TickGetDiv256() + (WORD)((TCP_CLOSE_WAIT_TIMEOUT)>>8);
03805                     break;
03806
03807                 case TCP_FIN_WAIT_1:
03808                     if(MyTCB.MySEQ == localAckNumber)
03809                     {
03810                         // RFC not recommended: We should be going to
03811                         // the TCP_TIME_WAIT state right here and
03812                         // starting a 2MSL timer, but since we have so
03813                         // few precious sockets, we can't afford to
03814                         // leave a socket waiting around doing nothing
03815                         // for a long time.  If the remote node does
03816                         // not recieve this ACK, it'll have to figure
03817                         // out on it's own that the connection is now
03818                         // closed.
03819                         SendTCP(ACK, 0);
03820                         CloseSocket();
03821                         return;
03822                     }
03823                     else
03824                     {
03825                         MyTCBStub.smState = TCP_CLOSING;
03826                     }
03827                     break;
03828
03829                 case TCP_FIN_WAIT_2:
03830                     // RFC not recommended: We should be going to
03831                     // the TCP_TIME_WAIT state right here and
03832                     // starting a 2MSL timer, but since we have so
03833                     // few precious sockets, we can't afford to
03834                     // leave a socket waiting around doing nothing
03835                     // for a long time.  If the remote node does
03836                     // not recieve this ACK, it'll have to figure
03837                     // out on it's own that the connection is now
03838                     // closed.
03839                     SendTCP(ACK, 0);
03840                     CloseSocket();
03841                     return;
03842
03843                 default:
03844                     break;
03845             }
03846
03847             // Acknowledge receipt of FIN
03848             SendTCP(ACK, SENDTCP_RESET_TIMERS);
03849         }
03850     }
03851 }
03852
03853 /****************************************************************************
03854   Section:
03855     Buffer Management Functions
03856   ***************************************************************************/
03857
03858 /*****************************************************************************
03859   Function:
03860     BOOL TCPAdjustFIFOSize(TCP_SOCKET hTCP, WORD wMinRXSize,
03861                             WORD wMinTXSize, BYTE vFlags)
03862
03863   Summary:
03864     Adjusts the relative sizes of the RX and TX buffers.
03865
03866   Description:
03867     This function can be used to adjust the relative sizes of the RX and
03868     TX FIFO depending on the immediate needs of an application.  Since a
03869     larger FIFO can allow more data to be sent in a given packet, adjusting
03870     the relative sizes on the fly can allow for optimal transmission speed
03871     for one-sided application protocols.  For example, HTTP typically
03872     begins by receiving large amounts of data from the client, then switches
03873     to serving large amounts of data back.  Adjusting the FIFO at these
03874     points can increase performance substantially.  Once the FIFO is
03875     adjusted, a window update is sent.
03876
03877     If neither or both of TCP_ADJUST_GIVE_REST_TO_TX and
03878     TCP_ADJUST_GIVE_REST_TO_RX are set, the function distributes the
03879     remaining space equally.
03880
03881     Received data can be preserved as long as the buffer is expanding and
03882     has not wrapped.
03883
03884   Precondition:
03885     TCP is initialized.
03886
03887   Parameters:
03888     hTCP        - The socket to be adjusted
03889     wMinRXSize  - Minimum number of byte for the RX FIFO
03890     wMinTXSize  - Minimum number of bytes for the RX FIFO
03891     vFlags      - Any combination of TCP_ADJUST_GIVE_REST_TO_RX,
03892                   TCP_ADJUST_GIVE_REST_TO_TX, TCP_ADJUST_PRESERVE_RX.
03893                   TCP_ADJUST_PRESERVE_TX is not currently supported.
03894
03895   Return Values:
03896     TRUE - The FIFOs were adjusted successfully
03897     FALSE - Minimum RX, Minimum TX, or flags couldn't be accommodated and
03898             therefore the socket was left unchanged.
03899
03900   Side Effects:
03901     Any unacknowledged or untransmitted data in the TX FIFO is always
03902     deleted.
03903
03904   Remarks:
03905     At least one byte must always be allocated to the RX buffer so that
03906     a FIN can be received.  The function automatically corrects for this.
03907   ***************************************************************************/
03908 BOOL TCPAdjustFIFOSize(TCP_SOCKET hTCP, WORD wMinRXSize, WORD wMinTXSize, BYTE vFlags)
03909 {
03910     PTR_BASE ptrTemp, ptrHead;
03911     WORD wTXAllocation;
03912
03913     // Load up info on this socket
03914     SyncTCBStub(hTCP);
03915
03916     // RX has to be at least 1 byte to receive SYN and FIN bytes
03917     // from the remote node, even if they aren't stored in the RX FIFO
03918     if(wMinRXSize == 0u)
03919         wMinRXSize = 1;
03920
03921     // SSL connections need to be able to send or receive at least
03922     // a full Alert record, MAC, and FIN
03923     #if defined(STACK_USE_SSL)
03924     if(TCPIsSSL(hTCP) && wMinRXSize < 25)
03925         wMinRXSize = 25;
03926     if(TCPIsSSL(hTCP) && wMinTXSize < 25)
03927         wMinTXSize = 25;
03928     #endif
03929
03930     // Make sure space is available for minimums
03931     ptrTemp = MyTCBStub.bufferEnd - MyTCBStub.bufferTxStart - 1;
03932     if(wMinRXSize + wMinTXSize > ptrTemp)
03933         return FALSE;
03934
03935     SyncTCB();
03936
03937     // Set both allocation flags if none set
03938     if(!(vFlags & (TCP_ADJUST_GIVE_REST_TO_TX | TCP_ADJUST_GIVE_REST_TO_RX)))
03939         vFlags |= TCP_ADJUST_GIVE_REST_TO_TX | TCP_ADJUST_GIVE_REST_TO_RX;
03940
03941
03942     // Allocate minimums
03943     wTXAllocation = wMinTXSize;
03944     ptrTemp -= wMinRXSize + wMinTXSize;
03945
03946     // Allocate extra
03947     if(vFlags & TCP_ADJUST_GIVE_REST_TO_TX)
03948     {
03949         if(vFlags & TCP_ADJUST_GIVE_REST_TO_RX)
03950         {
03951             // Do a 50%/50% split with any odd byte always going to the RX FIFO
03952             wTXAllocation += ptrTemp>>1;
03953         }
03954         else
03955         {
03956             wTXAllocation += ptrTemp;
03957         }
03958     }
03959
03960     // Calculate new bufferRxStart pointer
03961     ptrTemp = MyTCBStub.bufferTxStart + wTXAllocation + 1;
03962
03963     // Find the head pointer to use
03964     ptrHead = MyTCBStub.rxHead;
03965     #if defined(STACK_USE_SSL)
03966     if(TCPIsSSL(hTCP))
03967         ptrHead = MyTCBStub.sslRxHead;
03968     #endif
03969
03970     // If there's out-of-order data pending, adjust the head pointer to compensate
03971     if(MyTCB.sHoleSize != -1)
03972     {
03973         ptrHead += MyTCB.sHoleSize + MyTCB.wFutureDataSize;
03974         if(ptrHead > MyTCBStub.bufferEnd)
03975             ptrHead -= MyTCBStub.bufferEnd - MyTCBStub.bufferRxStart + 1;
03976     }
03977
03978     // Determine if resizing will lose any RX data
03979     if(MyTCBStub.rxTail < ptrHead)
03980     {
03981         if(ptrTemp > MyTCBStub.rxTail)
03982         {
03983             if(vFlags & TCP_ADJUST_PRESERVE_RX)
03984                 return FALSE;
03985             else
03986             {
03987                 MyTCBStub.rxTail = ptrTemp;
03988                 MyTCBStub.rxHead = ptrTemp;
03989
03990                 #if defined(STACK_USE_SSL)
03991                 MyTCBStub.sslRxHead = ptrTemp;
03992                 #endif
03993             }
03994         }
03995     }
03996     else if(MyTCBStub.rxTail > ptrHead)
03997     {
03998         if(ptrTemp > MyTCBStub.bufferRxStart)
03999         {
04000             if(vFlags & TCP_ADJUST_PRESERVE_RX)
04001                 return FALSE;
04002             else
04003             {
04004                 MyTCBStub.rxTail = ptrTemp;
04005                 MyTCBStub.rxHead = ptrTemp;
04006
04007                 #if defined(STACK_USE_SSL)
04008                 MyTCBStub.sslRxHead = ptrTemp;
04009                 #endif
04010             }
04011         }
04012     }
04013     else
04014     {
04015         // No data to preserve, but we may need to move
04016         // the pointers to stay in the RX space
04017         MyTCBStub.rxTail = ptrTemp;
04018         MyTCBStub.rxHead = ptrTemp;
04019
04020         #if defined(STACK_USE_SSL)
04021         MyTCBStub.sslRxHead = ptrTemp;
04022         #endif
04023     }
04024
04025     // If we need to preserve data that wrapped in the ring, we must copy
04026     if(ptrHead < MyTCBStub.rxTail && (vFlags & TCP_ADJUST_PRESERVE_RX))
04027     {
04028         TCPRAMCopy(ptrTemp, MyTCBStub.vMemoryMedium,
04029             MyTCBStub.bufferRxStart, MyTCBStub.vMemoryMedium,
04030             ptrHead - MyTCBStub.bufferRxStart);
04031
04032         // Move the pointers if they were in front of the tail
04033         #if defined(STACK_USE_SSL)
04034         if(TCPIsSSL(hTCP) && MyTCBStub.sslRxHead < MyTCBStub.rxTail)
04035             MyTCBStub.sslRxHead -= MyTCBStub.bufferRxStart - ptrTemp;
04036         #endif
04037         if(MyTCBStub.rxHead < MyTCBStub.rxTail)
04038             MyTCBStub.rxHead -= MyTCBStub.bufferRxStart - ptrTemp;
04039     }
04040
04041     // Move the RX buffer pointer - it's the one that divides the two
04042     MyTCBStub.bufferRxStart = ptrTemp;
04043
04044     // Empty the TX buffer
04045     MyTCB.txUnackedTail = MyTCBStub.bufferTxStart;
04046     MyTCBStub.txTail = MyTCBStub.bufferTxStart;
04047     MyTCBStub.txHead = MyTCBStub.bufferTxStart;
04048
04049     #if defined(STACK_USE_SSL)
04050     if(TCPIsSSL(hTCP))
04051         MyTCBStub.sslTxHead = MyTCBStub.txHead + 5;
04052     #endif
04053
04054     // Send a window update to notify remote node of change
04055     if(MyTCBStub.smState == TCP_ESTABLISHED)
04056         SendTCP(ACK, SENDTCP_RESET_TIMERS);
04057
04058     return TRUE;
04059
04060 }
04061
04062 /*****************************************************************************
04063   Function:
04064     static void TCPRAMCopy(PTR_BASE ptrDest, BYTE vDestType, PTR_BASE ptrSource,
04065                             BYTE vSourceType, WORD wLength)
04066
04067   Summary:
04068     Copies data to/from various memory mediums.
04069
04070   Description:
04071     This function copies data between memory mediums (PIC RAM, SPI
04072     RAM, and Ethernet buffer RAM).
04073
04074   Precondition:
04075     TCP is initialized.
04076
04077   Parameters:
04078     ptrDest     - Address to write to
04079     vDestType   - Destination meidum (TCP_PIC_RAM, TCP_ETH_RAM, TCP_SPI_RAM)
04080     ptrSource   - Address to copy from
04081     vSourceType - Source medium (TCP_PIC_RAM, TCP_ETH_RAM, or TCP_SPI_RAM)
04082     wLength     - Number of bytes to copy
04083
04084   Returns:
04085     None
04086
04087   Remarks:
04088     Copying to a destination region that overlaps with the source address
04089     is supported only if the destination start address is at a lower memory
04090     address (closer to 0x0000) than the source pointer.
04091   ***************************************************************************/
04092 static void TCPRAMCopy(PTR_BASE ptrDest, BYTE vDestType, PTR_BASE ptrSource, BYTE vSourceType, WORD wLength)
04093 {
04094     #if defined(SPIRAM_CS_TRIS)
04095     BYTE vBuffer[16];
04096     WORD w;
04097     #endif
04098
04099     switch(vSourceType)
04100     {
04101         case TCP_PIC_RAM:
04102             switch(vDestType)
04103             {
04104                 case TCP_PIC_RAM:
04105                     memcpy((void*)(BYTE*)ptrDest, (void*)(BYTE*)ptrSource, wLength);
04106                     break;
04107
04108                 case TCP_ETH_RAM:
04109                     if(!((WORD_VAL*)&ptrDest)->bits.b15)
04110                         MACSetWritePtr((WORD)ptrDest);
04111                     MACPutArray((BYTE*)ptrSource, wLength);
04112                     break;
04113
04114                 #if defined(SPIRAM_CS_TRIS)
04115                 case TCP_SPI_RAM:
04116                     SPIRAMPutArray(ptrDest, (BYTE*)ptrSource, wLength);
04117                     break;
04118                 #endif
04119             }
04120             break;
04121
04122         case TCP_ETH_RAM:
04123             switch(vDestType)
04124             {
04125                 case TCP_PIC_RAM:
04126                     if(!((WORD_VAL*)&ptrSource)->bits.b15)
04127                         MACSetReadPtr(ptrSource);
04128                     MACGetArray((BYTE*)ptrDest, wLength);
04129                     break;
04130
04131                 case TCP_ETH_RAM:
04132                     MACMemCopyAsync(ptrDest, ptrSource, wLength);
04133                     while(!MACIsMemCopyDone());
04134                     break;
04135
04136                 #if defined(SPIRAM_CS_TRIS)
04137                 case TCP_SPI_RAM:
04138                     if(!((WORD_VAL*)&ptrSource)->bits.b15)
04139                         MACSetReadPtr(ptrSource);
04140                     w = sizeof(vBuffer);
04141                     while(wLength)
04142                     {
04143                         if(w > wLength)
04144                             w = wLength;
04145
04146                         // Read and write a chunk
04147                         MACGetArray(vBuffer, w);
04148                         SPIRAMPutArray(ptrDest, vBuffer, w);
04149                         ptrDest += w;
04150                         wLength -= w;
04151                     }
04152                     break;
04153                 #endif
04154             }
04155             break;
04156
04157         #if defined(SPIRAM_CS_TRIS)
04158         case TCP_SPI_RAM:
04159             switch(vDestType)
04160             {
04161                 case TCP_PIC_RAM:
04162                     SPIRAMGetArray(ptrSource, (BYTE*)ptrDest, wLength);
04163                     break;
04164
04165                 case TCP_ETH_RAM:
04166                     if(!((WORD_VAL*)&ptrDest)->bits.b15)
04167                         MACSetWritePtr(ptrDest);
04168                     w = sizeof(vBuffer);
04169                     while(wLength)
04170                     {
04171                         if(w > wLength)
04172                             w = wLength;
04173
04174                         // Read and write a chunk
04175                         SPIRAMGetArray(ptrSource, vBuffer, w);
04176                         ptrSource += w;
04177                         MACPutArray(vBuffer, w);
04178                         wLength -= w;
04179                     }
04180                     break;
04181
04182                 case TCP_SPI_RAM:
04183                     // Copy all of the data over in chunks
04184                     w = sizeof(vBuffer);
04185                     while(wLength)
04186                     {
04187                         if(w > wLength)
04188                             w = wLength;
04189
04190                         SPIRAMGetArray(ptrSource, vBuffer, w);
04191                         SPIRAMPutArray(ptrDest, vBuffer, w);
04192                         ptrSource += w;
04193                         ptrDest += w;
04194                         wLength -= w;
04195                     }
04196                     break;
04197             }
04198             break;
04199         #endif
04200     }
04201 }
04202
04203 /*****************************************************************************
04204   Function:
04205     static void TCPRAMCopyROM(PTR_BASE wDest, BYTE wDestType, ROM BYTE* wSource,
04206                                 WORD wLength)
04207
04208   Summary:
04209     Copies data to/from various memory mediums.
04210
04211   Description:
04212     This function copies data between memory mediums (PIC RAM, SPI
04213     RAM, and Ethernet buffer RAM).  This function is to be used when
04214     copying from ROM.
04215
04216   Precondition:
04217     TCP is initialized.
04218
04219   Parameters:
04220     wDest       - Address to write to
04221     wDestType   - Destination meidum (TCP_PIC_RAM, TCP_ETH_RAM, TCP_SPI_RAM)
04222     wSource     - Address to copy from
04223     wLength     - Number of bytes to copy
04224
04225   Returns:
04226     None
04227
04228   Remarks:
04229     Copying to a destination region that overlaps with the source address
04230     is supported only if the destination start address is at a lower memory
04231     address (closer to 0x0000) than the source pointer.
04232
04233     This function is aliased to TCPRAMCopy on non-PIC18 platforms.
04234   ***************************************************************************/
04235 #if defined(__18CXX)
04236 static void TCPRAMCopyROM(PTR_BASE wDest, BYTE wDestType, ROM BYTE* wSource, WORD wLength)
04237 {
04238     BYTE vBuffer[16];
04239     WORD w;
04240
04241     switch(wDestType)
04242     {
04243         case TCP_PIC_RAM:
04244             memcpypgm2ram((void*)(BYTE*)wDest, (ROM void*)wSource, wLength);
04245             break;
04246
04247         case TCP_ETH_RAM:
04248             if(!((WORD_VAL*)&wDest)->bits.b15)
04249                 MACSetWritePtr(wDest);
04250             w = sizeof(vBuffer);
04251             while(wLength)
04252             {
04253                 if(w > wLength)
04254                     w = wLength;
04255
04256                 // Read and write a chunk
04257                 memcpypgm2ram(vBuffer, (ROM void*)wSource, w);
04258                 MACPutArray(vBuffer, w);
04259                 wSource += w;
04260                 wLength -= w;
04261             }
04262             break;
04263
04264         #if defined(SPIRAM_CS_TRIS)
04265         case TCP_SPI_RAM:
04266             w = sizeof(vBuffer);
04267             while(wLength)
04268             {
04269                 if(w > wLength)
04270                     w = wLength;
04271
04272                 // Read and write a chunk
04273                 memcpypgm2ram(vBuffer, (ROM void*)wSource, w);
04274                 SPIRAMPutArray(wDest, vBuffer, w);
04275                 wDest += w;
04276                 wSource += w;
04277                 wLength -= w;
04278             }
04279             break;
04280         #endif
04281     }
04282 }
04283 #endif
04284
04285 /****************************************************************************
04286   Section:
04287     SSL Functions
04288   ***************************************************************************/
04289
04290 /*****************************************************************************
04291   Function:
04292     BOOL TCPStartSSLClient(TCP_SOCKET hTCP, BYTE* host)
04293
04294   Summary:
04295     Begins an SSL client session.
04296
04297   Description:
04298     This function escalates the current connection to an SSL secured
04299     connection by initiating an SSL client handshake.
04300
04301   Precondition:
04302     TCP is initialized and hTCP is already connected.
04303
04304   Parameters:
04305     hTCP        - TCP connection to secure
04306     host        - Expected host name on certificate (currently ignored)
04307
04308   Return Values:
04309     TRUE        - an SSL connection was initiated
04310     FALSE       - Insufficient SSL resources (stubs) were available
04311
04312   Remarks:
04313     The host parameter is currently ignored and is not validated.
04314   ***************************************************************************/
04315 #if defined(STACK_USE_SSL_CLIENT)
04316 BOOL TCPStartSSLClient(TCP_SOCKET hTCP, BYTE* host)
04317 {
04318     BYTE i;
04319
04320     SyncTCBStub(hTCP);
04321
04322     // Make sure SSL is not established already
04323     if(MyTCBStub.sslStubID != SSL_INVALID_ID)
04324         return FALSE;
04325
04326     // Try to start the session
04327     MyTCBStub.sslStubID = SSLStartSession(hTCP);
04328
04329     // Make sure a session stub was obtained
04330     if(MyTCBStub.sslStubID == SSL_INVALID_ID)
04331         return FALSE;
04332
04333     // Mark connection as handshaking and return
04334     MyTCBStub.sslReqMessage = SSL_CLIENT_HELLO;
04335     MyTCBStub.sslRxHead = MyTCBStub.rxHead;
04336     MyTCBStub.sslTxHead = MyTCBStub.txHead;
04337     MyTCBStub.Flags.bSSLHandshaking = 1;
04338     for(i = 0; i < 5; i++)
04339     {// Skip first 5 bytes in TX for the record header
04340         if(++MyTCBStub.sslTxHead >= MyTCBStub.bufferRxStart)
04341             MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
04342     }
04343     return TRUE;
04344 }
04345 #endif // SSL Client
04346
04347 /*****************************************************************************
04348   Function:
04349     BOOL TCPStartSSLServer(TCP_SOCKET hTCP)
04350
04351   Summary:
04352     Begins an SSL server session.
04353
04354   Description:
04355     This function sets up an SSL server session when a new connection is
04356     established on an SSL port.
04357
04358   Precondition:
04359     TCP is initialized and hTCP is already connected.
04360
04361   Parameters:
04362     hTCP        - TCP connection to secure
04363
04364   Return Values:
04365     TRUE        - an SSL connection was initiated
04366     FALSE       - Insufficient SSL resources (stubs) were available
04367   ***************************************************************************/
04368 #if defined(STACK_USE_SSL_SERVER)
04369 BOOL TCPStartSSLServer(TCP_SOCKET hTCP)
04370 {
04371     BYTE i;
04372
04373     SyncTCBStub(hTCP);
04374     SyncTCB();
04375
04376     // Make sure SSL is not established already
04377     if(MyTCBStub.sslStubID != SSL_INVALID_ID)
04378         return TRUE;
04379
04380     // Try to start the session
04381     MyTCBStub.sslStubID = SSLStartSession(hTCP);
04382
04383     // Make sure a session stub was obtained
04384     if(MyTCBStub.sslStubID == SSL_INVALID_ID)
04385         return FALSE;
04386
04387     // Swap the localPort and localSSLPort
04388     MyTCBStub.remoteHash.Val = MyTCB.localPort.Val;
04389     MyTCB.localPort.Val = MyTCB.localSSLPort.Val;
04390     MyTCB.localSSLPort.Val = MyTCBStub.remoteHash.Val;
04391
04392     // Mark connection as handshaking and return
04393     MyTCBStub.sslReqMessage = SSL_NO_MESSAGE;
04394     MyTCBStub.sslRxHead = MyTCBStub.rxHead;
04395     MyTCBStub.sslTxHead = MyTCBStub.txHead;
04396     MyTCBStub.Flags.bSSLHandshaking = 1;
04397     for(i = 0; i < 5; i++)
04398     {// Skip first 5 bytes in TX for the record header
04399         if(++MyTCBStub.sslTxHead >= MyTCBStub.bufferRxStart)
04400             MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
04401     }
04402     return TRUE;
04403 }
04404 #endif // SSL Client
04405
04406 /*****************************************************************************
04407   Function:
04408     BOOL TCPAddSSLListener(TCP_SOCKET hTCP, WORD port)
04409
04410   Summary:
04411     Listens for SSL connection on a specific port.
04412
04413   Description:
04414     This function adds an additional listening port to a TCP connection.
04415     Connections made on this alternate port will be secured via SSL.
04416
04417   Precondition:
04418     TCP is initialized and hTCP is listening.
04419
04420   Parameters:
04421     hTCP        - TCP connection to secure
04422     port        - SSL port to listen on
04423
04424   Return Values:
04425     TRUE        - SSL port was added.
04426     FALSE       - The socket was not a listening socket.
04427   ***************************************************************************/
04428 #if defined(STACK_USE_SSL_SERVER)
04429 BOOL TCPAddSSLListener(TCP_SOCKET hTCP, WORD port)
04430 {
04431     SyncTCBStub(hTCP);
04432
04433     if(MyTCBStub.smState != TCP_LISTEN)
04434         return FALSE;
04435
04436     SyncTCB();
04437
04438     MyTCB.localSSLPort.Val = port;
04439     MyTCBStub.sslTxHead = port;
04440
04441     return TRUE;
04442 }
04443 #endif // SSL Server
04444
04445 /*****************************************************************************
04446   Function:
04447     BOOL TCPRequestSSLMessage(TCP_SOCKET hTCP, BYTE msg)
04448
04449   Summary:
04450     Requests an SSL message to be transmitted.
04451
04452   Description:
04453     This function is called to request that a specific SSL message be
04454     transmitted.  This message should only be called by the SSL module.
04455
04456   Precondition:
04457     TCP is initialized.
04458
04459   Parameters:
04460     hTCP        - TCP connection to use
04461     msg         - One of the SSL_MESSAGE types to transmit.
04462
04463   Return Values:
04464     TRUE        - The message was requested.
04465     FALSE       - Another message is already pending transmission.
04466   ***************************************************************************/
04467 #if defined(STACK_USE_SSL)
04468 BOOL TCPRequestSSLMessage(TCP_SOCKET hTCP, BYTE msg)
04469 {
04470     SyncTCBStub(hTCP);
04471
04472     if(msg == SSL_NO_MESSAGE || MyTCBStub.sslReqMessage == SSL_NO_MESSAGE)
04473     {
04474         MyTCBStub.sslReqMessage = msg;
04475         return TRUE;
04476     }
04477
04478     return FALSE;
04479 }
04480 #endif // SSL
04481
04482 /*****************************************************************************
04483   Function:
04484     BOOL TCPSSLIsHandshaking(TCP_SOCKET hTCP)
04485
04486   Summary:
04487     Determines if an SSL session is still handshaking.
04488
04489   Description:
04490     Call this function after calling TCPStartSSLClient until FALSE is
04491     returned.  Then your application may continue with its normal data
04492     transfer (which is now secured).
04493
04494   Precondition:
04495     TCP is initialized and hTCP is connected.
04496
04497   Parameters:
04498     hTCP        - TCP connection to check
04499
04500   Return Values:
04501     TRUE        - SSL handshake is still progressing
04502     FALSE       - SSL handshake has completed
04503   ***************************************************************************/
04504 #if defined(STACK_USE_SSL)
04505 BOOL TCPSSLIsHandshaking(TCP_SOCKET hTCP)
04506 {
04507     SyncTCBStub(hTCP);
04508     return MyTCBStub.Flags.bSSLHandshaking;
04509 }
04510 #endif // SSL
04511
04512 /*****************************************************************************
04513   Function:
04514     BOOL TCPIsSSL(TCP_SOCKET hTCP)
04515
04516   Summary:
04517     Determines if a TCP connection is secured with SSL.
04518
04519   Description:
04520     Call this function to determine whether or not a TCP connection is
04521     secured with SSL.
04522
04523   Precondition:
04524     TCP is initialized and hTCP is connected.
04525
04526   Parameters:
04527     hTCP        - TCP connection to check
04528
04529   Return Values:
04530     TRUE        - Connection is secured via SSL
04531     FALSE       - Connection is not secured
04532   ***************************************************************************/
04533 #if defined(STACK_USE_SSL)
04534 BOOL TCPIsSSL(TCP_SOCKET hTCP)
04535 {
04536     SyncTCBStub(hTCP);
04537
04538     if(MyTCBStub.sslStubID == SSL_INVALID_ID)
04539         return FALSE;
04540
04541     return TRUE;
04542 }
04543 #endif // SSL
04544
04545 /*****************************************************************************
04546   Function:
04547     void TCPSSLHandshakeComplete(TCP_SOCKET hTCP)
04548
04549   Summary:
04550     Clears the SSL handshake flag.
04551
04552   Description:
04553     This function clears the flag indicating that an SSL handshake is
04554     complete.
04555
04556   Precondition:
04557     TCP is initialized and hTCP is connected.
04558
04559   Parameters:
04560     hTCP        - TCP connection to set
04561
04562   Returns:
04563     None
04564
04565   Remarks:
04566     This function should never be called by an application.  It is used
04567     only by the SSL module itself.
04568   ***************************************************************************/
04569 #if defined(STACK_USE_SSL)
04570 void TCPSSLHandshakeComplete(TCP_SOCKET hTCP)
04571 {
04572     SyncTCBStub(hTCP);
04573     MyTCBStub.Flags.bSSLHandshaking = 0;
04574 }
04575 #endif // SSL
04576
04577 /*****************************************************************************
04578   Function:
04579     void TCPSSLDecryptMAC(TCP_SOCKET hTCP, ARCFOUR_CTX* ctx,
04580                             WORD len, BOOL inPlace)
04581
04582   Summary:
04583     Decrypts and MACs data arriving via SSL.
04584
04585   Description:
04586     This function decrypts data in the TCP buffer, calculates the MAC over
04587     the data, and optionally moves it to a new location within the buffer.
04588     It is called to help process incoming SSL records.
04589
04590   Precondition:
04591     TCP is initialized, hTCP is connected, and ctx's Sbox is loaded.
04592
04593   Parameters:
04594     hTCP        - TCP connection to decrypt in
04595     ctx         - ARCFOUR encryption context to use
04596     len         - Number of bytes to crypt
04597     inPlace     - TRUE to write back in place, FALSE to write at end of
04598                     currently visible data.
04599
04600   Returns:
04601     None
04602
04603   Remarks:
04604     This function should never be called by an application.  It is used
04605     only by the SSL module itself.
04606   ***************************************************************************/
04607 #if defined(STACK_USE_SSL)
04608 void TCPSSLDecryptMAC(TCP_SOCKET hTCP, ARCFOUR_CTX* ctx, WORD len, BOOL inPlace)
04609 {
04610     PTR_BASE wSrc, wDest, wBlockLen, wTemp;
04611     BYTE buffer[32];
04612
04613     // Set up the pointers
04614     SyncTCBStub(hTCP);
04615     wSrc = MyTCBStub.rxTail;
04616     if(inPlace)
04617         wDest = wSrc;
04618     else
04619         wDest = MyTCBStub.sslRxHead;
04620
04621     // Handle 32 bytes at a time
04622     while(len)
04623     {
04624         // Determine how many bytes we can read
04625         wBlockLen = sizeof(buffer);
04626         if(wBlockLen > len) // Don't do more than we should
04627             wBlockLen = len;
04628
04629         // Read those bytes to a buffer
04630         if(wSrc + wBlockLen > MyTCBStub.bufferEnd)
04631         {// Two part read
04632             wTemp = MyTCBStub.bufferEnd - wSrc + 1;
04633             TCPRAMCopy((PTR_BASE)buffer, TCP_PIC_RAM, wSrc, MyTCBStub.vMemoryMedium, wTemp);
04634             TCPRAMCopy((PTR_BASE)buffer+wTemp, TCP_PIC_RAM, MyTCBStub.bufferRxStart, MyTCBStub.vMemoryMedium, wBlockLen - wTemp);
04635             wSrc = MyTCBStub.bufferRxStart + wBlockLen - wTemp;
04636         }
04637         else
04638         {
04639             TCPRAMCopy((PTR_BASE)buffer, TCP_PIC_RAM, wSrc, MyTCBStub.vMemoryMedium, wBlockLen);
04640             wSrc += wBlockLen;
04641         }
04642
04643         // Decrypt and hash
04644         ARCFOURCrypt(ctx, buffer, wBlockLen);
04645         SSLMACAdd(buffer, wBlockLen);
04646
04647         // Write decrypted bytes back
04648         if(wDest + wBlockLen > MyTCBStub.bufferEnd)
04649         {// Two part write
04650             wTemp = MyTCBStub.bufferEnd - wDest + 1;
04651             TCPRAMCopy(wDest, MyTCBStub.vMemoryMedium, (PTR_BASE)buffer, TCP_PIC_RAM, wTemp);
04652             TCPRAMCopy(MyTCBStub.bufferRxStart, MyTCBStub.vMemoryMedium, (PTR_BASE)buffer+wTemp, TCP_PIC_RAM, wBlockLen - wTemp);
04653             wDest = MyTCBStub.bufferRxStart + wBlockLen - wTemp;
04654         }
04655         else
04656         {
04657             TCPRAMCopy(wDest, MyTCBStub.vMemoryMedium, (PTR_BASE)buffer, TCP_PIC_RAM, wBlockLen);
04658             wDest += wBlockLen;
04659         }
04660
04661         // Update the length remaining
04662         len -= wBlockLen;
04663     }
04664
04665     // If not in place, update the sslRxHead pointer
04666     if(!inPlace)
04667     {
04668         MyTCBStub.sslRxHead = wDest;
04669         MyTCBStub.rxTail = wSrc;
04670     }
04671
04672 }
04673 #endif // SSL
04674
04675 /*****************************************************************************
04676   Function:
04677     void TCPSSLInPlaceMACEncrypt(TCP_SOCKET hTCP, ARCFOUR_CTX* ctx,
04678                                     BYTE* MACSecret, WORD len)
04679
04680   Summary:
04681     Encrypts and MACs data in place in the TCP TX buffer.
04682
04683   Description:
04684     This function encrypts data in the TCP buffer while calcuating a MAC.
04685     When encryption is finished, the MAC is appended to the buffer and
04686     the record will be ready to transmit.
04687
04688   Precondition:
04689     TCP is initialized, hTCP is connected, and ctx's Sbox is loaded.
04690
04691   Parameters:
04692     hTCP        - TCP connection to encrypt in
04693     ctx         - ARCFOUR encryption context to use
04694     MACSecret   - MAC encryption secret to use
04695     len         - Number of bytes to crypt
04696
04697   Returns:
04698     None
04699
04700   Remarks:
04701     This function should never be called by an application.  It is used
04702     only by the SSL module itself.
04703   ***************************************************************************/
04704 #if defined(STACK_USE_SSL)
04705 void TCPSSLInPlaceMACEncrypt(TCP_SOCKET hTCP, ARCFOUR_CTX* ctx, BYTE* MACSecret, WORD len)
04706 {
04707     PTR_BASE pos;
04708     WORD blockLen;
04709     BYTE buffer[32];
04710
04711     // Set up the pointers
04712     SyncTCBStub(hTCP);
04713     pos = MyTCBStub.txHead;
04714     for(blockLen = 0; blockLen < 5; blockLen++)
04715     {// Skips first 5 bytes for the header
04716         if(++pos >= MyTCBStub.bufferRxStart)
04717             pos = MyTCBStub.bufferTxStart;
04718     }
04719
04720     // Handle 32 bytes at a time
04721     while(len)
04722     {
04723         // Determine how many bytes we can read
04724         blockLen = sizeof(buffer);
04725         if(blockLen > len) // Don't do more than we should
04726             blockLen = len;
04727         if(blockLen > MyTCBStub.bufferRxStart - pos) // Don't pass the end
04728             blockLen = MyTCBStub.bufferRxStart - pos;
04729
04730         // Read those bytes to a buffer
04731         TCPRAMCopy((PTR_BASE)buffer, TCP_PIC_RAM, pos, MyTCBStub.vMemoryMedium, blockLen);
04732
04733         // Hash and encrypt
04734         SSLMACAdd(buffer, blockLen);
04735         ARCFOURCrypt(ctx, buffer, blockLen);
04736
04737         // Put them back
04738         TCPRAMCopy(pos, MyTCBStub.vMemoryMedium, (PTR_BASE)buffer, TCP_PIC_RAM, blockLen);
04739
04740         // Update the pointers
04741         pos += blockLen;
04742         len -= blockLen;
04743         if(pos >= MyTCBStub.bufferRxStart)
04744             pos = MyTCBStub.bufferTxStart;
04745     }
04746
04747     // Calculate and add the MAC
04748     SSLMACCalc(MACSecret, buffer);
04749     ARCFOURCrypt(ctx, buffer, 16);
04750
04751     // Write the MAC to the TX FIFO
04752     // Can't use TCPPutArray here because TCPIsPutReady() saves 16 bytes for the MAC
04753     // TCPPut* functions use this to prevent writing too much data.  Therefore, the
04754     // functionality is duplicated here.
04755
04756     len = 16;
04757     blockLen = 0;
04758     // See if we need a two part put
04759     if(MyTCBStub.sslTxHead + len >= MyTCBStub.bufferRxStart)
04760     {
04761         blockLen = MyTCBStub.bufferRxStart-MyTCBStub.sslTxHead;
04762         TCPRAMCopy(MyTCBStub.sslTxHead, MyTCBStub.vMemoryMedium, (PTR_BASE)buffer, TCP_PIC_RAM, blockLen);
04763         len -= blockLen;
04764         MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
04765     }
04766
04767     TCPRAMCopy(MyTCBStub.sslTxHead, MyTCBStub.vMemoryMedium, (PTR_BASE)&buffer[blockLen], TCP_PIC_RAM, len);
04768     MyTCBStub.sslTxHead += len;
04769
04770 }
04771 #endif // SSL
04772
04773 /*****************************************************************************
04774   Function:
04775     void TCPSSLPutRecordHeader(TCP_SOCKET hTCP, BYTE* hdr, BOOL recDone)
04776
04777   Summary:
04778     Writes an SSL record header and sends an SSL record.
04779
04780   Description:
04781     This function writes an SSL record header to the pending TCP SSL data,
04782     then indicates that the data is ready to be sent by moving the txHead
04783     pointer.
04784
04785     If the record is complete, set recDone to TRUE.  The sslTxHead
04786     pointer will be moved forward 5 bytes to leave space for a future
04787     record header.  If the record is only partially sent, use FALSE and
04788     to leave the pointer where it is so that more data can be added
04789     to the record.  Partial records can only be used for the
04790     SERVER_CERTIFICATE handshake message.
04791
04792   Precondition:
04793     TCP is initialized, and hTCP is connected with an active SSL session.
04794
04795   Parameters:
04796     hTCP        - TCP connection to write the header and transmit with
04797     hdr         - Record header (5 bytes) to send or NULL to just
04798                   move the pointerctx
04799     recDone     - TRUE if the record is done, FALSE otherwise
04800
04801   Returns:
04802     None
04803
04804   Remarks:
04805     This function should never be called by an application.  It is used
04806     only by the SSL module itself.
04807   ***************************************************************************/
04808 #if defined(STACK_USE_SSL)
04809 void TCPSSLPutRecordHeader(TCP_SOCKET hTCP, BYTE* hdr, BOOL recDone)
04810 {
04811     BYTE i;
04812
04813     // Set up the pointers
04814     SyncTCBStub(hTCP);
04815
04816     // Write the header if needed
04817     if(hdr)
04818     {// This is a new record, so insert the header
04819         for(i = 0; i < 5; i++)
04820         {
04821             TCPRAMCopy(MyTCBStub.txHead, MyTCBStub.vMemoryMedium, (PTR_BASE)hdr+i, TCP_PIC_RAM, sizeof(BYTE));
04822             if(++MyTCBStub.txHead >= MyTCBStub.bufferRxStart)
04823                 MyTCBStub.txHead = MyTCBStub.bufferTxStart;
04824         }
04825     }
04826
04827     // Move the txHead pointer to indicate what data is ready
04828     // Also, flush just the header, then all the data.  This shotguns two
04829     // packets down the line, therefore causing immediate ACKs by the
04830     // remote node.  Reconnect handshakes are as much as 60% faster now.
04831     TCPFlush(hTCP);
04832     MyTCBStub.txHead = MyTCBStub.sslTxHead;
04833     TCPFlush(hTCP);
04834
04835     // If this record is done, move the sslTxHead forward
04836     // to accomodate the next record header
04837     if(recDone)
04838     {
04839         for(i = 0; i < 5; i++)
04840         {// Skip first 5 bytes in TX for the record header
04841             if(++MyTCBStub.sslTxHead >= MyTCBStub.bufferRxStart)
04842                 MyTCBStub.sslTxHead = MyTCBStub.bufferTxStart;
04843         }
04844     }
04845 }
04846 #endif // SSL
04847
04848 /*****************************************************************************
04849   Function:
04850     WORD TCPSSLGetPendingTxSize(TCP_SOCKET hTCP)
04851
04852   Summary:
04853     Determines how many bytes are pending for a future SSL record.
04854
04855   Description:
04856     This function determines how many bytes are pending for a future SSL
04857     record.
04858
04859   Precondition:
04860     TCP is initialized, and hTCP is connected with an active SSL connection.
04861
04862   Parameters:
04863     hTCP        - TCP connection to check
04864
04865   Returns:
04866     None
04867   ***************************************************************************/
04868 #if defined(STACK_USE_SSL)
04869 WORD TCPSSLGetPendingTxSize(TCP_SOCKET hTCP)
04870 {
04871     SyncTCBStub(hTCP);
04872
04873     // Non-SSL connections have no pending SSL data
04874     //if(MyTCBStub.sslStubID == SSL_INVALID_ID)
04875     //  return 0;
04876
04877     // Determine how many bytes are waiting to be written in this record
04878     if(MyTCBStub.sslTxHead > MyTCBStub.txHead)
04879         return MyTCBStub.sslTxHead - MyTCBStub.txHead - 5;
04880     else
04881         return (MyTCBStub.bufferRxStart - MyTCBStub.bufferTxStart - 1) - (MyTCBStub.txHead - MyTCBStub.sslTxHead - 1) - 5;
04882 }
04883 #endif
04884
04885
04886 /*****************************************************************************
04887   Function:
04888     void TCPSSLHandleIncoming(TCP_SOCKET hTCP)
04889
04890   Summary:
04891     Hands newly arrive TCP data to the SSL module for processing.
04892
04893   Description:
04894     This function processes incoming TCP data as an SSL record and
04895     performs any necessary repositioning and decrypting.
04896
04897   Precondition:
04898     TCP is initialized, and hTCP is connected with an active SSL session.
04899
04900   Parameters:
04901     hTCP        - TCP connection to handle incoming data on
04902
04903   Returns:
04904     None
04905
04906   Remarks:
04907     This function should never be called by an application.  It is used
04908     only by the SSL module itself.
04909   ***************************************************************************/
04910 #if defined(STACK_USE_SSL)
04911 void TCPSSLHandleIncoming(TCP_SOCKET hTCP)
04912 {
04913     PTR_BASE prevRxTail, prevRxHead, wSrc, wDest;
04914     WORD wToMove, wLen;
04915
04916     // Sync the stub
04917     SyncTCBStub(hTCP);
04918
04919     // If new data is waiting
04920     if(MyTCBStub.sslRxHead != MyTCBStub.rxHead)
04921     {
04922         // Sync the TCP so we can check the hole size
04923         SyncTCB();
04924
04925         // Reconfigure pointers for SSL use
04926         prevRxTail = MyTCBStub.rxTail;
04927         prevRxHead = MyTCBStub.rxHead;
04928         MyTCBStub.rxTail = MyTCBStub.rxHead;
04929         MyTCBStub.rxHead = MyTCBStub.sslRxHead;
04930         MyTCBStub.sslRxHead = prevRxHead;
04931
04932         // Handle incoming data
04933         SSLRxRecord(hTCP, MyTCBStub.sslStubID);
04934
04935         // If a MAC or new record header arrived, we now have a
04936         // hole in our TCP buffer.  Remaining data should be
04937         // moved forward to fill the hole, but optimizations are
04938         // possible in some cases.
04939         if(prevRxHead == MyTCBStub.rxTail)
04940         {// Didn't read anything, so nothing to move
04941             MyTCBStub.sslRxHead = MyTCBStub.rxHead;
04942             MyTCBStub.rxTail = prevRxTail;
04943             MyTCBStub.rxHead = prevRxHead;
04944         }
04945         else if(MyTCBStub.rxTail == MyTCBStub.rxHead && MyTCB.sHoleSize == -1)
04946         {// Nothing left out there, so just roll them back
04947             MyTCBStub.rxTail = prevRxTail;
04948             MyTCBStub.rxHead = MyTCBStub.sslRxHead;
04949         }
04950         else if(prevRxTail == prevRxHead)
04951         {// No previous data, so just roll forward
04952             MyTCBStub.sslRxHead = MyTCBStub.rxHead;
04953             MyTCBStub.rxHead = MyTCBStub.rxTail;
04954         }
04955         else
04956         {// Need to move data to fill the hole
04957             if(MyTCB.sHoleSize == -1)
04958             {// Just need to move pending SSL data
04959                 wToMove = TCPIsGetReady(hTCP);
04960             }
04961             else
04962             {// A TCP hole exists, so move all data
04963                 wToMove = TCPIsGetReady(hTCP) + MyTCB.sHoleSize + MyTCB.wFutureDataSize;
04964             }
04965
04966             // Start with the destination as the sslHead and source as rxTail
04967             wDest = MyTCBStub.sslRxHead;
04968             wSrc = MyTCBStub.rxTail;
04969
04970             // If data exists between the end of the buffer and
04971             // the destination, then move it forward
04972             if(wSrc > wDest)
04973             {
04974                 wLen = MyTCBStub.bufferEnd - wSrc + 1;
04975                 if(wLen > wToMove)
04976                     wLen = wToMove;
04977                 TCPRAMCopy(wDest, MyTCBStub.vMemoryMedium,
04978                            wSrc, MyTCBStub.vMemoryMedium, wLen);
04979                 wDest += wLen;
04980                 wSrc = MyTCBStub.bufferRxStart;
04981                 wToMove -= wLen;
04982             }
04983
04984             // If data remains to be moved, fill in to end of buffer
04985             if(wToMove > 0)
04986             {
04987                 wLen = MyTCBStub.bufferEnd - wDest + 1;
04988                 if(wLen > wToMove)
04989                     wLen = wToMove;
04990                 TCPRAMCopy(wDest, MyTCBStub.vMemoryMedium,
04991                            wSrc, MyTCBStub.vMemoryMedium, wLen);
04992                 wToMove -= wLen;
04993                 wDest += wLen;
04994                 wSrc += wLen;
04995                 if(wDest > MyTCBStub.bufferEnd)
04996                     wDest = MyTCBStub.bufferRxStart;
04997             }
04998
04999             // If data still remains, copy from from front + len to front
05000             if(wToMove > 0)
05001             {
05002                 TCPRAMCopy(wDest, MyTCBStub.vMemoryMedium,
05003                            wSrc, MyTCBStub.vMemoryMedium, wToMove);
05004                 wDest += wToMove;
05005             }
05006
05007             // Restore pointers to the right positions
05008             MyTCBStub.rxTail = prevRxTail;
05009             MyTCBStub.rxHead = MyTCBStub.sslRxHead;
05010             MyTCBStub.sslRxHead = wDest;
05011         }
05012
05013     }
05014
05015 }
05016 #endif
05017
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCP.h Source File

TCP.h

Go to the documentation of this file.
00001
00002
00003
00084 /*********************************************************************
00085  * Software License Agreement
00086  *
00087  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00088  * reserved.
00089  *
00090  * Microchip licenses to you the right to use, modify, copy, and
00091  * distribute:
00092  * (i)  the Software when embedded on a Microchip microcontroller or
00093  *      digital signal controller product ("Device") which is
00094  *      integrated into Licensee's product; or
00095  * (ii) ONLY the Software driver source files ENC28J60.c and
00096  *      ENC28J60.h ported to a non-Microchip device used in
00097  *      conjunction with a Microchip ethernet controller for the
00098  *      sole purpose of interfacing with the ethernet controller.
00099  *
00100  * You should refer to the license agreement accompanying this
00101  * Software for additional information regarding your rights and
00102  * obligations.
00103  *
00104  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00105  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00106  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00107  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00108  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00109  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00110  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00111  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00112  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00113  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00114  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00115  *
00116  *
00117  * Author               Date        Comment
00118  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00119  * Nilesh Rajbharti     5/8/01      Original        (Rev 1.0)
00120  * Howard Schlunder     11/30/06    See "TCPIP Stack Version.txt" file
00121  ********************************************************************/
00122 #ifndef __TCP_H
00123 #define __TCP_H
00124
00125 /****************************************************************************
00126   Section:
00127     Type Definitions
00128   ***************************************************************************/
00129
00130 // A TCP_SOCKET is stored as a single BYTE
00131 typedef BYTE TCP_SOCKET;
00132
00133 #define INVALID_SOCKET      (0xFE)  // The socket is invalid or could not be opened
00134 #define UNKNOWN_SOCKET      (0xFF)  // The socket is not known
00135
00136 /****************************************************************************
00137   Section:
00138     State Machine Variables
00139   ***************************************************************************/
00140
00141 // TCP States as defined by RFC 793
00142 typedef enum _TCP_STATE
00143 {
00144     TCP_GET_DNS_MODULE,     // Special state for TCP client mode sockets
00145     TCP_DNS_RESOLVE,        // Special state for TCP client mode sockets
00146     TCP_GATEWAY_SEND_ARP,   // Special state for TCP client mode sockets
00147     TCP_GATEWAY_GET_ARP,    // Special state for TCP client mode sockets
00148
00149     TCP_LISTEN,             // Socket is listening for connections
00150     TCP_SYN_SENT,           // A SYN has been sent, awaiting an SYN+ACK
00151     TCP_SYN_RECEIVED,       // A SYN has been received, awaiting an ACK
00152     TCP_ESTABLISHED,        // Socket is connected and connection is established
00153     TCP_FIN_WAIT_1,         // FIN WAIT state 1
00154     TCP_FIN_WAIT_2,         // FIN WAIT state 2
00155     TCP_CLOSING,            // Socket is closing
00156 //  TCP_TIME_WAIT, state is not implemented
00157     TCP_CLOSE_WAIT,         // Waiting to close the socket
00158     TCP_LAST_ACK,           // The final ACK has been sent
00159     TCP_CLOSED,             // Socket is idle and unallocated
00160
00161     TCP_CLOSED_BUT_RESERVED // Special state for TCP client mode sockets.  Socket is idle, but still allocated pending application closure of the handle.
00162 } TCP_STATE;
00163
00164 typedef enum _SSL_STATE
00165 {
00166     SSL_NONE = 0,           // No security is enabled
00167     SSL_HANDSHAKING,        // Handshake is progressing (no application data allowed)
00168     SSL_ESTABLISHED,        // Connection is established and secured
00169     SSL_CLOSED              // Connection has been closed (no applicaiton data is allowed)
00170 } SSL_STATE;
00171
00172 /****************************************************************************
00173   Section:
00174     TCB Definitions
00175   ***************************************************************************/
00176
00177 // TCP Control Block (TCB) stub data storage.  Stubs are stored in local PIC RAM for speed.
00178 // Current size is 29 bytes (PIC18), 30 bytes (PIC24/dsPIC), or 48 (PIC32)
00179 typedef struct _TCB_STUB
00180 {
00181     PTR_BASE bufferTxStart;     // First byte of TX buffer
00182     PTR_BASE bufferRxStart;     // First byte of RX buffer.  TX buffer ends 1 byte prior
00183     PTR_BASE bufferEnd;         // Last byte of RX buffer
00184     PTR_BASE txHead;            // Head pointer for TX
00185     PTR_BASE txTail;            // Tail pointer for TX
00186     PTR_BASE rxHead;            // Head pointer for RX
00187     PTR_BASE rxTail;            // Tail pointer for RX
00188     DWORD eventTime;            // Packet retransmissions, state changes
00189     WORD eventTime2;            // Window updates, automatic transmission
00190     union
00191     {
00192         WORD delayedACKTime;    // Delayed Acknowledgement timer
00193         WORD closeWaitTime;     // TCP_CLOSE_WAIT timeout timer
00194     } OverlappedTimers;
00195     TCP_STATE smState;          // State of this socket
00196     struct
00197     {
00198         unsigned char vUnackedKeepalives : 3;       // Count of how many keepalives have been sent with no response
00199         unsigned char bServer : 1;                  // Socket should return to listening state when closed
00200         unsigned char bTimerEnabled : 1;            // Timer is enabled
00201         unsigned char bTimer2Enabled : 1;           // Second timer is enabled
00202         unsigned char bDelayedACKTimerEnabled : 1;  // DelayedACK timer is enabled
00203         unsigned char bOneSegmentReceived : 1;      // A segment has been received
00204         unsigned char bHalfFullFlush : 1;           // Flush is for being half full
00205         unsigned char bTXASAP : 1;                  // Transmit as soon as possible (for Flush)
00206         unsigned char bTXASAPWithoutTimerReset : 1; // Transmit as soon as possible (for Flush), but do not reset retransmission timers
00207         unsigned char bTXFIN : 1;                   // FIN needs to be transmitted
00208         unsigned char bSocketReset : 1;             // Socket has been reset (self-clearing semaphore)
00209         unsigned char bSSLHandshaking : 1;          // Socket is in an SSL handshake
00210         unsigned char filler : 2;                   // Future expansion
00211     } Flags;
00212     WORD_VAL remoteHash;    // Consists of remoteIP, remotePort, localPort for connected sockets.  It is a localPort number only for listening server sockets.
00213
00214     #if defined(STACK_USE_SSL)
00215     PTR_BASE sslTxHead;     // Position of data being written in next SSL application record
00216                             //   Also serves as cache of localSSLPort when smState = TCP_LISTENING
00217     PTR_BASE sslRxHead;     // Position of incoming data not yet handled by SSL
00218     BYTE sslStubID;         // Which sslStub is associated with this connection
00219     BYTE sslReqMessage;     // Currently requested SSL message
00220     #endif
00221
00222     BYTE vMemoryMedium;     // Which memory medium the TCB is actually stored
00223
00224 } TCB_STUB;
00225
00226 // Remainder of TCP Control Block data.
00227 // The rest of the TCB is stored in Ethernet buffer RAM or elsewhere as defined by vMemoryMedium.
00228 // Current size is 37 (PIC18), 38 (PIC24/dsPIC), or 40 bytes (PIC32)
00229 typedef struct _TCB
00230 {
00231     DWORD       retryInterval;          // How long to wait before retrying transmission
00232     DWORD       MySEQ;                  // Local sequence number
00233     DWORD       RemoteSEQ;              // Remote sequence number
00234     PTR_BASE    txUnackedTail;          // TX tail pointer for data that is not yet acked
00235     WORD_VAL    remotePort;             // Remote port number
00236     WORD_VAL    localPort;              // Local port number
00237     WORD        remoteWindow;           // Remote window size
00238     WORD        wFutureDataSize;        // How much out-of-order data has been received
00239     union
00240     {
00241         NODE_INFO   niRemoteMACIP;      // 6 bytes for MAC and IP address
00242         DWORD       dwRemoteHost;       // RAM or ROM pointer to a hostname string (ex: "www.microchip.com")
00243     } remote;
00244     #if defined(STACK_USE_SSL)
00245     WORD_VAL    localSSLPort;           // Local SSL port number (for listening sockets)
00246     #endif
00247     SHORT       sHoleSize;              // Size of the hole, or -1 for none exists.  (0 indicates hole has just been filled)
00248     struct
00249     {
00250         unsigned char bFINSent : 1;     // A FIN has been sent
00251         unsigned char bSYNSent : 1;     // A SYN has been sent
00252         unsigned char bRemoteHostIsROM : 1; // Remote host is stored in ROM
00253         unsigned char bRXNoneACKed1 : 1;    // A duplicate ACK was likely received
00254         unsigned char bRXNoneACKed2 : 1;    // A second duplicate ACK was likely received
00255         unsigned char filler : 3;       // future use
00256     } flags;
00257     BYTE        retryCount;             // Counter for transmission retries
00258     BYTE        vSocketPurpose;         // Purpose of socket (as defined in TCPIPConfig.h)
00259 } TCB;
00260
00261 // Information about a socket
00262 typedef struct _SOCKET_INFO
00263 {
00264     NODE_INFO remote;       // NODE_INFO structure for remote node
00265     WORD_VAL remotePort;    // Port number associated with remote node
00266 } SOCKET_INFO;
00267
00268 /****************************************************************************
00269   Section:
00270     Function Declarations
00271   ***************************************************************************/
00272
00273 void TCPInit(void);
00274 SOCKET_INFO* TCPGetRemoteInfo(TCP_SOCKET hTCP);
00275
00276
00278
00307 BOOL TCPWasReset(TCP_SOCKET hTCP);
00308
00309
00311
00332 BOOL TCPIsConnected(TCP_SOCKET hTCP);
00333
00334
00336
00360 void TCPDisconnect(TCP_SOCKET hTCP);
00361
00362
00364
00381 WORD TCPIsPutReady(TCP_SOCKET hTCP);
00382
00383
00385
00398 BOOL TCPPut(TCP_SOCKET hTCP, BYTE byte);
00399
00400
00402
00417 WORD TCPPutArray(TCP_SOCKET hTCP, BYTE* Data, WORD Len);
00418
00419
00421
00444 BYTE* TCPPutString(TCP_SOCKET hTCP, BYTE* Data);
00445
00446
00448
00465 WORD TCPIsGetReady(TCP_SOCKET hTCP);
00466
00467
00468 WORD TCPGetRxFIFOFree(TCP_SOCKET hTCP);
00469
00470
00472
00485 BOOL TCPGet(TCP_SOCKET hTCP, BYTE* byte);
00486
00487
00488 WORD TCPGetArray(TCP_SOCKET hTCP, BYTE* buffer, WORD count);
00489
00490
00492
00528 WORD TCPFindEx(TCP_SOCKET hTCP, BYTE cFind, WORD wStart, WORD wSearchLen, BOOL bTextCompare);
00529
00530
00531 WORD TCPFindArrayEx(TCP_SOCKET hTCP, BYTE* cFindArray, WORD wLen, WORD wStart, WORD wSearchLen, BOOL bTextCompare);
00532 void TCPDiscard(TCP_SOCKET hTCP);
00533 BOOL TCPProcess(NODE_INFO* remote, IP_ADDR* localIP, WORD len);
00534 void TCPTick(void);
00535
00536
00538
00559 void TCPFlush(TCP_SOCKET hTCP);
00560
00561
00562 // Create a server socket and ignore dwRemoteHost.
00563 #define TCP_OPEN_SERVER     0
00564 #if defined(STACK_CLIENT_MODE)
00565     #if defined(STACK_USE_DNS)
00566         // Create a client socket and use dwRemoteHost as a RAM pointer to a hostname string.
00567         #define TCP_OPEN_RAM_HOST   1
00568         // Create a client socket and use dwRemoteHost as a ROM pointer to a hostname string.
00569         #define TCP_OPEN_ROM_HOST   2
00570     #else
00571         // Emit an undeclared identifier diagnostic if code tries to use TCP_OPEN_RAM_HOST while the DNS client module is not enabled.
00572         #define TCP_OPEN_RAM_HOST   You_need_to_enable_STACK_USE_DNS_to_use_TCP_OPEN_RAM_HOST
00573         // Emit an undeclared identifier diagnostic if code tries to use TCP_OPEN_ROM_HOST while the DNS client module is not enabled.
00574         #define TCP_OPEN_ROM_HOST   You_need_to_enable_STACK_USE_DNS_to_use_TCP_OPEN_ROM_HOST
00575     #endif
00576     // Create a client socket and use dwRemoteHost as a literal IP address.
00577     #define TCP_OPEN_IP_ADDRESS 3
00578     // Create a client socket and use dwRemoteHost as a pointer to a NODE_INFO structure containing the exact remote IP address and MAC address to use.
00579     #define TCP_OPEN_NODE_INFO  4
00580 #else
00581     // Emit an undeclared identifier diagnostic if code tries to use TCP_OPEN_RAM_HOST while STACK_CLIENT_MODE feature is not enabled.
00582     #define TCP_OPEN_RAM_HOST   You_need_to_enable_STACK_CLIENT_MODE_to_use_TCP_OPEN_RAM_HOST
00583     // Emit an undeclared identifier diagnostic if code tries to use TCP_OPEN_ROM_HOST while STACK_CLIENT_MODE feature is not enabled.
00584     #define TCP_OPEN_ROM_HOST   You_need_to_enable_STACK_CLIENT_MODE_to_use_TCP_OPEN_ROM_HOST
00585     // Emit an undeclared identifier diagnostic if code tries to use TCP_OPEN_IP_ADDRESS while STACK_CLIENT_MODE feature is not enabled.
00586     #define TCP_OPEN_IP_ADDRESS You_need_to_enable_STACK_CLIENT_MODE_to_use_TCP_OPEN_IP_ADDRESS
00587     // Emit an undeclared identifier diagnostic if code tries to use TCP_OPEN_NODE_INFO while STACK_CLIENT_MODE feature is not enabled.
00588     #define TCP_OPEN_NODE_INFO  You_need_to_enable_STACK_CLIENT_MODE_to_use_TCP_OPEN_NODE_INFO
00589 #endif
00590
00592
00667 TCP_SOCKET TCPOpen(DWORD dwRemoteHost, BYTE vRemoteHostType, WORD wPort, BYTE vSocketPurpose);
00668
00669 #if defined(__18CXX)
00670     WORD TCPFindROMArrayEx(TCP_SOCKET hTCP, ROM BYTE* cFindArray, WORD wLen, WORD wStart, WORD wSearchLen, BOOL bTextCompare);
00671
00672     /*****************************************************************************
00673       Summary:
00674         Alias to TCPFindROMArrayEx with no length parameter.
00675
00676       Description:
00677         This function is an alias to TCPFindROMArrayEx with no length parameter.
00678         It is provided for backwards compatibility with an older API.
00679       ***************************************************************************/
00680     #define TCPFindROMArray(a,b,c,d,e)      TCPFindROMArrayEx(a,b,c,d,0,e)
00681
00682     WORD TCPPutROMArray(TCP_SOCKET hTCP, ROM BYTE* Data, WORD Len);
00683     ROM BYTE* TCPPutROMString(TCP_SOCKET hTCP, ROM BYTE* Data);
00684 #else
00685     #define TCPFindROMArray(a,b,c,d,e)      TCPFindArray(a,(BYTE*)b,c,d,e)
00686     #define TCPFindROMArrayEx(a,b,c,d,e,f)  TCPFindArrayEx(a,(BYTE*)b,c,d,e,f)
00687     #define TCPPutROMArray(a,b,c)           TCPPutArray(a,(BYTE*)b,c)
00688     #define TCPPutROMString(a,b)            TCPPutString(a,(BYTE*)b)
00689 #endif
00690
00691 WORD TCPGetTxFIFOFull(TCP_SOCKET hTCP);
00692 // Alias to TCPIsGetReady provided for API completeness
00693 #define TCPGetRxFIFOFull(a)                 TCPIsGetReady(a)
00694 // Alias to TCPIsPutReady provided for API completeness
00695 #define TCPGetTxFIFOFree(a)                 TCPIsPutReady(a)
00696
00697 #define TCP_ADJUST_GIVE_REST_TO_RX  0x01u   // Resize flag: extra bytes go to RX
00698 #define TCP_ADJUST_GIVE_REST_TO_TX  0x02u   // Resize flag: extra bytes go to TX
00699 #define TCP_ADJUST_PRESERVE_RX      0x04u   // Resize flag: attempt to preserve RX buffer
00700 #define TCP_ADJUST_PRESERVE_TX      0x08u   // Resize flag: attempt to preserve TX buffer
00701 BOOL TCPAdjustFIFOSize(TCP_SOCKET hTCP, WORD wMinRXSize, WORD wMinTXSize, BYTE vFlags);
00702
00703 #if defined(STACK_USE_SSL)
00704 BOOL TCPStartSSLClient(TCP_SOCKET hTCP, BYTE* host);
00705 BOOL TCPStartSSLServer(TCP_SOCKET hTCP);
00706 BOOL TCPAddSSLListener(TCP_SOCKET hTCP, WORD port);
00707 BOOL TCPRequestSSLMessage(TCP_SOCKET hTCP, BYTE msg);
00708 BOOL TCPSSLIsHandshaking(TCP_SOCKET hTCP);
00709 BOOL TCPIsSSL(TCP_SOCKET hTCP);
00710 void TCPSSLHandshakeComplete(TCP_SOCKET hTCP);
00711 void TCPSSLDecryptMAC(TCP_SOCKET hTCP, ARCFOUR_CTX* ctx, WORD len, BOOL inPlace);
00712 void TCPSSLInPlaceMACEncrypt(TCP_SOCKET hTCP, ARCFOUR_CTX* ctx, BYTE* MACSecret, WORD len);
00713 void TCPSSLPutRecordHeader(TCP_SOCKET hTCP, BYTE* hdr, BOOL recDone);
00714 WORD TCPSSLGetPendingTxSize(TCP_SOCKET hTCP);
00715 void TCPSSLHandleIncoming(TCP_SOCKET hTCP);
00716 #endif
00717
00718 /*****************************************************************************
00719   Summary:
00720     Alias to TCPFindEx with no length parameter.
00721
00722   Description:
00723     This function is an alias to TCPFindEx with no length parameter.  It is
00724     provided for backwards compatibility with an older API.
00725   ***************************************************************************/
00726 #define TCPFind(a,b,c,d)                    TCPFindEx(a,b,c,0,d)
00727
00728
00729 /*****************************************************************************
00730   Summary:
00731     Alias to TCPFindArrayEx with no length parameter.
00732
00733   Description:
00734     This function is an alias to TCPFindArrayEx with no length parameter.  It is
00735     provided for backwards compatibility with an older API.
00736   ***************************************************************************/
00737 #define TCPFindArray(a,b,c,d,e)             TCPFindArrayEx(a,b,c,d,0,e)
00738
00739 /*****************************************************************************
00740   Summary:
00741     Alias to TCPOpen as a server.
00742
00743   Description:
00744     This function is an alias to TCPOpen for server sockets.  It is provided
00745     for backwards compatibility with older versions of the stack.  New
00746     applications should use the TCPOpen API instead.
00747   ***************************************************************************/
00748 #define TCPListen(port)         TCPOpen(0, TCP_OPEN_SERVER, port, TCP_PURPOSE_DEFAULT)
00749
00750 /*****************************************************************************
00751   Summary:
00752     Alias to TCPOpen as a client.
00753
00754   Description:
00755     This function is an alias to TCPOpen for client sockets.  It is provided
00756     for backwards compatibility with older versions of the stack.  New
00757     applications should use the TCPOpen API instead.
00758   ***************************************************************************/
00759 #define TCPConnect(remote,port) TCPOpen((DWORD)remote, TCP_OPEN_NODE_INFO, port, TCP_PURPOSE_DEFAULT)
00760
00761
00762 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCPIP.h Source File

TCPIP.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00017  /*********************************************************************
00018  * Software License Agreement
00019  *
00020  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00021  * reserved.
00022  *
00023  * Microchip licenses to you the right to use, modify, copy, and
00024  * distribute:
00025  * (i)  the Software when embedded on a Microchip microcontroller or
00026  *      digital signal controller product ("Device") which is
00027  *      integrated into Licensee's product; or
00028  * (ii) ONLY the Software driver source files ENC28J60.c and
00029  *      ENC28J60.h ported to a non-Microchip device used in
00030  *      conjunction with a Microchip ethernet controller for the
00031  *      sole purpose of interfacing with the ethernet controller.
00032  *
00033  * You should refer to the license agreement accompanying this
00034  * Software for additional information regarding your rights and
00035  * obligations.
00036  *
00037  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00038  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00039  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00040  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00041  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00042  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00043  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00044  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00045  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00046  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00047  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00048  *
00049  *
00050  * Author               Date        Comment
00051  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00052  * Howard Schlunder     12/20/06    Original
00053  ********************************************************************/
00054 #ifndef __TCPIP_H
00055 #define __TCPIP_H
00056
00057 #define VERSION         "v4.50"     // TCP/IP stack version
00058
00059 #include <string.h>
00060 #include <stdlib.h>
00061 #include "GenericTypeDefs.h"
00062 #include "Compiler.h"
00063
00064 /*******************************************************************
00065  * Memory Configuration
00066  *   The following section sets up the memory types for use by
00067  *   this application.
00068  *******************************************************************/
00069     // Represents data stored in Ethernet buffer RAM
00070     #define TCP_ETH_RAM 0
00071     // The base address for TCP data in Ethernet RAM
00072     #define TCP_ETH_RAM_BASE_ADDRESS            (BASE_TCB_ADDR)
00073     // Represents data stored in local PIC RAM
00074     #define TCP_PIC_RAM 1
00075     // The base address for TCP data in PIC RAM
00076     #define TCP_PIC_RAM_BASE_ADDRESS            ((PTR_BASE)&TCPBufferInPIC[0])
00077     // Represents data stored in external SPI RAM
00078     #define TCP_SPI_RAM 2
00079
00080 /*******************************************************************
00081  * User Configuration
00082  *   Load the user-specific configuration from TCPIPConfig.h
00083  *******************************************************************/
00084 #include "TCPIPConfig.h"
00085
00086 /*******************************************************************
00087  * Configuration Rules Enforcement
00088  *   The following section enforces requirements for modules based
00089  *   on configurations selected in TCPIPConfig.h
00090  *******************************************************************/
00091
00092     #if defined(STACK_USE_HTTP2_SERVER)
00093         #define STACK_USE_MPFS2
00094     #endif
00095
00096     // HTTP2 requires 2 MPFS2 handles per connection, plus one spare
00097     #if defined(STACK_USE_HTTP2_SERVER)
00098         #if MAX_MPFS_HANDLES < ((MAX_HTTP_CONNECTIONS * 2) + 1)
00099             #error HTTP2 requires 2 MPFS2 file handles per connection, plus one additional.
00100         #endif
00101     #endif
00102
00103 #include "StackTsk.h"
00104 #include "Helpers.h"
00105 #include "Tick.h"
00106 #include "MAC.h"
00107 #include "IP.h"
00108 #include "ARP.h"
00109 #include "UDP.h"
00110 #include "TCP.h"
00111 #include "DHCP.h"
00112 #include "ICMP.h"
00113 #include "MPFS2.h"
00114 #include "HTTP2.h"
00115 #include "../main.h"
00116
00117 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: TCPIPConfig.h Source File

TCPIPConfig.h

Go to the documentation of this file.
00001
00002
00003
00056 #ifndef __TCPIPCONFIG_H
00057 #define __TCPIPCONFIG_H
00058
00059 #include "TCPIP.h"
00060 #include "projectdefs.h"
00061
00062 // =======================================================================
00063 //   Application Options
00064 // =======================================================================
00065
00066 /* Application Level Module Selection
00067  *   Uncomment or comment the following lines to enable or
00068  *   disabled the following high-level application modules.
00069  */
00070 #define STACK_USE_ICMP_SERVER
00071 #define STACK_USE_HTTP2_SERVER
00072 #define STACK_USE_DHCP_CLIENT
00073 #define STACK_USE_MPFS2
00074
00075 /* MPFS File Handles
00076  *   Maximum number of simultaneously open MPFS2 files.
00077  *   For MPFS Classic, this has no effect.
00078  */
00079 #define MAX_MPFS_HANDLES                (5ul)
00080
00081 // =======================================================================
00082 //   Transport Layer Options
00083 // =======================================================================
00084
00085 /* Transport Layer Configuration
00086  *   The following low level modules are automatically enabled
00087  *   based on module selections above.  If your custom module
00088  *   requires them otherwise, enable them here.
00089  */
00090 #define STACK_USE_TCP
00091 #define STACK_USE_UDP
00092
00093 /* Client Mode Configuration
00094  *   Uncomment following line if this stack will be used in CLIENT
00095  *   mode.  In CLIENT mode, some functions specific to client operation
00096  *   are enabled.
00097  */
00098 #define STACK_CLIENT_MODE
00099
00100 /* TCP Socket Memory Allocation
00101  *   TCP needs memory to buffer incoming and outgoing data.  The
00102  *   amount and medium of storage can be allocated on a per-socket
00103  *   basis using the example below as a guide.
00104  */
00105     // Allocate how much total RAM (in bytes) you want to allocate
00106     // for use by your TCP TCBs, RX FIFOs, and TX FIFOs.
00107     #define TCP_ETH_RAM_SIZE                    (5220ul)
00108     #define TCP_PIC_RAM_SIZE                    (0ul)
00109     #define TCP_SPI_RAM_SIZE                    (0ul)
00110     #define TCP_SPI_RAM_BASE_ADDRESS            (0x00)
00111
00112     // Define names of socket types
00113     #define TCP_SOCKET_TYPES
00114         #define TCP_PURPOSE_GENERIC_TCP_CLIENT 0
00115         #define TCP_PURPOSE_GENERIC_TCP_SERVER 1
00116         #define TCP_PURPOSE_TELNET 2
00117         #define TCP_PURPOSE_FTP_COMMAND 3
00118         #define TCP_PURPOSE_FTP_DATA 4
00119         #define TCP_PURPOSE_TCP_PERFORMANCE_TX 5
00120         #define TCP_PURPOSE_TCP_PERFORMANCE_RX 6
00121         #define TCP_PURPOSE_UART_2_TCP_BRIDGE 7
00122         #define TCP_PURPOSE_HTTP_SERVER 8
00123         #define TCP_PURPOSE_DEFAULT 9
00124         #define TCP_PURPOSE_BERKELEY_SERVER 10
00125         #define TCP_PURPOSE_BERKELEY_CLIENT 11
00126     #define END_OF_TCP_SOCKET_TYPES
00127
00128     #if defined(__TCP_C)
00129         // Define what types of sockets are needed, how many of
00130         // each to include, where their TCB, TX FIFO, and RX FIFO
00131         // should be stored, and how big the RX and TX FIFOs should
00132         // be.  Making this initializer bigger or smaller defines
00133         // how many total TCP sockets are available.
00134         //
00135         // Each socket requires up to 48 bytes of PIC RAM and
00136         // 40+(TX FIFO size)+(RX FIFO size) bytes bytes of
00137         // TCP_*_RAM each.
00138         // Note: The RX FIFO must be at least 1 byte in order to
00139         // receive SYN and FIN messages required by TCP.  The TX
00140         // FIFO can be zero if desired.
00141         #define TCP_CONFIGURATION
00142         ROM struct
00143         {
00144             BYTE vSocketPurpose;
00145             BYTE vMemoryMedium;
00146             WORD wTXBufferSize;
00147             WORD wRXBufferSize;
00148         } TCPSocketInitializer[] =
00149         {
00150             {TCP_PURPOSE_HTTP_SERVER, TCP_ETH_RAM, 1500, 500},
00151
00152             PROJECT_SOCKET_CONFIGURATION
00153         };
00154         #define END_OF_TCP_CONFIGURATION
00155     #endif
00156
00157 /* UDP Socket Configuration
00158  *   Define the maximum number of available UDP Sockets, and whether
00159  *   or not to include a checksum on packets being transmitted.
00160  */
00161 #define MAX_UDP_SOCKETS     (5u)
00162 #define UDP_USE_TX_CHECKSUM     // This slows UDP TX performance by nearly 50%
00163
00164 // =======================================================================
00165 //   Application-Specific Options
00166 // =======================================================================
00167
00168 // -- HTTP2 Server options -----------------------------------------------
00169
00170     // Maximum numbers of simultaneous HTTP connections allowed.
00171     // Each connection consumes 2 bytes of RAM and a TCP socket
00172     #define MAX_HTTP_CONNECTIONS    (1u)
00173
00174     // Indicate what file to serve when no specific one is requested
00175     #define HTTP_DEFAULT_FILE       "index.htm"
00176     #define HTTPS_DEFAULT_FILE      "index.htm"
00177     #define HTTP_DEFAULT_LEN        (10u)           // For buffer overrun protection.
00178                                                 // Set to longest length of above two strings.
00179
00180     #define HTTP_USE_POST                   // Enable POST support
00181 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Tick.c Source File

Tick.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00021 /*********************************************************************
00022  * Software License Agreement
00023  *
00024  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00025  * reserved.
00026  *
00027  * Microchip licenses to you the right to use, modify, copy, and
00028  * distribute:
00029  * (i)  the Software when embedded on a Microchip microcontroller or
00030  *      digital signal controller product ("Device") which is
00031  *      integrated into Licensee's product; or
00032  * (ii) ONLY the Software driver source files ENC28J60.c and
00033  *      ENC28J60.h ported to a non-Microchip device used in
00034  *      conjunction with a Microchip ethernet controller for the
00035  *      sole purpose of interfacing with the ethernet controller.
00036  *
00037  * You should refer to the license agreement accompanying this
00038  * Software for additional information regarding your rights and
00039  * obligations.
00040  *
00041  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00042  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00043  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00044  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00045  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00046  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00047  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00048  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00049  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00050  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00051  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00052  *
00053  *
00054  * Author               Date        Comment
00055  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00056  * Nilesh Rajbharti     6/28/01     Original        (Rev 1.0)
00057  * Nilesh Rajbharti     2/9/02      Cleanup
00058  * Nilesh Rajbharti     5/22/02     Rev 2.0 (See version.log for detail)
00059  * Howard Schlunder     6/13/07     Changed to use timer without
00060  *                                  writing for perfect accuracy.
00061 ********************************************************************/
00062 #define __TICK_C
00063
00064 #include "TCPIP.h"
00065
00066 // Internal counter to store Ticks.
00067 static DWORD dwInternalTicks = 0;
00068
00069 // 6-byte value to store Ticks.  Allows for use over longer periods of time.
00070 static BYTE vTickReading[6];
00071
00072 static void GetTickCopy(void);
00073 void HighISR(void);
00074
00075 /*****************************************************************************
00076   Function:
00077     void TickInit(void)
00078
00079   Summary:
00080     Initializes the Tick manager module.
00081
00082   Description:
00083     Configures the Tick module and any necessary hardware resources.
00084
00085   Precondition:
00086     None
00087
00088   Parameters:
00089     None
00090
00091   Returns:
00092     None
00093
00094   Remarks:
00095     This function is called only one during lifetime of the application.
00096   ***************************************************************************/
00097 void TickInit(void)
00098 {
00099     // Use Timer0
00100     // Initialize the time
00101     TMR0H = 0;
00102     TMR0L = 0;
00103
00104     // Set up the timer interrupt
00105     INTCON2bits.TMR0IP = 1;     // High priority (MODIFIX: From low priority)
00106     INTCONbits.TMR0IF = 0;
00107     INTCONbits.TMR0IE = 1;      // Enable interrupt
00108
00109     // Timer0 on, 16-bit, internal timer, 1:256 prescaler
00110     T0CON = 0x87;
00111 }
00112
00113 /*****************************************************************************
00114   Function:
00115     static void GetTickCopy(void)
00116
00117   Summary:
00118     Reads the tick value.
00119
00120   Description:
00121     This function performs an interrupt-safe and synchronized read of the
00122     48-bit Tick value.
00123
00124   Precondition:
00125     None
00126
00127   Parameters:
00128     None
00129
00130   Returns:
00131     None
00132   ***************************************************************************/
00133 static void GetTickCopy(void)
00134 {
00135     // Perform an Interrupt safe and synchronized read of the 48-bit
00136     // tick value
00137     do
00138     {
00139         INTCONbits.TMR0IE = 1;      // Enable interrupt
00140         Nop();
00141         INTCONbits.TMR0IE = 0;      // Disable interrupt
00142         vTickReading[0] = TMR0L;
00143         vTickReading[1] = TMR0H;
00144         *((DWORD*)&vTickReading[2]) = dwInternalTicks;
00145     } while(INTCONbits.TMR0IF);
00146     INTCONbits.TMR0IE = 1;          // Enable interrupt
00147 }
00148
00149
00150 /*****************************************************************************
00151   Function:
00152     DWORD TickGet(void)
00153
00154   Summary:
00155     Obtains the current Tick value.
00156
00157   Description:
00158     This function retrieves the current Tick value, allowing timing and
00159     measurement code to be written in a non-blocking fashion.  This function
00160     retrieves the least significant 32 bits of the internal tick counter,
00161     and is useful for measuring time increments ranging from a few
00162     microseconds to a few hours.  Use TickGetDiv256 or TickGetDiv64K for
00163     longer periods of time.
00164
00165   Precondition:
00166     None
00167
00168   Parameters:
00169     None
00170
00171   Returns:
00172     Lower 32 bits of the current Tick value.
00173   ***************************************************************************/
00174 DWORD TickGet(void)
00175 {
00176     GetTickCopy();
00177     return *((DWORD*)&vTickReading[0]);
00178 }
00179
00180 /*****************************************************************************
00181   Function:
00182     DWORD TickGetDiv256(void)
00183
00184   Summary:
00185     Obtains the current Tick value divided by 256.
00186
00187   Description:
00188     This function retrieves the current Tick value, allowing timing and
00189     measurement code to be written in a non-blocking fashion.  This function
00190     retrieves the middle 32 bits of the internal tick counter,
00191     and is useful for measuring time increments ranging from a few
00192     minutes to a few weeks.  Use TickGet for shorter periods or TickGetDiv64K
00193     for longer ones.
00194
00195   Precondition:
00196     None
00197
00198   Parameters:
00199     None
00200
00201   Returns:
00202     Middle 32 bits of the current Tick value.
00203   ***************************************************************************/
00204 DWORD TickGetDiv256(void)
00205 {
00206     DWORD_VAL ret;
00207
00208     GetTickCopy();
00209     ret.v[0] = vTickReading[1]; // Note: This copy must be done one
00210     ret.v[1] = vTickReading[2]; // byte at a time to prevent misaligned
00211     ret.v[2] = vTickReading[3]; // memory reads, which will reset the PIC.
00212     ret.v[3] = vTickReading[4];
00213
00214     return ret.Val;
00215 }
00216
00217 // MODIFIX: Removed the function TickGetDiv64K because not needed by eWicht.
00218 // MODIFIX: Removed the function TickConvertToMilliseconds because not needed
00219 //          by eWicht. The ticks of eWicht are milliseconds!
00220
00221
00222 // MODIFIX: The TickUpdate function is replaced by a high prior ISR routine.
00223
00225 // High prior Interrupt Service Routine
00226
00227 #pragma code high_vector=0x08
00228 void high_interrupt (void)
00229 {
00230     _asm GOTO HighISR _endasm
00231 }
00232 #pragma code
00233
00234 #pragma interrupt HighISR
00235 void HighISR(void)
00236 {
00237     // Increment internal high tick counter
00238     dwInternalTicks++;
00239
00240     // Reset interrupt flag
00241     INTCONbits.TMR0IF = 0;
00242 }
00243
00244 // MODIFIX: Removed the function _T1Interrupt because not needed by eWicht.
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: Tick.h Source File

Tick.h

Go to the documentation of this file.
00001
00002
00003
00036
00037 /*********************************************************************
00038  * Software License Agreement
00039  *
00040  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00041  * reserved.
00042  *
00043  * Microchip licenses to you the right to use, modify, copy, and
00044  * distribute:
00045  * (i)  the Software when embedded on a Microchip microcontroller or
00046  *      digital signal controller product ("Device") which is
00047  *      integrated into Licensee's product; or
00048  * (ii) ONLY the Software driver source files ENC28J60.c and
00049  *      ENC28J60.h ported to a non-Microchip device used in
00050  *      conjunction with a Microchip ethernet controller for the
00051  *      sole purpose of interfacing with the ethernet controller.
00052  *
00053  * You should refer to the license agreement accompanying this
00054  * Software for additional information regarding your rights and
00055  * obligations.
00056  *
00057  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00058  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00059  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00060  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00061  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00062  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00063  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00064  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00065  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00066  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00067  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00068  *
00069  *
00070  * Author               Date    Comment
00071  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00072  * Nilesh Rajbharti     6/28/01 Original        (Rev 1.0)
00073  * Nilesh Rajbharti     2/9/02  Cleanup
00074  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
00075  ********************************************************************/
00076 #ifndef __TICK_H
00077 #define __TICK_H
00078
00079 #include "TCPIP.h"
00080
00081 // All TICKS are stored as 32-bit unsigned integers.
00082 typedef DWORD TICK;
00083
00084 // This value is used by TCP to implement timeout actions.
00085 // For this definition, the Timer must be initialized to use
00086 // a 1:256 prescaler in Tick.c.
00087 #define TICKS_PER_SECOND        ((GetPeripheralClock()+128ull)/256ull)  // Internal core clock drives timer
00088
00089 // Represents one second in Ticks
00090 #define TICK_SECOND             ((QWORD)TICKS_PER_SECOND)
00091 // Represents one minute in Ticks
00092 #define TICK_MINUTE             ((QWORD)TICKS_PER_SECOND)*60ull)
00093 // Represents one hour in Ticks
00094 #define TICK_HOUR               ((QWORD)TICKS_PER_SECOND*3600ull)
00095
00096 // Deprecated.  Do not use this function.
00097 #define TickGetDiff(a, b)       ((a)-(b))
00098
00099 void TickInit(void);
00100 DWORD TickGet(void);
00101 DWORD TickGetDiv256(void);
00102 // MODIFIX: Removed Prototype for TickGetDiv64K as not needed for eWicht.
00103 DWORD TickConvertToMilliseconds(DWORD dwTickValue);
00104 // MODIFIX: Removed Prototype for TickUpdate(void) because its replaced by
00105 //          an ISR.
00106
00108 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: UDP.c Source File

UDP.c

Go to the documentation of this file.
00001
00002
00003
00028 /*********************************************************************
00029  * Software License Agreement
00030  *
00031  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00032  * reserved.
00033  *
00034  * Microchip licenses to you the right to use, modify, copy, and
00035  * distribute:
00036  * (i)  the Software when embedded on a Microchip microcontroller or
00037  *      digital signal controller product ("Device") which is
00038  *      integrated into Licensee's product; or
00039  * (ii) ONLY the Software driver source files ENC28J60.c and
00040  *      ENC28J60.h ported to a non-Microchip device used in
00041  *      conjunction with a Microchip ethernet controller for the
00042  *      sole purpose of interfacing with the ethernet controller.
00043  *
00044  * You should refer to the license agreement accompanying this
00045  * Software for additional information regarding your rights and
00046  * obligations.
00047  *
00048  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00049  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00050  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00051  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00052  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00053  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00054  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00055  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00056  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00057  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00058  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00059  *
00060  *
00061  * Author               Date    Comment
00062  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00063  * Nilesh Rajbharti     3/19/01  Original        (Rev 1.0)
00064  * Nilesh Rajbharti     2/26/03  Fixed UDPGet and UDPProcess bugs
00065  *                               as discovered and fixed by John Owen
00066  *                               of Powerwave.
00067  *                               1. UDPGet would return FALSE on last good byte
00068  *                               2. UDPProcess was incorrectly calculating length.
00069  * Nilesh Rajbharti     5/19/03  Added bFirstRead flag similar to TCP
00070  *                               to detect very first UDPGet and
00071  *                               reset MAC Rx pointer to begining of
00072  *                               UDP data area.  This would ensure that
00073  *                               if UDP socket has pending Rx data and
00074  *                               another module resets MAC Rx pointer,
00075  *                               next UDP socket Get would get correct
00076  *                               data.
00077  * Robert Sloan (RSS)    5/29/03 Improved FindMatchingSocket()
00078  * Nilesh Rajbharti     12/2/03  Added UDPChecksum logic in UDPProcess()
00079  * Nilesh Rajbharti     12/5/03  Modified UDPProcess() and FindMatchingSocket()
00080  *                               to include localIP as new parameter.
00081  *                               This corrects pseudo header checksum
00082  *                               logic in UDPProcess().
00083  *                               It also corrects broadcast packet
00084  *                               matching correct in FindMatchingSocket().
00085  * Howard Schlunder     1/16/06  Fixed an imporbable RX checksum bug
00086  *                               when using a Microchip Ethernet controller)
00087  * Howard Schlunder     6/02/06  Fixed a bug where all RXed UDP packets
00088  *                               without a checksum (0x0000) were thrown
00089  *                               away.  No checksum is legal in UDP.
00090  * Howard Schlunder     8/10/06  Fixed a bug where UDP sockets would
00091  *                               unintentionally keep the remote MAC
00092  *                               address cached, even after calling
00093  *                               UDPInit(), UDPClose(), or reseting
00094  *                               the part without clearing all the
00095  *                               PIC memory.
00096  ********************************************************************/
00097 #define __UDP_C
00098
00099 #include "TCPIP.h"
00100 #include "mdns.h"
00101
00102
00103 /****************************************************************************
00104   Section:
00105     Configuration Parameters
00106   ***************************************************************************/
00107
00108 // First port number for randomized local port number selection
00109 #define LOCAL_UDP_PORT_START_NUMBER (4096u)
00110
00111 // Last port number for randomized local port number selection
00112 #define LOCAL_UDP_PORT_END_NUMBER   (8192u)
00113
00114 /****************************************************************************
00115   Section:
00116     UDP Global Variables
00117   ***************************************************************************/
00118
00119 // Stores an array of information pertaining to each UDP socket
00120 UDP_SOCKET_INFO     UDPSocketInfo[MAX_UDP_SOCKETS];
00121
00122 // Indicates which UDP socket is currently active
00123 UDP_SOCKET          activeUDPSocket;
00124
00125 WORD UDPTxCount;    // Number of bytes written to this UDP segment
00126 WORD UDPRxCount;    // Number of bytes read from this UDP segment
00127 static UDP_SOCKET   LastPutSocket = INVALID_UDP_SOCKET; // Indicates the last socket to which data was written
00128 static WORD wPutOffset;     // Offset from beginning of payload where data is to be written.
00129 static WORD wGetOffset;     // Offset from beginning of payload from where data is to be read.
00130
00131 // Stores various flags for the UDP module
00132 static struct
00133 {
00134     unsigned char bFirstRead : 1;       // No data has been read from this segment yet
00135     unsigned char bWasDiscarded : 1;    // The data in this segment has been discarded
00136 } Flags;
00137
00138 // Indicates which socket has currently received data for this loop
00139 static UDP_SOCKET SocketWithRxData = INVALID_UDP_SOCKET;
00140
00141 /****************************************************************************
00142   Section:
00143     Function Prototypes
00144   ***************************************************************************/
00145
00146 static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode,
00147                                     IP_ADDR *localIP);
00148
00149 /****************************************************************************
00150   Section:
00151     Connection Management Functions
00152   ***************************************************************************/
00153
00154 /*****************************************************************************
00155   Function:
00156     void UDPInit(void)
00157
00158   Summary:
00159     Initializes the UDP module.
00160
00161   Description:
00162     Initializes the UDP module.  This function initializes all the UDP
00163     sockets to the closed state.
00164
00165   Precondition:
00166     None
00167
00168   Parameters:
00169     None
00170
00171   Returns:
00172     None
00173
00174   Remarks:
00175     This function is called only one during lifetime of the application.
00176   ***************************************************************************/
00177 void UDPInit(void)
00178 {
00179     UDP_SOCKET s;
00180
00181     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
00182     {
00183         UDPClose(s);
00184     }
00185     Flags.bWasDiscarded = 1;
00186 }
00187
00188
00189 /*****************************************************************************
00190   Function:
00191     void UDPTask(void)
00192
00193   Summary:
00194     Performs state management and housekeeping for UDP.
00195
00196   Description:
00197     Performs state management and housekeeping for UDP.  This is an internal
00198     function meant to be called by StackTask() (not a user API).
00199
00200   Precondition:
00201     None
00202
00203   Parameters:
00204     None
00205
00206   Return Values:
00207     None
00208
00209   Remarks:
00210     UDPTask() is called once per StackTask() iteration to ensure that calls
00211     to UDPIsPutReady() always update the Ethernet Write pointer location
00212     between StackTask() iterations.
00213   ***************************************************************************/
00214 void UDPTask(void)
00215 {
00216     LastPutSocket = INVALID_UDP_SOCKET;
00217 }
00218
00219
00220 /*****************************************************************************
00221   Function:
00222     UDP_SOCKET UDPOpen(UDP_PORT localPort, NODE_INFO* remoteNode,
00223                         UDP_PORT remotePort)
00224
00225   Summary:
00226     Creates a UDP socket handle for transmiting or receiving UDP packets.
00227
00228   Description:
00229     Creates a UDP socket handle for transmiting or receiving UDP packets.
00230     Call this function to obtain a handle required by other UDP function.
00231
00232   Precondition:
00233     UDPInit() must have been previously called.
00234
00235   Parameters:
00236     localPort - UDP port number to listen on.  If 0, stack will dynamically
00237         assign a unique port number to use.
00238     remoteNode - Pointer to remote node info (MAC and IP address) for this
00239         connection.  If this is a server socket (receives the first packet)
00240         or the destination is the broadcast address, then this parameter
00241         should be NULL.
00242     remotePort - For client sockets, the remote port number.
00243
00244   Return Values:
00245     Success -
00246         A UDP socket handle that can be used for subsequent UDP API calls.
00247     Failure -
00248         INVALID_UDP_SOCKET.  This function fails when no more UDP socket
00249         handles are available.  Increase MAX_UDP_SOCKETS to make more sockets
00250         available.
00251
00252   Remarks:
00253     When finished using the UDP socket handle, call the UDPClose() function
00254     to free the socket and delete the handle.
00255   ***************************************************************************/
00256 UDP_SOCKET UDPOpen(UDP_PORT localPort,
00257                    NODE_INFO *remoteNode,
00258                    UDP_PORT remotePort)
00259 {
00260     UDP_SOCKET s;
00261     UDP_SOCKET_INFO *p;
00262
00263     // Local temp port numbers.
00264     static WORD NextPort __attribute__((persistent));
00265
00266
00267     p = UDPSocketInfo;
00268     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
00269     {
00270         if(p->localPort == INVALID_UDP_PORT)
00271         {
00272             p->localPort = localPort;
00273
00274             if(localPort == 0x0000u)
00275             {
00276                 if(NextPort > LOCAL_UDP_PORT_END_NUMBER || NextPort < LOCAL_UDP_PORT_START_NUMBER)
00277                     NextPort = LOCAL_UDP_PORT_START_NUMBER;
00278
00279                 p->localPort    = NextPort++;
00280             }
00281
00282             // If remoteNode is supplied, remember it.
00283             if(remoteNode)
00284             {
00285                 memcpy((void*)&p->remoteNode,
00286                         (const void*)remoteNode,
00287                         sizeof(p->remoteNode));
00288             }
00289             else
00290             {
00291                 // else Set broadcast address
00292                 memset((void*)&p->remoteNode, 0xFF, sizeof(p->remoteNode));
00293             }
00294
00295             p->remotePort   = remotePort;
00296
00297             // Mark this socket as active.
00298             // Once an active socket is set, subsequent operation can be
00299             // done without explicitely supply socket identifier.
00300             activeUDPSocket = s;
00301             return s;
00302         }
00303         p++;
00304     }
00305
00306     return (UDP_SOCKET)INVALID_UDP_SOCKET;
00307 }
00308
00309
00310
00311
00312 /*****************************************************************************
00313   Function:
00314     void UDPClose(UDP_SOCKET s)
00315
00316   Summary:
00317     Closes a UDP socket and frees the handle.
00318
00319   Description:
00320     Closes a UDP socket and frees the handle.  Call this function to release
00321     a socket and return it to the pool for use by future communications.
00322
00323   Precondition:
00324     UDPInit() must have been previously called.
00325
00326   Parameters:
00327     s - The socket handle to be released.
00328
00329   Returns:
00330     None
00331
00332   Remarks:
00333     This function does not affect the previously designated active socket.
00334   ***************************************************************************/
00335 void UDPClose(UDP_SOCKET s)
00336 {
00337     if(s == INVALID_UDP_SOCKET)
00338         return;
00339
00340     UDPSocketInfo[s].localPort = INVALID_UDP_PORT;
00341     UDPSocketInfo[s].remoteNode.IPAddr.Val = 0x00000000;
00342 }
00343
00344
00345 /*****************************************************************************
00346   Function:
00347     void UDPSetTxBuffer(WORD wOffset)
00348
00349   Summary:
00350     Moves the pointer within the TX buffer.
00351
00352   Description:
00353     This function allows the write location within the TX buffer to be
00354     specified.  Future calls to UDPPut, UDPPutArray, UDPPutString, etc will
00355     write data from the indicated location.
00356
00357   Precondition:
00358     UDPInit() must have been previously called and a socket is currently
00359     active.
00360
00361   Parameters:
00362     wOffset - Offset from beginning of UDP packet data payload to place the
00363         write pointer.
00364
00365   Returns:
00366     None
00367   ***************************************************************************/
00368 void UDPSetTxBuffer(WORD wOffset)
00369 {
00370     IPSetTxBuffer(wOffset+sizeof(UDP_HEADER));
00371     wPutOffset = wOffset;
00372 }
00373
00374
00375 /*****************************************************************************
00376   Function:
00377     void UDPSetRxBuffer(WORD wOffset)
00378
00379   Summary:
00380     Moves the pointer within the RX buffer.
00381
00382   Description:
00383     This function allows the read location within the RX buffer to be
00384     specified.  Future calls to UDPGet and UDPGetArray will read data from
00385     the indicated location forward.
00386
00387   Precondition:
00388     UDPInit() must have been previously called and a socket is currently
00389     active.
00390
00391   Parameters:
00392     wOffset - Offset from beginning of UDP packet data payload to place the
00393         read pointer.
00394
00395   Returns:
00396     None
00397   ***************************************************************************/
00398 void UDPSetRxBuffer(WORD wOffset)
00399 {
00400     IPSetRxBuffer(wOffset+sizeof(UDP_HEADER));
00401     wGetOffset = wOffset;
00402 }
00403
00404
00405
00406 /****************************************************************************
00407   Section:
00408     Transmit Functions
00409   ***************************************************************************/
00410
00411 /*****************************************************************************
00412   Function:
00413     WORD UDPIsPutReady(UDP_SOCKET s)
00414
00415   Summary:
00416     Determines how many bytes can be written to the UDP socket.
00417
00418   Description:
00419     This function determines if bytes can be written to the specified UDP
00420     socket.  It also prepares the UDP module for writing by setting the
00421     indicated socket as the currently active connection.
00422
00423   Precondition:
00424     UDPInit() must have been previously called.
00425
00426   Parameters:
00427     s - The socket to be made active
00428
00429   Returns:
00430     The number of bytes that can be written to this socket.
00431   ***************************************************************************/
00432 WORD UDPIsPutReady(UDP_SOCKET s)
00433 {
00434     if(!MACIsTxReady())
00435         return 0;
00436
00437     if(LastPutSocket != s)
00438     {
00439         LastPutSocket = s;
00440         UDPTxCount = 0;
00441         UDPSetTxBuffer(0);
00442     }
00443
00444     activeUDPSocket = s;
00445
00446     return MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER) - UDPTxCount;
00447 }
00448
00449 /*****************************************************************************
00450   Function:
00451     BOOL UDPPut(BYTE v)
00452
00453   Summary:
00454     Writes a byte to the currently active socket.
00455
00456   Description:
00457     This function writes a single byte to the currently active UDP socket,
00458     while incrementing the buffer length.  UDPIsPutReady should be used
00459     before calling this function to specify the currently active socket.
00460
00461   Precondition:
00462     UDPIsPutReady() was previously called to specify the current socket.
00463
00464   Parameters:
00465     v - The byte to be loaded into the transmit buffer.
00466
00467   Return Values:
00468     TRUE - The byte was successfully written to the socket.
00469     FALSE - The transmit buffer is already full and so the write failed.
00470   ***************************************************************************/
00471 BOOL UDPPut(BYTE v)
00472 {
00473     // See if we are out of transmit space.
00474     if(wPutOffset >= (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)))
00475     {
00476         return FALSE;
00477     }
00478
00479     // Load application data byte
00480     MACPut(v);
00481     wPutOffset++;
00482     if(wPutOffset > UDPTxCount)
00483         UDPTxCount = wPutOffset;
00484
00485     return TRUE;
00486 }
00487
00488 /*****************************************************************************
00489   Function:
00490     WORD UDPPutArray(BYTE *cData, WORD wDataLen)
00491
00492   Summary:
00493     Writes an array of bytes to the currently active socket.
00494
00495   Description:
00496     This function writes an array of bytes to the currently active UDP socket,
00497     while incrementing the buffer length.  UDPIsPutReady should be used
00498     before calling this function to specify the currently active socket.
00499
00500   Precondition:
00501     UDPIsPutReady() was previously called to specify the current socket.
00502
00503   Parameters:
00504     cData - The array to write to the socket.
00505     wDateLen - Number of bytes from cData to be written.
00506
00507   Returns:
00508     The number of bytes successfully placed in the UDP transmit buffer.  If
00509     this value is less than wDataLen, then the buffer became full and the
00510     input was truncated.
00511   ***************************************************************************/
00512 WORD UDPPutArray(BYTE *cData, WORD wDataLen)
00513 {
00514     WORD wTemp;
00515
00516     wTemp = (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)) - wPutOffset;
00517     if(wTemp < wDataLen)
00518         wDataLen = wTemp;
00519
00520     wPutOffset += wDataLen;
00521     if(wPutOffset > UDPTxCount)
00522         UDPTxCount = wPutOffset;
00523
00524     // Load application data bytes
00525     MACPutArray(cData, wDataLen);
00526
00527     return wDataLen;
00528 }
00529
00530 /*****************************************************************************
00531   Function:
00532     WORD UDPPutROMArray(ROM BYTE *cData, WORD wDataLen)
00533
00534   Summary:
00535     Writes an array of bytes from ROM to the currently active socket.
00536
00537   Description:
00538     This function writes an array of bytes from ROM to the currently active
00539     UDP socket, while incrementing the buffer length.  UDPIsPutReady should
00540     be used before calling this function to specify the currently active
00541     socket.
00542
00543   Precondition:
00544     UDPIsPutReady() was previously called to specify the current socket.
00545
00546   Parameters:
00547     cData - The array to write to the socket.
00548     wDateLen - Number of bytes from cData to be written.
00549
00550   Returns:
00551     The number of bytes successfully placed in the UDP transmit buffer.  If
00552     this value is less than wDataLen, then the buffer became full and the
00553     input was truncated.
00554
00555   Remarks:
00556     This function is aliased to UDPPutArray on non-PIC18 platforms.
00557   ***************************************************************************/
00558 #if defined(__18CXX)
00559 WORD UDPPutROMArray(ROM BYTE *cData, WORD wDataLen)
00560 {
00561     WORD wTemp;
00562
00563     wTemp = (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)) - wPutOffset;
00564     if(wTemp < wDataLen)
00565         wDataLen = wTemp;
00566
00567     wPutOffset += wDataLen;
00568     if(wPutOffset > UDPTxCount)
00569         UDPTxCount = wPutOffset;
00570
00571     // Load application data bytes
00572     MACPutROMArray(cData, wDataLen);
00573
00574     return wDataLen;
00575 }
00576 #endif
00577
00578 /*****************************************************************************
00579   Function:
00580     BYTE* UDPPutString(BYTE *strData)
00581
00582   Summary:
00583     Writes null-terminated string to the currently active socket.
00584
00585   Description:
00586     This function writes a null-terminated string to the currently active
00587     UDP socket, while incrementing the buffer length.  UDPIsPutReady should
00588     be used before calling this function to specify the currently active
00589     socket.
00590
00591   Precondition:
00592     UDPIsPutReady() was previously called to specify the current socket.
00593
00594   Parameters:
00595     cData - Pointer to the string to be written to the socket.
00596
00597   Returns:
00598     A pointer to the byte following the last byte written.  Note that this
00599     is different than the UDPPutArray functions.  If this pointer does not
00600     dereference to a NULL byte, then the buffer became full and the input
00601     data was truncated.
00602   ***************************************************************************/
00603 BYTE* UDPPutString(BYTE *strData)
00604 {
00605     return strData + UDPPutArray(strData, strlen((char*)strData));
00606 }
00607
00608 /*****************************************************************************
00609   Function:
00610     BYTE* UDPPutString(BYTE *strData)
00611
00612   Summary:
00613     Writes null-terminated string from ROM to the currently active socket.
00614
00615   Description:
00616     This function writes a null-terminated string from ROM to the currently
00617     active UDP socket, while incrementing the buffer length.  UDPIsPutReady
00618     should be used before calling this function to specify the currently
00619     active socket.
00620
00621   Precondition:
00622     UDPIsPutReady() was previously called to specify the current socket.
00623
00624   Parameters:
00625     cData - Pointer to the string to be written to the socket.
00626
00627   Returns:
00628     A pointer to the byte following the last byte written.  Note that this
00629     is different than the UDPPutArray functions.  If this pointer does not
00630     dereference to a NULL byte, then the buffer became full and the input
00631     data was truncated.
00632
00633   Remarks:
00634     This function is aliased to UDPPutString on non-PIC18 platforms.
00635   ***************************************************************************/
00636 #if defined(__18CXX)
00637 ROM BYTE* UDPPutROMString(ROM BYTE *strData)
00638 {
00639     return strData + UDPPutROMArray(strData, strlenpgm((ROM char*)strData));
00640 }
00641 #endif
00642
00643 /*****************************************************************************
00644   Function:
00645     void UDPFlush(void)
00646
00647   Summary:
00648     Transmits all pending data in a UDP socket.
00649
00650   Description:
00651     This function builds a UDP packet with the pending TX data and marks it
00652     for transmission over the network interface.  Since UDP is a frame-based
00653     protocol, this function must be called before returning to the main
00654     stack loop whenever any data is written.
00655
00656   Precondition:
00657     UDPIsPutReady() was previously called to specify the current socket, and
00658     data has been written to the socket using the UDPPut family of functions.
00659
00660   Parameters:
00661     None
00662
00663   Returns:
00664     None
00665
00666   Remarks:
00667     Note that unlike TCPFlush, UDPFlush must be called before returning to
00668     the main stack loop.  There is no auto transmit for UDP segments.
00669   ***************************************************************************/
00670 void UDPFlush(void)
00671 {
00672     UDP_HEADER      h;
00673     UDP_SOCKET_INFO *p;
00674     WORD            wReadPtrSave;
00675     WORD            wChecksum;
00676     WORD            wUDPLength;
00677
00678     p = &UDPSocketInfo[activeUDPSocket];
00679
00680     wUDPLength = UDPTxCount + sizeof(UDP_HEADER);
00681
00682     // Generate the correct UDP header
00683     h.SourcePort        = swaps(p->localPort);
00684     h.DestinationPort   = swaps(p->remotePort);
00685     h.Length            = swaps(wUDPLength);
00686     h.Checksum          = 0x0000;
00687
00688     // Calculate IP pseudoheader checksum if we are going to enable
00689     // the checksum field
00690     #if defined(UDP_USE_TX_CHECKSUM)
00691     {
00692         PSEUDO_HEADER   pseudoHeader;
00693
00694         // MODIFIX: Use the eWicht structure sIPConfig.
00695         pseudoHeader.SourceAddress  = sIPConfig.MyIPAddr;
00696         pseudoHeader.DestAddress    = p->remoteNode.IPAddr;
00697         pseudoHeader.Zero           = 0x0;
00698         pseudoHeader.Protocol       = IP_PROT_UDP;
00699         pseudoHeader.Length         = wUDPLength;
00700         SwapPseudoHeader(pseudoHeader);
00701         h.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader));
00702     }
00703     #endif
00704
00705     // Position the hardware write pointer where we will need to
00706     // begin writing the IP header
00707     MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
00708
00709     // Write IP header to packet
00710     IPPutHeader(&p->remoteNode, IP_PROT_UDP, wUDPLength);
00711
00712     // Write UDP header to packet
00713     MACPutArray((BYTE*)&h, sizeof(h));
00714
00715     // Calculate the final UDP checksum and write it in, if enabled
00716     #if defined(UDP_USE_TX_CHECKSUM)
00717     {
00718         wReadPtrSave = MACSetReadPtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER));
00719         wChecksum = CalcIPBufferChecksum(wUDPLength);
00720         MACSetReadPtr(wReadPtrSave);
00721         MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + 6);    // 6 is the offset to the Checksum field in UDP_HEADER
00722         MACPutArray((BYTE*)&wChecksum, sizeof(wChecksum));
00723     }
00724     #endif
00725
00726     // Transmit the packet
00727     MACFlush();
00728
00729     // Reset packet size counter for the next TX operation
00730     UDPTxCount = 0;
00731     LastPutSocket = INVALID_UDP_SOCKET;
00732 }
00733
00734
00735
00736 /****************************************************************************
00737   Section:
00738     Receive Functions
00739   ***************************************************************************/
00740
00741 /*****************************************************************************
00742   Function:
00743     WORD UDPIsGetReady(UDP_SOCKET s)
00744
00745   Summary:
00746     Determines how many bytes can be read from the UDP socket.
00747
00748   Description:
00749     This function determines if bytes can be read from the specified UDP
00750     socket.  It also prepares the UDP module for reading by setting the
00751     indicated socket as the currently active connection.
00752
00753   Precondition:
00754     UDPInit() must have been previously called.
00755
00756   Parameters:
00757     s - The socket to be made active (which has already been opened or is
00758         listening)
00759
00760   Returns:
00761     The number of bytes that can be read from this socket.
00762   ***************************************************************************/
00763 WORD UDPIsGetReady(UDP_SOCKET s)
00764 {
00765     activeUDPSocket = s;
00766     if(SocketWithRxData != s)
00767         return 0;
00768
00769     // If this is the very first time we are accessing this packet,
00770     // move the read point to the begining of the packet.
00771     if(Flags.bFirstRead)
00772     {
00773         Flags.bFirstRead = 0;
00774         UDPSetRxBuffer(0);
00775     }
00776
00777     return UDPRxCount;
00778 }
00779
00780 /*****************************************************************************
00781   Function:
00782     BOOL UDPGet(BYTE *v)
00783
00784   Summary:
00785     Reads a byte from the currently active socket.
00786
00787   Description:
00788     This function reads a single byte from the currently active UDP socket,
00789     while decrementing the remaining buffer length.  UDPIsGetReady should be
00790     used before calling this function to specify the currently active socket.
00791
00792   Precondition:
00793     UDPIsGetReady() was previously called to specify the current socket.
00794
00795   Parameters:
00796     v - The buffer to receive the data being read.
00797
00798   Return Values:
00799     TRUE - A byte was successfully read
00800     FALSE - No data remained in the read buffer
00801   ***************************************************************************/
00802 BOOL UDPGet(BYTE *v)
00803 {
00804     // Make sure that there is data to return
00805     if((wGetOffset >= UDPRxCount) || (SocketWithRxData != activeUDPSocket))
00806         return FALSE;
00807
00808     *v = MACGet();
00809     wGetOffset++;
00810
00811     return TRUE;
00812 }
00813
00814
00815 /*****************************************************************************
00816   Function:
00817     WORD UDPGetArray(BYTE *cData, WORD wDataLen)
00818
00819   Summary:
00820     Reads an array of bytes from the currently active socket.
00821
00822   Description:
00823     This function reads an array from bytes to the currently active UDP socket,
00824     while decrementing the remaining buffer length.  UDPIsGetReady should be
00825     used before calling this function to specify the currently active socket.
00826
00827   Precondition:
00828     UDPIsPutReady() was previously called to specify the current socket.
00829
00830   Parameters:
00831     cData - The buffer to receive the bytes being read.
00832     wDateLen - Number of bytes to be read from the socket.
00833
00834   Returns:
00835     The number of bytes successfully read from the UDP buffer.  If this
00836     value is less than wDataLen, then the buffer was emptied and no more
00837     data is available.
00838   ***************************************************************************/
00839 WORD UDPGetArray(BYTE *cData, WORD wDataLen)
00840 {
00841     WORD wBytesAvailable;
00842
00843     // Make sure that there is data to return
00844     if((wGetOffset >= UDPRxCount) || (SocketWithRxData != activeUDPSocket))
00845         return 0;
00846
00847     // Make sure we don't try to read more data than exists
00848     wBytesAvailable = UDPRxCount - wGetOffset;
00849     if(wBytesAvailable < wDataLen)
00850         wDataLen = wBytesAvailable;
00851
00852     wDataLen = MACGetArray(cData, wDataLen);
00853     wGetOffset += wDataLen;
00854
00855     return wDataLen;
00856 }
00857
00858 /*****************************************************************************
00859   Function:
00860     void UDPDiscard(void)
00861
00862   Summary:
00863     Discards any remaining RX data from a UDP socket.
00864
00865   Description:
00866     This function discards any remaining received data in the currently
00867     active UDP socket.
00868
00869   Precondition:
00870     UDPIsGetReady() was previously called to select the currently active
00871     socket.
00872
00873   Parameters:
00874     None
00875
00876   Returns:
00877     None
00878
00879   Remarks:
00880     It is safe to call this function more than is necessary.  If no data is
00881     available, this function does nothing.
00882   ***************************************************************************/
00883 void UDPDiscard(void)
00884 {
00885     if(!Flags.bWasDiscarded)
00886     {
00887         MACDiscardRx();
00888         UDPRxCount = 0;
00889         Flags.bWasDiscarded = 1;
00890     }
00891 }
00892
00893
00894
00895 /****************************************************************************
00896   Section:
00897     Data Processing Functions
00898   ***************************************************************************/
00899
00900 /*****************************************************************************
00901   Function:
00902     BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
00903
00904   Summary:
00905     Handles an incoming UDP segment.
00906
00907   Description:
00908     This function handles an incoming UDP segment to determine if it is
00909     acceptable and should be handed to one of the stack applications for
00910     processing.
00911
00912   Precondition:
00913     UDPInit() has been called an a UDP segment is ready in the MAC buffer.
00914
00915   Parameters:
00916     remoteNode - The remote node that sent this segment.
00917     localIP - The destination IP address for this segment.
00918     len - Total length of the UDP segment.
00919
00920   Return Values:
00921     TRUE - A valid packet is waiting and the stack applications should be
00922         called to handle it.
00923     FALSE - The packet was discarded.
00924   ***************************************************************************/
00925
00926 BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
00927 {
00928     UDP_HEADER      h;
00929     UDP_SOCKET      s;
00930     PSEUDO_HEADER   pseudoHeader;
00931     DWORD_VAL       checksums;
00932
00933     // MODIFIX: Check for valid IP addresses here, else return!
00934     // Valid IP addresses:
00935     // 1) Broadcast (255.255.255.255)
00936     // 2) Multicast (All in-between 224.0.0.0 and 239.255.255.255)
00937     // 3) Network-Broadcast (i.e for a 192.168.1/24 network this is 192.168.1.255)
00938     //      ->  not supported and therefore commented out.
00939     // 4) Unicast with matching IP address.
00940     if ((localIP->Val != 0xFFFFFFFFul) &&
00941         ((localIP->v[0] < 224) || (localIP->v[0] > 239)) &&
00942 //      (localIP->Val != (sIPConfig.MyIPAddr.Val | (~sIPConfig.MyMask.Val))) &&
00943         (localIP->Val != sIPConfig.MyIPAddr.Val))
00944     {
00945         return FALSE;
00946     }
00947
00948
00949     SocketWithRxData = INVALID_UDP_SOCKET;
00950     UDPRxCount = 0;
00951
00952     // Retrieve UDP header.
00953     MACGetArray((BYTE*)&h, sizeof(h));
00954
00955     h.SourcePort        = swaps(h.SourcePort);
00956     h.DestinationPort   = swaps(h.DestinationPort);
00957     h.Length            = swaps(h.Length) - sizeof(UDP_HEADER);
00958
00959     // See if we need to validate the checksum field (0x0000 is disabled)
00960     if(h.Checksum)
00961     {
00962         // Calculate IP pseudoheader checksum.
00963         pseudoHeader.SourceAddress      = remoteNode->IPAddr;
00964         pseudoHeader.DestAddress.Val    = localIP->Val;
00965         pseudoHeader.Zero               = 0x0;
00966         pseudoHeader.Protocol           = IP_PROT_UDP;
00967         pseudoHeader.Length             = len;
00968
00969         SwapPseudoHeader(pseudoHeader);
00970
00971         checksums.w[0] = ~CalcIPChecksum((BYTE*)&pseudoHeader,
00972                                         sizeof(pseudoHeader));
00973
00974
00975         // Now calculate UDP packet checksum in NIC RAM -- should match pseudoHeader
00976         IPSetRxBuffer(0);
00977         checksums.w[1] = CalcIPBufferChecksum(len);
00978
00979         if(checksums.w[0] != checksums.w[1])
00980         {
00981             MACDiscardRx();
00982             return FALSE;
00983         }
00984     }
00985
00986     s = FindMatchingSocket(&h, remoteNode, localIP);
00987     if(s == INVALID_UDP_SOCKET)
00988     {
00989         // If there is no matching socket, There is no one to handle
00990         // this data.  Discard it.
00991         MACDiscardRx();
00992         return FALSE;
00993     }
00994     else
00995     {
00996         SocketWithRxData = s;
00997         UDPRxCount = h.Length;
00998         Flags.bFirstRead = 1;
00999         Flags.bWasDiscarded = 0;
01000     }
01001
01002     // MODIFIX: Add this request for a quick processing of the MDNS frames.
01003     // Especially the remote node and destination data is needed by MDNS
01004     // responder for answering via MDNS unicasts.
01005     if(UDPSocketInfo[s].remotePort == MDNS_PORT)
01006     {
01007         MDNSProcessFrame(remoteNode, localIP);
01008         return FALSE;
01009     }
01010
01011     return TRUE;
01012 }
01013
01014 /*****************************************************************************
01015   Function:
01016     static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode,
01017                                             IP_ADDR *localIP)
01018
01019   Summary:
01020     Matches an incoming UDP segment to a currently active socket.
01021
01022   Description:
01023     This function attempts to match an incoming UDP segment to a currently
01024     active socket for processing.
01025
01026   Precondition:
01027     UDP segment header and IP header have both been retrieved.
01028
01029   Parameters:
01030     h - The UDP header that was received.
01031     remoteNode - IP and MAC of the remote node that sent this segment.
01032     localIP - IP address that this segment was destined for.
01033
01034   Returns:
01035     A UDP_SOCKET handle of a matching socket, or INVALID_UDP_SOCKET when no
01036     match could be made.
01037   ***************************************************************************/
01038 static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h,
01039                                      NODE_INFO *remoteNode,
01040                                      IP_ADDR *localIP)
01041 {
01042     UDP_SOCKET s;
01043     UDP_SOCKET partialMatch;
01044     UDP_SOCKET_INFO *p;
01045
01046     partialMatch = INVALID_UDP_SOCKET;
01047
01048     p = UDPSocketInfo;
01049     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
01050     {
01051         // This packet is said to be matching with current socket:
01052         // 1. If its destination port matches with our local port and
01053         // 2. Packet source IP address matches with socket remote IP address.
01054         //    OR this socket had transmitted packet with destination address as broadcast (subnet or limited broadcast).
01055         if ( p->localPort == h->DestinationPort )
01056         {
01057             if(p->remotePort == h->SourcePort)
01058             {
01059                 // MODIFIX: Special handling for MDNS frames:
01060                 if (p->remotePort == MDNS_PORT)
01061                 {
01062                     return s;
01063                 }
01064
01065                 // MODIFIX: Removed the IP request, is done before.
01066                 if (p->remoteNode.IPAddr.Val == remoteNode->IPAddr.Val)
01067                 {
01068                     return s;
01069                 }
01070             }
01071
01072             partialMatch = s;
01073         }
01074         p++;
01075     }
01076
01077     if ( partialMatch != INVALID_UDP_SOCKET )
01078     {
01079         p = &UDPSocketInfo[partialMatch];
01080
01081         memcpy((void*)&p->remoteNode,
01082                 (const void*)remoteNode, sizeof(p->remoteNode));
01083
01084         p->remotePort = h->SourcePort;
01085     }
01086     return partialMatch;
01087 }
01088
01089
01092
01093 // MODIFIX: Added the following function for retrieving the amount of already
01094 // put bytes.
01095 WORD UDPGetPutOffset(void)
01096 {
01097     return wPutOffset;
01098 }
01099
01102 // MODIFIX: Added the following function for retrieving the amount of already
01103 // got bytes.
01104
01105 WORD UDPGetGetOffset(void)
01106 {
01107     return wGetOffset;
01108 }
01109
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: UDP.h Source File

UDP.h

Go to the documentation of this file.
00001
00002
00003
00029 /*********************************************************************
00030  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00031  * reserved.
00032  *
00033  * Microchip licenses to you the right to use, modify, copy, and
00034  * distribute:
00035  * (i)  the Software when embedded on a Microchip microcontroller or
00036  *      digital signal controller product ("Device") which is
00037  *      integrated into Licensee's product; or
00038  * (ii) ONLY the Software driver source files ENC28J60.c and
00039  *      ENC28J60.h ported to a non-Microchip device used in
00040  *      conjunction with a Microchip ethernet controller for the
00041  *      sole purpose of interfacing with the ethernet controller.
00042  *
00043  * You should refer to the license agreement accompanying this
00044  * Software for additional information regarding your rights and
00045  * obligations.
00046  *
00047  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00048  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00049  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00050  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00051  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00052  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00053  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00054  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00055  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00056  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00057  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00058  *
00059  *
00060  * Author               Date    Comment
00061  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00062  * Nilesh Rajbharti     3/19/01  Original        (Rev 1.0)
00063  ********************************************************************/
00064 #ifndef __UDP_H
00065 #define __UDP_H
00066
00067 // Stores a UDP Port Number
00068 typedef WORD UDP_PORT;
00069
00070 // Provides a handle to a UDP Socket
00071 typedef BYTE UDP_SOCKET;
00072
00073 // Stores information about a current UDP socket
00074 typedef struct _UDP_SOCKET_INFO
00075 {
00076     NODE_INFO   remoteNode;     // IP and MAC of remote node
00077     UDP_PORT    remotePort;     // Remote node's UDP port number
00078     UDP_PORT    localPort;      // Local UDP port number, or INVALID_UDP_PORT when free
00079 } UDP_SOCKET_INFO;
00080
00081
00082 #define INVALID_UDP_SOCKET      (0xffu)     // Indicates a UDP socket that is not valid
00083 #define INVALID_UDP_PORT        (0ul)       // Indicates a UDP port that is not valid
00084
00085 /****************************************************************************
00086   Section:
00087     External Global Variables
00088   ***************************************************************************/
00089 #if !defined(__UDP_C)
00090     extern UDP_SOCKET activeUDPSocket;
00091     extern UDP_SOCKET_INFO  UDPSocketInfo[MAX_UDP_SOCKETS];
00092     extern WORD UDPTxCount;
00093     extern WORD UDPRxCount;
00094 #endif
00095
00096 // Stores the header of a UDP packet
00097 typedef struct _UDP_HEADER
00098 {
00099     UDP_PORT    SourcePort;             // Source UDP port
00100     UDP_PORT    DestinationPort;        // Destination UDP port
00101     WORD        Length;                 // Length of data
00102     WORD        Checksum;               // UDP checksum of the data
00103 } UDP_HEADER;
00104
00105 /****************************************************************************
00106   Section:
00107     Function Prototypes
00108   ***************************************************************************/
00109 void UDPInit(void);
00110 void UDPTask(void);
00111
00112 UDP_SOCKET UDPOpen(UDP_PORT localPort, NODE_INFO *remoteNode, UDP_PORT remotePort);
00113 void UDPClose(UDP_SOCKET s);
00114 BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len);
00115
00116 void UDPSetTxBuffer(WORD wOffset);
00117 void UDPSetRxBuffer(WORD wOffset);
00118 WORD UDPIsPutReady(UDP_SOCKET s);
00119 BOOL UDPPut(BYTE v);
00120 WORD UDPPutArray(BYTE *cData, WORD wDataLen);
00121 BYTE* UDPPutString(BYTE *strData);
00122 void UDPFlush(void);
00123
00124 // ROM function variants for PIC18
00125 #if defined(__18CXX)
00126     WORD UDPPutROMArray(ROM BYTE *cData, WORD wDataLen);
00127     ROM BYTE* UDPPutROMString(ROM BYTE *strData);
00128 #else
00129     #define UDPPutROMArray(a,b) UDPPutArray((BYTE*)a,b)
00130     #define UDPPutROMString(a)  UDPPutString((BYTE*)a)
00131 #endif
00132
00133 WORD UDPIsGetReady(UDP_SOCKET s);
00134 BOOL UDPGet(BYTE *v);
00135 WORD UDPGetArray(BYTE *cData, WORD wDataLen);
00136 void UDPDiscard(void);
00137
00138 // MODIFIX: Added the following function prototypes
00139 WORD UDPGetPutOffset(void);
00140 WORD UDPGetGetOffset(void);
00141
00142 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: XEEPROM.h Source File

XEEPROM.h

Go to the documentation of this file.
00001
00002
00003
00040 /*********************************************************************
00041  * Software License Agreement
00042  *
00043  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights
00044  * reserved.
00045  *
00046  * Microchip licenses to you the right to use, modify, copy, and
00047  * distribute:
00048  * (i)  the Software when embedded on a Microchip microcontroller or
00049  *      digital signal controller product ("Device") which is
00050  *      integrated into Licensee's product; or
00051  * (ii) ONLY the Software driver source files ENC28J60.c and
00052  *      ENC28J60.h ported to a non-Microchip device used in
00053  *      conjunction with a Microchip ethernet controller for the
00054  *      sole purpose of interfacing with the ethernet controller.
00055  *
00056  * You should refer to the license agreement accompanying this
00057  * Software for additional information regarding your rights and
00058  * obligations.
00059  *
00060  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
00061  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
00062  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
00063  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00064  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
00065  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
00066  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
00067  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
00068  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
00069  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
00070  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00071  *
00072  *
00073  * Author               Date        Comment
00074  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00075  * Nilesh Rajbharti     5/20/02     Original (Rev. 1.0)
00076 ********************************************************************/
00077 #ifndef __XEEPROM_H
00078 #define __XEEPROM_H
00079
00080
00081 // MODIFIX: Introduce this size macro
00082 #define EEPROM_SIZE             (4096u)
00083
00084 // MODIFIX: Only define the following macro to emulate an empty EEPROM.
00085 //#define EEPROM_ERASE
00086
00087
00088 typedef WORD XEE_ADDR;
00089 typedef BOOL XEE_RESULT;
00090 #define XEE_SUCCESS FALSE
00091
00092
00093 // MODIFIX: Deleted the function XEEInit, XEERead, and XEEBeginRead
00094 // MODIFIX: Moved XEEBeginWrite, XEEWrite, XEEIsBusy, XEEEndWrite to
00095 //          SPIEEPROM.c
00096
00097
00099
00113 XEE_RESULT XEEReadArray(XEE_ADDR address, BYTE *buffer, BYTE length);
00114
00115
00116
00118
00132 void XEEEraseEEPROM(void);
00133
00134
00135 // MODIFIX: Added the bFlags parameter to the XEEWriteArray function (see
00136 // below).
00138
00155 void XEEWriteArray(WORD u16Address, BYTE * pu8Data, BYTE u8Len);
00156
00157
00158 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: appl.c Source File

appl.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00014     #define     APPL_C
00015
00016
00017 // ////////////////////////////////////////////////////////////////////////////
00018 // Includes
00019 // ////////////////////////////////////////////////////////////////////////////
00020
00021     #include    "appl.h"
00022     #include    "mdns.h"
00023     #include    "TCPIP.h"
00024     #include    "stringtable.h"
00025
00026     #include    "projectdefs.h"
00027
00028
00029 // ////////////////////////////////////////////////////////////////////////////
00030 // Local Defines
00031 // ////////////////////////////////////////////////////////////////////////////
00032
00033
00034 // ////////////////////////////////////////////////////////////////////////////
00035 // Local Typedefs
00036 // ////////////////////////////////////////////////////////////////////////////
00037
00038 // States of application
00039 typedef enum
00040 {
00041     APPL_SM_START = 0,
00042     APPL_SM_ADD_ERR_ACK,
00043     APPL_SM_PROCESS_ADD,
00044     APPL_SM_PREPARE_SRCP,
00045     APPL_SM_SET_SRCP,
00046     APPL_SM_PROCESS_SRCP,
00047     APPL_SM_WAIT_FOR_MDNS_RESOLVE,
00048     APPL_SM_RESOLVE_MAC,
00049     APPL_SM_WAIT_FOR_SERVER_REPLY,
00050     APPL_SM_IDLE_CONNECT,
00051     APPL_SM_HANDLE_CONNECTION,
00052     APPL_SM_WAIT_FOR_USER,
00053     APPL_SM_CONNECTED,
00054     APPL_SM_CONNECTION_CLOSED,
00055     APPL_SM_START_SHUTDOWN,
00056     APPL_SM_SHUTDOWN,
00057     APPL_SM_SERVERSET,
00058     APPL_SM_ERROR_CONNECT
00059 } SM_APPL;
00060
00061 typedef struct __attribute__((__packed__)) _servernet_config
00062 {
00063     NODE_INFO   sSrvAdd;
00064     WORD_VAL    sPort;
00065 } SSERVERNET;
00066
00067
00068 // ////////////////////////////////////////////////////////////////////////////
00069 // Local variables
00070 // ////////////////////////////////////////////////////////////////////////////
00071
00072 static SM_APPL _eApplSM;
00073 static BYTE _u8retry_counter;
00074 static SSERVERNET _sServerConfig;
00075
00076
00077 // ////////////////////////////////////////////////////////////////////////////
00078 // Local function prototypes
00079 // ////////////////////////////////////////////////////////////////////////////
00080
00081 static BOOL disconnect(void);
00082
00083
00084 // ////////////////////////////////////////////////////////////////////////////
00085 // ////////////////////////////////////////////////////////////////////////////
00086
00087 void ApplInit(void)
00088 {
00089     _eApplSM = APPL_SM_START;
00090     u8ApplTimer = 0;
00091
00092     BootupInit();
00093
00094     // Network-Application data from external EEPROM
00095     {
00096         BYTE * confPtr = (BYTE *)(&sPApplConfig);
00097         XEEReadArray(APPL_EEPROM_ADD, confPtr, sizeof(SPAPPLDATA));
00098     }
00099
00100     // ////////////////////////////////////////////////////////////////////////
00101     // Init the 10 ms timer:
00102
00103     // Switch timer3 off
00104     T3CON = 0;
00105
00106     // Init the periode register for a 10 ms duration...
00107     CCPR2H = (GetPeripheralClock() * 0.005) / 256;
00108     CCPR2L = (GetPeripheralClock() * 0.005);
00109     CCP2CON = 0x0B;     // Compare mode, generate software interrupt on match.
00110     IPR2bits.CCP2IP = 0;    // Low interrupt priority.
00111     PIR2bits.CCP2IF = 0;    // Interrupt flag zuruecksetzen.
00112     PIE2bits.CCP2IE = 0;    // Disable the interrupt flag.
00113
00114     TMR3L = 0;  // Reset the
00115     TMR3H = 0;  // timer.
00116
00117     // Timer1 as clock source for CCP1, Timer3 as clock source for CCP2
00118     T3CONbits.T3CCP1 = 1;
00119
00120     // Set prescaler to 1:2
00121     T3CONbits.T3CKPS0 = 1;
00122
00123     // Enable timer
00124     T3CONbits.TMR3ON = 1;
00125
00126
00127     PROJECT_INITIAL_INIT();
00128 }
00129
00130 // ////////////////////////////////////////////////////////////////////////////
00131 // ////////////////////////////////////////////////////////////////////////////
00132
00133 IP_ADDR * ApplGetServerIP(void)
00134 {
00135     return &_sServerConfig.sSrvAdd.IPAddr;
00136 }
00137
00138 // ////////////////////////////////////////////////////////////////////////////
00139 // ////////////////////////////////////////////////////////////////////////////
00140
00141 NODE_INFO * ApplGetServerNodeInfo(void)
00142 {
00143     return &_sServerConfig.sSrvAdd;
00144 }
00145
00146 // ////////////////////////////////////////////////////////////////////////////
00147 // ////////////////////////////////////////////////////////////////////////////
00148
00149 WORD_VAL ApplGetServerPort(void)
00150 {
00151     return _sServerConfig.sPort;
00152 }
00153
00154 // ////////////////////////////////////////////////////////////////////////////
00155 // ////////////////////////////////////////////////////////////////////////////
00156
00157 BOOL ApplIsConnected(void)
00158 {
00159     return PROJECT_IS_CONNECTED();
00160 }
00161
00162 // ////////////////////////////////////////////////////////////////////////////
00163 // ////////////////////////////////////////////////////////////////////////////
00164
00165 static BOOL disconnect(void)
00166 {
00167     PROJECT_START_DISCONNECT();
00168 }
00169
00170 // ////////////////////////////////////////////////////////////////////////////
00171 // ////////////////////////////////////////////////////////////////////////////
00172
00173 void ApplStop(void)
00174 {
00175     InputResetPowerButton();
00176
00177     while (1)
00178     {
00179         if (PIR2bits.CCP2IF == 1)
00180         {
00181             // Reset the timer flag.
00182             PIR2bits.CCP2IF = 0;
00183
00184             // call the input routines every 10 ms!
00185             InputMain();
00186             if (bInputButtonPushed(PWR_BTN) == TRUE)
00187             {
00188                 break;
00189             }
00190         }
00191     }
00192 }
00193
00194 // ////////////////////////////////////////////////////////////////////////////
00195 // ////////////////////////////////////////////////////////////////////////////
00196
00197 void ApplMain(void)
00198 {
00199     // Execute the application all 10 ms!
00200     if (PIR2bits.CCP2IF == 0)
00201     {
00202         return;
00203     }
00204
00205     // Reset the timer flag.
00206     PIR2bits.CCP2IF = 0;
00207
00208     InputMain();
00209
00210
00211     if (((u16GlobalFlags & SHUTDOWN_MASK) == 0) &&
00212          (bInputButtonPushedLong(PWR_BTN) == TRUE))
00213     {
00214         // Starting shut down sequence...
00215         ApplShutDown();
00216     }
00217
00218
00219     // ////////////////////////////////////////////////////////////////////////
00220     // Application Task starts here!!!!
00221
00222     if (u8ApplTimer > 0)
00223     {
00224         u8ApplTimer--;
00225     }
00226
00227     if (bBootupMain() == FALSE)
00228     {
00229         if (u16GlobalFlags & SHUTDOWN_MASK)
00230         {
00231             _eApplSM = APPL_SM_SHUTDOWN;
00232         }
00233         else
00234         {
00235             _eApplSM = APPL_SM_START;
00236         }
00237         return;
00238     }
00239
00240     if ((_eApplSM>APPL_SM_START)&&(_eApplSM<APPL_SM_WAIT_FOR_USER))
00241     {
00242         if (bInputButtonPushed(ENC_BTN) == TRUE)
00243         {
00244             _eApplSM = APPL_SM_WAIT_FOR_USER;
00245         }
00246
00247         switch(u8ApplTimer)
00248         {
00249             case 200:
00250                 OutSetLED(LED_F1, LED_ON);
00251                 OutSetLED(LED_F4, LED_OFF);
00252                 break;
00253
00254             case 150:
00255                 OutSetLED(LED_F2, LED_ON);
00256                 OutSetLED(LED_F1, LED_OFF);
00257                 break;
00258
00259             case 100:
00260                 OutSetLED(LED_F3, LED_ON);
00261                 OutSetLED(LED_F2, LED_OFF);
00262                 break;
00263
00264             case 50:
00265                 OutSetLED(LED_F4, LED_ON);
00266                 OutSetLED(LED_F3, LED_OFF);
00267                 break;
00268
00269             case 0:
00270                 u8ApplTimer = 201;
00271                 break;
00272         }
00273
00274         if(OutIsLCDBusy()==TRUE)
00275         {
00276             return;
00277         }
00278     }
00279
00280
00281     switch(_eApplSM)
00282     {
00283     case APPL_SM_START:
00284         if (sPApplConfig.eFindMode == SEARCH_UNKNOWN)
00285         {
00286             // The first time or after a factory reset:
00287             IPSetInit(TRUE);
00288             _eApplSM = APPL_SM_SERVERSET;
00289             break;
00290         }
00291
00292         StrTbl_GetString(lcdram_row1, STRTBLID_SEARCHING);
00293         if (sPApplConfig.eFindMode==SEARCH_IP)
00294         {
00295             sprintf(lcdram_row2, (ROM char *) "%hhu.%hhu.%hhu.%hhu",
00296                     sPApplConfig.sSrvIPAdd.v[0], sPApplConfig.sSrvIPAdd.v[1],
00297                     sPApplConfig.sSrvIPAdd.v[2], sPApplConfig.sSrvIPAdd.v[3]);
00298         }
00299         else if (sPApplConfig.eFindMode==SEARCH_NAME)
00300         {
00301             strcpy(lcdram_row2, sPApplConfig.au8Name);
00302         }
00303         else if (sPApplConfig.eFindMode==SEARCH_SERVICE)
00304         {
00305             strcpy(lcdram_row2, sPApplConfig.au8Service);
00306         }
00307
00308         lcd_addr2 = (16 - strlen(lcdram_row2))>>1;
00309         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK |
00310                      LCD_CENTER1_MASK | LCD_ROW2_MASK;
00311
00312         // Prepare encoder button for abortion of server search:
00313         InputButtonReset(ENC_BTN);
00314
00315         // Prepare the server configuration:
00316         memset(&_sServerConfig, 0, sizeof(SSERVERNET));
00317
00318         // Init ARP (ARP flush):
00319         ARPFlush();
00320
00321         u8ApplTimer = 0;
00322
00323         if (sPApplConfig.eFindMode == SEARCH_IP)
00324         {
00325             _sServerConfig.sSrvAdd.IPAddr.Val = sPApplConfig.sSrvIPAdd.Val;
00326             _sServerConfig.sPort.Val = sPApplConfig.sIPPort.Val;
00327              _eApplSM = APPL_SM_RESOLVE_MAC;
00328             break;
00329         }
00330
00331         if (sPApplConfig.eFindMode == SEARCH_SERVICE)
00332         {
00333             MDNSResolveService(sPApplConfig.au8Service,(ROM char *) PROJECT_SERVICE_NAME);
00334         }
00335         else if (sPApplConfig.eFindMode == SEARCH_NAME)
00336         {
00337             MDNSResolveName(sPApplConfig.au8Name);
00338         }
00339
00340         _eApplSM = APPL_SM_WAIT_FOR_MDNS_RESOLVE;
00341         break;
00342
00343     case APPL_SM_WAIT_FOR_MDNS_RESOLVE:
00344         if (bMDNSNameIsResolved(&_sServerConfig.sSrvAdd.IPAddr) == TRUE)
00345         {
00346             // Successfully resolved the name of the server.
00347             if (sPApplConfig.eFindMode == SEARCH_SERVICE)
00348             {
00349                 // A service query also resolves the port of the server!
00350                 bMDNSServiceIsResolved(&_sServerConfig.sSrvAdd.IPAddr,
00351                                             &_sServerConfig.sPort);
00352             }
00353             else
00354             {
00355                 _sServerConfig.sPort.Val = sPApplConfig.sNamePort.Val;
00356             }
00357
00358             _eApplSM = APPL_SM_RESOLVE_MAC;
00359         }
00360         break;
00361
00362     case APPL_SM_RESOLVE_MAC:
00363         if (MACIsTxReady())
00364         {
00365             // Send ARP request
00366             ARPResolve(&_sServerConfig.sSrvAdd.IPAddr);
00367             _eApplSM = APPL_SM_WAIT_FOR_SERVER_REPLY;
00368         }
00369         break;
00370
00371     case APPL_SM_WAIT_FOR_SERVER_REPLY:
00372         if (u8ApplTimer == 1)
00373         {
00374             _eApplSM = APPL_SM_RESOLVE_MAC;
00375         }
00376         else if (ARPIsResolved(&_sServerConfig.sSrvAdd.IPAddr,
00377                                &_sServerConfig.sSrvAdd.MACAddr))
00378         {
00379             _eApplSM = APPL_SM_IDLE_CONNECT;
00380             StrTbl_GetString(lcdram_row1, STRTBLID_CONNECT_TO);
00381             lcd_status |= LCD_ROW1_MASK | LCD_CENTER1_MASK;
00382         }
00383         break;
00384
00385     case APPL_SM_SERVERSET:
00386         // Call periodically the IP set menu (Server) and wait for
00387         // finish.
00388         if (IPSetMain() == TRUE)
00389         {
00390             _eApplSM = APPL_SM_START;
00391         }
00392         break;
00393
00394     case APPL_SM_IDLE_CONNECT:
00395         if (u8ApplTimer == 1)
00396         {
00397             PROJECT_PREPARE_CONNECTION();
00398
00399             InputButtonReset(ALL_BTN);
00400             _eApplSM = APPL_SM_HANDLE_CONNECTION;
00401         }
00402         break;
00403
00404     case APPL_SM_HANDLE_CONNECTION:
00405     {
00406         APPL_CONNECTING_RETCODE ret;
00407
00408         ret = PROJECT_HANDLE_SERVER_CONNECTION();
00409
00410         if (ret == APPL_CR_ERROR)
00411         {
00412             // Errors occured during connect resp. disconnect.
00413             _eApplSM = APPL_SM_ERROR_CONNECT;
00414         }
00415         else if (ret == APPL_CR_CLOSED)
00416         {
00417             // Closing of the connection was handled by the application
00418             // module.
00419             _eApplSM = APPL_SM_CONNECTION_CLOSED;
00420         }
00421         else if (ret == APPL_CR_CONNECTED)
00422         {
00423             // Successfully connected to server! Show user:
00424             StrTbl_GetString(lcdram_row1, STRTBLID_SUCCESSFULLY_CONNECTED);
00425             sprintf(lcdram_row2, (ROM char *) "%hhu.%hhu.%hhu.%hhu",
00426                     _sServerConfig.sSrvAdd.IPAddr.v[0],
00427                     _sServerConfig.sSrvAdd.IPAddr.v[1],
00428                     _sServerConfig.sSrvAdd.IPAddr.v[2],
00429                     _sServerConfig.sSrvAdd.IPAddr.v[3]);
00430
00431             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00432                          LCD_ROW2_MASK | LCD_CENTER2_MASK;
00433
00434             _eApplSM = APPL_SM_CONNECTED;
00435         }
00436         break;
00437     }
00438
00439     case APPL_SM_CONNECTED:
00440         if (PROJECT_MAIN() == FALSE)
00441         {
00442             _eApplSM = APPL_SM_HANDLE_CONNECTION;
00443         }
00444         break;
00445
00446     case APPL_SM_CONNECTION_CLOSED:
00447         // Connection was closed. Show user:
00448         OutSwitchOffAllLEDs();
00449         StrTbl_GetString(lcdram_row1, STRTBLID_CONNECTION_CLOSED1);
00450         StrTbl_GetString(lcdram_row2, STRTBLID_CONNECTION_CLOSED2);
00451         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00452                      LCD_ROW2_MASK | LCD_CENTER2_MASK;
00453
00454         InputButtonReset(ALL_BTN);
00455
00456         if (u16GlobalFlags & SHUTDOWN_MASK)
00457         {
00458             _eApplSM = APPL_SM_START_SHUTDOWN;
00459             u8ApplTimer = 100;
00460             break;
00461         }
00462
00463         // Wait for acknowledging user.
00464         _eApplSM = APPL_SM_WAIT_FOR_USER;
00465
00466         // Intented fall through.
00467
00468     case APPL_SM_WAIT_FOR_USER:
00469         OutSwitchOffAllLEDs();
00470
00471         if (ApplIsConnected())
00472         {
00473             InputButtonReset(ALL_BTN);
00474             disconnect();
00475             _eApplSM = APPL_SM_HANDLE_CONNECTION;
00476             break;
00477         }
00478
00479         if (bInputButtonPushedOnce(ENC_BTN) == TRUE)
00480         {
00481             // New server settings:
00482             IPSetInit(TRUE);
00483             _eApplSM = APPL_SM_SERVERSET;
00484         }
00485         else if(bInputButtonPushedTwice(ENC_BTN)||bInputButtonPushedLong(ENC_BTN))
00486         {
00487             // Setting the whole IP data!
00488             IPSetInit(FALSE);
00489             BootupSetIP();
00490             _eApplSM = APPL_SM_START;
00491         }
00492
00493         break;
00494
00495     case APPL_SM_START_SHUTDOWN:
00496         if ((u8ApplTimer == 0) && (HTTPCheckForIdle() == TRUE))
00497         {
00498             // Stop the MDNS service...
00499             StopMDNSResponder();
00500             _eApplSM = APPL_SM_SHUTDOWN;
00501         }
00502         break;
00503
00504     case APPL_SM_ERROR_CONNECT:
00505         StrTbl_GetString(lcdram_row1, STRTBLID_CONNECTION_ERROR1);
00506         StrTbl_GetString(lcdram_row2, STRTBLID_CONNECTION_ERROR2);
00507         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00508                      LCD_ROW2_MASK | LCD_CENTER2_MASK;
00509         _eApplSM = APPL_SM_WAIT_FOR_USER;
00510         InputButtonReset(ALL_BTN);
00511         break;
00512     }
00513 }
00514
00515 // ////////////////////////////////////////////////////////////////////////////
00516 // ////////////////////////////////////////////////////////////////////////////
00517
00518 void ApplShutDown(void)
00519 {
00520     if (ApplIsConnected())
00521     {
00522         // Before shuting down, all connection will be closed!
00523         disconnect();
00524         _eApplSM = APPL_SM_HANDLE_CONNECTION;
00525     }
00526     else
00527     {
00528         _eApplSM = APPL_SM_START_SHUTDOWN;
00529         u8ApplTimer = 100;
00530     }
00531
00532     // Remember the shutdown request.
00533     u16GlobalFlags |= SHUTDOWN_MASK;
00534 }
00535
00536 // ////////////////////////////////////////////////////////////////////////////
00537 // ////////////////////////////////////////////////////////////////////////////
00538
00539 BOOL ApplIsRunning(void)
00540 {
00541     if (_eApplSM == APPL_SM_SHUTDOWN)
00542     {
00543         return FALSE;
00544     }
00545     else
00546     {
00547         return TRUE;
00548     }
00549 }
00550
00551 // ////////////////////////////////////////////////////////////////////////////
00552 // ////////////////////////////////////////////////////////////////////////////
00553
00554 void ApplResetToFactory(BOOL KeepBootup)
00555 {
00556     BYTE * confPtr = (BYTE *)(&sPApplConfig);
00557
00558     // Erase the EEPROM before rewriting the standard settings:
00559     XEEEraseEEPROM();
00560
00561
00562     // Restore BOOTUP!
00563     if (KeepBootup == TRUE)
00564     {
00565         BootupRestoreState();
00566     }
00567     else
00568     {
00569         BootupResetToFactory();
00570     }
00571
00572     // Restoring application specific network data:
00573     sPApplConfig.sSrvIPAdd.v[0] = 192;
00574     sPApplConfig.sSrvIPAdd.v[1] = 168;
00575     sPApplConfig.sSrvIPAdd.v[2] = 1;
00576     sPApplConfig.sSrvIPAdd.v[3] = 1;
00577     sPApplConfig.sIPPort.Val = PROJECT_DEFAULT_PORT;
00578     sPApplConfig.sNamePort.Val = sPApplConfig.sIPPort.Val;
00579     sPApplConfig.eFindMode = SEARCH_UNKNOWN;
00580     memset(sPApplConfig.au8Name, 0, sizeof(sPApplConfig.au8Name));
00581     memset(sPApplConfig.au8Service, 0, sizeof(sPApplConfig.au8Service));
00582     sPApplConfig.sFlags.bToggleLocoDirMode = TOGGLEDIRMODE_CLICK;
00583
00584     XEEWriteArray(APPL_EEPROM_ADD, confPtr, sizeof(SPAPPLDATA));
00585
00586
00587     // Restore application related:
00588     PROJECT_RESET_TO_FACTORY();
00589 }
00590
00591 // ////////////////////////////////////////////////////////////////////////////
00592 // ////////////////////////////////////////////////////////////////////////////
00593
00594 void ApplChangeLocoDirMode(BOOL Mode)
00595 {
00596     if (Mode != sPApplConfig.sFlags.bToggleLocoDirMode)
00597     {
00598         sPApplConfig.sFlags.bToggleLocoDirMode = Mode;
00599         XEEWriteArray(APPL_EEPROM_ADD,(BYTE *)(&sPApplConfig), sizeof(SPAPPLDATA));
00600
00601         PROJECT_LOCO_DIR_MODE_HAS_CHANGED();
00602     }
00603 }
00604
00605 // ////////////////////////////////////////////////////////////////////////////
00606 // ////////////////////////////////////////////////////////////////////////////
00607
00608 void ApplRestart(BOOL ResetToFactory)
00609 {
00610     if ((u16GlobalFlags & SHUTDOWN_MASK) == 0)
00611     {
00612         if (ResetToFactory == TRUE)
00613         {
00614             // Reset to factory settings requested
00615             u16GlobalFlags |= FACRES_MASK;
00616         }
00617         else
00618         {
00619             // Restart requested
00620             u16GlobalFlags |= RESTART_MASK;
00621         }
00622
00623         StopMDNSResponder();
00624         ApplShutDown();
00625     }
00626 }
00627
00628 // ////////////////////////////////////////////////////////////////////////////
00629 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:37 2011 for eWicht by doxygen 1.5.5


eWicht: appl.h Source File

appl.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00021 // ////////////////////////////////////////////////////////////////////////////
00022 // ////////////////////////////////////////////////////////////////////////////
00023
00024
00025 #ifndef APPL_H
00026
00027 #define     APPL_H
00028
00029
00030 // ////////////////////////////////////////////////////////////////////////////
00031 // Includes
00032 // ////////////////////////////////////////////////////////////////////////////
00033
00034 #include    <stdio.h>
00035 #include    "main.h"
00036 #include    "ipset.h"
00037 #include    "XEEPROM.h"
00038 #include    "eeprom_adds.h"
00039
00040
00041 // ////////////////////////////////////////////////////////////////////////////
00042 // Defines
00043 // ////////////////////////////////////////////////////////////////////////////
00044
00045 #ifdef APPL_C
00046     #define PROTO
00047 #else
00048     #define PROTO extern
00049 #endif
00050
00051
00053 // Typedefs
00055
00056 #include "appldefs.h"
00057
00061 typedef enum _SEARCH_MODES
00062 {
00064     SEARCH_UNKNOWN = 0,
00066     SEARCH_IP,
00068     SEARCH_NAME,
00070     SEARCH_SERVICE
00071 } SEARCH_MODE;
00072
00073
00077 typedef struct __attribute__((__packed__))
00078 {
00079     SEARCH_MODE eFindMode;
00080
00081     IP_ADDR     sSrvIPAdd;
00084     WORD_VAL    sIPPort;
00087     WORD_VAL    sNamePort;
00090     BYTE        au8Name[LCD_CHARS_IN_A_ROW+1];
00093     BYTE        au8Service[LCD_CHARS_IN_A_ROW+1];
00095     struct
00096     {
00098         BYTE        bToggleLocoDirMode : 1;
00100             #define     TOGGLEDIRMODE_CLICK     FALSE
00102             #define     TOGGLEDIRMODE_ZERO      TRUE
00103     } sFlags;
00104
00105 } SPAPPLDATA;
00106
00107
00109 // Global variables
00111
00119 PROTO SPAPPLDATA sPApplConfig;
00120
00121
00125 PROTO BYTE u8ApplTimer;
00126
00127
00128 // ////////////////////////////////////////////////////////////////////////////
00129 // Function prototypes
00130 // ////////////////////////////////////////////////////////////////////////////
00131
00135 void ApplInit(void);
00136
00139 void ApplMain(void);
00140
00141
00147 IP_ADDR * ApplGetServerIP(void);
00148
00149
00155 NODE_INFO * ApplGetServerNodeInfo(void);
00156
00157
00163 WORD_VAL ApplGetServerPort(void);
00164
00165
00173 BOOL ApplIsConnected(void);
00174
00175
00181 void ApplResetToFactory(BOOL KeepBootup);
00182
00183
00187 void ApplShutDown(void);
00188
00189
00195 BOOL ApplIsRunning(void);
00196
00197
00201 void ApplStop(void);
00202
00203
00210 void ApplChangeLocoDirMode(BOOL Mode);
00211
00212
00217 void ApplRestart(BOOL ResetToFactory);
00218
00221 // ////////////////////////////////////////////////////////////////////////////
00222 // Epilogue
00223 // ////////////////////////////////////////////////////////////////////////////
00224
00225     #undef      PROTO
00226 #endif
Generated on Sun Nov 27 20:02:37 2011 for eWicht by doxygen 1.5.5


eWicht: appldefs.h Source File

appldefs.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00017
00018
00019 #ifndef APPLDEFS_H
00020
00021 #define     APPLDEFS_H
00022
00024 typedef enum
00025 {
00026     APPL_CR_IN_PROGRESS = 0,
00027     APPL_CR_ERROR,
00028     APPL_CR_CLOSED,
00029     APPL_CR_CONNECTED
00030 } APPL_CONNECTING_RETCODE;
00031
00032 #endif  // #ifdef APPLDEFS_H
Generated on Sun Nov 27 20:02:37 2011 for eWicht by doxygen 1.5.5


eWicht: bootup.c Source File

bootup.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00014 // ////////////////////////////////////////////////////////////////////////////
00015 // ////////////////////////////////////////////////////////////////////////////
00016
00017
00018 // ////////////////////////////////////////////////////////////////////////////
00019 // Local Includes
00020 // ////////////////////////////////////////////////////////////////////////////
00021
00022     #define     BOOTUP_C
00023     #include    "bootup.h"
00024     #include    "mdns.h"
00025     #include    "TCPIP.h"
00026     #include    "stringtable.h"
00027     #include    "sralloc.h"
00028
00029     #include    "projectdefs.h"
00030
00031
00032 // ////////////////////////////////////////////////////////////////////////////
00033 // Local Typedefs
00034 // ////////////////////////////////////////////////////////////////////////////
00035
00036 // States of bootup
00037 typedef enum
00038 {
00039     BOOTUP_SM_STARTUP = 0,
00040     BOOTUP_SM_STARTUP_WAIT,
00041     BOOTUP_SM_STARTUP_LANGUAGE,
00042     BOOTUP_SM_STARTUP_FINI,
00043     BOOTUP_SM_IPSET,
00044     BOOTUP_SM_NOLINK,
00045     BOOTUP_SM_NOLINK_WAIT,
00046     BOOTUP_SM_WAIT_FOR_IP,
00047     BOOTUP_SM_START_CHECK_IP,
00048     BOOTUP_SM_CHECK_IP,
00049     BOOTUP_SM_IP_ERROR,
00050     BOOTUP_SM_SHOW_IP_ERROR,
00051     BOOTUP_SM_DISPLAY_IPDATA,
00052     BOOTUP_SM_WAIT_FOR_USER,
00053     BOOTUP_SM_WAIT_FOR_NAMESERVICE,
00054     BOOTUP_SM_WAIT_FOR_USER2,
00055     BOOTUP_SM_READY
00056 } SM_BOOTUP;
00057
00058
00059 // ////////////////////////////////////////////////////////////////////////////
00060 // Local Defines
00061 // ////////////////////////////////////////////////////////////////////////////
00062
00063 // ////////////////////////////////////////////////////////////////////////////
00064 // Local Variables
00065 // ////////////////////////////////////////////////////////////////////////////
00066
00070 static SM_BOOTUP _eBootUpSM;
00071
00075 static BOOL _bFirstTime;
00076
00077
00081 static BYTE _au8NetworkDataForBootloader[12];
00082
00083
00084 // ////////////////////////////////////////////////////////////////////////////
00085 // Local function prototypes
00086 // ////////////////////////////////////////////////////////////////////////////
00087
00088 static void BootupCheckVersionTag(void);
00089
00090
00091 // ////////////////////////////////////////////////////////////////////////////
00092 // ////////////////////////////////////////////////////////////////////////////
00093
00094 void BootupInit(void)
00095 {
00096     _bFirstTime = TRUE;
00097     _eBootUpSM = BOOTUP_SM_STARTUP;
00098
00099
00100     // ////////////////////////////////////////////////////////////////////////
00101     // IP level
00102
00103     // Get the common and network related data from external EEPROM:
00104     {
00105         XEEReadArray(BOOTUP_EEPROM_ADD, (BYTE *)(&sPCommonConfig), sizeof(PCOMMON_CONFIG));
00106     }
00107
00108
00109     // Check, if any updates have been done and the EEPROM data must be
00110     // updated somehow.
00111     BootupCheckVersionTag();
00112
00113
00114     // ////////////////////////////////////////////////////////////////////////
00115     // DHCP level
00116
00117     if (sPCommonConfig.Flags.bIsDHCPEnabled == TRUE)
00118     {
00119         // Starting automatic IP discovery (including AutoIP if DHCP fails).
00120         DHCPEnable();
00121         DHCPReset(FALSE);
00122     }
00123     else
00124     {
00125         // Starting manual IP discovery...
00126         DHCPDisable();
00127         sIPConfig.MyIPAddr.Val = sPCommonConfig.ManIPAddr.Val;
00128         sIPConfig.MyMask.Val = IPConvertSubnetToMask(sPCommonConfig.ManMask);
00129         sIPConfig.MyGateway.Val = sPCommonConfig.ManGateway.Val;
00130         sIPConfig.Flags.bIPunique = FALSE;
00131     }
00132 }
00133
00134
00135 // ////////////////////////////////////////////////////////////////////////////
00136 // ////////////////////////////////////////////////////////////////////////////
00137
00138 void BootupSetIP(void)
00139 {
00140     // Entering the IP set menu.
00141     _eBootUpSM = BOOTUP_SM_IPSET;
00142 }
00143
00144 // ////////////////////////////////////////////////////////////////////////////
00145 // ////////////////////////////////////////////////////////////////////////////
00146
00147 BOOL bBootupMain(void)
00148 {
00149     // Reset the application if the network connection is lost.
00150     if ((_eBootUpSM > BOOTUP_SM_NOLINK_WAIT) && (MACIsLinked()) == 0)
00151     {
00152         OutSwitchOffAllLEDs();
00153         u16GlobalFlags &= ~(LINKISUP_MASK); // Stop executing TCP/IP stack.
00154         _eBootUpSM = BOOTUP_SM_NOLINK;
00155         // Reset the heap!
00156         SRAMInitHeap();
00157     }
00158
00159
00160     // ////////////////////////////////////////////////////////////////////////
00161     // The State Machine implementation.
00162
00163     switch(_eBootUpSM)
00164     {
00165     case BOOTUP_SM_STARTUP:
00166         // Display the startup string and waiting for some time. In this time
00167         // also the physical network layer comes up.
00168
00169         strcpypgm2ram(lcdram_row1, (ROM char *) "eWicht " PROJECT_NAME);
00170
00171         strcpypgm2ram(lcdram_row2, (ROM char *) FIRMWARE_VERSION_STRING);
00172         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00173                      LCD_ROW2_MASK | LCD_CENTER2_MASK;
00174
00175         if (_bFirstTime == TRUE)
00176         {
00177             u8ApplTimer = 250;  // Wait 2.5 seconds.
00178         }
00179         else
00180         {
00181             u8ApplTimer = 50;   // Wait 0.5 seconds.
00182         }
00183
00184         InputButtonReset(ENC_BTN);
00185         _eBootUpSM = BOOTUP_SM_STARTUP_WAIT;
00186         // Intented fall through.
00187
00188     case BOOTUP_SM_STARTUP_WAIT:
00189         // Switch on all the LEDs in a serial fashion for testing purposes.
00190         // Go to the next state if the intitial wait time is over.
00191
00192 #ifndef DEBEXT_MODE
00193         if (_bFirstTime == TRUE)
00194         {
00195             switch (u8ApplTimer)
00196             {
00197             case 250:
00198                 OutSetLED(LED_ACC, LED_ON);
00199                 break;
00200
00201             case 240:
00202                 OutSetLED(LED_FL, LED_ON);
00203                 break;
00204
00205             case 230:
00206                 OutSetLED(LED_F1, LED_ON);
00207                 break;
00208
00209             case 220:
00210                 OutSetLED(LED_F2, LED_ON);
00211                 break;
00212
00213             case 210:
00214                 OutSetLED(LED_F3, LED_ON);
00215                 break;
00216
00217             case 200:
00218                 OutSetLED(LED_F4, LED_ON);
00219                 break;
00220
00221             case 190:
00222                 OutSetLED(LED_PWR, LED_ON);
00223                 break;
00224
00225             case 180:
00226                 OutSetLED(LED_SEL, LED_ON);
00227                 break;
00228
00229             case 170:
00230                 OutSetLED(LED_ACC, LED_OFF);
00231                 break;
00232
00233             case 160:
00234                 OutSetLED(LED_FL, LED_OFF);
00235                 break;
00236
00237             case 150:
00238                 OutSetLED(LED_F1, LED_OFF);
00239                 break;
00240
00241             case 140:
00242                 OutSetLED(LED_F2, LED_OFF);
00243                 break;
00244
00245             case 130:
00246                 OutSetLED(LED_F3, LED_OFF);
00247                 break;
00248
00249             case 120:
00250                 OutSetLED(LED_F4, LED_OFF);
00251                 break;
00252
00253             case 110:
00254                 OutSetLED(LED_PWR, LED_OFF);
00255                 break;
00256
00257             case 100:
00258                 OutSetLED(LED_SEL, LED_OFF);
00259                 break;
00260             }
00261         }
00262 #endif
00263
00264         if (u8ApplTimer == 0)
00265         {
00266             if (sPCommonConfig.u8LanguageID != LANGID_NOTSPECIFIED)
00267             {
00268                 // Valid language configured, go ahead.
00269                 StrTbl_SetLanguage(sPCommonConfig.u8LanguageID);
00270                 _eBootUpSM = BOOTUP_SM_STARTUP_FINI;
00271                 break;
00272             }
00273
00274             InputEncoderInit(0, 0, LANGID_MAX, 0);
00275             _eBootUpSM = BOOTUP_SM_STARTUP_LANGUAGE;
00276         }
00277         break;
00278
00279     case BOOTUP_SM_STARTUP_LANGUAGE:
00280         if (bInputButtonPushed(ENC_BTN)||bInputButtonPushed(F4_BTN))
00281         {
00282             // Language dialog was finished!
00283             sPCommonConfig.u8LanguageID = (BYTE)s16InputEncoderGetValue();
00284             // Write the new language ID to the EEPROM:
00285             XEEWriteArray(BOOTUP_EEPROM_ADD, (BYTE *)&sPCommonConfig, sizeof(PCOMMON_CONFIG));
00286             InputButtonReset(ENC_BTN);
00287             _eBootUpSM = BOOTUP_SM_STARTUP_FINI;
00288         }
00289         else if (bInputEncoderValueChanged() == TRUE)
00290         {
00291             strcpypgm2ram(lcdram_row1, (ROM char *) "eWicht");
00292             StrTbl_SetLanguage((BYTE)s16InputEncoderGetValue());
00293             StrTbl_GetString(lcdram_row2, STRTBLID_LANGUAGE_NAME);
00294             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK | LCD_ROW2_MASK | LCD_CENTER2_MASK;
00295         }
00296         break;
00297
00298     case BOOTUP_SM_STARTUP_FINI:
00299         // Mark this session as booted:
00300         _bFirstTime = FALSE;
00301         StackInit();
00302         bInitMDNSResponder();   // Initialize the MDNS Responder.
00303         u16GlobalFlags |= LINKISUP_MASK;    // Start executing TCP/IP stack.
00304
00305         if (bInputButtonPushed(ENC_BTN) == TRUE)
00306         {
00307             // User pushed the encoder button -> Entering the IP menu.
00308             IPSetInit(FALSE);
00309             _eBootUpSM = BOOTUP_SM_IPSET;
00310         }
00311         else if (sPCommonConfig.Flags.bIsDHCPEnabled == TRUE)
00312         {
00313             // Inform the user about the enabled DHCP and the starting
00314             // discovery.
00315             StrTbl_GetString(lcdram_row1, STRTBLID_ALLOCATE);
00316             StrTbl_GetString(lcdram_row2, STRTBLID_IP_ADDRESS);
00317
00318             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00319                     LCD_ROW2_MASK | LCD_CENTER2_MASK | LCD_PROGRESS_MASK;
00320             _eBootUpSM = BOOTUP_SM_WAIT_FOR_IP;
00321             InputButtonReset(ENC_BTN);
00322         }
00323         else
00324         {
00325             // IP Address was manual set by user...
00326             _eBootUpSM = BOOTUP_SM_START_CHECK_IP;
00327         }
00328         break;
00329
00330     case BOOTUP_SM_WAIT_FOR_IP:
00331         if (bInputButtonPushed(ENC_BTN) == TRUE)
00332         {
00333             // During the discovery phase the user has the possibility to enter
00334             // the IP menu.
00335             IPSetInit(FALSE);
00336             _eBootUpSM = BOOTUP_SM_IPSET;
00337             break;
00338         }
00339
00340         if (DHCPIsBound())
00341         {
00342             // The DHCP discovery phase was successful. No IP check is needed
00343             // here.
00344
00345             // Starting the MDNS service.
00346             StartMDNSResponder();
00347             _eBootUpSM = BOOTUP_SM_DISPLAY_IPDATA;
00348         }
00349         else if (sIPConfig.MyIPAddr.Val)
00350         {
00351             // AUTO-IP (DHCP discovery not successful). Check the choosen IP
00352             // for uniqueness.
00353             _eBootUpSM = BOOTUP_SM_START_CHECK_IP;
00354         }
00355         break;
00356
00357     case BOOTUP_SM_START_CHECK_IP:
00358         // Gracious ARP phase. Checking for the uniqueness of the choosen IP
00359         // address (only needed if the IP address was choosen manually or by
00360         // AutoIP).
00361         // Sending three ARP requests to the choosen IP and waiting for
00362         // answers. If receiving an answer the gracious ARP phase fails.
00363         if (sIPConfig.Flags.bIPunique == TRUE)
00364         {
00365             _eBootUpSM = BOOTUP_SM_DISPLAY_IPDATA;
00366             break;
00367         }
00368         else
00369         {
00370             u8ApplTimer = 255;
00371             _eBootUpSM = BOOTUP_SM_CHECK_IP;
00372         }
00373         // Intented fall through.
00374
00375     case BOOTUP_SM_CHECK_IP:
00376         // Do three gracious ARP for ensuring that IP is unique.
00377         {
00378             MAC_ADDR dummy;
00379             if (u8ApplTimer == 0)
00380             {
00381                 // Gracious ARP time is over.
00382
00383                 // The uniqness of IP is ensured!
00384                 sIPConfig.Flags.bIPunique = TRUE;
00385
00386                 // Starting the MDNS service.
00387                 StartMDNSResponder();
00388
00389                 // Displaying the choosen IP Address to the user.
00390                 _eBootUpSM = BOOTUP_SM_DISPLAY_IPDATA;
00391                 break;
00392             }
00393
00394             if (ARPIsResolved(&sIPConfig.MyIPAddr, &dummy) == FALSE)
00395             {
00396                 // ARP is still not resolved! That is good.
00397                 switch(u8ApplTimer)
00398                 {
00399                 case 255:   // 2.55 seconds to go
00400                 case 192:   // 1.92 seconds to go
00401                 case 129:   // 1.29 seconds to go
00402                     ARPResolve(&sIPConfig.MyIPAddr);
00403                 }
00404             }
00405             else
00406                 // Got an answer! Gracious ARP failed.
00407                 _eBootUpSM = BOOTUP_SM_SHOW_IP_ERROR;
00408
00409             break;
00410         }
00411
00412     case BOOTUP_SM_SHOW_IP_ERROR:
00413         // An IP related error has occured.
00414
00415         // Disable the IP address!!!
00416         sIPConfig.MyIPAddr.Val = 0;
00417         sIPConfig.MyMask.Val = 0;
00418         sIPConfig.MyGateway.Val = 0;
00419
00420         // Show the error to the user.
00421         StrTbl_GetString(lcdram_row1, STRTBLID_ADDRESS_CONFLICT1);
00422         StrTbl_GetString(lcdram_row2, STRTBLID_ADDRESS_CONFLICT2);
00423         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00424                     LCD_ROW2_MASK | LCD_CENTER2_MASK;
00425
00426         InputButtonReset(ENC_BTN);
00427         _eBootUpSM = BOOTUP_SM_IP_ERROR;
00428         break;
00429
00430     case BOOTUP_SM_IP_ERROR:
00431         // Waiting for user acknowledgement of the error. After the push of the
00432         // rotary encoder the IP menu is entered.
00433         if (bInputButtonPushed(ENC_BTN) == TRUE)
00434         {
00435             IPSetInit(FALSE);
00436             _eBootUpSM = BOOTUP_SM_IPSET;
00437         }
00438         break;
00439
00440     case BOOTUP_SM_IPSET:
00441         // Call the IP menu periodically:
00442         if (IPSetMain() == TRUE)
00443         {
00444             // Restart the application...
00445             _eBootUpSM = BOOTUP_SM_STARTUP;
00446         }
00447         break;
00448
00449     case BOOTUP_SM_NOLINK:
00450         // A network connection is lost (PHY layer). Show this to the user.
00451         StrTbl_GetString(lcdram_row1, STRTBLID_CABEL_UNPLUGGED1);
00452         StrTbl_GetString(lcdram_row2, STRTBLID_CABEL_UNPLUGGED2);
00453         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00454                      LCD_ROW2_MASK | LCD_CENTER2_MASK;
00455         _eBootUpSM = BOOTUP_SM_NOLINK_WAIT;
00456         break;
00457
00458     case BOOTUP_SM_NOLINK_WAIT:
00459         // The eWicht is in a state without a network connection (PHY layer).
00460         // With a push of the rotary encoder the IP menu is entered. A detected
00461         // network connection leads to the normal bootup state.
00462         if (bInputButtonPushed(ENC_BTN) == TRUE)
00463         {
00464             IPSetInit(FALSE);
00465             _eBootUpSM = BOOTUP_SM_IPSET;
00466         }
00467         else if (MACIsLinked())
00468         {
00469             if (sPCommonConfig.Flags.bIsDHCPEnabled)
00470             {
00471                 DHCPReset(FALSE);
00472             }
00473             else
00474             {
00475                 sIPConfig.Flags.bIPunique = FALSE;
00476             }
00477
00478             _eBootUpSM = BOOTUP_SM_STARTUP;
00479         }
00480         break;
00481
00482     case BOOTUP_SM_DISPLAY_IPDATA:
00483         // In case the IP was obtained automatically (via DHCP or AutoIP), the
00484         // IP is shown to the user.
00485         if (sPCommonConfig.Flags.bIsDHCPEnabled == TRUE)
00486         {
00487             StrTbl_GetString(lcdram_row1, STRTBLID_OBTAINED_IP);
00488         }
00489         else
00490         {
00491             StrTbl_GetString(lcdram_row1, STRTBLID_MANUAL_IP);
00492         }
00493
00494         sprintf(lcdram_row2, (ROM char *) "%hhu.%hhu.%hhu.%hhu",
00495                         sIPConfig.MyIPAddr.v[0], sIPConfig.MyIPAddr.v[1],
00496                         sIPConfig.MyIPAddr.v[2], sIPConfig.MyIPAddr.v[3]);
00497         lcd_addr2 = 0;
00498         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00499                      LCD_CENTER2_MASK | LCD_ROW2_MASK;
00500
00501         InputButtonReset(ENC_BTN);
00502         u8ApplTimer = 250;
00503         _eBootUpSM = BOOTUP_SM_WAIT_FOR_USER;
00504         break;
00505
00506     case BOOTUP_SM_WAIT_FOR_USER:
00507         if ((u8ApplTimer == 0) || (bInputButtonPushed(ENC_BTN) == TRUE))
00508         {
00509             _eBootUpSM = BOOTUP_SM_WAIT_FOR_NAMESERVICE;
00510         }
00511         break;
00512
00513     case BOOTUP_SM_WAIT_FOR_NAMESERVICE:
00514         if(eGetMDNSState() == MDNS_HAS_STOPPED)
00515         {
00516             // Nameserver has stopped! Thats bad but the eWicht will work
00517             // anyway. Display to user, that nameserver could not be
00518             // started. Connection to the eWicht via its name is not
00519             // possible than.
00520             // A reason for this can be that another device in the network
00521             // has the same name.
00522
00523             StrTbl_GetString(lcdram_row1, STRTBLID_NAMESERVICE);
00524             StrTbl_GetString(lcdram_row2, STRTBLID_STOPPED);
00525             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00526                          LCD_ROW2_MASK | LCD_CENTER2_MASK;
00527
00528             InputButtonReset(ENC_BTN);
00529             u8ApplTimer = 250;
00530             _eBootUpSM = BOOTUP_SM_WAIT_FOR_USER2;
00531         }
00532         else if(eGetMDNSState() == MDNS_IS_RUNNING)
00533         {
00534             _eBootUpSM = BOOTUP_SM_READY;
00535         }
00536
00537         break;
00538
00539     case BOOTUP_SM_WAIT_FOR_USER2:
00540         if ((u8ApplTimer == 0) || (bInputButtonPushed(ENC_BTN) == TRUE))
00541         {
00542             _eBootUpSM = BOOTUP_SM_READY;
00543         }
00544         break;
00545
00546     case BOOTUP_SM_READY:
00547         // The boot up is finished. Indicate this to the calling application.
00548         return TRUE;
00549     }
00550
00551     return FALSE;
00552 }
00553
00554 // ////////////////////////////////////////////////////////////////////////////
00555 // ////////////////////////////////////////////////////////////////////////////
00556
00557 void BootupEnterBootloader(void)
00558 {
00559     // Fetch the MAC address from MAC module.
00560     memcpypgm2ram(_au8NetworkDataForBootloader, pu8MAC, 6);
00561     memcpy((void *)&_au8NetworkDataForBootloader[6], (void *)&sIPConfig.MyIPAddr, 4);
00562     *(WORD *)(&_au8NetworkDataForBootloader[10]) = CalcIPChecksum(_au8NetworkDataForBootloader, 6+4);
00563
00564     PROD = (WORD) _au8NetworkDataForBootloader;
00565 }
00566
00567 // ////////////////////////////////////////////////////////////////////////////
00568 // ////////////////////////////////////////////////////////////////////////////
00569
00570 void BootupRestoreState(void)
00571 {
00572     // Write the bulk of new data to the web EEPROM:
00573     XEEWriteArray(BOOTUP_EEPROM_ADD, (BYTE *)(&sPCommonConfig), sizeof(PCOMMON_CONFIG));
00574 }
00575
00576 // ////////////////////////////////////////////////////////////////////////////
00577 // ////////////////////////////////////////////////////////////////////////////
00578
00579 void BootupResetToFactory(void)
00580 {
00581     int i = 0;
00582
00583     // Restoring IP specific data:
00584
00585     // The DHCP Flag automatically resets MyIPAddr, MyMask and MyGateway to 0
00586     // in the application.
00587     sPCommonConfig.Flags.bIsDHCPEnabled = TRUE;
00588
00589     sPCommonConfig.ManIPAddr.v[0] = 192;
00590     sPCommonConfig.ManIPAddr.v[1] = 168;
00591     sPCommonConfig.ManIPAddr.v[2] = 0;
00592     sPCommonConfig.ManIPAddr.v[3] = 10;
00593     sPCommonConfig.ManMask = 24;
00594     sPCommonConfig.ManGateway.v[0] = 192;
00595     sPCommonConfig.ManGateway.v[1] = 168;
00596     sPCommonConfig.ManGateway.v[2] = 0;
00597     sPCommonConfig.ManGateway.v[3] = 1;
00598
00599     sPCommonConfig.LastAutoIP = GenerateAutoIP(0);
00600
00601     sPCommonConfig.u8LCDLight = 20;
00602
00603     sPCommonConfig.u32VersionTag = FIRMWARE_VERSION;
00604
00605     sPCommonConfig.TargetProject = PROJECT_ID;
00606
00607     // The user selects the language at eWicht after a restart:
00608     sPCommonConfig.u8LanguageID = 0xFF;
00609
00610     BootupRestoreState();
00611 }
00612
00613 // ////////////////////////////////////////////////////////////////////////////
00614 // ////////////////////////////////////////////////////////////////////////////
00615
00616 static void BootupCheckVersionTag(void)
00617 {
00618     if (sPCommonConfig.u32VersionTag == 0xFFFFFFFF)
00619     {
00620         // Indicator for first time being here (first switch on with an empty
00621         // EEPROM)! Filling the EEPROM with typical application data:
00622         ApplResetToFactory(FALSE);
00623     }
00624     else if (sPCommonConfig.u32VersionTag < FIRMWARE_VERSION)
00625     {
00626         // This EEPROM is from an old version (older than this).
00627
00628         // Migrate!
00629         sPCommonConfig.u32VersionTag = FIRMWARE_VERSION;
00630         XEEWriteArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, u32VersionTag), (BYTE *)&sPCommonConfig.u32VersionTag, 4);
00631     }
00632
00633     if (sPCommonConfig.TargetProject != PROJECT_ID)
00634     {
00635         // Trying to preserve the boot data:
00636         sPCommonConfig.TargetProject = PROJECT_ID;
00637
00638         // This EEPROM content is from another target.
00639         ApplResetToFactory(TRUE);
00640     }
00641 }
00642
00643 // ////////////////////////////////////////////////////////////////////////////
00644 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: bootup.h Source File

bootup.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00027 // ////////////////////////////////////////////////////////////////////////////
00028 // ////////////////////////////////////////////////////////////////////////////
00029
00030
00031 #ifndef BOOTUP_H
00032
00033 #define     BOOTUP_H
00034
00035
00036 // ////////////////////////////////////////////////////////////////////////////
00037 // Includes
00038 // ////////////////////////////////////////////////////////////////////////////
00039
00040 #include    <stdio.h>
00041 #include    "main.h"
00042 #include    "ipset.h"
00043 #include    "eeprom_adds.h"
00044
00045
00046 // ////////////////////////////////////////////////////////////////////////////
00047 // Defines
00048 // ////////////////////////////////////////////////////////////////////////////
00049
00050 #ifdef BOOTUP_C
00051     #define PROTO
00052 #else
00053     #define PROTO extern
00054 #endif
00055
00056
00060 #ifdef __DEBUG
00061     #define HOSTNAME    ((ROM BYTE *) "ew7c4000")
00062 #else // Located in bootloader...
00063     #define HOSTNAME    ((ROM BYTE *) 0x01fbf0)
00064 #endif
00065
00066
00067 // ////////////////////////////////////////////////////////////////////////////
00068 // Typedefs
00069 // ////////////////////////////////////////////////////////////////////////////
00070
00071
00075 typedef struct __attribute__((__packed__)) _IP_CONFIG
00076 {
00077     IP_ADDR     MyIPAddr;
00078     IP_ADDR     MyMask;
00079     IP_ADDR     MyGateway;
00080     struct
00081     {
00082         unsigned char : 7;
00083         unsigned char bIPunique : 1;
00084     } Flags;
00085 } IP_CONFIG;
00086
00087
00091 typedef struct
00092 {
00093     unsigned char : 7;
00094
00096     unsigned char bIsDHCPEnabled : 1;
00097 } sIPFlags;
00098
00099
00101 typedef enum
00102 {
00103     SRCP_PROJECT = 0xFF,
00104     ROCRAIL_PROJECT
00105 } eWichtProjects;
00106
00107
00112 typedef struct __attribute__((__packed__))
00113 {
00114     IP_ADDR     ManIPAddr;
00115     BYTE        ManMask;
00116     IP_ADDR     ManGateway;
00117     IP_ADDR     LastAutoIP;
00118     sIPFlags    Flags;
00119
00122     BYTE        u8LCDLight;
00123
00127     DWORD       u32VersionTag;
00128
00132     eWichtProjects  TargetProject;
00133
00136     BYTE        u8LanguageID;
00137
00138 } PCOMMON_CONFIG;
00139
00140
00141 // ////////////////////////////////////////////////////////////////////////////
00142 // Global variables
00143 // ////////////////////////////////////////////////////////////////////////////
00144
00148 PROTO IP_CONFIG sIPConfig;
00149
00156 PROTO PCOMMON_CONFIG sPCommonConfig;
00157
00158
00159 // ////////////////////////////////////////////////////////////////////////////
00160 // Global function prototypes
00161 // ////////////////////////////////////////////////////////////////////////////
00162
00163 // ////////////////////////////////////////////////////////////////////////////
00177 void BootupInit(void);
00178
00179
00180 // ////////////////////////////////////////////////////////////////////////////
00210 BOOL bBootupMain(void);
00211
00212
00213 // ////////////////////////////////////////////////////////////////////////////
00229 void BootupSetIP(void);
00230
00231
00232 // ////////////////////////////////////////////////////////////////////////////
00247 void BootupResetToFactory(void);
00248
00249
00250 // ////////////////////////////////////////////////////////////////////////////
00256 void BootupEnterBootloader(void);
00257
00258
00259 // ////////////////////////////////////////////////////////////////////////////
00264 void BootupRestoreState(void);
00265
00266
00267 // ////////////////////////////////////////////////////////////////////////////
00268 // Epilogue
00269 // ////////////////////////////////////////////////////////////////////////////
00270
00273 #undef PROTO
00274
00275 #endif  // #ifndef BOOTUP_H
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: config.c Source File

config.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00014     #define     CONFIG_C
00015
00016
00017 // ////////////////////////////////////////////////////////////////////////////
00018 // Includes
00019 // ////////////////////////////////////////////////////////////////////////////
00020
00021     #include    "config.h"
00022     #include    "webprocess.h"
00023     #include    "xml.h"
00024
00025
00026 // ////////////////////////////////////////////////////////////////////////////
00027 // Defines
00028 // ////////////////////////////////////////////////////////////////////////////
00029
00030 #define EXEC_POSTCONFIG_NAME_LENGTH     (20+1)
00031 #define EXEC_POSTCONFIG_VALUE_LENGTH    (32+1)
00032
00033 #define EXEC_POSTCONFIG_NEEDED_SPACE    (EXEC_POSTCONFIG_NAME_LENGTH+EXEC_POSTCONFIG_VALUE_LENGTH)
00034
00035
00036 #define SM_FILE_READ_SEPARATOR  (0u)
00037 #define SM_FILE_SKIP_TO_DATA    (1u)
00038 #define SM_FILE_PARSE_HEADER    (2u)
00039 #define SM_FILE_PARSE_XML       (3u)
00040 #define SM_FILE_POST_COMPLETE   (4u)
00041 #define SM_FILE_PARSE_CONFIG    (5u)
00042 #define SM_FILE_PARSE_SRCPPROTO (6u)
00043 #define SM_FILE_PARSE_SRCPDB    (7u)
00044
00045
00046 // ////////////////////////////////////////////////////////////////////////////
00047 // ////////////////////////////////////////////////////////////////////////////
00048
00049 HTTP_IO_RESULT ConfigPostFile(BYTE * pu8Workspace)
00050 {
00051     auto BYTE * name = pu8Workspace;
00052     auto BYTE * value = &name[EXEC_POSTCONFIG_NAME_LENGTH];
00053
00054     WORD lenA, lenB;
00055
00056
00057
00058     // Don't care about curHTTP.data at this point, so use that for buffer
00059     switch(curHTTP.smPost)
00060     {
00061         // Just started, so try to find the separator string
00062         case SM_FILE_READ_SEPARATOR:
00063
00064             // See if a CRLF is in the buffer
00065             lenA = TCPFindROMArray(sktHTTP, (ROM BYTE*)"\r\n", 2, 0, FALSE);
00066             if(lenA == 0xffff)
00067             {//if not, ask for more data
00068                 return HTTP_IO_NEED_DATA;
00069             }
00070
00071             // If so, figure out where the last byte of data is
00072             // Data ends at CRLFseparator--CRLF, so 6+len bytes
00073             curHTTP.byteCount -= lenA + 6;
00074
00075             // Read past the CRLF
00076             curHTTP.byteCount -= TCPGetArray(sktHTTP, NULL, lenA+2);
00077
00078             // Save the next state (skip to CRLFCRLF)
00079             curHTTP.smPost = SM_FILE_SKIP_TO_DATA;
00080
00081             // No break...continue reading the headers if possible
00082
00083         // Skip the headers
00084         case SM_FILE_SKIP_TO_DATA:
00085             // Look for the CRLFCRLF
00086             lenA = TCPFindROMArray(sktHTTP, (ROM BYTE*)"\r\n\r\n", 4, 0, FALSE);
00087
00088             if(lenA != 0xffff)
00089             {
00090                 // Found it, so remove all data up to and including
00091                 lenA = TCPGetArray(sktHTTP, NULL, lenA+4);
00092                 curHTTP.byteCount -= lenA;
00093                 curHTTP.smPost = SM_FILE_PARSE_HEADER;
00094             }
00095             else
00096             {
00097                 // Otherwise, remove as much as possible
00098                 lenA = TCPGetArray(sktHTTP, NULL, TCPIsGetReady(sktHTTP) - 4);
00099                 curHTTP.byteCount -= lenA;
00100
00101                 // Return the need more data flag
00102                 return HTTP_IO_NEED_DATA;
00103             }
00104
00105             // No break if we found the header terminator
00106             InitXMLProcessor(XML_CONFIG_HANDLE, sktHTTP);
00107
00108
00109         case SM_FILE_PARSE_HEADER:
00110         case SM_FILE_PARSE_CONFIG:
00111             while(1)
00112             {
00113 continueXMLParsingLabel:
00114
00115                 if (bXMLWalkTheTree(XML_CONFIG_HANDLE) == FALSE)
00116                 {
00117                     // Ask for more data
00118                     return HTTP_IO_NEED_DATA;
00119                 }
00120
00121                 if (eXMLGetState(XML_CONFIG_HANDLE) == XML_ROOT_LEAVED)
00122                 {
00123                     // Root level leaved: file completely processed!
00124                     curHTTP.smPost = SM_FILE_POST_COMPLETE;
00125                     return HTTP_IO_DONE;
00126                 }
00127                 else if (curHTTP.smPost == SM_FILE_PARSE_HEADER)
00128                 {
00129                     if (bXMLCheckForNode(XML_CONFIG_HANDLE, 0, (ROM char *)"config"))
00130                     {
00131                         curHTTP.smPost = SM_FILE_PARSE_CONFIG;
00132                     }
00133                 }
00134                 else if (curHTTP.smPost == SM_FILE_PARSE_CONFIG)
00135                 {
00136                     if (bXMLCheckForNode(XML_CONFIG_HANDLE, 1, (ROM char *)"common"))
00137                     {
00138                         while (bXMLGetNextAttribute(XML_CONFIG_HANDLE, name, EXEC_POSTCONFIG_NAME_LENGTH, value, EXEC_POSTCONFIG_VALUE_LENGTH) == TRUE)
00139                         {
00140                             if (strcmppgm2ram(name, (ROM char *)"language") == 0)
00141                             {
00142                                 strcpypgm2ram(name, (ROM char *)"ubg");
00143                             }
00144                             else if (strcmppgm2ram(name, (ROM char *)"lcdlight") == 0)
00145                             {
00146                                 strcpypgm2ram(name, (ROM char *)"ubi");
00147                             }
00148                             else if (strcmppgm2ram(name, (ROM char *)"toggle") == 0)
00149                             {
00150                                 strcpypgm2ram(name, (ROM char *)"ubt");
00151                             }
00152                             else if (strcmppgm2ram(name, (ROM char *)"autoip") == 0)
00153                             {
00154                                 strcpypgm2ram(name, (ROM char *)"ubm");
00155                             }
00156                             else if (strcmppgm2ram(name, (ROM char *)"ip") == 0)
00157                             {
00158                                 strcpypgm2ram(name, (ROM char *)"p");
00159                             }
00160                             else if (strcmppgm2ram(name, (ROM char *)"sub") == 0)
00161                             {
00162                                 strcpypgm2ram(name, (ROM char *)"s");
00163                             }
00164                             else if (strcmppgm2ram(name, (ROM char *)"gate") == 0)
00165                             {
00166                                 strcpypgm2ram(name, (ROM char *)"a");
00167                             }
00168                             else if (strcmppgm2ram(name, (ROM char *)"server") == 0)
00169                             {
00170                                 strcpypgm2ram(name, (ROM char *)"x");
00171                             }
00172                             else
00173                             {
00174                                 continue;
00175                             }
00176
00177                             ProcessCommonData(name, value);
00178                         }
00179
00180                         strcpypgm2ram(name, (ROM char *)"0");
00181                         ProcessCommonData(name, NULL);
00182                     }
00183 #ifdef _SRCP
00184                     else if (bXMLCheckForNode(XML_CONFIG_HANDLE, 1, (ROM char *)"srcp"))
00185                     {
00186                         while (bXMLGetNextAttribute(XML_CONFIG_HANDLE, name, EXEC_POSTCONFIG_NAME_LENGTH, value, EXEC_POSTCONFIG_VALUE_LENGTH) == TRUE)
00187                         {
00188                             if (strcmppgm2ram(name, (ROM char *)"locoprotorequest") == 0)
00189                             {
00190                                 strcpypgm2ram(name, (ROM char *)"ubL");
00191                             }
00192                             else if (strcmppgm2ram(name, (ROM char *)"accprotorequest") == 0)
00193                             {
00194                                 strcpypgm2ram(name, (ROM char *)"ubA");
00195                             }
00196                             else if (strcmppgm2ram(name, (ROM char *)"locostandard") == 0)
00197                             {
00198                                 strcpypgm2ram(name, (ROM char *)"ubB");
00199                             }
00200                             else if (strcmppgm2ram(name, (ROM char *)"accstandard") == 0)
00201                             {
00202                                 strcpypgm2ram(name, (ROM char *)"ubD");
00203                             }
00204                             else if (strcmppgm2ram(name, (ROM char *)"accdelay") == 0)
00205                             {
00206                                 strcpypgm2ram(name, (ROM char *)"dV");
00207                             }
00208                             else
00209                             {
00210                                 continue;
00211                             }
00212
00213                             ProcessSRCPData(name, value);
00214                         }
00215
00216                         strcpypgm2ram(name, (ROM char *)"0");
00217                         ProcessSRCPData(name, NULL);
00218                     }
00219                     else if (bXMLCheckForNode(XML_CONFIG_HANDLE, 1, (ROM char *)"srcpproto"))
00220                     {
00221                         // Fetch Id into value...
00222                         if (bXMLSearchAttribute(XML_CONFIG_HANDLE, (ROM char *)"id", value, EXEC_POSTCONFIG_VALUE_LENGTH) == FALSE)
00223                         {
00224                             // Invalid proto tag (no id given)
00225                             continue;
00226                         }
00227
00228                         name[0] = 'A';
00229                         ProcessProtoData(&pu8Workspace[EXEC_POSTCONFIG_NEEDED_SPACE], name, value);
00230                         name[0] = 'c';
00231                         ProcessProtoData(&pu8Workspace[EXEC_POSTCONFIG_NEEDED_SPACE], name, NULL);
00232
00233                         // Fetch the given parameters:
00234                         curHTTP.smPost = SM_FILE_PARSE_SRCPPROTO;
00235                         goto ParseSRCPProtoDataLabel;
00236                     }
00237                     else if (bXMLCheckForNode(XML_CONFIG_HANDLE, 1, (ROM char *)"srcpdb"))
00238                     {
00239                         // Fetch Id into value...
00240                         if (bXMLSearchAttribute(XML_CONFIG_HANDLE, (ROM char *)"id", value, EXEC_POSTCONFIG_VALUE_LENGTH) == FALSE)
00241                         {
00242                             // Invalid proto tag (no id given)
00243                             continue;
00244                         }
00245
00246                         name[0] = 'A';
00247                         name[1] = 's';
00248                         ProcessSetData(&pu8Workspace[EXEC_POSTCONFIG_NEEDED_SPACE], name, value);
00249
00250                         // Fetch the given parameters:
00251                         curHTTP.smPost = SM_FILE_PARSE_SRCPDB;
00252                         goto ParseSRCPDBDataLabel;
00253                     }
00254 #endif  // #ifdef _SRCP
00255                 }
00256             }
00257
00258             // We never should come in here!
00259             break;
00260
00261
00262 #ifdef _SRCP
00263         case SM_FILE_PARSE_SRCPDB:
00264 ParseSRCPDBDataLabel:
00265
00266             while(1)
00267             {
00268                 if (bXMLWalkTheTree(XML_CONFIG_HANDLE) == FALSE)
00269                 {
00270                     // Ask for more data
00271                     return HTTP_IO_NEED_DATA;
00272                 }
00273
00274                 if (eXMLGetState(XML_CONFIG_HANDLE) == XML_LEVEL_LEAVED)
00275                 {
00276                     name[0] = 'E';
00277                     ProcessSetData(&pu8Workspace[EXEC_POSTCONFIG_NEEDED_SPACE], name, NULL);
00278                     curHTTP.smPost = SM_FILE_PARSE_CONFIG;
00279                     goto continueXMLParsingLabel;
00280                 }
00281
00282                 if (bXMLCheckForNode(XML_CONFIG_HANDLE, 2, (ROM char *)"data"))
00283                 {
00284                     while (bXMLGetNextAttribute(XML_CONFIG_HANDLE, name, EXEC_POSTCONFIG_NAME_LENGTH, value, EXEC_POSTCONFIG_VALUE_LENGTH) == TRUE)
00285                     {
00286                         if (strcmppgm2ram(name, (ROM char *)"name") == 0)
00287                         {
00288                             name[0] = 'n';
00289                         }
00290                         else if (strcmppgm2ram(name, (ROM char *)"bus") == 0)
00291                         {
00292                             strcpypgm2ram(name, (ROM char *)"ubb");
00293                         }
00294                         else if (strcmppgm2ram(name, (ROM char *)"proto") == 0)
00295                         {
00296                             name[0] = 'p';
00297                         }
00298                         else if (strcmppgm2ram(name, (ROM char *)"add") == 0)
00299                         {
00300                             strcpypgm2ram(name, (ROM char *)"usm");
00301                         }
00302                         else if (strcmppgm2ram(name, (ROM char *)"maxspeed") == 0)
00303                         {
00304                             strcpypgm2ram(name, (ROM char *)"ush");
00305                         }
00306                         else if (strcmppgm2ram(name, (ROM char *)"steps") == 0)
00307                         {
00308                             strcpypgm2ram(name, (ROM char *)"ubs");
00309                         }
00310                         else if (strcmppgm2ram(name, (ROM char *)"funcs") == 0)
00311                         {
00312                             strcpypgm2ram(name, (ROM char *)"ubf");
00313                         }
00314                         else if (strcmppgm2ram(name, (ROM char *)"minport") == 0)
00315                         {
00316                             strcpypgm2ram(name, (ROM char *)"ubq");
00317                         }
00318                         else if (strcmppgm2ram(name, (ROM char *)"maxport") == 0)
00319                         {
00320                             strcpypgm2ram(name, (ROM char *)"ubr");
00321                         }
00322                         else if (strcmppgm2ram(name, (ROM char *)"togglemask") == 0)
00323                         {
00324                             strcpypgm2ram(name, (ROM char *)"uF");
00325                         }
00326                         else if (strcmppgm2ram(name, (ROM char *)"delay") == 0)
00327                         {
00328                             strcpypgm2ram(name, (ROM char *)"dd");
00329                         }
00330                         else
00331                         {
00332                             continue;
00333                         }
00334
00335                         ProcessSetData(&pu8Workspace[EXEC_POSTCONFIG_NEEDED_SPACE], name, value);
00336                     }
00337                 }
00338             }
00339             break;
00340
00341         case SM_FILE_PARSE_SRCPPROTO:
00342 ParseSRCPProtoDataLabel:
00343
00344             while(1)
00345             {
00346                 if (bXMLWalkTheTree(XML_CONFIG_HANDLE) == FALSE)
00347                 {
00348                     // Ask for more data
00349                     return HTTP_IO_NEED_DATA;
00350                 }
00351
00352                 if (eXMLGetState(XML_CONFIG_HANDLE) == XML_LEVEL_LEAVED)
00353                 {
00354                     name[0] = 'E';
00355                     ProcessProtoData(&pu8Workspace[EXEC_POSTCONFIG_NEEDED_SPACE], name, NULL);
00356                     curHTTP.smPost = SM_FILE_PARSE_CONFIG;
00357                     goto continueXMLParsingLabel;
00358                 }
00359
00360                 if (bXMLCheckForNode(XML_CONFIG_HANDLE, 2, (ROM char *)"data"))
00361                 {
00362                     while (bXMLGetNextAttribute(XML_CONFIG_HANDLE, name, EXEC_POSTCONFIG_NAME_LENGTH, value, EXEC_POSTCONFIG_VALUE_LENGTH) == TRUE)
00363                     {
00364                         if (strcmppgm2ram(name, (ROM char *)"name") == 0)
00365                         {
00366                             name[0] = 'n';
00367                         }
00368                         else if (strcmppgm2ram(name, (ROM char *)"bus") == 0)
00369                         {
00370                             strcpypgm2ram(name, (ROM char *)"ubb");
00371                         }
00372                         else if (strcmppgm2ram(name, (ROM char *)"proto") == 0)
00373                         {
00374                             name[0] = 'p';
00375                         }
00376                         else if (strcmppgm2ram(name, (ROM char *)"minadd") == 0)
00377                         {
00378                             strcpypgm2ram(name, (ROM char *)"usm");
00379                         }
00380                         else if (strcmppgm2ram(name, (ROM char *)"maxadd") == 0)
00381                         {
00382                             strcpypgm2ram(name, (ROM char *)"usx");
00383                         }
00384                         else if (strcmppgm2ram(name, (ROM char *)"steps") == 0)
00385                         {
00386                             strcpypgm2ram(name, (ROM char *)"ubs");
00387                         }
00388                         else if (strcmppgm2ram(name, (ROM char *)"funcs") == 0)
00389                         {
00390                             strcpypgm2ram(name, (ROM char *)"ubf");
00391                         }
00392                         else if (strcmppgm2ram(name, (ROM char *)"minport") == 0)
00393                         {
00394                             strcpypgm2ram(name, (ROM char *)"ubq");
00395                         }
00396                         else if (strcmppgm2ram(name, (ROM char *)"maxport") == 0)
00397                         {
00398                             strcpypgm2ram(name, (ROM char *)"ubr");
00399                         }
00400                         else
00401                         {
00402                             continue;
00403                         }
00404
00405                         ProcessProtoData(&pu8Workspace[EXEC_POSTCONFIG_NEEDED_SPACE], name, value);
00406                     }
00407                 }
00408             }
00409             break;
00410 #endif // #ifdef _SRCP
00411
00412     }
00413
00414     return HTTP_IO_DONE;
00415 }
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: config.h Source File

config.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00016 // ////////////////////////////////////////////////////////////////////////////
00017 // ////////////////////////////////////////////////////////////////////////////
00018
00019
00020 #ifndef CONFIG_H
00021
00022 #define     CONFIG_H
00023
00024 // ////////////////////////////////////////////////////////////////////////////
00025 // Includes
00026 // ////////////////////////////////////////////////////////////////////////////
00027
00028 #include    "main.h"
00029
00030
00031
00032 // ////////////////////////////////////////////////////////////////////////////
00033 // Defines
00034 // ////////////////////////////////////////////////////////////////////////////
00035
00036 #ifdef CONFIG_C
00037     #define PROTO
00038 #else
00039     #define PROTO extern
00040 #endif
00041
00042
00043 // ////////////////////////////////////////////////////////////////////////////
00044 // Function prototypes
00045 // ////////////////////////////////////////////////////////////////////////////
00046
00047 PROTO HTTP_IO_RESULT ConfigPostFile(BYTE * pu8Workspace);
00048
00049
00052 // ////////////////////////////////////////////////////////////////////////////
00053 // Epilogue
00054 // ////////////////////////////////////////////////////////////////////////////
00055
00056     #undef      PROTO
00057 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: dialog.c Source File

dialog.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00015     #define     DIALOG_C
00016
00017
00018 // ////////////////////////////////////////////////////////////////////////////
00019 // Includes
00020 // ////////////////////////////////////////////////////////////////////////////
00021
00022     #include    "dialog.h"
00023     #include    "sralloc.h"
00024
00025
00026
00027 // ////////////////////////////////////////////////////////////////////////////
00028 // Local Defines
00029 // ////////////////////////////////////////////////////////////////////////////
00030
00031 #define DIALOG_LETTERS_COUNT        sizeof(_LetterList)
00032 #define DIALOG_CAPITALS_COUNT       sizeof(_CapitalList)
00033 #define DIALOG_WHITESPACE_COUNT     1
00034 #define DIALOG_NUMBERS_COUNT        sizeof(_NumberList)
00035 #define DIALOG_DASH_COUNT           1
00036 #define DIALOG_SPECIAL_COUNT        10
00037
00038
00039 // ////////////////////////////////////////////////////////////////////////////
00040 // Local Typedefs
00041 // ////////////////////////////////////////////////////////////////////////////
00042
00043 typedef struct
00044 {
00045     BYTE * pDispRow;
00046     BYTE MaxCursorPos;
00047     BYTE CursorPos;
00048     BYTE DispRow;
00049     BYTE ControlFlags;
00050     BOOL DisplayCursor;
00051     DialogRetValue_t RetValue;
00052 //  BYTE [] CharSetArray;
00053 } sDialogState;
00054
00055
00056 // ////////////////////////////////////////////////////////////////////////////
00057 // Local variables
00058 // ////////////////////////////////////////////////////////////////////////////
00059
00060 ROM BYTE _LetterList[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
00061      'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
00062      'y', 'z' };
00063
00064 ROM BYTE _CapitalList[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
00065      'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00066      'Y', 'Z' };
00067
00068 ROM BYTE _NumberList[] = {'0','1','2','3','4','5','6','7','8','9'};
00069
00070 static sDialogState * _psState = NULL;
00071
00072
00073 // ////////////////////////////////////////////////////////////////////////////
00074 // Local function prototypes
00075 // ////////////////////////////////////////////////////////////////////////////
00076
00077 // ////////////////////////////////////////////////////////////////////////////
00078 // ////////////////////////////////////////////////////////////////////////////
00079
00080 BOOL bInitInputDialog(BYTE * pu8DefaultString, BYTE u8AllowedCharacters,
00081                       BYTE u8DispRow, BYTE u8MaxCursorPos, BYTE u8ControlFlags)
00082 {
00083     BYTE i;
00084     BYTE charSetCount;
00085     BYTE * pCharsList = NULL;
00086
00087 inputDialogGetCharacters:
00088     // Determine the count of maximum possible input characters:
00089
00090     charSetCount = 0;
00091     if (u8AllowedCharacters & DIALOG_LETTERS_FLAG)
00092     {
00093         charSetCount = DIALOG_LETTERS_COUNT;
00094         if (pCharsList)
00095             memcpypgm2ram(pCharsList, _LetterList, DIALOG_LETTERS_COUNT);
00096     }
00097     if (u8AllowedCharacters & DIALOG_CAPITALS_FLAG)
00098     {
00099         if (pCharsList)
00100             memcpypgm2ram(&pCharsList[charSetCount], _CapitalList, DIALOG_CAPITALS_COUNT);
00101         charSetCount += DIALOG_CAPITALS_COUNT;
00102     }
00103     if (u8AllowedCharacters & DIALOG_WHITESPACE_FLAG)
00104     {
00105         if (pCharsList)
00106             pCharsList[charSetCount] = ' ';
00107         charSetCount++;
00108     }
00109     if (u8AllowedCharacters & DIALOG_DASH_FLAG)
00110     {
00111         if (pCharsList)
00112             pCharsList[charSetCount] = '-';
00113         charSetCount++;
00114     }
00115     if (u8AllowedCharacters & DIALOG_NUMBERS_FLAG)
00116     {
00117         if (pCharsList)
00118             memcpypgm2ram(&pCharsList[charSetCount], _NumberList, DIALOG_NUMBERS_COUNT);
00119         charSetCount += DIALOG_NUMBERS_COUNT;
00120     }
00121     if (u8AllowedCharacters & DIALOG_SPECIAL_FLAG)
00122     {
00123         if (pCharsList)
00124             pCharsList[charSetCount] = '.';
00125         charSetCount++;
00126     }
00127
00128     // Obtaining a heap array and prepare the state and character set then:
00129     if (_psState == NULL)
00130     {
00131         _psState = (sDialogState*)SRAMalloc(sizeof(sDialogState)+charSetCount);
00132
00133         if (_psState==NULL)
00134             return FALSE;
00135
00136         pCharsList = (BYTE *)_psState + sizeof(sDialogState);
00137         goto inputDialogGetCharacters;
00138     }
00139
00140
00141     _psState->CursorPos = strlen(pu8DefaultString);
00142     if (_psState->CursorPos)
00143     {
00144         // Trying to find the last character in the corresponding character
00145         // list.
00146         _psState->CursorPos--;
00147         for(i = 0; i < charSetCount; i++)
00148         {
00149             if (pu8DefaultString[_psState->CursorPos] == pCharsList[i])
00150                 break;
00151         }
00152
00153         if (i == charSetCount)
00154             i = 0;
00155     }
00156     else
00157     {
00158         // Start with the first character.
00159         i = 0;
00160     }
00161
00162
00164     // Preparing the buttons:
00165     InputEncoderInit(i, 0, charSetCount-1, 0);
00166     InputButtonReset(ALL_BTN);
00167
00168
00170     // Preparing the display:
00171
00172     _psState->MaxCursorPos = u8MaxCursorPos;
00173     _psState->DispRow = u8DispRow;
00174
00175     if (u8DispRow==0)
00176     {
00177         _psState->pDispRow = lcdram_row1;
00178     }
00179     else
00180     {
00181         _psState->pDispRow = lcdram_row2;
00182     }
00183
00184     strncpy(_psState->pDispRow, pu8DefaultString, LCD_CHARS_IN_A_ROW);
00185     _psState->pDispRow[LCD_CHARS_IN_A_ROW] = 0;
00186     lcd_addr1 = 0;
00187     lcd_addr2 = 0;
00188     lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
00189
00190     if (u8ControlFlags & DIALOG_DESCRIPTION_FLAG)
00191     {
00192         memset(lcdram_row2, ' ', LCD_CHARS_IN_A_ROW);
00193         lcdram_row2[LCD_CHARS_IN_A_ROW] = 0;
00194
00195         if (u8ControlFlags & DIALOG_PREV_FLAG)
00196         {
00197             lcdram_row2[0] = 0xFB;  // <<
00198         }
00199         if (u8ControlFlags & DIALOG_ESC_FLAG)
00200         {
00201             memcpypgm2ram(&lcdram_row2[4], (ROM char *) "ESC", 3);
00202         }
00203         if (u8ControlFlags & DIALOG_BACKSPACE_FLAG)
00204         {
00205             lcdram_row2[10] = 0x7F; // <-
00206         }
00207         if (u8ControlFlags & DIALOG_NEXT_FLAG)
00208         {
00209             lcdram_row2[15] = 0xFC; // >>
00210         }
00211     }
00212     _psState->ControlFlags = u8ControlFlags;
00213
00214     OutEnableCursor(TRUE);
00215     _psState->DisplayCursor = TRUE;
00216
00217     return TRUE;
00218 }
00219
00220 // ////////////////////////////////////////////////////////////////////////////
00221 // ////////////////////////////////////////////////////////////////////////////
00222
00223 BOOL bHandleInputDialog(void)
00224 {
00225     if (OutIsLCDBusy()==TRUE)
00226     {
00227         return FALSE;
00228     }
00229     else if (_psState->DisplayCursor == TRUE)
00230     {
00231         OutSetCursor(_psState->CursorPos, _psState->DispRow);
00232         _psState->DisplayCursor = FALSE;
00233         return FALSE;
00234     }
00235
00236     if ((bInputEncoderValueChanged() == TRUE) && (_psState->CursorPos < _psState->MaxCursorPos))
00237     {
00238         BYTE*pChar=(BYTE*)_psState+sizeof(sDialogState)+s16InputEncoderGetValue();
00239         _psState->pDispRow[_psState->CursorPos] = *pChar;
00240     }
00241     else if (bInputButtonPushed(ENC_BTN) == TRUE)
00242     {
00243         // Next position is selected.
00244         InputButtonReset(ENC_BTN);
00245
00246         if ((_psState->pDispRow[_psState->CursorPos]) &&
00247             (_psState->CursorPos < (_psState->MaxCursorPos-1)))
00248         {
00249             InputEncoderSetValue(0, TRUE);
00250             _psState->CursorPos++;
00251         }
00252     }
00253     else if ((_psState->ControlFlags & DIALOG_BACKSPACE_FLAG) &&
00254              (bInputButtonPushed(F3_BTN) == TRUE))
00255     {
00256         BYTE i = 0;
00257
00258         // Backspace emulation
00259         InputButtonReset(F3_BTN);
00260         _psState->pDispRow[_psState->CursorPos] = ' ';
00261
00262         if (_psState->CursorPos)
00263         {
00264             BYTE*pCharSet = (BYTE*)_psState+sizeof(sDialogState);
00265             _psState->CursorPos--;
00266             while(_psState->pDispRow[_psState->CursorPos] != pCharSet[i++]);
00267         }
00268         else
00269         {
00270             // Display the first character.
00271             i = 1;
00272         }
00273         InputEncoderSetValue(i-1, TRUE);
00274     }
00275     else if ((_psState->ControlFlags & DIALOG_NEXT_FLAG) && (bInputButtonPushed(F4_BTN) == TRUE))
00276     {
00277         // Dialog is finished with OK!
00278         _psState->RetValue = DIALOG_FINI_OK;
00279         return TRUE;
00280     }
00281     else if ((_psState->ControlFlags & DIALOG_ESC_FLAG) && (bInputButtonPushed(F2_BTN) == TRUE))
00282     {
00283         // Dialog is finished with escape!
00284         _psState->RetValue = DIALOG_FINI_ESC;
00285         return TRUE;
00286     }
00287     else if ((_psState->ControlFlags & DIALOG_PREV_FLAG) && (bInputButtonPushed(F1_BTN) == TRUE))
00288     {
00289         // Dialog is finished with cancel!
00290         _psState->RetValue = DIALOG_FINI_CANCEL;
00291         return TRUE;
00292     }
00293     else
00294     {
00295         return FALSE;
00296     }
00297
00298     lcd_status = LCD_ROW1_MASK | LCD_ROW2_MASK;
00299     _psState->DisplayCursor = TRUE;
00300
00301     return FALSE;
00302 }
00303
00304 // ////////////////////////////////////////////////////////////////////////////
00305 // ////////////////////////////////////////////////////////////////////////////
00306
00307 DialogRetValue_t FiniDialog(BYTE * pResultString)
00308 {
00309     DialogRetValue_t ret;
00310     ret = _psState->RetValue;
00311
00312     if (_psState == NULL)
00313     {
00314         return DIALOG_FINI_CANCEL;
00315     }
00316
00317     if ((ret == DIALOG_FINI_OK) && (pResultString))
00318     {
00319         strncpy(pResultString, _psState->pDispRow, _psState->MaxCursorPos);
00320         pResultString[_psState->MaxCursorPos] = 0;
00321     }
00322
00323     OutEnableCursor(FALSE);
00324     InputButtonReset(ALL_BTN);
00325
00326
00327     SRAMfree((BYTE *)_psState);
00328     _psState = NULL;
00329
00330     return ret;
00331 }
00332
00333 // ////////////////////////////////////////////////////////////////////////////
00334 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: dialog.h Source File

dialog.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00015 // ////////////////////////////////////////////////////////////////////////////
00016 // ////////////////////////////////////////////////////////////////////////////
00017
00018
00019 #ifndef DIALOG_H
00020
00021 #define     DIALOG_H
00022
00023 // ////////////////////////////////////////////////////////////////////////////
00024 // Includes
00025 // ////////////////////////////////////////////////////////////////////////////
00026
00027 #include    "main.h"
00028
00029
00030 // ////////////////////////////////////////////////////////////////////////////
00031 // Defines
00032 // ////////////////////////////////////////////////////////////////////////////
00033
00035 #define DIALOG_LETTERS_FLAG     0x01
00037 #define DIALOG_CAPITALS_FLAG    0x02
00039 #define DIALOG_WHITESPACE_FLAG  0x04
00041 #define DIALOG_DASH_FLAG        0x08
00043 #define DIALOG_NUMBERS_FLAG     0x10
00045 #define DIALOG_SPECIAL_FLAG     0x20
00047 #define DIALOG_ALL_LETTERS      0xFF
00048
00049
00051 #define DIALOG_PREV_FLAG        0x01
00052
00054 #define DIALOG_ESC_FLAG         0x02
00055
00057 #define DIALOG_BACKSPACE_FLAG   0x04
00058
00060 #define DIALOG_NEXT_FLAG        0x08
00061
00063 #define DIALOG_DESCRIPTION_FLAG 0x10
00064
00066 #define DIALOG_DESCTOGGLE_FLAG  0x20
00067
00068
00069 // ////////////////////////////////////////////////////////////////////////////
00070 // Typedefs
00071 // ////////////////////////////////////////////////////////////////////////////
00072
00073 typedef enum
00074 {
00075     DIALOG_FINI_OK = 0,
00076     DIALOG_FINI_ESC,
00077     DIALOG_FINI_CANCEL
00078 } DialogRetValue_t;
00079
00080 // ////////////////////////////////////////////////////////////////////////////
00081 // Function prototypes
00082 // ////////////////////////////////////////////////////////////////////////////
00083
00084 BOOL bInitInputDialog(BYTE * pu8DefaultString, BYTE u8AllowedCharacters,
00085                      BYTE u8DispRow, BYTE u8MaxCursorPos, BYTE u8ControlFlags);
00086 BOOL bHandleInputDialog(void);
00087 DialogRetValue_t FiniDialog(BYTE * pResultString);
00088
00091 // ////////////////////////////////////////////////////////////////////////////
00092 // Epilogue
00093 // ////////////////////////////////////////////////////////////////////////////
00094
00095
00096 #endif  // #ifndef DIALOG_H
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: eeprom_adds.h Source File

eeprom_adds.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00008 // ////////////////////////////////////////////////////////////////////////////
00009 // ////////////////////////////////////////////////////////////////////////////
00010
00011
00018 #define BOOTUP_EEPROM_ADD           (0x0000u)
00019
00026 #define APPL_EEPROM_ADD             (0x0100u)
00027
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: error.c Source File

error.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00014     #define     ERROR_C
00015
00016
00017 // ////////////////////////////////////////////////////////////////////////////
00018 // Includes
00019 // ////////////////////////////////////////////////////////////////////////////
00020
00021     #include    "error.h"
00022     #include    "output.h"
00023     #include    "stringtable.h"
00024
00025
00026 // ////////////////////////////////////////////////////////////////////////////
00027 // ////////////////////////////////////////////////////////////////////////////
00028
00029 void PrintCommonError(eCommonErrorCodes eErrorCode)
00030 {
00031     lcd_addr1 = 0;
00032     lcd_addr2 = 0;
00033     StrTbl_GetString(lcdram_row1, STRTBLID_COMMON_ERROR1);
00034     sprintf(lcdram_row2,
00035             StrTbl_cau8GetStringPointer(STRTBLID_COMMON_ERROR2),
00036             eErrorCode);
00037     lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00038                     LCD_ROW2_MASK | LCD_CENTER2_MASK;
00039 }
00040
00041 // ////////////////////////////////////////////////////////////////////////////
00042 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: error.h Source File

error.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00018 // ////////////////////////////////////////////////////////////////////////////
00019 // ////////////////////////////////////////////////////////////////////////////
00020
00021
00022 #ifndef ERROR_H
00023
00024 #define     ERROR_H
00025
00026
00027 // ////////////////////////////////////////////////////////////////////////////
00028 // Includes
00029 // ////////////////////////////////////////////////////////////////////////////
00030
00031
00032 // ////////////////////////////////////////////////////////////////////////////
00033 // Defines
00034 // ////////////////////////////////////////////////////////////////////////////
00035
00036 #ifdef ERROR_C
00037     #define PROTO
00038 #else
00039     #define PROTO extern
00040 #endif
00041
00042
00043 // ////////////////////////////////////////////////////////////////////////////
00044 // Typedefs
00045 // ////////////////////////////////////////////////////////////////////////////
00046
00047 /* This enum lists all possible error codes of the application. If the display
00048 shows a common error, please refer to this list to get mor knowledge about the
00049 error reason.
00050 */
00051 typedef enum
00052 {
00053     COMMON_ERROR_LOADING_SRCP_PROTOCOL = 1, // 1
00054     COMMON_ERROR_OUT_OF_MEMORY,             // 2
00055     COMMON_ERROR_NULL_POINTER,              // 3
00056     COMMON_ERROR_SRCP_NO_POWER_DEVICE,      // 4
00057     COMMON_ERROR_ROCRAIL_LOCO_NOT_FOUND     // 5
00058 } eCommonErrorCodes;
00059
00060
00061 // ////////////////////////////////////////////////////////////////////////////
00062 // Function prototypes
00063 // ////////////////////////////////////////////////////////////////////////////
00064
00065 /* This function prints the code as formated string on the display.
00066 \param eErrorCode A error code to print.
00067 */
00068 PROTO void PrintCommonError(eCommonErrorCodes eErrorCode);
00069
00072 // ////////////////////////////////////////////////////////////////////////////
00073 // Epilogue
00074 // ////////////////////////////////////////////////////////////////////////////
00075
00076     #undef      PROTO
00077
00078 #endif  // #ifndef ERROR_H
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields - Variables

  • All
  • Variables
  • a
  • b
  • e
  • f
  • l
  • m
  • s
  • t
  • u

- a -

  • au8Desc : _PERS_PROTOCOL_CONFIG
  • au8Name : SPAPPLDATA , SPSET
  • au8Proto : _PERS_PROTOCOL_CONFIG , SPSET
  • au8Service : SPAPPLDATA

- b -

  • bActive : _PERS_PROTOCOL_CONFIG , SPSET
  • bGAAskForLock : SPSRCPCONFIG
  • bGAAskForProto : SPSRCPCONFIG
  • bGALock : SPSRCPCONFIG
  • bGL : _PERS_PROTOCOL_CONFIG , SPSET
  • bGLAskForLock : SPSRCPCONFIG
  • bGLAskForProto : SPSRCPCONFIG
  • bGLLock : SPSRCPCONFIG
  • bIPunique : _IP_CONFIG
  • bIsDHCPEnabled : sIPFlags
  • bToggleLocoDirMode : SPAPPLDATA

- e -

  • eFindMode : SPAPPLDATA

- f -

  • Flags : PCOMMON_CONFIG

- l -

  • LastAutoIP : PCOMMON_CONFIG

- m -

  • ManGateway : PCOMMON_CONFIG
  • ManIPAddr : PCOMMON_CONFIG
  • ManMask : PCOMMON_CONFIG
  • MyGateway : _IP_CONFIG
  • MyIPAddr : _IP_CONFIG
  • MyMask : _IP_CONFIG

- s -

  • s32Delay : SPSET
  • s32GADelay : SPSRCPCONFIG
  • sIPPort : SPAPPLDATA
  • sNamePort : SPAPPLDATA
  • sSrvIPAdd : SPAPPLDATA

- t -

  • TargetProject : PCOMMON_CONFIG

- u -

  • u16MaxAdd : _PERS_PROTOCOL_CONFIG
  • u16MaxV : SPSET
  • u16MinAdd : _PERS_PROTOCOL_CONFIG
  • u32Address : SPSET
  • u32VersionTag : PCOMMON_CONFIG
  • u8Bus : _PERS_PROTOCOL_CONFIG
  • u8BusNr : SPSET
  • u8DefaultGAProtoId : SPSRCPCONFIG
  • u8DefaultGLProtoId : SPSRCPCONFIG
  • u8LanguageID : PCOMMON_CONFIG
  • u8LCDLight : PCOMMON_CONFIG
  • u8MaxP : _PERS_PROTOCOL_CONFIG , SPSET
  • u8MaxSteps : SPSET , _PERS_PROTOCOL_CONFIG
  • u8MinP : _PERS_PROTOCOL_CONFIG , SPSET
  • u8NrFunc : _PERS_PROTOCOL_CONFIG , SPSET
  • u8Reserved1 : SPSRCPCONFIG
  • u8Reserved2 : SPSRCPCONFIG
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- l -

  • LANGID_ENGLISH : stringtable.h
  • LANGID_GERMAN : stringtable.h
  • LANGID_MAX : stringtable.h
  • LANGID_NOTSPECIFIED : stringtable.h
  • LCD_CENTER1_MASK : output.h
  • LCD_CENTER2_MASK : output.h
  • LCD_CHARS_IN_A_ROW : output.h
  • LCD_CLR_MASK : output.h
  • LCD_CLR_PROG_MASK : output.h
  • LCD_IDLE_TIME : output.h
  • LCD_PROGRESS_CHAR : output.h
  • LCD_PROGRESS_MASK : output.h
  • LCD_PROGRESS_TIME : output.h
  • LCD_ROW1_MASK : output.h
  • LCD_ROW2_MASK : output.h
  • LCD_ROW3_MASK : output.h
  • lcd_status : output.h
  • LED_ACC : output.h
  • LED_BLINK : output.h
  • LED_BLINK_INTERVAL : output.h
  • LED_F1 : output.h
  • LED_F2 : output.h
  • LED_F3 : output.h
  • LED_F4 : output.h
  • LED_FL : output.h
  • LED_OFF : output.h
  • LED_ON : output.h
  • LED_PWR : output.h
  • LED_SEL : output.h
  • LED_TOGGLE : output.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- m -

  • MAC_ADDR : StackTsk.h
  • MACIsLinked() : ETH97J60.c , MAC.h
  • MAX_PROTO_SLOTS : srcp/projectdefs.h
  • MAX_SRCP_FUNCTIONS : srcp/projectdefs.h
  • MAX_SRCP_SPEEDSTEPS : srcp/projectdefs.h
  • MDNS_HAS_STOPPED : mdns.h
  • MDNS_IS_RUNNING : mdns.h
  • MDNS_IS_STARTING_UP : mdns.h
  • MDNS_PORT : mdns.h
  • MDNSProcessFrame() : mdns.c , mdns.h
  • MDNSResolveName() : mdns.c , mdns.h
  • MDNSResolveService() : mdns.h , mdns.c
  • MDNSResponder() : mdns.c , mdns.h
  • MDNSStopResolving() : mdns.h , mdns.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- n -

  • NODE_INFO : StackTsk.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- o -

  • OutConvertNameForDisplay() : output.c , output.h
  • OutDebugOut() : output.h
  • OutEnableCursor() : output.c , output.h
  • OutGetLEDMode() : output.c , output.h
  • OutInit() : output.c , output.h
  • OutIsLCDBusy() : output.c , output.h
  • OutMain() : output.c , output.h
  • OutSetCursor() : output.c , output.h
  • OutSetLED() : output.c , output.h
  • OutSetLEDMask() : output.c , output.h
  • OutSwitchLCDBacklight() : output.h , output.c
  • OutSwitchOffAllLEDs() : output.h , output.c
  • OutSwitchOffLCD() : output.h , output.c
  • OutTriggerDisplay() : output.h , output.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- a -

  • ACC_BTN : input.h
  • ALL_BTN : input.h
  • APPL_CONNECTING_RETCODE : appldefs.h
  • APPL_CR_CLOSED : appldefs.h
  • APPL_CR_CONNECTED : appldefs.h
  • APPL_CR_ERROR : appldefs.h
  • APPL_CR_IN_PROGRESS : appldefs.h
  • APPL_EEPROM_ADD : eeprom_adds.h
  • ApplChangeLocoDirMode() : appl.c , appl.h
  • ApplGetServerIP() : appl.c , appl.h
  • ApplGetServerNodeInfo() : appl.c , appl.h
  • ApplGetServerPort() : appl.h , appl.c
  • ApplInit() : appl.c , appl.h
  • ApplIsConnected() : appl.c , appl.h
  • ApplIsRunning() : appl.c , appl.h
  • ApplMain() : appl.c , appl.h
  • ApplResetToFactory() : appl.c , appl.h
  • ApplRestart() : appl.c , appl.h
  • ApplShutDown() : appl.c , appl.h
  • ApplStop() : appl.h , appl.c
  • ARPFlush() : ARP.h , ARP.c
  • ARPIsResolved() : ARP.c , ARP.h
  • ARPResolve() : ARP.c , ARP.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- b -

  • bBootupMain() : bootup.c , bootup.h
  • bInitMDNSResponder() : mdns.h , mdns.c
  • bInputButtonPressed() : input.c , input.h
  • bInputButtonPushed() : input.h , input.c
  • bInputButtonPushedLong() : input.c , input.h
  • bInputButtonPushedOnce() : input.c , input.h
  • bInputButtonPushedTwice() : input.c , input.h
  • bInputEncoderValueChanged() : input.h , input.c
  • bMDNSNameIsResolved() : mdns.c , mdns.h
  • bMDNSServiceIsResolved() : mdns.c , mdns.h
  • BOOTUP_EEPROM_ADD : eeprom_adds.h
  • BootupEnterBootloader() : bootup.c , bootup.h
  • BootupInit() : bootup.h , bootup.c
  • BootupResetToFactory() : bootup.c , bootup.h
  • BootupRestoreState() : bootup.c , bootup.h
  • BootupSetIP() : bootup.h , bootup.c
  • BTN_COUNT : input.h
  • BTN_DOUBLE_PUSH_TIME : input.h
  • BTN_LONG_PUSH_TIME : input.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- d -

  • DHCPDisable() : DHCP.c , DHCP.h
  • DHCPEnable() : DHCP.h , DHCP.c
  • DHCPFlags : DHCP.c , DHCP.h
  • DHCPIsBound : DHCP.h
  • DHCPReset() : DHCP.c , DHCP.h
  • DHCPTask() : DHCP.c , DHCP.h
  • DIALOG_ALL_LETTERS : dialog.h
  • DIALOG_BACKSPACE_FLAG : dialog.h
  • DIALOG_CAPITALS_FLAG : dialog.h
  • DIALOG_DASH_FLAG : dialog.h
  • DIALOG_DESCRIPTION_FLAG : dialog.h
  • DIALOG_DESCTOGGLE_FLAG : dialog.h
  • DIALOG_ESC_FLAG : dialog.h
  • DIALOG_LETTERS_FLAG : dialog.h
  • DIALOG_NEXT_FLAG : dialog.h
  • DIALOG_NUMBERS_FLAG : dialog.h
  • DIALOG_PREV_FLAG : dialog.h
  • DIALOG_SPECIAL_FLAG : dialog.h
  • DIALOG_WHITESPACE_FLAG : dialog.h
  • DNS_TYPE_A : mdns.h
  • DNS_TYPE_ANY : mdns.h
  • DNS_TYPE_MX : mdns.h
  • DNS_TYPE_PTR : mdns.h
  • DNS_TYPE_SRV : mdns.h
  • DNS_TYPE_TXT : mdns.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- e -

  • eButtonID : input.h
  • eGetMDNSState() : mdns.c , mdns.h
  • eLED_Modes : output.h
  • ENC_BTN : input.h
  • ENC_ENDSTOP_MASK : input.h
  • ENC_NOCHANGE_MASK : input.h
  • ENC_TURBO_MASK : input.h
  • eWichtProjects : bootup.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- f -

  • F1_BTN : input.h
  • F2_BTN : input.h
  • F3_BTN : input.h
  • F4_BTN : input.h
  • FL_BTN : input.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- g -

  • GenerateAutoIP() : DHCP.c , DHCP.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- h -

  • HALF_DUPLEX : ETH97J60.c
  • HOSTNAME : bootup.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- i -

  • InputButtonReset() : input.c , input.h
  • InputEncoderGetDirection() : input.h , input.c
  • InputEncoderInit() : input.c , input.h
  • InputEncoderSetValue() : input.h , input.c
  • InputForceChangedEncoderValue() : input.c , input.h
  • InputInit() : input.c , input.h
  • InputInterruptHandler() : input.c , input.h
  • InputMain() : input.h , input.c
  • InputResetButtonPush() : input.c , input.h
  • InputResetPowerButton() : input.h , input.c
  • IPConvertMaskToSubnet() : IP.c , IP.h
  • IPConvertSubnetToMask() : IP.c , IP.h
  • IPSetInit() : ipset.c , ipset.h
  • IPSetMain() : ipset.h , ipset.c
  • IsEncoderTurning() : input.c , input.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- p -

  • PROJECT_DEFAULT_PORT : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_HANDLE_SERVER_CONNECTION : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_ID : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_INITIAL_INIT : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_IS_CONNECTED : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_LOCO_DIR_MODE_HAS_CHANGED : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_MAIN : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_NAME : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_PREPARE_CONNECTION : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_PROCESS_POST : rocrail/projectdefs.h
  • PROJECT_RESET_TO_FACTORY : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_SERVICE_NAME : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_SOCKET_CONFIGURATION : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_START_DISCONNECT : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_WEBSITES : rocrail/projectdefs.h , srcp/projectdefs.h
  • PWR_BTN : input.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- r -

  • RocrailHandleServerConnection() : rocrail/projectdefs.h , rocrail.c
  • RocrailIsConnected() : rocrail.c , rocrail/projectdefs.h
  • RocrailLocoDirModeHasChanged() : rocrail/projectdefs.h , rocrail.c
  • RocrailMain() : rocrail.c , rocrail/projectdefs.h
  • RocrailPrepareConnection() : rocrail.c , rocrail/projectdefs.h
  • RocrailStartDisconnect() : rocrail/projectdefs.h , rocrail.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- s -

  • s16InputEncoderGetValue() : input.c , input.h
  • SEARCH_IP : appl.h
  • SEARCH_NAME : appl.h
  • SEARCH_SERVICE : appl.h
  • SEARCH_UNKNOWN : appl.h
  • SEL_BTN : input.h
  • sIPConfig : bootup.h
  • sPApplConfig : appl.h
  • sPCommonConfig : bootup.h
  • sPSRCPConfig : srcp.h
  • SRCP_CONFIG_EEPROM_ADD : srcp/projectdefs.h
  • SRCP_EEPROMSET_COUNT : srcp/projectdefs.h
  • SRCP_EEPROMSET_GA_MASK : srcp/projectdefs.h
  • SRCP_EEPROMSET_ID : srcp/projectdefs.h
  • SRCP_EEPROMSET_IDX_MASK : srcp/projectdefs.h
  • SRCP_GAEEPROMSET_COUNT : srcp/projectdefs.h
  • SRCP_GLEEPROMSET_COUNT : srcp/projectdefs.h
  • SRCP_NAME_MAXLEN : srcp/projectdefs.h
  • SRCP_PROTO_MAXLEN : srcp/projectdefs.h
  • SRCP_PROTOS_EEPROM_ADD : srcp/projectdefs.h
  • SRCP_SERVERCACHE_ID : srcp/projectdefs.h
  • SRCP_SETS_EEPROM_ADD : srcp/projectdefs.h
  • SRCPHandleServerConnection() : srcp/projectdefs.h , srcp.c
  • SRCPInitialInit() : srcp/projectdefs.h , srcp.c
  • SRCPIsConnected() : srcp/projectdefs.h , srcp.c
  • SRCPLocoDirModeHasChanged() : srcp/projectdefs.h , srcp.c
  • SRCPMain() : srcp/projectdefs.h , srcp.c
  • SRCPPrepareConnection() : srcp/projectdefs.h , srcp.c
  • SRCPRestoreToFactory() : srcp/projectdefs.h , srcp.c
  • SRCPStartDisconnect() : srcp/projectdefs.h , srcp.c
  • StackApplications() : StackTsk.c , StackTsk.h
  • StackInit() : StackTsk.c , StackTsk.h
  • StackTask() : StackTsk.c , StackTsk.h
  • StartMDNSResponder() : mdns.h , mdns.c
  • StopMDNSResponder() : mdns.c , mdns.h
  • StrTbl_cau8GetLanguageStringPointer() : stringtable.c , stringtable.h
  • StrTbl_cau8GetStringPointer() : stringtable.c , stringtable.h
  • StrTbl_GetString() : stringtable.h , stringtable.c
  • StrTbl_GetStringN() : stringtable.c , stringtable.h
  • StrTbl_SetLanguage() : stringtable.c , stringtable.h
  • STRTBLIDS : stringtable.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- t -

  • TCPDisconnect() : TCP.c , TCP.h
  • TCPFindEx() : TCP.h , TCP.c
  • TCPFlush() : TCP.c , TCP.h
  • TCPGet() : TCP.h , TCP.c
  • TCPIsConnected() : TCP.c , TCP.h
  • TCPIsGetReady() : TCP.c , TCP.h
  • TCPIsPutReady() : TCP.c , TCP.h
  • TCPOpen() : TCP.h , TCP.c
  • TCPPut() : TCP.c , TCP.h
  • TCPPutArray() : TCP.c , TCP.h
  • TCPPutString() : TCP.c , TCP.h
  • TCPWasReset() : TCP.c , TCP.h
  • TOGGLEDIRMODE_CLICK : appl.h
  • TOGGLEDIRMODE_ZERO : appl.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- u -

  • u8ApplTimer : appl.h
  • u8InputButtonQuickPushed() : input.h , input.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • f
  • g
  • h
  • i
  • l
  • m
  • n
  • o
  • p
  • r
  • s
  • t
  • u
  • x

Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- x -

  • XEEEraseEEPROM() : SPIEEPROM.c , XEEPROM.h
  • XEEReadArray() : XEEPROM.h , SPIEEPROM.c
  • XEEWriteArray() : XEEPROM.h , SPIEEPROM.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • a
  • b
  • d
  • e
  • h
  • l
  • m
  • p
  • s
  • t

- a -

  • APPL_EEPROM_ADD : eeprom_adds.h

- b -

  • BOOTUP_EEPROM_ADD : eeprom_adds.h
  • BTN_COUNT : input.h
  • BTN_DOUBLE_PUSH_TIME : input.h
  • BTN_LONG_PUSH_TIME : input.h

- d -

  • DHCPIsBound : DHCP.h
  • DIALOG_ALL_LETTERS : dialog.h
  • DIALOG_BACKSPACE_FLAG : dialog.h
  • DIALOG_CAPITALS_FLAG : dialog.h
  • DIALOG_DASH_FLAG : dialog.h
  • DIALOG_DESCRIPTION_FLAG : dialog.h
  • DIALOG_DESCTOGGLE_FLAG : dialog.h
  • DIALOG_ESC_FLAG : dialog.h
  • DIALOG_LETTERS_FLAG : dialog.h
  • DIALOG_NEXT_FLAG : dialog.h
  • DIALOG_NUMBERS_FLAG : dialog.h
  • DIALOG_PREV_FLAG : dialog.h
  • DIALOG_SPECIAL_FLAG : dialog.h
  • DIALOG_WHITESPACE_FLAG : dialog.h
  • DNS_TYPE_A : mdns.h
  • DNS_TYPE_ANY : mdns.h
  • DNS_TYPE_MX : mdns.h
  • DNS_TYPE_PTR : mdns.h
  • DNS_TYPE_SRV : mdns.h
  • DNS_TYPE_TXT : mdns.h

- e -

  • ENC_ENDSTOP_MASK : input.h
  • ENC_NOCHANGE_MASK : input.h
  • ENC_TURBO_MASK : input.h

- h -

  • HALF_DUPLEX : ETH97J60.c
  • HOSTNAME : bootup.h

- l -

  • LANGID_ENGLISH : stringtable.h
  • LANGID_GERMAN : stringtable.h
  • LANGID_MAX : stringtable.h
  • LANGID_NOTSPECIFIED : stringtable.h
  • LCD_CENTER1_MASK : output.h
  • LCD_CENTER2_MASK : output.h
  • LCD_CHARS_IN_A_ROW : output.h
  • LCD_CLR_MASK : output.h
  • LCD_CLR_PROG_MASK : output.h
  • LCD_IDLE_TIME : output.h
  • LCD_PROGRESS_CHAR : output.h
  • LCD_PROGRESS_MASK : output.h
  • LCD_PROGRESS_TIME : output.h
  • LCD_ROW1_MASK : output.h
  • LCD_ROW2_MASK : output.h
  • LCD_ROW3_MASK : output.h
  • LED_ACC : output.h
  • LED_BLINK_INTERVAL : output.h
  • LED_F1 : output.h
  • LED_F2 : output.h
  • LED_F3 : output.h
  • LED_F4 : output.h
  • LED_FL : output.h
  • LED_PWR : output.h
  • LED_SEL : output.h

- m -

  • MAX_PROTO_SLOTS : srcp/projectdefs.h
  • MAX_SRCP_FUNCTIONS : srcp/projectdefs.h
  • MAX_SRCP_SPEEDSTEPS : srcp/projectdefs.h
  • MDNS_PORT : mdns.h

- p -

  • PROJECT_DEFAULT_PORT : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_HANDLE_SERVER_CONNECTION : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_ID : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_INITIAL_INIT : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_IS_CONNECTED : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_LOCO_DIR_MODE_HAS_CHANGED : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_MAIN : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_NAME : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_PREPARE_CONNECTION : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_PROCESS_POST : rocrail/projectdefs.h
  • PROJECT_RESET_TO_FACTORY : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_SERVICE_NAME : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_SOCKET_CONFIGURATION : rocrail/projectdefs.h , srcp/projectdefs.h
  • PROJECT_START_DISCONNECT : srcp/projectdefs.h , rocrail/projectdefs.h
  • PROJECT_WEBSITES : srcp/projectdefs.h , rocrail/projectdefs.h

- s -

  • SRCP_CONFIG_EEPROM_ADD : srcp/projectdefs.h
  • SRCP_EEPROMSET_COUNT : srcp/projectdefs.h
  • SRCP_EEPROMSET_GA_MASK : srcp/projectdefs.h
  • SRCP_EEPROMSET_ID : srcp/projectdefs.h
  • SRCP_EEPROMSET_IDX_MASK : srcp/projectdefs.h
  • SRCP_GAEEPROMSET_COUNT : srcp/projectdefs.h
  • SRCP_GLEEPROMSET_COUNT : srcp/projectdefs.h
  • SRCP_NAME_MAXLEN : srcp/projectdefs.h
  • SRCP_PROTO_MAXLEN : srcp/projectdefs.h
  • SRCP_PROTOS_EEPROM_ADD : srcp/projectdefs.h
  • SRCP_SERVERCACHE_ID : srcp/projectdefs.h
  • SRCP_SETS_EEPROM_ADD : srcp/projectdefs.h

- t -

  • TOGGLEDIRMODE_CLICK : appl.h
  • TOGGLEDIRMODE_ZERO : appl.h
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines

  • _MDNS_STATE : mdns.h
  • _SEARCH_MODES : appl.h
  • APPL_CONNECTING_RETCODE : appldefs.h
  • eButtonID : input.h
  • eLED_Modes : output.h
  • eWichtProjects : bootup.h
  • STRTBLIDS : stringtable.h
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines

  • ACC_BTN : input.h
  • ALL_BTN : input.h
  • APPL_CR_CLOSED : appldefs.h
  • APPL_CR_CONNECTED : appldefs.h
  • APPL_CR_ERROR : appldefs.h
  • APPL_CR_IN_PROGRESS : appldefs.h
  • ENC_BTN : input.h
  • F1_BTN : input.h
  • F2_BTN : input.h
  • F3_BTN : input.h
  • F4_BTN : input.h
  • FL_BTN : input.h
  • LED_BLINK : output.h
  • LED_OFF : output.h
  • LED_ON : output.h
  • LED_TOGGLE : output.h
  • MDNS_HAS_STOPPED : mdns.h
  • MDNS_IS_RUNNING : mdns.h
  • MDNS_IS_STARTING_UP : mdns.h
  • PWR_BTN : input.h
  • SEARCH_IP : appl.h
  • SEARCH_NAME : appl.h
  • SEARCH_SERVICE : appl.h
  • SEARCH_UNKNOWN : appl.h
  • SEL_BTN : input.h
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- _ -

  • _bGetNextWord() : srcp.c
  • _CheckForQueryResponse() : mdns.c
  • _eHandShake() : srcp.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- m -

  • MACIsLinked() : ETH97J60.c , MAC.h
  • MDNSProcessFrame() : mdns.h , mdns.c
  • MDNSResolveName() : mdns.c , mdns.h
  • MDNSResolveService() : mdns.h , mdns.c
  • MDNSResponder() : mdns.h , mdns.c
  • MDNSStopResolving() : mdns.c , mdns.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- o -

  • OutConvertNameForDisplay() : output.c , output.h
  • OutDebugOut() : output.h
  • OutEnableCursor() : output.c , output.h
  • OutGetLEDMode() : output.c , output.h
  • OutInit() : output.c , output.h
  • OutIsLCDBusy() : output.c , output.h
  • OutMain() : output.c , output.h
  • OutSetCursor() : output.c , output.h
  • OutSetLED() : output.c , output.h
  • OutSetLEDMask() : output.c , output.h
  • OutSwitchLCDBacklight() : output.h , output.c
  • OutSwitchOffAllLEDs() : output.h , output.c
  • OutSwitchOffLCD() : output.h , output.c
  • OutTriggerDisplay() : output.h , output.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- a -

  • ApplChangeLocoDirMode() : appl.c , appl.h
  • ApplGetServerIP() : appl.h , appl.c
  • ApplGetServerNodeInfo() : appl.c , appl.h
  • ApplGetServerPort() : appl.h , appl.c
  • ApplInit() : appl.c , appl.h
  • ApplIsConnected() : appl.c , appl.h
  • ApplIsRunning() : appl.c , appl.h
  • ApplMain() : appl.h , appl.c
  • ApplResetToFactory() : appl.c , appl.h
  • ApplRestart() : appl.h , appl.c
  • ApplShutDown() : appl.c , appl.h
  • ApplStop() : appl.c , appl.h
  • ARPFlush() : ARP.c , ARP.h
  • ARPIsResolved() : ARP.h , ARP.c
  • ARPResolve() : ARP.c , ARP.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- b -

  • bBootupMain() : bootup.c , bootup.h
  • bInitMDNSResponder() : mdns.h , mdns.c
  • bInputButtonPressed() : input.c , input.h
  • bInputButtonPushed() : input.h , input.c
  • bInputButtonPushedLong() : input.c , input.h
  • bInputButtonPushedOnce() : input.c , input.h
  • bInputButtonPushedTwice() : input.c , input.h
  • bInputEncoderValueChanged() : input.h , input.c
  • bMDNSNameIsResolved() : mdns.c , mdns.h
  • bMDNSServiceIsResolved() : mdns.h , mdns.c
  • BootupEnterBootloader() : bootup.c , bootup.h
  • BootupInit() : bootup.c , bootup.h
  • BootupResetToFactory() : bootup.c , bootup.h
  • BootupRestoreState() : bootup.h , bootup.c
  • BootupSetIP() : bootup.c , bootup.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- d -

  • DHCPDisable() : DHCP.c , DHCP.h
  • DHCPEnable() : DHCP.h , DHCP.c
  • DHCPReset() : DHCP.c , DHCP.h
  • DHCPTask() : DHCP.h , DHCP.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- e -

  • eGetMDNSState() : mdns.c , mdns.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- g -

  • GenerateAutoIP() : DHCP.c , DHCP.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- i -

  • InputButtonReset() : input.c , input.h
  • InputEncoderGetDirection() : input.h , input.c
  • InputEncoderInit() : input.c , input.h
  • InputEncoderSetValue() : input.h , input.c
  • InputForceChangedEncoderValue() : input.c , input.h
  • InputInit() : input.c , input.h
  • InputInterruptHandler() : input.c , input.h
  • InputMain() : input.h , input.c
  • InputResetButtonPush() : input.c , input.h
  • InputResetPowerButton() : input.h , input.c
  • IPConvertMaskToSubnet() : IP.c , IP.h
  • IPConvertSubnetToMask() : IP.c , IP.h
  • IPSetInit() : ipset.c , ipset.h
  • IPSetMain() : ipset.h , ipset.c
  • IsEncoderTurning() : input.c , input.h
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- r -

  • RocrailHandleServerConnection() : rocrail/projectdefs.h , rocrail.c
  • RocrailIsConnected() : rocrail.c , rocrail/projectdefs.h
  • RocrailLocoDirModeHasChanged() : rocrail/projectdefs.h , rocrail.c
  • RocrailMain() : rocrail.c , rocrail/projectdefs.h
  • RocrailPrepareConnection() : rocrail.c , rocrail/projectdefs.h
  • RocrailStartDisconnect() : rocrail/projectdefs.h , rocrail.c
Generated on Sun Nov 27 20:02:40 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- s -

  • s16InputEncoderGetValue() : input.c , input.h
  • SRCPHandleServerConnection() : srcp.c , srcp/projectdefs.h
  • SRCPInitialInit() : srcp/projectdefs.h , srcp.c
  • SRCPIsConnected() : srcp.c , srcp/projectdefs.h
  • SRCPLocoDirModeHasChanged() : srcp/projectdefs.h , srcp.c
  • SRCPMain() : srcp/projectdefs.h , srcp.c
  • SRCPPrepareConnection() : srcp/projectdefs.h , srcp.c
  • SRCPRestoreToFactory() : srcp.c , srcp/projectdefs.h
  • SRCPStartDisconnect() : srcp/projectdefs.h , srcp.c
  • StackApplications() : StackTsk.c , StackTsk.h
  • StackInit() : StackTsk.c , StackTsk.h
  • StackTask() : StackTsk.c , StackTsk.h
  • StartMDNSResponder() : mdns.c , mdns.h
  • StopMDNSResponder() : mdns.c , mdns.h
  • StrTbl_cau8GetLanguageStringPointer() : stringtable.c , stringtable.h
  • StrTbl_cau8GetStringPointer() : stringtable.h , stringtable.c
  • StrTbl_GetString() : stringtable.c , stringtable.h
  • StrTbl_GetStringN() : stringtable.c , stringtable.h
  • StrTbl_SetLanguage() : stringtable.c , stringtable.h
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- t -

  • TCPDisconnect() : TCP.c , TCP.h
  • TCPFindEx() : TCP.h , TCP.c
  • TCPFlush() : TCP.c , TCP.h
  • TCPGet() : TCP.h , TCP.c
  • TCPIsConnected() : TCP.c , TCP.h
  • TCPIsGetReady() : TCP.c , TCP.h
  • TCPIsPutReady() : TCP.c , TCP.h
  • TCPOpen() : TCP.c , TCP.h
  • TCPPut() : TCP.c , TCP.h
  • TCPPutArray() : TCP.c , TCP.h
  • TCPPutString() : TCP.c , TCP.h
  • TCPWasReset() : TCP.h , TCP.c
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- u -

  • u8InputButtonQuickPushed() : input.c , input.h
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines
  • _
  • a
  • b
  • d
  • e
  • g
  • i
  • m
  • o
  • r
  • s
  • t
  • u
  • x

- x -

  • XEEEraseEEPROM() : SPIEEPROM.c , XEEPROM.h
  • XEEReadArray() : XEEPROM.h , SPIEEPROM.c
  • XEEWriteArray() : XEEPROM.h , SPIEEPROM.c
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines

  • MAC_ADDR : StackTsk.h
  • NODE_INFO : StackTsk.h
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: Data Fields

  • All
  • Functions
  • Variables
  • Typedefs
  • Enumerations
  • Enumerator
  • Defines

  • _au8NetworkDataForBootloader : bootup.c
  • _bFirstTime : bootup.c
  • _eBootUpSM : bootup.c
  • DHCPFlags : DHCP.c , DHCP.h
  • lcd_status : output.h
  • sIPConfig : bootup.h
  • sPApplConfig : appl.h
  • sPCommonConfig : bootup.h
  • sPSRCPConfig : srcp.h
  • u8ApplTimer : appl.h
Generated on Sun Nov 27 20:02:41 2011 for eWicht by doxygen 1.5.5


eWicht: input.c Source File

input.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00013 // ////////////////////////////////////////////////////////////////////////////
00014 // ////////////////////////////////////////////////////////////////////////////
00015
00016     #define     INPUT_C
00017     #include    "input.h"
00018
00019
00020 // ////////////////////////////////////////////////////////////////////////////
00021 // Local Defines
00022 // ////////////////////////////////////////////////////////////////////////////
00023
00024 #define BTSM_START          0x00 // Waiting for a released button.
00025 #define BTSM_IDLE           0x01 // Button is idle.
00026 #define BTSM_PRESSED_FIRST  0x02 // Button pressed first, waiting for release.
00027 #define BTSM_RELEASED_FIRST 0x04 // Button released the first time.
00028 #define BTSM_PRESSED_SECOND 0x08 // Button pressed second, waiting for release.
00029 #define BTSM_DOUBLE_MASK    0x10 // Double push recognized.
00030 #define BTSM_PUSH_MASK      0x20
00031 #define BTSM_PUSH_TEST_MASK 0x22
00032 #define BTSM_LONG_PUSH_MASK 0x40
00033
00034
00035 // ////////////////////////////////////////////////////////////////////////////
00036 // Local Variables
00037 // ////////////////////////////////////////////////////////////////////////////
00038
00039 static BYTE _u8BtnDebounce[BTN_COUNT];
00040 static BYTE _u8BtnSM[BTN_COUNT];
00041 static BYTE _u8PwrSM;
00042 static WORD _u16PwrTimer;
00043 static WORD _u16BtnTimer[BTN_COUNT];
00044
00045 static WORD _u16Enc;
00046 static SHORT _s16EncVal;
00047 static BYTE _u8EncFlags;
00048 static SHORT _s16EncMin;
00049 static SHORT _s16EncMax;
00050 static SHORT _s16EncLastVal;
00051 static SHORT _u16EncMaxInc;
00052
00053 static BOOL _bEncTurning;
00054 static WORD _u16EncIncrement;
00055 static BOOL _bEncDirection;
00056 static BOOL _bEncTrigger;
00057 static BYTE _u8EncPause;
00058
00059 // ////////////////////////////////////////////////////////////////////////////
00060 // Local function prototypes
00061 // ////////////////////////////////////////////////////////////////////////////
00062
00063 static BOOL _bCheckPush(eButtonID eBtn);
00064 static void initTimer(void);
00065
00066
00067 // ////////////////////////////////////////////////////////////////////////////
00068 // Function implementations
00069 // ////////////////////////////////////////////////////////////////////////////
00070
00071 void InputInit(void)
00072 {
00073     int i = 0;
00074
00075     PORTE = 0xFF;           // 8 buttons.
00076     TRISE = 0xFF;
00077
00078     PORTB |= 0x30;
00079     TRISB |= 0x30;
00080
00081     PORTD = 0xFF;           // Rotary encoder.
00082     TRISD = 0xFF;
00083
00084     // Enable pullups!
00085     INTCON2bits.RBPU = 0;   // For PORTB
00086     LATAbits.REPU = 1;      // For PORTE
00087     LATAbits.RDPU = 1;      // For PORTD
00088
00089     // Initialize the state machines:
00090     for (i = 0; i < BTN_COUNT; i++)
00091     {
00092         _u8BtnDebounce[i] = 0xFF;
00093         _u8BtnSM[i] = BTSM_START;
00094         _u16BtnTimer[i] = 0;
00095     }
00096     _u8PwrSM = BTSM_START;
00097
00098     _u16Enc = 0x0F;
00099     _bEncTurning = FALSE;
00100     _u16EncIncrement = 1;
00101     _u8EncPause = 0;
00102     _bEncTrigger = FALSE;
00103
00104     initTimer();
00105 }
00106
00107 // ////////////////////////////////////////////////////////////////////////////
00108 // ////////////////////////////////////////////////////////////////////////////
00109
00110 void InputMain(void)
00111 {
00112     // Reading from all the input devices and shift them into the state
00113     //registers.
00114     BYTE i = 0;
00115     for (i = 0; i < BTN_COUNT; i++)
00116     {
00117         _u8BtnDebounce[i] = _u8BtnDebounce[i] << 1;
00118     }
00119
00120     _u8BtnDebounce[PWR_BTN] |= PORTEbits.RE0;
00121     _u8BtnDebounce[SEL_BTN] |= PORTEbits.RE1;
00122     _u8BtnDebounce[ACC_BTN] |= PORTEbits.RE2;
00123     _u8BtnDebounce[FL_BTN] |= PORTEbits.RE3;
00124     _u8BtnDebounce[F1_BTN] |= PORTEbits.RE4;
00125     _u8BtnDebounce[F2_BTN] |= PORTEbits.RE5;
00126     _u8BtnDebounce[F3_BTN] |= PORTBbits.RB4;
00127     _u8BtnDebounce[F4_BTN] |= PORTBbits.RB5;
00128     _u8BtnDebounce[ENC_BTN] |= PORTDbits.RD0;
00129
00130
00131     // The button state machines:
00132     for (i = 0; i < BTN_COUNT; i++)
00133     {
00134         // The power button always will be checked for a long push separately
00135         // because that's the signal for eWicht to turn off.
00136         if (i == PWR_BTN)
00137         {
00138             if ((_u8PwrSM == BTSM_START) && (_u8BtnDebounce[PWR_BTN] == 0xFF))
00139             {
00140                 // After reseting the state machine the SM waits for a released
00141                 // button (Release = 80 ms an inactive button).
00142                 _u8PwrSM = BTSM_IDLE;
00143             }
00144
00145             switch (_u8PwrSM)
00146             {
00147                 case BTSM_IDLE:
00148                     // Waiting for a pushed button (pushed = 80 ms active).
00149                     if (_u8BtnDebounce[PWR_BTN] == 0x00)
00150                     {
00151                         // Push detected!
00152                         _u8PwrSM = BTSM_PRESSED_FIRST;
00153                         // Measure the push time to detect a long push:
00154                         _u16PwrTimer = BTN_LONG_PUSH_TIME;
00155                     }
00156                     break;
00157
00158                 case BTSM_PRESSED_FIRST:
00159                     if (_u8BtnDebounce[PWR_BTN] == 0xFF)
00160                     {
00161                         // Not long enough pushed for a long pushed, reset the
00162                         // state machine and start again.
00163                         _u8PwrSM = BTSM_START;
00164                     }
00165                     else if ( _u16PwrTimer == 0 )
00166                     {
00167                         // Long push detected!
00168                         _u8PwrSM = BTSM_LONG_PUSH_MASK;
00169                     }
00170                     else
00171                     {
00172                         // Waiting...
00173                         _u16PwrTimer--;
00174                     }
00175                     break;
00176             }
00177         }
00178
00179         if ((_u8BtnSM[i] == BTSM_START) && (_u8BtnDebounce[i] == 0xFF))
00180         {
00181             // After reseting the state machine the SM waits for a released
00182             // button (Release = 80 ms an inactive button).
00183             _u8BtnSM[i] = BTSM_IDLE;
00184         }
00185         else
00186         {
00187             switch(_u8BtnSM[i] & 0x0F)
00188             {
00189                 case BTSM_IDLE:
00190                     // Waiting for a pushed button (pushed = 80 ms active).
00191                     if (_u8BtnDebounce[i] == 0x00)
00192                     {
00193                         // Push detected!
00194                         _u8BtnSM[i] = BTSM_PRESSED_FIRST;
00195                         // Wait for releasing the button (longer pushes
00196                         // lead to the set of the flag BTSM_LONG_PUSH_MASK).
00197                         _u16BtnTimer[i] = BTN_LONG_PUSH_TIME;
00198                     }
00199                     break;
00200
00201                 case BTSM_PRESSED_FIRST:
00202                     // First button push is recognized, waiting for a button
00203                     // release now (Release = 80 ms an inactive button).
00204                     if (_u8BtnDebounce[i] == 0xFF)
00205                     {
00206                         // Set the flag for a detected single push and enter
00207                         // the next state.
00208                         _u8BtnSM[i] = BTSM_RELEASED_FIRST | BTSM_PUSH_MASK;
00209                         // Wait some time for a second push:
00210                         _u16BtnTimer[i] = BTN_DOUBLE_PUSH_TIME;
00211                     }
00212                     else if (_u16BtnTimer[i] == 0)
00213                     {
00214                         // Time for a long push has elapsed, set the flag for a
00215                         // long push. This flag is set independently of the
00216                         // button state machine.
00217                         _u8BtnSM[i] = BTSM_LONG_PUSH_MASK;
00218                     }
00219                     else
00220                     {
00221                         // Decrease the timer until zero.
00222                         _u16BtnTimer[i]--;
00223                     }
00224                     break;
00225
00226                 case BTSM_RELEASED_FIRST:
00227                     if (_u8BtnDebounce[i] == 0x00)
00228                     {
00229                         // The second push was detected. Enter the next state
00230                         // but without affecting the flags which may be set
00231                         // like the single and long push flags.
00232                         _u8BtnSM[i] &= ~BTSM_RELEASED_FIRST;
00233                         _u8BtnSM[i] |= BTSM_PRESSED_SECOND;
00234                     }
00235                     else if (_u16BtnTimer[i] == 0)
00236                     {
00237                         // The time for a double push has elapsed, reset the
00238                         // state machine (state = BTSM_START).
00239                         _u8BtnSM[i] &= 0xF0;
00240                     }
00241                     else
00242                     {
00243                         // Waiting...
00244                         _u16BtnTimer[i]--;
00245                     }
00246                     break;
00247
00248                 case BTSM_PRESSED_SECOND:
00249                     if (_u8BtnDebounce[i] == 0xFF)
00250                     {
00251                         // The double push event is perfect, the user has
00252                         // released the button a second time.
00253
00254                         // Set the flag for the double push event and reset the
00255                         // state machine (state = BTSM_START).
00256                         _u8BtnSM[i] &= 0xF0;
00257                         _u8BtnSM[i] |= BTSM_DOUBLE_MASK;
00258                     }
00259                     break;
00260             }
00261         }
00262     }
00263 }
00264
00265 // ////////////////////////////////////////////////////////////////////////////
00266 // ////////////////////////////////////////////////////////////////////////////
00267
00268 void InputButtonReset(eButtonID eBtn)
00269 {
00270     if (eBtn == ALL_BTN)
00271     {
00272         BYTE i = 0;
00273         for ( ; i < BTN_COUNT; i++)
00274         {
00275             _u8BtnSM[i] = BTSM_START;
00276         }
00277     }
00278     else
00279     {
00280         _u8BtnSM[eBtn] = BTSM_START;
00281     }
00282 }
00283
00284 // ////////////////////////////////////////////////////////////////////////////
00285 // ////////////////////////////////////////////////////////////////////////////
00286
00287 BOOL bInputButtonPushedOnce(eButtonID eBtn)
00288 {
00289     if ((_u8BtnSM[eBtn] & BTSM_PUSH_TEST_MASK) == BTSM_PUSH_MASK)
00290     {
00291         return TRUE;
00292     }
00293     else
00294     {
00295         return FALSE;
00296     }
00297 }
00298
00299 // ////////////////////////////////////////////////////////////////////////////
00300 // ////////////////////////////////////////////////////////////////////////////
00301
00302 void InputResetButtonPush(eButtonID eBtn)
00303 {
00304     _u8BtnSM[eBtn] &= ~BTSM_PUSH_MASK;
00305 }
00306
00307 // ////////////////////////////////////////////////////////////////////////////
00308 // ////////////////////////////////////////////////////////////////////////////
00309
00310 void InputResetPowerButton(void)
00311 {
00312     _u8PwrSM = BTSM_START;
00313     _u8BtnSM[PWR_BTN] = BTSM_START;
00314 }
00315
00316 // ////////////////////////////////////////////////////////////////////////////
00317 // ////////////////////////////////////////////////////////////////////////////
00318
00319 BOOL bInputButtonPushedTwice(eButtonID eBtn)
00320 {
00321     if (_u8BtnSM[eBtn] & BTSM_DOUBLE_MASK)
00322     {
00323         return TRUE;
00324     }
00325     else
00326     {
00327         return FALSE;
00328     }
00329 }
00330
00331 // ////////////////////////////////////////////////////////////////////////////
00332 // ////////////////////////////////////////////////////////////////////////////
00333
00334 BOOL bInputButtonPushedLong(eButtonID eBtn)
00335 {
00336     if (eBtn == PWR_BTN)
00337     {
00338         if (_u8PwrSM == BTSM_LONG_PUSH_MASK)
00339         {
00340             return TRUE;
00341         }
00342     }
00343     else
00344     {
00345         if (_u8BtnSM[eBtn] == BTSM_LONG_PUSH_MASK)
00346         {
00347             return TRUE;
00348         }
00349     }
00350     return FALSE;
00351 }
00352
00353 // ////////////////////////////////////////////////////////////////////////////
00354 // ////////////////////////////////////////////////////////////////////////////
00355
00356 BYTE u8InputButtonQuickPushed(void)
00357 {
00358     if (_bCheckPush(F1_BTN))
00359     {
00360         return 0;
00361     }
00362     if (_bCheckPush(F2_BTN))
00363     {
00364         return 1;
00365     }
00366     if (_bCheckPush(F3_BTN))
00367     {
00368         return 2;
00369     }
00370     if (_bCheckPush(F4_BTN))
00371     {
00372         return 3;
00373     }
00374
00375     return 0xFF;
00376 }
00377
00378 // ////////////////////////////////////////////////////////////////////////////
00379 // ////////////////////////////////////////////////////////////////////////////
00380
00381 static BOOL _bCheckPush(eButtonID eBtn)
00382 {
00383     if (eBtn == ALL_BTN)
00384     {
00385         return FALSE;
00386     }
00387     else if ((_u8BtnSM[eBtn] & (BTSM_DOUBLE_MASK | BTSM_PUSH_MASK)) ||
00388         (_u8BtnSM[eBtn] == BTSM_LONG_PUSH_MASK))
00389     {
00390         return TRUE;
00391     }
00392     else
00393     {
00394         return FALSE;
00395     }
00396 }
00397
00398 // ////////////////////////////////////////////////////////////////////////////
00399 // ////////////////////////////////////////////////////////////////////////////
00400
00401 BOOL bInputButtonPressed(eButtonID eBtn)
00402 {
00403     if (_u8BtnDebounce[eBtn] == 0x00)
00404     {
00405         return TRUE;
00406     }
00407
00408     return FALSE;
00409 }
00410
00411 // ////////////////////////////////////////////////////////////////////////////
00412 // ////////////////////////////////////////////////////////////////////////////
00413
00414 BOOL bInputButtonPushed(eButtonID eBtn)
00415 {
00416     if (eBtn == ALL_BTN)
00417     {
00418         eButtonID i = 0;
00419         for (i=PWR_BTN; i <= ENC_BTN; i++)
00420         {
00421             if(_bCheckPush(i)==TRUE)
00422             {
00423                 return TRUE;
00424             }
00425         }
00426         return FALSE;
00427     }
00428     else
00429     {
00430         return _bCheckPush(eBtn);
00431     }
00432 }
00433
00434 // ////////////////////////////////////////////////////////////////////////////
00435 // ////////////////////////////////////////////////////////////////////////////
00436
00437 void InputEncoderInit(SHORT s16Val, SHORT s16Min, SHORT s16Max, BYTE u8Flags)
00438 {
00439     BOOL tmp = PIE1bits.CCP1IE;     // Remember current interrupt state.
00440
00441     // Thread safe access.
00442     PIE1bits.CCP1IE = 0;
00443
00444     if (u8Flags & ENC_NOCHANGE_MASK)
00445     {
00446         InputEncoderSetValue(s16Val, FALSE);
00447     }
00448     else
00449     {
00450         InputEncoderSetValue(s16Val, TRUE);
00451     }
00452
00453     _s16EncMin = s16Min;
00454     _s16EncMax = s16Max;
00455     _u8EncFlags = u8Flags;
00456
00457     if (((s16Max - s16Min) <= 30) || ((u8Flags & ENC_TURBO_MASK)==0))
00458     {
00459         _u16EncMaxInc = 1;
00460     }
00461     else if ((s16Max - s16Min) <= 99)
00462     {
00463         _u16EncMaxInc = 5;
00464     }
00465     else
00466     {
00467         _u16EncMaxInc = 10;
00468     }
00469
00470     // Reset interrupt to last state.
00471     PIE1bits.CCP1IE = tmp;
00472 }
00473
00474 // ////////////////////////////////////////////////////////////////////////////
00475 // ////////////////////////////////////////////////////////////////////////////
00476
00477 SHORT s16InputEncoderGetValue(void)
00478 {
00479     SHORT tmpEncVal;
00480     BOOL tmp = PIE1bits.CCP1IE;     // Remember current interrupt state.
00481
00482     // Thread safe access.
00483     PIE1bits.CCP1IE = 0;
00484
00485     _s16EncLastVal = _s16EncVal;
00486      tmpEncVal = _s16EncVal;
00487
00488     // Reset interrupt to last state.
00489     PIE1bits.CCP1IE = tmp;
00490
00491     return tmpEncVal;
00492 }
00493
00494 // ////////////////////////////////////////////////////////////////////////////
00495 // ////////////////////////////////////////////////////////////////////////////
00496
00497 void InputEncoderSetValue(short s16NewVal, BOOL bRemember)
00498 {
00499     BOOL tmp = PIE1bits.CCP1IE;     // Remember current interrupt state.
00500
00501     // Thread safe access.
00502     PIE1bits.CCP1IE = 0;
00503
00504     _s16EncVal = s16NewVal;
00505     if (bRemember == TRUE)
00506     {
00507         _s16EncLastVal = s16NewVal+1;// For requesting bInputEncoderValueChanged()
00508     }
00509     else
00510     {
00511         _s16EncLastVal = s16NewVal;
00512     }
00513
00514     // Reset interrupt to last state.
00515     PIE1bits.CCP1IE = tmp;
00516 }
00517
00518 // ////////////////////////////////////////////////////////////////////////////
00519 // ////////////////////////////////////////////////////////////////////////////
00520
00521 BOOL bInputEncoderValueChanged(void)
00522 {
00523     BOOL ret = TRUE;
00524     BOOL tmp = PIE1bits.CCP1IE;     // Remember current interrupt state.
00525     PIE1bits.CCP1IE = 0;            // Thread safe access.
00526
00527     if (_s16EncLastVal == _s16EncVal)
00528     {
00529         ret = FALSE;
00530     }
00531
00532     // Reset interrupt to last state.
00533     PIE1bits.CCP1IE = tmp;
00534
00535     return ret;
00536 }
00537
00538 // ////////////////////////////////////////////////////////////////////////////
00539 // ////////////////////////////////////////////////////////////////////////////
00540
00541 void InputForceChangedEncoderValue(void)
00542 {
00543     BOOL tmp = PIE1bits.CCP1IE;     // Remember current interrupt state.
00544     PIE1bits.CCP1IE = 0;            // Thread safe access.
00545
00546     _s16EncLastVal = _s16EncVal+1;
00547
00548     // Reset interrupt to last state.
00549     PIE1bits.CCP1IE = tmp;
00550 }
00551
00552 // ////////////////////////////////////////////////////////////////////////////
00553 // ////////////////////////////////////////////////////////////////////////////
00554
00555 BOOL InputEncoderGetDirection(void)
00556 {
00557     return _bEncDirection;
00558 }
00559
00560 // ////////////////////////////////////////////////////////////////////////////
00561 // ////////////////////////////////////////////////////////////////////////////
00562
00563 BOOL IsEncoderTurning(void)
00564 {
00565     return _bEncTurning;
00566 }
00567
00568 // ////////////////////////////////////////////////////////////////////////////
00569 // ////////////////////////////////////////////////////////////////////////////
00570
00571
00572 #if 0
00573
00574 static BYTE u8EncTestSM = 0;
00575
00576 void InputEncoderTest(void)
00577 {
00578     switch(u8EncTestSM)
00579     {
00580     case 0:
00581         InputEncoderInit(0, 0, 10000, ENC_TURBO_MASK);
00582         u8EncTestSM++;
00583         // Intended fall through.
00584
00585     case 1:
00586         if (bInputEncoderValueChanged() == TRUE)
00587         {
00588             lcd_addr1 = 0;
00589             sprintf(lcdram_row2, (ROM char *) "%hu", s16InputEncoderGetValue());
00590             lcd_addr2 = 0;
00591             lcd_status = LCD_CLR_MASK | LCD_ROW2_MASK;
00592         }
00593     }
00594     return;
00595 }
00596
00597 #endif
00598
00599 // ////////////////////////////////////////////////////////////////////////////
00600 // ////////////////////////////////////////////////////////////////////////////
00601
00602 static void initTimer(void)
00603 {
00604     // Init the 10 ms timer:
00605     T3CON = 0;  // Timer1 as clock source for CCP1
00606     T1CON = 0;  // Stop timer.
00607     // Init the periode register for a 10 ms duration and 1:2 prescaler...
00608     CCPR1H = (GetPeripheralClock() * 0.002) / 256;
00609     CCPR1L = (GetPeripheralClock() * 0.002);
00610     CCP1CON = 0x0A;     // Compare mode, generate software interrupt on match.
00611     IPR1bits.CCP1IP = 0;    // Low interrupt priority.
00612     PIE1bits.CCP1IE = 0;    // Disable the interrupt flag.
00613
00614     PIR1bits.CCP1IF = 0;    // Clearing the compare match interrupt flag.
00615     TMR1H = 0;              // Clearing the
00616     TMR1L = 0;              // timer values.
00617     T1CON = 0x81;           // 16 Bit | 1:1 Prescaler | internal source | on
00618     PIE1bits.CCP1IE = 1;    // Enable the interrupt.
00619 }
00620
00621 // ////////////////////////////////////////////////////////////////////////////
00622 // ////////////////////////////////////////////////////////////////////////////
00623
00624 // Define the encoder periodic of timer in units of ms:
00625 #define ENCODER_CYCLE   2u
00626
00627 #define ENCODER_PAUSE                       (250u)
00628 #define ENCODER_PAUSE_CYCLE                 (10u)
00629 #define ENCODER_FIRST_ACCELERATION_STEP     (30u)
00630 #define ENCODER_SECOND_ACCELERATION_STEP    (10u)
00631
00632
00633
00634 // Calculation defines, do not change!
00635 #define ENCODER_PAUSE_CALCED    (ENCODER_PAUSE / ENCODER_CYCLE)
00636 #define ENCODER_PAUSE_CYCLE_CALCED  (ENCODER_PAUSE_CYCLE / ENCODER_CYCLE)
00637 #define ENCODER_FIRST_ACCELERATION_STEP_CALCED  (ENCODER_FIRST_ACCELERATION_STEP / ENCODER_CYCLE)
00638 #define ENCODER_SECOND_ACCELERATION_STEP_CALCED (ENCODER_SECOND_ACCELERATION_STEP / ENCODER_CYCLE)
00639
00640
00641 void InputInterruptHandler(void)
00642 {
00643     if (PIR1bits.CCP1IF == 0)
00644     {
00645         return;
00646     }
00647
00648
00649     // ////////////////////////////////////////////////////////////////////////
00650     // Rotary encoder input handling
00651     // ////////////////////////////////////////////////////////////////////////
00652
00653     if (_bEncTurning == TRUE)
00654     {
00655         if (_bEncTrigger == FALSE)
00656         {
00657             if (_u8EncPause++ > ENCODER_PAUSE_CALCED)
00658             {
00659                 _bEncTurning = FALSE;
00660                 _u16EncIncrement = 1;
00661                 _u8EncPause = 0;
00662             }
00663         }
00664         else
00665         {
00666             if ((_u8EncPause == 0) || (_u8EncPause > ENCODER_FIRST_ACCELERATION_STEP_CALCED))
00667             {
00668                 // First step || big delay between the triggers: Small step.
00669                 _u16EncIncrement = 1;
00670             }
00671             else if (_u8EncPause > ENCODER_SECOND_ACCELERATION_STEP_CALCED)
00672             {
00673                 // Middle delay between the triggers: Middle step.
00674                 if (_u16EncMaxInc >= 10)
00675                 {
00676                     _u16EncIncrement = 5;
00677                 }
00678                 else
00679                 {
00680                     _u16EncIncrement = _u16EncMaxInc;
00681                 }
00682             }
00683             else
00684             {
00685                 // Small delay between the triggers: Big step.
00686                 _u16EncIncrement = _u16EncMaxInc;
00687             }
00688
00689             _u8EncPause = ENCODER_PAUSE_CYCLE_CALCED;
00690         }
00691     }
00692
00693
00694     // Read in the rotary encoder inputs:
00695     _u16Enc = (_u16Enc << 2) & 0x0C;
00696     _u16Enc |= (PORTD >> 1) & 0x03;
00697
00698
00699     // Check for any pushes on the encoder button. If detected, abort the
00700     // rotary input processing for a better usage.
00701     if(_u8BtnSM[ENC_BTN] <= BTSM_IDLE)
00702     {
00703
00704         // ////////////////////////////////////////////////////////////////////////
00705         // Analysing the encoder value (Greycode statemachine):
00706         // -> Bit 3 and bit 2 are the old states, bit 1 and bit 0 are the new ones.
00707         // -> State transitions, which are not allowed in greycode are ignored.
00708         // -> State transitions, where the old state is equal the new state are
00709         //    ignored.
00710         // State table (4 bit means 16 possibilities):
00711         // Index |      Old      |      New      |  Addend for
00712         //       | Bit 3 | Bit 2 | Bit 1 | Bit 0 | encoder value
00713         //       | RIGHT | LEFT  | RIGHT | LEFT  |
00714         //   0   |   0   |   0   |   0   |   0   |       0
00715         //   1   |   0   |   0   |   0   |   1   |       0
00716         //   2   |   0   |   0   |   1   |   0   |       0
00717         //   3   |   0   |   0   |   1   |   1   |      -1
00718         //   4   |   0   |   1   |   0   |   0   |       0
00719         //   5   |   0   |   1   |   0   |   1   |       0
00720         //   6   |   0   |   1   |   1   |   0   |       0
00721         //   7   |   0   |   1   |   1   |   1   |       0
00722         //   8   |   1   |   0   |   0   |   0   |      -1
00723         //   9   |   1   |   0   |   0   |   1   |       0
00724         //  10   |   1   |   0   |   1   |   0   |       0
00725         //  11   |   1   |   0   |   1   |   1   |      +1
00726         //  12   |   1   |   1   |   0   |   0   |      +1
00727         //  13   |   1   |   1   |   0   |   1   |       0
00728         //  14   |   1   |   1   |   1   |   0   |       0
00729         //  15   |   1   |   1   |   1   |   1   |       0
00730         // It appears from the indices when increment the encoder value: 12, 11.
00731         // And the decrement indices are: 3, 8. The rest of the indices are
00732         // don't cares.
00733
00734
00735         _bEncTrigger = FALSE;
00736
00737         switch(_u16Enc)
00738         {
00739         case 12:
00740         case 11:
00741             if ((_bEncTurning == FALSE) || (_bEncDirection==FALSE))
00742             {
00743                 // Only jump in here if the encoder wheel is already turning
00744                 // or if turning the direction is left.
00745
00746                 _s16EncVal += _u16EncIncrement;
00747                 _bEncTurning = TRUE;
00748                 _bEncDirection = FALSE;
00749                 _bEncTrigger = TRUE;
00750
00751                 if (_s16EncVal > _s16EncMax)
00752                 {
00753                     if (_u8EncFlags & ENC_ENDSTOP_MASK)
00754                     {
00755                         _s16EncVal = _s16EncMax;
00756                     }
00757                     else
00758                     {
00759                         _s16EncVal = _s16EncMin;
00760                     }
00761                 }
00762             }
00763             break;
00764
00765         case 3:
00766         case 8:
00767             if ((_bEncTurning == FALSE)||(_bEncDirection==TRUE))
00768             {
00769                 // Only jump in here if the encoder wheel is already turning
00770                 // or if turning the direction is right.
00771
00772                 _s16EncVal -= _u16EncIncrement;
00773                 _bEncTurning = TRUE;
00774                 _bEncDirection = TRUE;
00775                 _bEncTrigger = TRUE;
00776
00777                 if (_s16EncMin > _s16EncVal)
00778                 {
00779                     if (_u8EncFlags & ENC_ENDSTOP_MASK)
00780                     {
00781                         _s16EncVal = _s16EncMin;
00782                     }
00783                     else
00784                     {
00785                         _s16EncVal = _s16EncMax;
00786                     }
00787                 }
00788             }
00789             break;
00790         }
00791     }
00792
00794     // Clear interrupt flag before leaving:
00795     PIR1bits.CCP1IF = 0;
00796 }
00797
00798 // ////////////////////////////////////////////////////////////////////////////
00799 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: input.h Source File

input.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00023 // ////////////////////////////////////////////////////////////////////////////
00024 // ////////////////////////////////////////////////////////////////////////////
00025
00026
00027 #ifndef INPUT_H
00028
00029     #define INPUT_H
00030
00031
00032 // ////////////////////////////////////////////////////////////////////////////
00033 // Includes
00034 // ////////////////////////////////////////////////////////////////////////////
00035
00036     #include    "GenericTypeDefs.h"
00037
00038
00039 // ////////////////////////////////////////////////////////////////////////////
00040 // Defines
00041 // ////////////////////////////////////////////////////////////////////////////
00042
00043
00045 #define     BTN_COUNT               0x09
00046
00052 #define     ENC_ENDSTOP_MASK        0x01
00053
00058 #define     ENC_TURBO_MASK          0x02
00059
00064 #define     ENC_NOCHANGE_MASK       0x04
00065
00071 #define     BTN_LONG_PUSH_TIME      (100u)
00072
00078 #define     BTN_DOUBLE_PUSH_TIME    (60u)
00079
00080
00081 // ////////////////////////////////////////////////////////////////////////////
00082 // Typedefs
00083 // ////////////////////////////////////////////////////////////////////////////
00084
00088 typedef enum
00089 {
00090     PWR_BTN = 0,
00091     SEL_BTN,
00092     ACC_BTN,
00093     FL_BTN,
00094     F1_BTN,
00095     F2_BTN,
00096     F3_BTN,
00097     F4_BTN,
00098     ENC_BTN,
00099     ALL_BTN
00100 } eButtonID;
00101
00102
00103 // ////////////////////////////////////////////////////////////////////////////
00104 // Function prototypes
00105 // ////////////////////////////////////////////////////////////////////////////
00106
00107
00108 // ////////////////////////////////////////////////////////////////////////////
00121 void InputInit(void);
00122
00123
00124 // ////////////////////////////////////////////////////////////////////////////
00138 void InputMain(void);
00139
00140
00141 // ////////////////////////////////////////////////////////////////////////////
00161 void InputButtonReset(eButtonID eBtn);
00162
00163
00164 // ////////////////////////////////////////////////////////////////////////////
00187 void InputResetPowerButton(void);
00188
00189
00190 // ////////////////////////////////////////////////////////////////////////////
00207 void InputResetButtonPush(eButtonID eBtn);
00208
00209
00210 // ////////////////////////////////////////////////////////////////////////////
00231 BOOL bInputButtonPushedOnce(eButtonID eBtn);
00232
00233
00234 // ////////////////////////////////////////////////////////////////////////////
00256 BOOL bInputButtonPushedTwice(eButtonID eBtn);
00257
00258
00259 // ////////////////////////////////////////////////////////////////////////////
00281 BOOL bInputButtonPushedLong(eButtonID eBtn);
00282
00283
00284 // ////////////////////////////////////////////////////////////////////////////
00305 BOOL bInputButtonPushed(eButtonID eBtn);
00306
00307
00308 // ////////////////////////////////////////////////////////////////////////////
00321 SHORT s16InputEncoderGetValue(void);
00322
00323
00324 // ////////////////////////////////////////////////////////////////////////////
00344 void InputEncoderInit(SHORT s16Val,SHORT s16Min,SHORT s16Max,BYTE u8Flags);
00345
00346
00347 // ////////////////////////////////////////////////////////////////////////////
00363 BOOL bInputEncoderValueChanged(void);
00364
00365
00366 // ////////////////////////////////////////////////////////////////////////////
00377 void InputEncoderSetValue(short s16NewVal, BOOL bRemember);
00378
00379
00380 // ////////////////////////////////////////////////////////////////////////////
00388 void InputForceChangedEncoderValue(void);
00389
00390
00391 // ////////////////////////////////////////////////////////////////////////////
00404 BOOL InputEncoderGetDirection(void);
00405
00406
00407 // ////////////////////////////////////////////////////////////////////////////
00419 BYTE u8InputButtonQuickPushed(void);
00420
00421
00422 // ////////////////////////////////////////////////////////////////////////////
00434 BOOL bInputButtonPressed(eButtonID eBtn);
00435
00436
00437 // ////////////////////////////////////////////////////////////////////////////
00447 BOOL IsEncoderTurning(void);
00448
00449
00450 // ////////////////////////////////////////////////////////////////////////////
00455 void InputInterruptHandler(void);
00456
00460 void InputEncoderTest(void);
00461
00462 // ////////////////////////////////////////////////////////////////////////////
00463 // Epilogue
00464 // ////////////////////////////////////////////////////////////////////////////
00465
00466
00467     #include    "main.h"
00468
00469 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: ipset.c Source File

ipset.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00013 // ////////////////////////////////////////////////////////////////////////////
00014 // ////////////////////////////////////////////////////////////////////////////
00015
00016     #define     IPSET_C
00017
00018     #include    <stdio.h>
00019
00020     #include    "appl.h"
00021     #include    "ipset.h"
00022     #include    "mdns.h"
00023     #include    "stringtable.h"
00024     #include    "sralloc.h"
00025
00026 // ////////////////////////////////////////////////////////////////////////////
00027 // Local Typedefs
00028 // ////////////////////////////////////////////////////////////////////////////
00029
00030 // States of ipset SM
00031 typedef enum
00032 {
00033     IPSET_SM_STARTUP = 0,
00034     IPSET_SM_WAIT_FOR_IP_USER,
00035     IPSET_SM_PREPARE_IPMODE,
00036     IPSET_SM_IPMODE,
00037     IPSET_SM_PREPARE_IPDIAG,
00038     IPSET_SM_PREPARE_DIAG,
00039     IPSET_SM_IP_DIAG,
00040     IPSET_SM_PREPARE_SUBDIAG,
00041     IPSET_SM_SUB_DIAG,
00042     IPSET_SM_PREPARE_GATEDIAG,
00043     IPSET_SM_GATE_DIAG,
00044     IPSET_SM_IP_FINISHED,
00045     IPSET_SM_SERVER_STARTUP,
00046     IPSET_SM_SERVER_STARTUP_WAIT,
00047     IPSET_SM_PREPARE_SERVER_FINDMODE,
00048     IPSET_SM_SERVER_FINDMODE,
00049     IPSET_SM_SERVER_AFTER_FINDMODE,
00050     IPSET_SM_SERVER_PREPARE_IP_DIAG,
00051     IPSET_SM_SERVER_IP_DIAG,
00052     IPSET_SM_SERVER_PREPARE_PORT_DIAG,
00053     IPSET_SM_SERVER_PORT_WAIT_FOR_DIAG,
00054     IPSET_SM_SERVER_PORT_DIAG,
00055     IPSET_SM_SERVER_PREPARE_NAME_DIAG,
00056     IPSET_SM_SERVER_NAME_WAIT_FOR_DIAG,
00057     IPSET_SM_SERVER_NAME_DIAG,
00058     IPSET_SM_SERVER_PORT_CORRECTED,
00059     IPSET_SM_SERVER_FINISHED,
00060     IPSET_SM_SAVED,
00061     IPSET_SM_WAIT_FOR_USER,
00062     IPSET_SM_FINISHED
00063 } SM_IPSET;
00064
00065 typedef struct
00066 {
00067     DWORD   u32oldSrvIp;
00068     DWORD   u32oldIp;
00069     DWORD   u32oldGate;
00070     WORD    u16oldSrvIPPort;
00071     WORD    u16oldSrvNamePort;
00072     SM_IPSET eState;
00073     BYTE    u8oldMask;
00074     BOOL    boldDHCP;
00075     SEARCH_MODE eoldSrvFindMode;
00076     BYTE au8oldSrvName[sizeof(sPApplConfig.au8Name)];
00077     BYTE    au8oldSrvService[sizeof(sPApplConfig.au8Service)];
00078 } sIPsetControl;
00079
00080
00081 // ////////////////////////////////////////////////////////////////////////////
00082 // Local Constants
00083 // ////////////////////////////////////////////////////////////////////////////
00084
00085 ROM BYTE _cau8hostname_chars[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
00086      'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
00087      'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' };
00088
00089 // ////////////////////////////////////////////////////////////////////////////
00090 // Local Variables
00091 // ////////////////////////////////////////////////////////////////////////////
00092
00093 static BYTE * pdata;
00094 static BYTE _u8CursorPos;
00095 static sIPsetControl * _pIPSetCtrl = NULL;
00096
00097
00098 // ////////////////////////////////////////////////////////////////////////////
00099 // Local function prototypes
00100 // ////////////////////////////////////////////////////////////////////////////
00101
00102 static void _cancelDialog(void);
00103
00104
00105 // ////////////////////////////////////////////////////////////////////////////
00106 // ////////////////////////////////////////////////////////////////////////////
00107
00108 void IPSetInit(BOOL bServer)
00109 {
00110     // Prepare buttons for the dialog:
00111     InputButtonReset(ALL_BTN);
00112     SRAMInitHeap();
00113
00114     _pIPSetCtrl = (sIPsetControl* )(SRAMalloc(sizeof(sIPsetControl)));
00115     if (_pIPSetCtrl == NULL)
00116     {
00117         return;
00118     }
00119
00120     if (bServer == TRUE)
00121     {
00122         _pIPSetCtrl->eState = IPSET_SM_SERVER_STARTUP;
00123     }
00124     else
00125     {
00126         _pIPSetCtrl->eState = IPSET_SM_STARTUP;
00127     }
00128
00129     _pIPSetCtrl->u32oldIp = sPCommonConfig.ManIPAddr.Val;
00130     _pIPSetCtrl->u8oldMask = sPCommonConfig.ManMask;
00131     _pIPSetCtrl->u32oldGate = sPCommonConfig.ManGateway.Val;
00132
00133     _pIPSetCtrl->boldDHCP = sPCommonConfig.Flags.bIsDHCPEnabled;
00134     _pIPSetCtrl->eoldSrvFindMode = sPApplConfig.eFindMode;
00135     _pIPSetCtrl->u32oldSrvIp = sPApplConfig.sSrvIPAdd.Val;
00136     _pIPSetCtrl->u16oldSrvIPPort = sPApplConfig.sIPPort.Val;
00137     _pIPSetCtrl->u16oldSrvNamePort = sPApplConfig.sNamePort.Val;
00138
00139     memcpy(_pIPSetCtrl->au8oldSrvName, (void*)sPApplConfig.au8Name, sizeof(_pIPSetCtrl->au8oldSrvName));
00140     memcpy(_pIPSetCtrl->au8oldSrvService, (void*)sPApplConfig.au8Service, sizeof(_pIPSetCtrl->au8oldSrvService));
00141 }
00142
00143 // ////////////////////////////////////////////////////////////////////////////
00144 // ////////////////////////////////////////////////////////////////////////////
00145
00146 BOOL IPSetMain(void)
00147 {
00148     if (_pIPSetCtrl == NULL)
00149     {
00150         return TRUE;
00151     }
00152
00153     // F2_BTN button is for canceling the dialog!
00154     if ((bInputButtonPushed(F2_BTN) == TRUE) && (_pIPSetCtrl->eState < IPSET_SM_SAVED))
00155     {
00156         _cancelDialog();
00157     }
00158
00159
00160     switch(_pIPSetCtrl->eState)
00161     {
00162     case IPSET_SM_STARTUP:
00163         StrTbl_GetString(lcdram_row1, STRTBLID_IP_MENU);
00164         lcd_addr2 = 0;
00165         strcpypgm2ram(lcdram_row2, (ROM char *) "    ESC         ");
00166         lcdram_row2[0] = 0xFB;
00167         lcdram_row2[15] = 0xFC;
00168         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK | LCD_ROW2_MASK;
00169
00170         InputButtonReset(ENC_BTN);
00171         _pIPSetCtrl->eState = IPSET_SM_WAIT_FOR_IP_USER;
00172         break;
00173
00174     case IPSET_SM_WAIT_FOR_IP_USER:
00175         if (bInputButtonPushed(F1_BTN))
00176         {
00177             _cancelDialog();
00178         }
00179
00180         if (bInputButtonPushed(ENC_BTN) || bInputButtonPushed(F4_BTN))
00181         {
00182             _pIPSetCtrl->eState = IPSET_SM_PREPARE_IPMODE;
00183         }
00184         break;
00185
00186     case IPSET_SM_PREPARE_IPMODE:
00187         StrTbl_GetString(lcdram_row1, STRTBLID_IP_ALLOCATION);
00188         _pIPSetCtrl->eState = IPSET_SM_IPMODE;
00189         InputEncoderInit(sPCommonConfig.Flags.bIsDHCPEnabled, 0, 1,ENC_ENDSTOP_MASK);
00190         InputButtonReset(ALL_BTN);
00191         // Intended fall through
00192
00193     case IPSET_SM_IPMODE:
00194         if (bInputButtonPushed(ENC_BTN) || bInputButtonPushed(F4_BTN))
00195         {
00196             sPCommonConfig.Flags.bIsDHCPEnabled = (BOOL) s16InputEncoderGetValue();
00197             if ( sPCommonConfig.Flags.bIsDHCPEnabled == FALSE)
00198             {
00199                 _pIPSetCtrl->eState = IPSET_SM_PREPARE_IPDIAG;
00200             }
00201             else
00202             {
00203                 _pIPSetCtrl->eState = IPSET_SM_IP_FINISHED;
00204             }
00205         }
00206         else if (bInputButtonPushed(F1_BTN))
00207         {
00208             _pIPSetCtrl->eState = IPSET_SM_STARTUP;
00209         }
00210         else if (bInputEncoderValueChanged() == TRUE)
00211         {
00212             if (s16InputEncoderGetValue() == 0)
00213             {
00214                 StrTbl_GetString(lcdram_row2, STRTBLID_MANUAL);
00215             }
00216             else
00217             {
00218                 StrTbl_GetString(lcdram_row2, STRTBLID_AUTO);
00219             }
00220
00221             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00222                          LCD_ROW2_MASK | LCD_CENTER2_MASK;
00223         }
00224         break;
00225
00226     case IPSET_SM_PREPARE_IPDIAG:
00227         pdata = sPCommonConfig.ManIPAddr.v;
00228         StrTbl_GetString(lcdram_row1, STRTBLID_IP_ADDRESS);
00229         _pIPSetCtrl->eState = IPSET_SM_PREPARE_DIAG;
00230         break;
00231
00232     case IPSET_SM_PREPARE_GATEDIAG:
00233     case IPSET_SM_PREPARE_DIAG:
00234     case IPSET_SM_SERVER_PREPARE_IP_DIAG:
00235         InputButtonReset(ALL_BTN);
00236         _u8CursorPos = 0;
00237         InputEncoderInit(pdata[0], 1, 223, 0);
00238         lcd_addr2 = 0;
00239         sprintf(lcdram_row2, (ROM char *) "%3hhu.%3hhu.%3hhu.%3hhu",
00240                                 pdata[0], pdata[1], pdata[2], pdata[3]);
00241         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK |
00242                      LCD_CENTER1_MASK | LCD_ROW2_MASK;
00243         _pIPSetCtrl->eState++;
00244         break;
00245
00246     case IPSET_SM_IP_DIAG:
00247     case IPSET_SM_SERVER_IP_DIAG:
00248     case IPSET_SM_GATE_DIAG:
00249         {
00250             BOOL bpushed = FALSE;
00251             BOOL bchanged = FALSE;
00252
00253             if(OutIsLCDBusy())
00254             {
00255                 // Doing nothing until the LCD has finished.
00256                 break;
00257             }
00258
00259             bchanged = bInputEncoderValueChanged();
00260             pdata[_u8CursorPos] = s16InputEncoderGetValue();
00261
00262             if (bInputButtonPushed(F4_BTN))
00263             {
00264                 // IP or gateway dialog was finished!
00265                 _pIPSetCtrl->eState++;
00266                 break;
00267             }
00268             else if (bInputButtonPushed(F1_BTN))
00269             {
00270                 if (_pIPSetCtrl->eState == IPSET_SM_SERVER_IP_DIAG)
00271                 {
00272                     _pIPSetCtrl->eState = IPSET_SM_PREPARE_SERVER_FINDMODE;
00273                 }
00274                 else if (_pIPSetCtrl->eState == IPSET_SM_GATE_DIAG)
00275                 {
00276                     _pIPSetCtrl->eState = IPSET_SM_PREPARE_SUBDIAG;
00277                 }
00278                 else if (_pIPSetCtrl->eState == IPSET_SM_IP_DIAG)
00279                 {
00280                     _pIPSetCtrl->eState = IPSET_SM_PREPARE_IPMODE;
00281                 }
00282                 break;
00283             }
00284             else if (bInputButtonPushed(ENC_BTN))
00285             {
00286                 // Next digit (single push)
00287                 InputButtonReset(ENC_BTN);
00288                 lcdram_row2[2] = ' ';
00289                 u8ApplTimer = 0;
00290                 bpushed = TRUE;
00291             }
00292             else if (bchanged == TRUE)
00293             {
00294                 lcdram_row2[2] = ' ';
00295                 u8ApplTimer = 0;
00296             }
00297
00298             if (u8ApplTimer == 0)
00299             {
00300                 lcd_addr2 = 4*_u8CursorPos;
00301                 if (lcdram_row2[2] != ' ')
00302                 {
00303                     u8ApplTimer = 50;
00304                     strcpypgm2ram(lcdram_row2, (ROM char *) "   ");
00305                 }
00306                 else
00307                 {
00308                     u8ApplTimer = 150;
00309                     sprintf(lcdram_row2, (ROM char *) "%3hhu", pdata[_u8CursorPos]);
00310                 }
00311
00312                 lcd_status |= LCD_ROW2_MASK;
00313             }
00314
00315             if (bpushed == TRUE)
00316             {
00317                 if (++_u8CursorPos == 4)
00318                 {
00319                     _u8CursorPos = 0;
00320                     InputEncoderInit(pdata[0], 1, 223, 0);
00321                 }
00322                 else
00323                 {
00324                     InputEncoderInit(pdata[_u8CursorPos], 0, 255, 0);
00325                 }
00326
00327                 u8ApplTimer = 0;
00328                 s16InputEncoderGetValue();
00329             }
00330             break;
00331         }
00332     case IPSET_SM_PREPARE_SUBDIAG:
00333         InputButtonReset(ALL_BTN);
00334         StrTbl_GetString(lcdram_row1, STRTBLID_SUBNETMASK);
00335         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK;
00336         InputEncoderInit(sPCommonConfig.ManMask, 8, 30, 0);
00337         _pIPSetCtrl->eState = IPSET_SM_SUB_DIAG;
00338         // Intended fall through
00339
00340     case IPSET_SM_SUB_DIAG:
00341         if (bInputButtonPushed(ENC_BTN)||bInputButtonPushed(F4_BTN))
00342         {
00343             // Subnetmask dialog was finished!
00344             sPCommonConfig.ManMask = (BYTE) s16InputEncoderGetValue();
00345
00346             if ((_pIPSetCtrl->u32oldIp != sPCommonConfig.ManIPAddr.Val) ||
00347                 (_pIPSetCtrl->u8oldMask != sPCommonConfig.ManMask))
00348             {
00349                 DWORD_VAL tempMask;
00350                 tempMask.Val = IPConvertSubnetToMask(sPCommonConfig.ManMask);
00351
00352                 sPCommonConfig.ManGateway.Val =
00353                                        tempMask.Val & sPCommonConfig.ManIPAddr.Val;
00354                 sPCommonConfig.ManGateway.v[3] += 1;
00355             }
00356
00357             _pIPSetCtrl->eState = IPSET_SM_PREPARE_GATEDIAG;
00358             pdata = sPCommonConfig.ManGateway.v;
00359             StrTbl_GetString(lcdram_row1, STRTBLID_GATEWAY_ADDRESS);
00360         }
00361         else if (bInputButtonPushed(F1_BTN))
00362         {
00363             _pIPSetCtrl->eState = IPSET_SM_PREPARE_IPDIAG;
00364         }
00365         else if (bInputEncoderValueChanged() == TRUE)
00366         {
00367             DWORD_VAL sub;
00368             sub.Val = IPConvertSubnetToMask((BYTE) s16InputEncoderGetValue());
00369             lcd_addr2 = 0;
00370             sprintf(lcdram_row2, (ROM char *) "%3hhu.%3hhu.%3hhu.%3hhu",
00371                                        sub.v[0], sub.v[1], sub.v[2], sub.v[3]);
00372             lcd_status |= LCD_ROW2_MASK;
00373         }
00374         break;
00375
00376     case IPSET_SM_IP_FINISHED:
00377         if (_pIPSetCtrl->u32oldIp != sPCommonConfig.ManIPAddr.Val ||
00378             _pIPSetCtrl->u8oldMask != sPCommonConfig.ManMask ||
00379             _pIPSetCtrl->u32oldGate != sPCommonConfig.ManGateway.Val ||
00380             _pIPSetCtrl->boldDHCP != sPCommonConfig.Flags.bIsDHCPEnabled)
00381         {
00382             BYTE * confPtr = (BYTE *)(&sPCommonConfig);
00383             StopMDNSResponder();
00384
00385             // If IP or mode has changed, than a gratious ARP is necessary!
00386             if ((_pIPSetCtrl->u32oldIp != sPCommonConfig.ManIPAddr.Val)||
00387                 (_pIPSetCtrl->boldDHCP != sPCommonConfig.Flags.bIsDHCPEnabled))
00388             {
00389                 sIPConfig.Flags.bIPunique = FALSE;
00390             }
00391
00392             if (sPCommonConfig.Flags.bIsDHCPEnabled == FALSE)
00393             {
00394                 DHCPDisable();
00395                 sIPConfig.MyIPAddr.Val = sPCommonConfig.ManIPAddr.Val;
00396                 sIPConfig.MyMask.Val = IPConvertSubnetToMask(sPCommonConfig.ManMask);
00397                 sIPConfig.MyGateway.Val = sPCommonConfig.ManGateway.Val;
00398             }
00399             else
00400             {
00401                 DHCPEnable();
00402                 DHCPReset(FALSE);
00403             }
00404
00405             // write the entire data into EEPROM
00406             XEEWriteArray(BOOTUP_EEPROM_ADD, confPtr, sizeof(PCOMMON_CONFIG));
00407
00408             _pIPSetCtrl->eState = IPSET_SM_SAVED;
00409         }
00410         else
00411         {
00412             DHCPReset(TRUE);
00413             _pIPSetCtrl->eState = IPSET_SM_FINISHED;
00414         }
00415         break;
00416
00417     case IPSET_SM_SERVER_STARTUP:
00418         StrTbl_GetString(lcdram_row1, STRTBLID_SERVER_MENU);
00419         lcd_addr2 = 0;
00420         strcpypgm2ram(lcdram_row2, (ROM char *) "    ESC         ");
00421         lcdram_row2[0] = 0xFB;
00422         lcdram_row2[10] = 0x7F;
00423         lcdram_row2[15] = 0xFC;
00424         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK |
00425                      LCD_CENTER1_MASK | LCD_ROW2_MASK;
00426         InputButtonReset(ALL_BTN);
00427         _pIPSetCtrl->eState = IPSET_SM_SERVER_STARTUP_WAIT;
00428         break;
00429
00430     case IPSET_SM_SERVER_STARTUP_WAIT:
00431         if (bInputButtonPushed(F1_BTN))
00432         {
00433             _cancelDialog();
00434         }
00435
00436         if ((bInputButtonPushed(ENC_BTN) == TRUE)||(bInputButtonPushed(F4_BTN) == TRUE))
00437         {
00438             _pIPSetCtrl->eState = IPSET_SM_PREPARE_SERVER_FINDMODE;
00439         }
00440         break;
00441
00442     case IPSET_SM_PREPARE_SERVER_FINDMODE:
00443         StrTbl_GetString(lcdram_row1, STRTBLID_FIND_SERVER);
00444         _pIPSetCtrl->eState = IPSET_SM_SERVER_FINDMODE;
00445         if (sPApplConfig.eFindMode == SEARCH_UNKNOWN)
00446         {
00447             sPApplConfig.eFindMode = SEARCH_IP;
00448         }
00449
00450         InputEncoderInit(sPApplConfig.eFindMode, 1, 3, 0);
00451         InputButtonReset(ALL_BTN);
00452         OutEnableCursor(FALSE);
00453         break;
00454
00455     case IPSET_SM_SERVER_FINDMODE:
00456         if ((bInputButtonPushed(ENC_BTN) == TRUE)||
00457             (bInputButtonPushed(F4_BTN) == TRUE))
00458         {
00459             sPApplConfig.eFindMode = (BOOL)s16InputEncoderGetValue();
00460             _pIPSetCtrl->eState = IPSET_SM_SERVER_AFTER_FINDMODE;
00461         }
00462         else if (bInputButtonPushed(F1_BTN) == TRUE)
00463         {
00464             // Shift TAB -> Go back to the last menu item.
00465             _pIPSetCtrl->eState = IPSET_SM_SERVER_STARTUP;
00466         }
00467         else if (bInputEncoderValueChanged() == TRUE)
00468         {
00469             BYTE val = (BYTE) s16InputEncoderGetValue();
00470
00471             if (val == SEARCH_IP)
00472             {
00473                 StrTbl_GetString(lcdram_row2, STRTBLID_IP_ADDRESS);
00474             }
00475             else if (val == SEARCH_NAME)
00476             {
00477                 StrTbl_GetString(lcdram_row2, STRTBLID_NETWORK_NAME);
00478             }
00479             else
00480             {
00481                 StrTbl_GetString(lcdram_row2, STRTBLID_NETWORK_SERVICE);
00482             }
00483
00484             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK | LCD_ROW2_MASK | LCD_CENTER2_MASK;
00485         }
00486         break;
00487
00488     case IPSET_SM_SERVER_AFTER_FINDMODE:
00489         if (sPApplConfig.eFindMode == SEARCH_IP)
00490         {
00491             _pIPSetCtrl->eState = IPSET_SM_SERVER_PREPARE_IP_DIAG;
00492             pdata = sPApplConfig.sSrvIPAdd.v;
00493             StrTbl_GetString(lcdram_row1, STRTBLID_SERVER_ADDRESS);
00494         }
00495         else
00496         {
00497             if(sPApplConfig.eFindMode == SEARCH_NAME)
00498             {
00499                 pdata = sPApplConfig.au8Name;
00500                 StrTbl_GetString(lcdram_row1, STRTBLID_SERVER_NAME);
00501             }
00502             else
00503             {
00504                 pdata = sPApplConfig.au8Service;
00505                 StrTbl_GetString(lcdram_row1, STRTBLID_SERVICE_NAME);
00506             }
00507
00508             _pIPSetCtrl->eState = IPSET_SM_SERVER_PREPARE_NAME_DIAG;
00509         }
00510         break;
00511
00512     case IPSET_SM_SERVER_PREPARE_PORT_DIAG:
00513         StrTbl_GetString(lcdram_row1, STRTBLID_PORT);
00514         lcd_addr1 = 0;
00515         lcd_addr2 = 0;
00516         if (sPApplConfig.eFindMode == SEARCH_IP)
00517         {
00518             pdata = (BYTE *)&sPApplConfig.sIPPort.Val;
00519         }
00520         else
00521         {
00522             pdata = (BYTE *)&sPApplConfig.sNamePort.Val;
00523         }
00524
00525         sprintf(lcdram_row2, (ROM char *)"%05hu", *((WORD *)pdata));
00526         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
00527
00528         InputEncoderInit(lcdram_row2[0]-'0'+26, 26, 35, 0);
00529         InputButtonReset(ALL_BTN);
00530         _u8CursorPos = 0;
00531         _pIPSetCtrl->eState = IPSET_SM_SERVER_PORT_WAIT_FOR_DIAG;
00532         OutEnableCursor(TRUE);
00533         break;
00534
00535
00536     case IPSET_SM_SERVER_PORT_DIAG:
00537         if (bInputButtonPushed(F4_BTN) == TRUE)
00538         {
00539             DWORD val = (DWORD)(atol(lcdram_row2));
00540             OutEnableCursor(FALSE);
00541
00542             if (val > 65535)
00543             {
00544                 *((WORD *)pdata) = 65535;
00545             }
00546             else if (val == 0)
00547             {
00548                 *((WORD *)pdata) = 1;
00549             }
00550             else
00551             {
00552                 *((WORD *)pdata) = (WORD) val;
00553                 _pIPSetCtrl->eState = IPSET_SM_SERVER_FINISHED;
00554                 break;
00555             }
00556
00557             _pIPSetCtrl->eState = IPSET_SM_SERVER_PORT_CORRECTED;
00558             StrTbl_GetString(lcdram_row1, STRTBLID_SET_PORT_TO1);
00559             sprintf(lcdram_row2, StrTbl_cau8GetStringPointer(STRTBLID_SET_PORT_TO2), *((WORD *)pdata));
00560
00561             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK | LCD_ROW2_MASK | LCD_CENTER2_MASK;
00562             u8ApplTimer = 200;
00563             InputButtonReset(ENC_BTN);
00564         }
00565         else if (bInputButtonPushed(F1_BTN) == TRUE)
00566         {
00567             _pIPSetCtrl->eState = IPSET_SM_SERVER_AFTER_FINDMODE;
00568             OutEnableCursor(FALSE);
00569         }
00570         else if (bInputEncoderValueChanged() == TRUE)
00571         {
00572             lcdram_row2[_u8CursorPos] = _cau8hostname_chars[s16InputEncoderGetValue()];
00573             lcd_status |= LCD_ROW2_MASK;
00574             _pIPSetCtrl->eState--;
00575         }
00576         else if (bInputButtonPushed(ENC_BTN) == TRUE)
00577         {
00578             InputButtonReset(ENC_BTN);
00579             if (++_u8CursorPos > 4)
00580             {
00581                 _u8CursorPos = 0;
00582             }
00583             InputEncoderSetValue(lcdram_row2[_u8CursorPos] - '0' + 26, TRUE);
00584             _pIPSetCtrl->eState--;
00585         }
00586         break;
00587
00588     case IPSET_SM_SERVER_PREPARE_NAME_DIAG:
00589     {
00590         BYTE i;
00591         _u8CursorPos = strlen(pdata);
00592         if (_u8CursorPos)
00593         {
00594             _u8CursorPos--;
00595             while(pdata[_u8CursorPos]!=_cau8hostname_chars[i++]);
00596         }
00597         else
00598         {
00599             i = 1;
00600         }
00601
00602         InputEncoderInit(i-1, 0, sizeof(_cau8hostname_chars)-1, 0);
00603
00604         strcpy(lcdram_row2, pdata);
00605         lcd_addr1 = 0;
00606         lcd_addr2 = 0;
00607         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
00608
00609         InputButtonReset(ALL_BTN);
00610         _pIPSetCtrl->eState = IPSET_SM_SERVER_NAME_WAIT_FOR_DIAG;
00611         OutEnableCursor(TRUE);
00612         break;
00613     }
00614
00615     case IPSET_SM_SERVER_PORT_WAIT_FOR_DIAG:
00616     case IPSET_SM_SERVER_NAME_WAIT_FOR_DIAG:
00617         if (OutIsLCDBusy()==FALSE)
00618         {
00619             OutSetCursor(_u8CursorPos, 1);
00620             _pIPSetCtrl->eState++;
00621         }
00622         break;
00623
00624     case IPSET_SM_SERVER_NAME_DIAG:
00625         if (bInputButtonPushed(F4_BTN) == TRUE)
00626         {
00627             OutEnableCursor(FALSE);
00628             if (sPApplConfig.eFindMode == SEARCH_NAME)
00629             {
00630                 _pIPSetCtrl->eState = IPSET_SM_SERVER_PREPARE_PORT_DIAG;
00631             }
00632             else
00633             {
00634                 _pIPSetCtrl->eState = IPSET_SM_SERVER_FINISHED;
00635             }
00636         }
00637         else if (bInputButtonPushed(F1_BTN) == TRUE)
00638         {
00639             // Shift TAB -> Go back to the last menu item.
00640             OutEnableCursor(FALSE);
00641             _pIPSetCtrl->eState = IPSET_SM_PREPARE_SERVER_FINDMODE;
00642         }
00643         else if ((bInputEncoderValueChanged() == TRUE) && (_u8CursorPos<16))
00644         {
00645             pdata[_u8CursorPos] = _cau8hostname_chars[s16InputEncoderGetValue()];
00646             strcpy(lcdram_row2, pdata);
00647             lcd_status |= LCD_ROW2_MASK;
00648
00649             // Waiting for the display:
00650             _pIPSetCtrl->eState--;
00651         }
00652         else if (bInputButtonPushed(ENC_BTN) == TRUE)
00653         {
00654             // Next position is selected
00655             InputButtonReset(ENC_BTN);
00656
00657             if (pdata[_u8CursorPos] && (_u8CursorPos<15))
00658             {
00659                 InputEncoderSetValue(0, TRUE);
00660                 _u8CursorPos++;
00661                 _pIPSetCtrl->eState--;
00662             }
00663         }
00664         else if (bInputButtonPushed(F3_BTN) == TRUE)
00665         {
00666             // Backspace emulation
00667             InputButtonReset(F3_BTN);
00668             pdata[_u8CursorPos] = 0;
00669             lcdram_row2[_u8CursorPos] = ' ';
00670             lcdram_row2[_u8CursorPos+1] = 0;
00671             lcd_status |= LCD_ROW2_MASK;
00672
00673             if (_u8CursorPos)
00674             {
00675                 BYTE i = 0;
00676                 _u8CursorPos--;
00677                 while(pdata[_u8CursorPos]!=_cau8hostname_chars[i++]);
00678                 InputEncoderSetValue(i-1, TRUE);
00679             }
00680             else
00681             {
00682                 InputEncoderSetValue(0, FALSE);
00683             }
00684             _pIPSetCtrl->eState--;
00685         }
00686
00687         break;
00688
00689     case IPSET_SM_SERVER_FINISHED:
00690         if (_pIPSetCtrl->eoldSrvFindMode != sPApplConfig.eFindMode ||
00691             _pIPSetCtrl->u32oldSrvIp != sPApplConfig.sSrvIPAdd.Val ||
00692             _pIPSetCtrl->u16oldSrvIPPort != sPApplConfig.sIPPort.Val ||
00693             _pIPSetCtrl->u16oldSrvNamePort != sPApplConfig.sNamePort.Val ||
00694             (strcmp(_pIPSetCtrl->au8oldSrvName, sPApplConfig.au8Name) != 0) ||
00695             (strcmp(_pIPSetCtrl->au8oldSrvService, sPApplConfig.au8Service) != 0))
00696         {
00697             BYTE * confPtr = (BYTE *)(&sPApplConfig);
00698
00699             // write the entire data into EEPROM
00700             XEEWriteArray(APPL_EEPROM_ADD, confPtr, sizeof(SPAPPLDATA));
00701
00702             _pIPSetCtrl->eState = IPSET_SM_SAVED;
00703         }
00704         else
00705         {
00706             _pIPSetCtrl->eState = IPSET_SM_FINISHED;
00707         }
00708         break;
00709
00710     case IPSET_SM_SAVED:
00711         StrTbl_GetString(lcdram_row1, STRTBLID_DATA_WAS);
00712         StrTbl_GetString(lcdram_row2, STRTBLID_SAVED);
00713         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00714                      LCD_ROW2_MASK | LCD_CENTER2_MASK;
00715         _pIPSetCtrl->eState = IPSET_SM_WAIT_FOR_USER;
00716         u8ApplTimer = 200;
00717         InputButtonReset(ALL_BTN);
00718         break;
00719
00720     case IPSET_SM_SERVER_PORT_CORRECTED:
00721     case IPSET_SM_WAIT_FOR_USER:
00722         if ((u8ApplTimer == 0) || (bInputButtonPushed(ENC_BTN)))
00723         {
00724             _pIPSetCtrl->eState++;
00725         }
00726         break;
00727
00728     case IPSET_SM_FINISHED:
00729         SRAMfree((BYTE *)_pIPSetCtrl);
00730         _pIPSetCtrl = NULL;
00731         return TRUE;
00732     }
00733
00734     return FALSE;
00735 }
00736
00737 // ////////////////////////////////////////////////////////////////////////////
00738 // ////////////////////////////////////////////////////////////////////////////
00739
00740 static void _cancelDialog(void)
00741 {
00742     // Disable the cursor, if enabled.
00743     OutEnableCursor(FALSE);
00744
00745     // write the data back without taking changes in account
00746     sPCommonConfig.ManIPAddr.Val = _pIPSetCtrl->u32oldIp;
00747     sPCommonConfig.ManMask = _pIPSetCtrl->u8oldMask;
00748     sPCommonConfig.ManGateway.Val = _pIPSetCtrl->u32oldGate;
00749     sPCommonConfig.Flags.bIsDHCPEnabled = _pIPSetCtrl->boldDHCP;
00750     sPApplConfig.eFindMode = _pIPSetCtrl->eoldSrvFindMode;
00751     sPApplConfig.sSrvIPAdd.Val = _pIPSetCtrl->u32oldSrvIp;
00752     sPApplConfig.sIPPort.Val = _pIPSetCtrl->u16oldSrvIPPort;
00753     sPApplConfig.sNamePort.Val = _pIPSetCtrl->u16oldSrvNamePort;
00754     memcpy(sPApplConfig.au8Name, (void *)_pIPSetCtrl->au8oldSrvName,
00755                                            sizeof(_pIPSetCtrl->au8oldSrvName));
00756     memcpy(sPApplConfig.au8Service, (void *)_pIPSetCtrl->au8oldSrvService,
00757                                         sizeof(_pIPSetCtrl->au8oldSrvService));
00758
00759     StrTbl_GetString(lcdram_row1, STRTBLID_DATA_NOT);
00760     StrTbl_GetString(lcdram_row2, STRTBLID_SAVED);
00761     lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
00762                  LCD_ROW2_MASK | LCD_CENTER2_MASK;
00763
00764     u8ApplTimer = 200;
00765     InputButtonReset(ALL_BTN);
00766     _pIPSetCtrl->eState = IPSET_SM_WAIT_FOR_USER;
00767 }
00768
00769 // ////////////////////////////////////////////////////////////////////////////
00770 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: ipset.h Source File

ipset.h

Go to the documentation of this file.
00001
00002
00003
00013
00014
00015
00024
00025
00026
00027 #ifndef IPSET_H
00028
00029     #define     IPSET_H
00030
00031
00040     void IPSetInit(BOOL bServer);
00041
00042
00057     BOOL IPSetMain(void);
00058
00059 #endif
00060
00063
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: Main Page

eWicht Documentation

1.1

  • Main Page
  • Related Pages
  • Modules
  • Data Structures
    • Data Structures
  • Files
    • File List
  • Data Structures
Generated on Sun Nov 27 20:02:37 2011 for eWicht by doxygen 1.5.5


eWicht: main.c Source File

main.c

Go to the documentation of this file.
00001
00002
00003
00016
00017
00018
00019
00020     #define     MAIN_C
00021
00022     #include    "main.h"
00023     #include    "mdns.h"
00024     #include    "sralloc.h"
00025
00026 // ////////////////////////////////////////////////////////////////////////////
00027
00028
00029 // ////////////////////////////////////////////////////////////////////////////
00030 // ////////////////////////////////////////////////////////////////////////////
00031
00032 void main()
00033 {
00034     u16GlobalFlags = 0; // Reset the indicator field.
00035
00036     // Operate at 41.66667MHz (T=24 ns)
00037     OSCTUNE = 0x40;
00038
00039     INTCON = 0;         // Disable all interrupts.
00040
00041     TickInit();         // Initializes our tick module.
00042
00043     RCONbits.IPEN = 1;  // Enable priority levels on interrupts.
00044     INTCONbits.GIEL = 1;    // Enable interrupts with low priority.
00045     INTCONbits.GIEH = 1;    // Enable interrupts with high priority.
00046
00047     // Initializes the display and switch LEDs.
00048     OutInit();
00049
00050
00051     // For debugging reasons: Reset the EEPROMs content to 0xFF.
00052 #ifdef  EEPROM_ERASE
00053     XEEEraseEEPROM( );
00054 #endif
00055
00056     // Initialize the heap
00057     SRAMInitHeap();
00058
00059     // Initialize Microchip File System module
00060     MPFSInit();
00061
00062     // Initialize input hardware (buttons and rotary encoder)
00063     InputInit();
00064
00065     // Initialize eWicht application
00066     ApplInit();
00067
00068     // Initialize MAC layer
00069     MACInit();
00070
00071     while(ApplIsRunning() == TRUE)
00072     {
00073         if (u16GlobalFlags & LINKISUP_MASK)
00074         {
00075             // This task performs normal stack task including checking
00076             // for incoming packet, type of packet and calling
00077             // appropriate stack entity to process it.
00078             StackTask();
00079
00080             StackApplications();
00081
00082             // Call the MDNS responder
00083             MDNSResponder();
00084         }
00085
00086         ApplMain();
00087
00088         OutMain();
00089     }
00090
00091
00092     // Actions after switch off:
00093     OutSwitchOffLCD();
00094     OutSwitchOffAllLEDs();
00095     MACPowerDown();
00096
00097     // Factory reset starts the eWicht immediately...
00098     if (u16GlobalFlags & FACRES_MASK)
00099     {
00100         ApplResetToFactory(FALSE);
00101     }
00102     else if (!(u16GlobalFlags & RESTART_MASK))
00103     {
00104         // Shut down!
00105         ApplStop();
00106     }
00107     else if (u16GlobalFlags & BOOTLOADER_MASK)
00108     {
00109         // Prepare the MAC and IP address for bootloader.
00110         BootupEnterBootloader();
00111         RCONbits.NOT_POR = 0;
00112         Reset();
00113     }
00114
00115     RCONbits.POR = 1;
00116     Reset();
00117 }
00118
00119 // ////////////////////////////////////////////////////////////////////////////
00120 // ////////////////////////////////////////////////////////////////////////////
00121
00123 // Lowprior Interrupt Service Routine
00125
00126 #pragma interruptlow _peripheralTimerISR
00127
00128 void _peripheralTimerISR(void)
00129 {
00130     InputInterruptHandler();
00131
00132     OutInterruptHandler();
00133 }
00134
00135 // ////////////////////////////////////////////////////////////////////////////
00136 // ////////////////////////////////////////////////////////////////////////////
00137
00138 #pragma code low_vector=0x18
00139 void low_interrupt(void)
00140 {
00141     _asm GOTO _peripheralTimerISR _endasm
00142 }
00143
00144 #pragma code
00145
00146 // ////////////////////////////////////////////////////////////////////////////
00147 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: main.h Source File

main.h

Go to the documentation of this file.
00001
00002
00003
00013
00014
00015
00016 #ifndef MAIN_H
00017
00018     #define     MAIN_H
00019
00020     #include    <p18f67j60.h>
00021     #include    <string.h>
00022
00023     #include    "version.h"
00024
00025     #include    "TCPIP.h"
00026     #include    "output.h"
00027     #include    "appl.h"
00028     #include    "bootup.h"
00029     #include    "input.h"
00030
00031     #ifdef MAIN_C
00032         #define PROTO
00033     #else
00034         #define PROTO extern
00035     #endif
00036
00037 //  #define     DEBEXT_MODE
00038
00039
00040
00042 // Fuse settings (This fuses must be the same like in the bootloader!)
00044
00045     #ifdef MAIN_C
00046         #ifdef __DEBUG
00047             #pragma config DEBUG = ON
00048         #else
00049             #pragma config DEBUG = OFF
00050         #endif
00051         #pragma config XINST = OFF  // Instruction set extension and Indexed Addressing mode disabled
00052         #pragma config STVR = OFF   // Reset on stack overflow/underflow disabled
00053         #pragma config WDT = OFF    // WDT disabled (control is placed on SWDTEN bit)
00054         #pragma config CP0 = OFF    // Program memory is not code-protected
00055         #pragma config FCMEN = OFF  // Fail-Safe Clock Monitor disabled
00056         #pragma config IESO = OFF   // Two-Speed Start-up disabled
00057         #pragma config FOSC2 = ON   // Clock selected by FOSC1:FOSC0 as system clock is enabled when OSCCON<1:0> = 00
00058         #pragma config ETHLED = ON  // RA0/RA1 are multiplexed with LEDA/LEDB when Ethernet module is enabled and function as I/O when Ethernet is disabled
00059         #pragma config FOSC = HSPLL // HSPLL oscillator (eWicht runs with max. speed)
00060         #pragma config WDTPS = 1    // Watchdog prescaler 1:1
00061     #endif
00062
00063
00065 // Global variables
00067
00068     PROTO WORD u16GlobalFlags;
00069         #define FACRES_MASK         0x0001 // Factory reset requested...
00070         #define SHUTDOWN_MASK       0x0002 // Shut down of eWicht is pending...
00071         #define RESTART_MASK        0x0004 // Restart of eWicht is pending...
00072         #define BOOTLOADER_MASK     0x0008 // Enter boot mode after restart...
00073         #define LINKISUP_MASK       0x0010 // Indicates a up link (stack task execution)
00074
00075
00077 // Platform specific information defines
00079
00080 #define GetSystemClock()        (41666667ul)      // Hz
00081 #define GetInstructionClock()   (GetSystemClock()/4)
00082 #define GetPeripheralClock()    GetInstructionClock()
00083
00084 #undef PROTO    // #ifndef MAIN_H
00085
00086 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: mdns.c Source File

mdns.c

Go to the documentation of this file.
00001
00002
00003
00014
00015
00016
00017
00018 #define MDNS_C
00019
00020
00022 // Includes
00024
00025 #include "TCPIP.h"
00026 #include "mdns.h"
00027
00028
00030 // Local defines
00032
00033 // Thats the maximum interval for an MDNS resolve. The resolve message is
00034 // repeated starting with 1 second interval and doubling each time until this
00035 // maximum interval is reached.
00036 #define MAXREPEAT_INTERVAL (TICK_HOUR)
00037
00038 // The predefined TTLs are used in the DNS entries...
00039 #define DNS_DEFAULT_TTL 120ul   // In seconds...
00040 #define DNS_RR_TTL      4500ul  // In seconds...
00041
00042 // Some special label identifiers...
00043 #define DNS_ROOT_LABEL          (0xFF)
00044 #define DNS_UNSPECIFIED_LABEL   (0xFF)
00045
00046
00047 // Indices for dynamic label list entries.
00048 #define TCP_SERVICE_NAME_IDX    (14)
00049 #define QUERY_SERVICE_NAME_IDX  (15)
00050 #define QUERY_NAME_IDX          (16)
00051
00052
00053 // Count of labels and DNS entries stored here (see the lists below).
00054 #define DNS_ENTRIES (sizeof(_asDNSEntries)/sizeof(DNS_ENTRY))
00055 #define DNS_LABELS (sizeof(_asROMLabelList)/sizeof(ROM char *))
00056
00057
00058 // This define sets the number of probe entries (from index zero to this
00059 // number). The probe packets include only this entries:
00060 #define DNS_PROBE_ENTRIES   2
00061
00062 // This define sets the number of goodbye entries (counted from the last
00063 // index downwards).
00064 #define DNS_GOODBYE_ENTRIES 1
00065
00066 // Needed maximum string length (must be greater than the maximum stored name
00067 // in the DNS entry table.
00068 #define MAX_DNS_NAME_LEN    100
00069
00070
00072 // Local typedefs
00074
00075 // Internal MDNS states
00076 typedef enum
00077 {
00078     MDNS_STOPPED = 0,
00079     MDNS_WAIT_FOR_PROBING,
00080     MDNS_SECOND_PROBE,
00081     MDNS_THIRD_PROBE,
00082     MDNS_FIRST_ANNOUNCING,
00083     MDNS_SECOND_ANNOUNCING,
00084     MDNS_THIRD_ANNOUNCING,
00085     MDNS_FOURTH_ANNOUNCING,
00086     MDNS_FIFTH_ANNOUNCING,
00087     MDNS_IDLE
00088 } SM_MDNS;
00089
00090 // Internal MDNS Responder states
00091 typedef enum
00092 {
00093     MDNSR_STOPPED = 0,
00094     MDNSR_SERVICE,
00095     MDNSR_NAME,
00096     MDNSR_RESOLVED
00097 } SM_MDNSR;
00098
00099
00100 // Header of the (M)DNS message
00101 typedef struct _DNS_HEADER
00102 {
00103     WORD_VAL TransactionID;
00104     WORD_VAL Flags;
00105     WORD_VAL Questions;
00106     WORD_VAL Answers;
00107     WORD_VAL AuthoritativeRecords;
00108     WORD_VAL AdditionalRecords;
00109 } DNS_HEADER;
00110
00111 // Structure of one DNS entry.
00112 typedef struct
00113 {
00114     BYTE        u8FirstLabelIdx;
00115     WORD_VAL    u16Type;
00116     DWORD_VAL   u32TTL;
00117     WORD_VAL    u16DataLength;
00118     void *      pData;
00119     BYTE        u8DNSFirstLabelIdx;
00120     BYTE        u8NumberOfAddRRs;
00121     ROM char *  pAddRRList;
00122     BOOL        bUnique;
00123 } DNS_ENTRY;
00124
00125 // Single chain link structure for DNS names (pointer to the higher DNS tree
00126 // hierarchy) which are located in flash.
00127 typedef struct
00128 {
00129     ROM char *  pLabel; // Pointer to a DNS label (maximum 63 bytes) as string.
00130     BYTE        u8PrevIndex;    // 0xFF if root
00131 } DNS_ROMLABEL;
00132
00133
00134 // Simple structure for DNS names located in RAM (dynamic labels).
00135 typedef struct
00136 {
00137     char *  pLabel;
00138 } DNS_RAMLABEL;
00139
00140 // With this structure an DNS query (consisting of DNS name and type qualifier)
00141 // is described. The structure is therefore used for sending queries.
00142 typedef struct
00143 {
00144     BYTE        u8FirstLabelIdx;
00145     WORD_VAL    u16Type;
00146 } DNS_QUERY;
00147
00148 // This structures describes the architeture of an DNS service record.
00149 typedef struct
00150 {
00151     WORD_VAL    u16Priority;
00152     WORD_VAL    u16Weight;
00153     WORD_VAL    u16Port;
00154 } SRV_ENTRY;
00155
00156 // Control fields for processing received queries and answers.
00157 typedef struct
00158 {
00159     BYTE bAnswer : 1;
00160     BYTE bUCAnswer : 1;
00161     BYTE bAdditional : 1;
00162 } DNS_CONTROL;
00163
00164
00166 // Local Variables
00168
00169 // Internal MDNS state machine
00170 static SM_MDNS _eSM_MDNS = MDNS_STOPPED;
00171 static UDP_SOCKET _sMDNSMCSocket = INVALID_UDP_SOCKET;
00172 static DWORD _u32MdnsTimer;
00173
00174
00176 // Variables for resolving services and names
00177
00178 static BYTE _au8QuerySrvName[17];
00179 static SRV_ENTRY _sQuerySrv;
00180 static BYTE _au8QueryName[64];
00181 static BYTE _au8QueryIP[4];
00182 static DWORD _u32RetryTimer;
00183 static DWORD _u32IntervalTime;
00184 static SM_MDNSR _eSMResolver = MDNSR_STOPPED;
00185
00186
00187
00189 // Lists for ROM and RAM DNS label storage
00190
00191 // The list stores all known labels and forms a DNS tree due the single chain
00192 // link mechanism. ROM Labels which consits of a single byte equal or greater
00193 // '0x80' are pointer to the dynamic label list (_asRAMLabelList). In case the
00194 // processing function looks up such a value, it can simple substract '0x80' to
00195 // get the index for _asRAMLabelList.
00196 ROM DNS_ROMLABEL _asROMLabelList[] =
00197 {
00198 // 0
00199     {HOSTNAME, 1},
00200 // 1
00201     {(ROM BYTE *) "local", DNS_ROOT_LABEL},
00202 // 2
00203     {(ROM BYTE *) "_http", 3},
00204 // 3
00205     {(ROM BYTE *) "_tcp", 1},
00206 // 4
00207     {(ROM BYTE *) "in-addr", 5},
00208 // 5
00209     {(ROM BYTE *) "arpa", DNS_ROOT_LABEL},
00210 // 6
00211     {(ROM BYTE *) "_services", 7},
00212 // 7
00213     {(ROM BYTE *) "_dns-sd", 8},
00214 // 8
00215     {(ROM BYTE *) "_udp", 1},
00216 // 9
00217     {(ROM BYTE *) "\x80", 4},
00218 // 10
00219     {(ROM BYTE *) "\x81", 9},
00220 // 11
00221     {(ROM BYTE *) "\x82", 10},
00222 // 12
00223     {(ROM BYTE *) "\x83", 11},
00224 // 13
00225     {HOSTNAME, 2},
00226 // 14 (TCP_QUERY_SERVICE_IDX) -> _pQuerySrv
00227     {(ROM BYTE *) "\x84", 3},
00228 // 15 (QUERY_SERVICE_NAME_IDX) -> _pQueryName
00229     {(ROM BYTE *) "\x85", 14},
00230 // 16 (QUERY_NAME_IDX) -> _pQueryName
00231     {(ROM BYTE *) "\x85", 1},
00232 };
00233
00234
00235
00236 // Buffer for the (dynamic) IP label:
00237 static BYTE _u8IPbuf[16];
00238
00239
00240 // This list stores all dynamic labels. This labels are located in RAM, the
00241 // pointers to this locations are stored here. Due the ROM label mechanism
00242 // this list is part of the ROM label list (see documenation of
00243 // _asROMLabelList).
00244 ROM DNS_RAMLABEL _asRAMLabelList[] =
00245 {
00246     _u8IPbuf,
00247     &_u8IPbuf[4],
00248     &_u8IPbuf[8],
00249     &_u8IPbuf[12],
00250     _au8QuerySrvName,
00251     _au8QueryName,
00252 };
00253
00254
00256 // DNS entry table
00257 // Each entry is a unique key value entry. The key consists of name and type.
00258
00259 // This a simple placeholder for a DNS name with zero length. Zero length label
00260 // must store at least the zero for the root.
00261 static BYTE _u8ZeroLength = 0;
00262
00263 // This service entry for the eWicht HTTP service is used by the DNS entry
00264 // table.
00265 static SRV_ENTRY _sHttpService = {0,0,0x5000};  // htons(80)=0x5000
00266
00267
00268 ROM DNS_ENTRY _asDNSEntries[] =
00269 {
00270     // hostname.local. A -> Local IP Address
00271     {0, DNS_TYPE_A, DNS_DEFAULT_TTL, 4, (void *) &sIPConfig.MyIPAddr,
00272         DNS_UNSPECIFIED_LABEL, 0, 0, TRUE},
00273
00274     // hostname._http._tcp.local. SRV -> hostname.local.
00275     {13, DNS_TYPE_SRV, DNS_DEFAULT_TTL, sizeof(SRV_ENTRY), &_sHttpService,
00276         0, 1, (ROM BYTE *) "\x000", TRUE},
00277
00278     // ipaddr.in-addr.arpa. PTR -> hostname.local.
00279     {12, DNS_TYPE_PTR, DNS_DEFAULT_TTL, 0, 0, 0, 0, 0, TRUE},
00280
00281     // _services._dns-sd._udp.local. PTR -> PTR
00282     {6, DNS_TYPE_PTR, DNS_RR_TTL, 0, 0, 2, 0, 0, FALSE},
00283
00284     // hostname._http._tcp.local. TXT -> hostname.local.
00285     {13, DNS_TYPE_TXT, DNS_RR_TTL, 1, (void *) &_u8ZeroLength,
00286         DNS_UNSPECIFIED_LABEL, 1, (ROM BYTE *) "\x000", TRUE},
00287
00288     // _http._tcp.local. PTR -> hostname._http._tcp.local.
00289     {2, DNS_TYPE_PTR, DNS_RR_TTL, 0, 0,
00290         13, 3, (ROM BYTE *) "\x000\x001\x004", FALSE}
00291 };
00292
00293
00294
00296 // Control structures and variables for processing and sending frames.
00297
00298 static WORD_VAL _au16SendEntries[DNS_LABELS];
00299 static DNS_CONTROL _sControl[DNS_ENTRIES];
00300 static BYTE _u8UniqueEntries;
00301
00302
00303
00305 // Local function prototypes
00307
00308 static void _PutQuery(BOOL bProbe, BOOL bQU, DNS_QUERY * pQuery);
00309 static BOOL _PrepareMulticast(BYTE nQueries, BYTE nAnswers,
00310                                          BYTE nAuthoritives, BYTE nAdditional);
00311 static void _SendRRList(BYTE nEntries, ROM DNS_ENTRY * pRRList, BOOL bGoodbye);
00312 static void _PutDNSName(BYTE u8StartIndex);
00313 static BYTE _u8GetDNSNameLength(BYTE u8LabelIndex);
00314 static void _GetQueryData(WORD_VAL * psType, WORD_VAL * psClass);
00315 static void _QueryLookUp(void);
00316 static void _AnswerLookUp(BOOL bQuery);
00317 BYTE _u8GetRRData(WORD_VAL * pType, WORD_VAL * pClass);
00318 BYTE _u8GetStartLabelFromFrame(void);
00319 void _CheckForQueryResponse(WORD_VAL u16Type, WORD_VAL * pu16Length,
00320                                                             BYTE u8Startlabel);
00321
00323 // Implementation
00325
00330 BOOL bInitMDNSResponder(void)
00331 {
00332     BYTE i = 0;
00333     NODE_INFO nodeInfo;
00334
00335     // Prepare multicast address data for the frame.
00336     nodeInfo.MACAddr.v[0]= 0x01;
00337     nodeInfo.MACAddr.v[1]= 0x00;
00338     nodeInfo.MACAddr.v[2]= 0x5e;
00339     nodeInfo.MACAddr.v[3]= 0x00;
00340     nodeInfo.MACAddr.v[4]= 0x00;
00341     nodeInfo.MACAddr.v[5]= 0xfb;
00342     nodeInfo.IPAddr.v[0] = 224;
00343     nodeInfo.IPAddr.v[1] = 0;
00344     nodeInfo.IPAddr.v[2] = 0;
00345     nodeInfo.IPAddr.v[3] = 251;
00346
00347     _eSM_MDNS = MDNS_STOPPED;
00348
00349     _sMDNSMCSocket = UDPOpen(MDNS_PORT, &nodeInfo, MDNS_PORT);
00350
00351     if(_sMDNSMCSocket == INVALID_UDP_SOCKET)
00352         return FALSE;
00353
00354     // Determine the count of unique DNS entries (no PTR records!)
00355     _u8UniqueEntries = 0;
00356     for (i=0; i < DNS_ENTRIES; i++)
00357     {
00358         if ((_asDNSEntries[i].u16Type.Val != DNS_TYPE_PTR)&&
00359             (_asDNSEntries[i].bUnique==TRUE))
00360                 _u8UniqueEntries++;
00361     }
00362
00363     return TRUE;
00364 }
00365
00368
00369 void StartMDNSResponder(void)
00370 {
00371     BYTE i = 0;
00372
00373     MDNSStopResolving();
00374
00375     // Prepare the IP labels!
00376     for (i=0;i<4;i++)
00377         sprintf(&_u8IPbuf[i<<2], "%u", sIPConfig.MyIPAddr.v[i]);
00378
00379     // Start probing the DNS entries like described in the Multicast DNS
00380     // internet draft chapter 9.1.
00381
00382     _u32MdnsTimer = TickGet() + (rand() % ((DWORD)(TICKS_PER_SECOND >> 2)));
00383     _eSM_MDNS = MDNS_WAIT_FOR_PROBING;
00384
00385 /*
00386     From mDNS draft:
00387     When ready to send its mDNS probe packet(s) the host should first
00388     wait for a short random delay time, uniformly distributed in the
00389     range 0-250ms. This random delay is to guard against the case where a
00390     group of devices are powered on simultaneously, or a group of devices
00391     are connected to an Ethernet hub which is then powered on, or some
00392     other external event happens that might cause a group of hosts to all
00393     send synchronized probes.
00394 */
00395 }
00396
00399
00400 void StopMDNSResponder(void)
00401 {
00402     // Stop any pending queries...
00403     MDNSStopResolving();
00404
00405     if (_eSM_MDNS > MDNS_THIRD_PROBE)
00406     {
00407         // As seen in the Bonjour traces, we only send entries in the goodbye
00408         // packet which are shared entries which point to unique entries.
00409         _PrepareMulticast(0, DNS_GOODBYE_ENTRIES, 0, 0);
00410         _SendRRList(DNS_GOODBYE_ENTRIES,
00411                 &_asDNSEntries[DNS_ENTRIES-DNS_GOODBYE_ENTRIES],
00412                 TRUE);
00413         UDPFlush();
00414     }
00415
00416     _eSM_MDNS = MDNS_STOPPED;
00417 }
00418
00421
00422 MDNS_STATE eGetMDNSState(void)
00423 {
00424     if (_eSM_MDNS == MDNS_STOPPED)
00425         return MDNS_HAS_STOPPED;
00426     else if (_eSM_MDNS > MDNS_FIRST_ANNOUNCING)
00427         return MDNS_IS_RUNNING;
00428     else
00429         return MDNS_IS_STARTING_UP;
00430 }
00431
00434
00435 void MDNSResponder()
00436 {
00437     BOOL bSendUnicast = TRUE;
00438     BYTE i=0;
00439
00440     switch(_eSM_MDNS)
00441     {
00442     case MDNS_STOPPED:
00443         break;
00444
00445     case MDNS_THIRD_PROBE:
00446         bSendUnicast = FALSE;
00447     case MDNS_SECOND_PROBE:
00448     case MDNS_WAIT_FOR_PROBING:
00449         if (TickGet() > _u32MdnsTimer)
00450         {
00451             /*
00452             From mDNS internet draft:
00453             250ms after the first query the host should send a second, then
00454             250ms after that a third. If, by 250ms after the third probe, no
00455             conflicting Multicast DNS responses have been received, the host may
00456             move to the next step, announcing. (Note that this is the one
00457             exception from the normal rule that there should be at least one
00458             second between repetitions of the same question, and the interval
00459             between subsequent repetitions should double.)
00460             */
00461
00462             // Send a probe packet...
00463             _PrepareMulticast(DNS_PROBE_ENTRIES, 0, _u8UniqueEntries, 0);
00464
00465             for(i=0; i < DNS_PROBE_ENTRIES; i++)
00466             {
00467                 DNS_QUERY query;
00468                 query.u8FirstLabelIdx = _asDNSEntries[i].u8FirstLabelIdx;
00469                 query.u16Type = _asDNSEntries[i].u16Type;
00470                 _PutQuery(TRUE, bSendUnicast, &query);
00471             }
00472
00473             // Transfer the unique entries a authoritive nameserver...
00474             for (i=0; i < DNS_ENTRIES; i++)
00475             {
00476                 if((_asDNSEntries[i].bUnique==TRUE)&&
00477                    (_asDNSEntries[i].u16Type.Val != DNS_TYPE_PTR))
00478                 {
00479                     _SendRRList(1, &_asDNSEntries[i], FALSE);
00480                 }
00481             }
00482             UDPFlush();
00483
00484             _u32MdnsTimer += (DWORD)(TICKS_PER_SECOND >> 2);
00485             _eSM_MDNS++;
00486         }
00487         break;
00488
00489     case MDNS_FIRST_ANNOUNCING:
00490     case MDNS_SECOND_ANNOUNCING:
00491     case MDNS_THIRD_ANNOUNCING:
00492     case MDNS_FOURTH_ANNOUNCING:
00493     case MDNS_FIFTH_ANNOUNCING:
00494         if (TickGet() > _u32MdnsTimer)
00495         {
00496             /* From mDNS internet draft:
00497             The Multicast DNS Responder MUST send at least two gratuitous
00498             responses, one second apart. A Responder MAY send up to eight
00499             gratuitous Responses, provided that the interval between gratuitous
00500             responses doubles with every response sent. */
00501
00502             // Send an announce packet...
00503             _PrepareMulticast(0, DNS_ENTRIES, 0, 0);
00504             _SendRRList(DNS_ENTRIES, _asDNSEntries, FALSE);
00505             UDPFlush();
00506
00507             _u32MdnsTimer += (TICKS_PER_SECOND)*
00508                                          (1<<(_eSM_MDNS-(MDNS_FIRST_ANNOUNCING)));
00509             _eSM_MDNS++;
00510         }
00511         break;
00512     }
00513
00514     if((_eSM_MDNS > MDNS_FIRST_ANNOUNCING)&&
00515        ((_eSMResolver == MDNSR_SERVICE) || (_eSMResolver == MDNSR_NAME)))
00516     {
00517         if (TickGet() > _u32RetryTimer)
00518         {
00519             if (_u32IntervalTime<MAXREPEAT_INTERVAL)
00520                 _u32IntervalTime = _u32IntervalTime << 1;
00521
00522             _u32RetryTimer += _u32IntervalTime;
00523             if (_eSMResolver == MDNSR_SERVICE)
00524                 MDNSResolveService(0, 0);
00525             else
00526                 MDNSResolveName(0);
00527         }
00528     }
00529 }
00530
00533
00534 void MDNSProcessFrame(NODE_INFO *remoteNode, IP_ADDR *localIP)
00535 {
00536     DNS_HEADER head;
00537     BYTE i;
00538
00539     // Multicast-IP 224.0.0.251 regardless of source IP OR
00540     // same subnet of local IP and source IP
00541     if ((localIP->Val != 0xFB0000E0ul) &&
00542         ((remoteNode->IPAddr.Val & sIPConfig.MyMask.Val) !=
00543          (sIPConfig.MyIPAddr.Val & sIPConfig.MyMask.Val)))
00544     {
00545         return;
00546     }
00547
00548
00549     // The following function call should always return TRUE!!!
00550     if (!UDPIsGetReady(_sMDNSMCSocket))
00551         return;
00552
00553     // Received a frame to process. Prepare status fields:
00554     memset(_sControl, 0, sizeof(_sControl));
00555
00556
00557     // ToDo: Add unicast support here!
00558     // It is recommended feature of the mDNS internet draft (chapter 6) to
00559     // answer as a unicast frame on unicast queries. It is not mandatory!
00560     // All informations are available here to generate a unicast answer easily.
00561
00562
00563
00564
00565     // Retrieve the DNS header and de-big-endian it
00566
00567     // MDNS ignores the Query ID field (except for generating legacy responses)
00568     UDPGet(&head.TransactionID.v[1]);
00569     UDPGet(&head.TransactionID.v[0]);
00570
00571     UDPGet(&head.Flags.v[1]);
00572     UDPGet(&head.Flags.v[0]);
00573
00574     UDPGet(&head.Questions.v[1]);
00575     UDPGet(&head.Questions.v[0]);
00576     UDPGet(&head.Answers.v[1]);
00577     UDPGet(&head.Answers.v[0]);
00578     UDPGet(&head.AuthoritativeRecords.v[1]);
00579     UDPGet(&head.AuthoritativeRecords.v[0]);
00580     UDPGet(&head.AdditionalRecords.v[1]);
00581     UDPGet(&head.AdditionalRecords.v[0]);
00582
00583
00584     if (head.Flags.Val == 0)
00585     {
00586         // Standard query received. Maybe we can response it?
00587         BYTE j, answers = 0, additional = 0;
00588
00589         // The responder only processes frames after probing is successfull.
00590         if (_eSM_MDNS < MDNS_SECOND_ANNOUNCING)
00591             goto MDNSProcessEnd;
00592
00593         // We only reply to requests with at least one query.
00594         if (head.Questions.Val == 0)
00595             goto MDNSProcessEnd;
00596
00597         while(head.Questions.Val--)
00598         {
00599             // Check all questions for known answers!
00600             _QueryLookUp();
00601         }
00602
00603         while(head.Answers.Val--)
00604         {
00605             // Check all answers for known answers!
00606             _AnswerLookUp(TRUE);
00607         }
00608
00609         // count the valid answers...
00610         for(i = 0; i < DNS_ENTRIES; i++)
00611         {
00612             if (_sControl[i].bAnswer == TRUE)
00613             {
00614                 answers++;
00615
00616                 // Mark the additional records!
00617                 // (see dns-sd internet draft chapter 13)
00618                 for(j = 0; j < _asDNSEntries[i].u8NumberOfAddRRs; j++)
00619                 {
00620                     BYTE add = _asDNSEntries[i].pAddRRList[j];
00621                     if (_sControl[add].bAnswer == FALSE)
00622                         _sControl[add].bAdditional = TRUE;
00623                 }
00624             }
00625         }
00626
00627         // count the valid additional fields...
00628         for(i = 0; i < DNS_ENTRIES; i++)
00629         {
00630             if (_sControl[i].bAdditional == TRUE)
00631                 additional++;
00632         }
00633
00634         if (answers)
00635         {
00636             // Send an answer packet...
00637             _PrepareMulticast(0, answers, 0, additional);
00638
00639             for(i = 0; i < DNS_ENTRIES; i++)
00640             {
00641                 if (_sControl[i].bAnswer == TRUE)
00642                     _SendRRList(1, &_asDNSEntries[i], FALSE);
00643             }
00644
00645             if (additional)
00646             {
00647                 for(i = 0; i < DNS_ENTRIES; i++)
00648                 {
00649                     if (_sControl[i].bAdditional == TRUE)
00650                         _SendRRList(1, &_asDNSEntries[i], FALSE);
00651                 }
00652             }
00653
00654             UDPFlush();
00655         }
00656     }
00657     else if (head.Flags.Val & 0x8000)
00658     {
00659         // Response received.
00660
00661         // 1.1 Compare all answers (TYPE and NAME) with our local DNS entry
00662         // list. If the found matches include unique entries, there is a
00663         // conflict on the network! The service will be stopped.
00664
00665         // 1.2 If a DNS query is pending, save the matching answer to a
00666         // answer list.
00667
00668         while(head.Answers.Val--)
00669             _AnswerLookUp(FALSE);
00670
00671         while(head.AuthoritativeRecords.Val--)
00672             _AnswerLookUp(FALSE);
00673
00674         while(head.AdditionalRecords.Val--)
00675             _AnswerLookUp(FALSE);
00676
00677         // Look for found answers which are ambiguous!
00678         for(i = 0; i < DNS_ENTRIES; i++)
00679         {
00680             if (_sControl[i].bAnswer == TRUE)
00681                 break;
00682         }
00683
00684         // Ambiguity is very bad and leads to a stopped MDNS service!
00685         if (i != DNS_ENTRIES)
00686             StopMDNSResponder();
00687
00688     }
00689
00690 MDNSProcessEnd:
00691     UDPDiscard();
00692 }
00693
00696
00697 BOOL bMDNSNameIsResolved(IP_ADDR * pIP)
00698 {
00699     if (_eSMResolver != MDNSR_RESOLVED)
00700         return FALSE;
00701     memcpy(pIP,(void *)_au8QueryIP, 4);
00702     return TRUE;
00703 }
00704
00707
00708 BOOL bMDNSServiceIsResolved(IP_ADDR * pIP, WORD_VAL * pu16Port)
00709 {
00710     if (bMDNSNameIsResolved(pIP) == TRUE)
00711     {
00712         *pu16Port = _sQuerySrv.u16Port;
00713         return TRUE;
00714     }
00715     return FALSE;
00716 }
00717
00720
00721 void MDNSStopResolving(void)
00722 {
00723     _eSMResolver = MDNSR_STOPPED;
00724 }
00725
00728
00729 void MDNSResolveName(char * pName)
00730 {
00731     DNS_QUERY query;
00732
00733     // Copy the name to query in dynamic query field.
00734     if (pName)
00735     {
00736         // Initial query!
00737         strcpy(_au8QueryName, pName);
00738         _u32RetryTimer = TickGet() + TICKS_PER_SECOND;
00739         _u32IntervalTime = TICKS_PER_SECOND;
00740     }
00741
00742     query.u16Type.Val = DNS_TYPE_A;
00743     query.u8FirstLabelIdx = QUERY_NAME_IDX;
00744
00745     _PrepareMulticast(1, 0, 0, 0);
00746     _PutQuery(FALSE, FALSE, &query);
00747
00748     UDPFlush();
00749
00750     _eSMResolver = MDNSR_NAME;
00751 }
00752
00755
00756 void MDNSResolveService(char * pName, ROM char * pServiceName)
00757 {
00758     DNS_QUERY query;
00759
00760     // Copy the name and the service to query in dynamic query field.
00761     if (pName)
00762     {
00763         // Initial query
00764         strcpypgm2ram(_au8QuerySrvName, pServiceName);
00765         strcpy(_au8QueryName, pName);
00766         _u32RetryTimer = TickGet() + TICKS_PER_SECOND;
00767         _u32IntervalTime = TICKS_PER_SECOND;
00768     }
00769
00770     query.u16Type.Val = DNS_TYPE_SRV;
00771     query.u8FirstLabelIdx = QUERY_SERVICE_NAME_IDX;
00772
00773     _PrepareMulticast(1, 0, 0, 0);
00774     _PutQuery(FALSE, FALSE, &query);
00775
00776     UDPFlush();
00777
00778     _eSMResolver = MDNSR_SERVICE;
00779 }
00780
00783
00784 static BYTE _u8GetDNSNameLength(BYTE u8LabelIndex)
00785 {
00786     BYTE i=0;
00787
00788     while(u8LabelIndex != DNS_ROOT_LABEL)
00789     {
00790         ROM BYTE * pRomLabel = _asROMLabelList[u8LabelIndex].pLabel;
00791
00792         if (_au16SendEntries[u8LabelIndex].Val)
00793         {
00794             // Message compression field.
00795             i+=2;
00796             return i;
00797         }
00798
00799         // Add one length byte for the length field
00800         i++;
00801         if (*pRomLabel & 0x80)
00802         {
00803             // Pointer to a RAM-Label.
00804             BYTE ramidx = (*pRomLabel) & 0x7F;
00805             BYTE * pRamLabel = _asRAMLabelList[ramidx].pLabel;
00806
00807             // Put the length...
00808             i += strlen(pRamLabel);
00809         }
00810         else
00811             i += strlenpgm(pRomLabel);
00812
00813         u8LabelIndex = _asROMLabelList[u8LabelIndex].u8PrevIndex;
00814     }
00815
00816     // Add the root label length indicator.
00817     return i++;
00818 }
00819
00822
00823 static void _PutDNSName(BYTE u8LabelIndex)
00824 {
00825     while(u8LabelIndex != DNS_ROOT_LABEL)
00826     {
00827         ROM BYTE * pRomLabel = _asROMLabelList[u8LabelIndex].pLabel;
00828
00829         if (_au16SendEntries[u8LabelIndex].Val)
00830         {
00831             // DNS name already sent via UDP (Do message compression).
00832             UDPPut(0xc0 | (_au16SendEntries[u8LabelIndex].v[1]));
00833
00834             // Insert the position.
00835             UDPPut(_au16SendEntries[u8LabelIndex].v[0]);
00836             return;
00837         }
00838         else
00839         {
00840             // Save the offset for message compression:
00841             _au16SendEntries[u8LabelIndex].Val = UDPGetPutOffset();
00842
00843             if (*pRomLabel & 0x80)
00844             {
00845                 // Pointer to a RAM-Label.
00846                 BYTE ramidx = (*pRomLabel) & 0x7F;
00847                 BYTE * pRamLabel = _asRAMLabelList[ramidx].pLabel;
00848
00849                 // Put the length...
00850                 UDPPut(strlen(pRamLabel));
00851
00852                 UDPPutString(pRamLabel);
00853             }
00854             else
00855             {
00856                 // Pointer to a ROM-Label.
00857
00858                 // Put the length...
00859                 UDPPut(strlenpgm(pRomLabel));
00860
00861                 UDPPutROMString(pRomLabel);
00862             }
00863
00864             u8LabelIndex = _asROMLabelList[u8LabelIndex].u8PrevIndex;
00865         }
00866     }
00867
00868     // Put the string terminator character
00869     UDPPut(0x00);
00870 }
00871
00874
00875 static void _GetQueryData(WORD_VAL * psType, WORD_VAL * psClass)
00876 {
00877     // Get the type from the received packet
00878     UDPGet(&psType->v[1]);
00879     UDPGet(&psType->v[0]);
00880
00881     // Get the class from the received packet
00882     UDPGet(&psClass->v[1]);
00883     UDPGet(&psClass->v[0]);
00884 }
00885
00888
00889 static void _AnswerLookUp(BOOL bQuery)
00890 {
00891     BYTE startlabel=0, i=0;
00892     WORD j=0;
00893     WORD_VAL type=0, class=0;
00894     WORD_VAL length, locallength;
00895     DWORD_VAL ttl = 0;
00896     BOOL bKeyMatch = FALSE;
00897     BOOL bEntryMatch = FALSE;
00898
00899     // 1) Get the start label from the frame...
00900     startlabel = _u8GetRRData(&type, &class);
00901
00902
00903     // 2) Read out the rest of the answer section...
00904     UDPGet(&ttl.v[3]);
00905     UDPGet(&ttl.v[2]);
00906     UDPGet(&ttl.v[1]);
00907     UDPGet(&ttl.v[0]);
00908
00909     UDPGet(&length.v[1]);
00910     UDPGet(&length.v[0]);
00911
00912
00913     // 3) Unknown DNS name: Stop the processing.
00914     if (startlabel == DNS_UNSPECIFIED_LABEL)
00915     {
00916         // read out the payload and throw it away
00917         UDPGetArray(NULL, length.Val);
00918         return;
00919     }
00920
00921
00922     // 4) Get the DNS entry for the found name/type key.
00923     for(i=0; i < DNS_ENTRIES; i++)
00924     {
00925         if ((_asDNSEntries[i].u8FirstLabelIdx == startlabel)&&
00926             (_asDNSEntries[i].u16Type.Val == type.Val))
00927         {
00928             bKeyMatch = TRUE;
00929             locallength.Val =
00930                       _u8GetDNSNameLength(_asDNSEntries[i].u8DNSFirstLabelIdx);
00931
00932             if(length.Val != _asDNSEntries[i].u16DataLength.Val+locallength.Val)
00933                 break;
00934
00935             // Check the payload for equality!
00936             for (j=0; j<_asDNSEntries[i].u16DataLength.Val; j++)
00937             {
00938                 BYTE tmp = 0;
00939                 UDPGet(&tmp);
00940                 length.Val--;
00941                 if (tmp!=((BYTE *)(_asDNSEntries[i].pData))[j])
00942                     break;
00943             }
00944
00945             if (j!=_asDNSEntries[i].u16DataLength.Val)
00946                 break;
00947
00948             if ((_asDNSEntries[i].u8DNSFirstLabelIdx!=DNS_UNSPECIFIED_LABEL)&&
00949                 (_u8GetStartLabelFromFrame() !=
00950                                           _asDNSEntries[i].u8DNSFirstLabelIdx))
00951             {
00952                 // _u8GetStartLabelFromFrame() reads out the hole name:
00953                 // No payload is left?! Check this out!
00954                 length.Val = 0;
00955                 break;
00956             }
00957
00958             // Like described in mDNS internet draft (chapter 7.1 Known Answer
00959             // Suppression): Check the TTL of an received possible answer. If
00960             // the entry is to old, send a new answer.
00961             if ((_asDNSEntries[i].u32TTL.Val >> 1)<ttl.Val)
00962             {
00963                 // Thats our answer. Surpress it in a answer packet!
00964                 _sControl[i].bAnswer = FALSE;
00965             }
00966
00967             bEntryMatch = TRUE;
00968             break;
00969         }
00970     }
00971
00972     // Look, if it is a answer for a running query...
00973     if ((bQuery==FALSE)&&(bKeyMatch==FALSE))
00974         _CheckForQueryResponse(type, &length, startlabel);
00975
00976
00977     // read out the rest of the answer RR.
00978     if (length.Val)
00979         UDPGetArray(NULL,length.Val);
00980
00981     // Check the uniqueness of the found DNS entry!
00982     if ((bQuery==FALSE)&&(bKeyMatch==TRUE)&&(_asDNSEntries[i].bUnique==TRUE))
00983     {
00984         // Thats a ambiguous DNS entry! Mark it for the calling function.
00985         _sControl[i].bAnswer = TRUE;
00986     }
00987     return;
00988 }
00989
00992
00993 static void _QueryLookUp(void)
00994 {
00995     BYTE labellen = 0;
00996     BYTE namelen = 0;
00997     BYTE startlabel = 0, j = 0;
00998     WORD_VAL type = 0, class = 0;
00999
01000     // 1) Get the start label from the frame.
01001     startlabel = _u8GetRRData(&type, &class);
01002     if (startlabel == DNS_UNSPECIFIED_LABEL)
01003         return;
01004
01005
01006     // 2) Get the DNS entry for the found label row
01007     for(j=0; j < DNS_ENTRIES; j++)
01008     {
01009         if ((_asDNSEntries[j].u8FirstLabelIdx == startlabel)&&
01010             ((_asDNSEntries[j].u16Type.Val == type.Val) ||
01011              (type.Val == DNS_TYPE_ANY)))
01012         {
01013             // We know the answer!
01014             _sControl[j].bAnswer = TRUE;
01015
01016             // Is a unicast reponse requested?
01017             if (class.v[1] & 0x80)
01018                 _sControl[j].bUCAnswer = TRUE;
01019         }
01020     }
01021
01022     return;
01023 }
01024
01027
01028 BYTE _u8GetRRData(WORD_VAL * pType, WORD_VAL * pClass)
01029 {
01030     BYTE label = _u8GetStartLabelFromFrame();
01031     _GetQueryData(pType, pClass);
01032
01033     // Check the class (only internet class is supported)
01034     if ((pClass->Val & 0x7FFF) != 0x0001)
01035         return DNS_UNSPECIFIED_LABEL;
01036
01037     return label;
01038 }
01039
01042
01043 void _CheckForQueryResponse(WORD_VAL u16Type, WORD_VAL * pu16Length,
01044                                                              BYTE u8Startlabel)
01045 {
01046     if ((u16Type.Val==DNS_TYPE_SRV)&&
01047         (_eSMResolver == MDNSR_SERVICE)&&
01048         (u8Startlabel == QUERY_SERVICE_NAME_IDX))
01049     {
01050         // Service query is running and is resolved.
01051         BYTE labellen;
01052
01053         // Name query is running and is resolved.
01054         UDPGet(&_sQuerySrv.u16Priority.v[1]);
01055         UDPGet(&_sQuerySrv.u16Priority.v[0]);
01056         UDPGet(&_sQuerySrv.u16Weight.v[1]);
01057         UDPGet(&_sQuerySrv.u16Weight.v[0]);
01058         UDPGet(&_sQuerySrv.u16Port.v[1]);
01059         UDPGet(&_sQuerySrv.u16Port.v[0]);
01060
01061         pu16Length->Val = pu16Length->Val - sizeof(SRV_ENTRY);
01062
01063         UDPGet(&labellen);
01064         if (labellen & 0xc0)
01065         {
01067             /*
01068             WORD_VAL pos;
01069             pos.v[1] = labellen & 0x3F;
01070             UDPGet(&pos.v[0]);
01071             labellen++;
01072             */
01073         }
01074         else
01075             UDPGetArray(_au8QueryName, labellen);
01076
01077         _au8QueryName[labellen] = 0;    // Terminate the string.
01078         pu16Length->Val-= labellen+1;   // Correct the length field.
01079
01080         // Start resolving the found name...
01081         _u32RetryTimer = TickGet() + TICKS_PER_SECOND;
01082         _u32IntervalTime = TICKS_PER_SECOND;
01083         _eSMResolver = MDNSR_NAME;
01084         strlwr(_au8QueryName);
01085     }
01086     else if ((u16Type.Val==DNS_TYPE_A)&&
01087         (_eSMResolver == MDNSR_NAME)&&
01088         (u8Startlabel == QUERY_NAME_IDX))
01089     {
01090         // Name query is running and is resolved.
01091         UDPGetArray(_au8QueryIP, 4);
01092         pu16Length->Val = 0;
01093         _eSMResolver = MDNSR_RESOLVED;
01094     }
01095 }
01096
01099
01100 BYTE _u8GetStartLabelFromFrame(void)
01101 {
01102     BOOL bFound = FALSE;
01103     BOOL bNoSpaceLeft = FALSE;
01104     BYTE labellen = 0, namelen = 0, labelcount = 0, i, j;
01105     BYTE name[MAX_DNS_NAME_LEN];
01106     WORD_VAL udppos = u16MACGetCurrentReadPtrPos();
01107
01108     memset(name, 0, MAX_DNS_NAME_LEN);
01109
01110     // 1) Fetch complete DNS name (until pointer or root) from UDP frame.
01111     while(1)
01112     {
01113         labellen = MACGet();        // Get the length field
01114
01115         if (labellen & 0xc0)
01116         {
01117             // Message compression label
01118             WORD_VAL address;
01119             address.v[1] = labellen & 0x3F;
01120             address.v[0] = MACGet();
01121
01122             // Seek to the label position
01123             MACSetReadPtrInRx(sizeof(IP_HEADER)+sizeof(UDP_HEADER)+address.Val);
01124             continue;
01125         }
01126
01127         if (labellen == 0)
01128             // root
01129             break;
01130
01131
01132         // Is space left for more names?
01133         if ((namelen+labellen) > MAX_DNS_NAME_LEN)
01134         {
01135             // No space left...
01136             bNoSpaceLeft = TRUE;
01137             break;
01138         }
01139
01140         name[namelen++] = labellen;
01141
01142         MACGetArray(&name[namelen], labellen);
01143
01144         // DNS does not distinguish between lower and upper:
01145         strlwr(&name[namelen]);
01146
01147         namelen += labellen;
01148     }
01149
01150     // 3) Reseek
01151     MACSetCurrentReadPtrPos(udppos);
01152
01153
01154     //  4) Read out the name from the UDP frame
01155     while(UDPGet(&labellen) == TRUE)
01156     {
01157         if (labellen & 0xc0)
01158         {
01159             BYTE dummy;
01160             UDPGet(&dummy);
01161             break;
01162         }
01163         else if (labellen == 0)
01164             break;
01165
01166         UDPGetArray(NULL, labellen);
01167     }
01168
01169     if (bNoSpaceLeft == TRUE)
01170         return DNS_UNSPECIFIED_LABEL;
01171
01172
01173     // 5) Compare the local labels with the DNS labels (starting at the leafs).
01174     for(i=0; i<DNS_LABELS; i++)
01175     {
01176         BYTE index = i; // Startindex
01177         namelen = 0;
01178
01179         while(1)
01180         {
01181             ROM BYTE * pRomLabel;
01182
01183             labellen = name[namelen++];
01184             if (labellen == 0)
01185             {
01186                 // Root
01187                 if (index == DNS_ROOT_LABEL)
01188                     bFound = TRUE;
01189
01190                 break;
01191             }
01192
01193             pRomLabel = _asROMLabelList[index].pLabel;
01194             if (*pRomLabel & 0x80)
01195             {
01196                 // RAM-Label
01197                 BYTE ramidx = (*pRomLabel) & 0x7F;
01198                 BYTE * pRamLabel = _asRAMLabelList[ramidx].pLabel;
01199
01200                 if (memcmp((void*)&name[namelen],(void*) pRamLabel, labellen)!=0)
01201                     break;
01202             }
01203             else
01204             {
01205                 // ROM-Label
01206                 if (memcmppgm2ram(&name[namelen], pRomLabel, labellen)!=0)
01207                     break;
01208             }
01209
01210             index = _asROMLabelList[index].u8PrevIndex;
01211             namelen += labellen;
01212         };
01213
01214         // DNS name already found?
01215         if(bFound == TRUE)
01216             break;
01217     }
01218
01219
01220
01221     // Go back, if we have not found anything.
01222     if (bFound == FALSE)
01223         return DNS_UNSPECIFIED_LABEL;
01224
01225     return i;
01226 }
01227
01230
01231 static BOOL _PrepareMulticast(BYTE nQueries, BYTE nAnswers,
01232                                           BYTE nAuthoritives, BYTE nAdditional)
01233 {
01234     if(!UDPIsPutReady(_sMDNSMCSocket))
01235         return FALSE;
01236
01237     // Reset the message compression fields...
01238     memset(_au16SendEntries, 0, sizeof(_au16SendEntries));
01239
01240     UDPPut(0x00);   // Transaction ID is always zero in multicasts.
01241     UDPPut(0x00);
01242
01243
01244     /*
01245     Taken from Internet draft:
01246     AA (Authoritative Answer) Bit
01247
01248     In query messages, the Authoritative Answer bit MUST be zero on
01249     transmission, and MUST be ignored on reception.
01250
01251     In response messages for Multicast Domains, the Authoritative Answer
01252     bit MUST be set to one (not setting this bit implies there's some
01253     other place where "better" information may be found) and MUST be
01254     ignored on reception.
01255     */
01256
01257     if (nQueries)
01258         UDPPut(0x00);       // Standard query without recursion
01259     else
01260         UDPPut(0x84);       // Response
01261     UDPPut(0x00);
01262
01263     UDPPut(0x00);
01264     UDPPut(nQueries);       // questions
01265
01266     UDPPut(0x00);
01267     UDPPut(nAnswers);       // answers
01268
01269     UDPPut(0x00);
01270     UDPPut(nAuthoritives);      // Name server resource records.
01271     UDPPut(0x00);
01272     UDPPut(nAdditional);        // Additional records
01273
01274     return TRUE;
01275 }
01276
01279
01280 static void _SendRRList(BYTE nEntries, ROM DNS_ENTRY * pRRList, BOOL bGoodbye)
01281 {
01282     BYTE i = 0;
01283
01284     for(; i < nEntries; i++)
01285     {
01286         WORD_VAL len = 0;
01287
01288         _PutDNSName(pRRList[i].u8FirstLabelIdx);
01289
01290         // Transfer type...
01291         UDPPut(pRRList[i].u16Type.v[1]);
01292         UDPPut(pRRList[i].u16Type.v[0]);
01293
01294         // Transfer class (Internet)
01295         UDPPut(pRRList[i].bUnique<<7);
01296         UDPPut(0x01);
01297
01298         // Transfer TTL (zero if goodbye)
01299         if (bGoodbye == FALSE)
01300         {
01301             UDPPut(pRRList[i].u32TTL.v[3]);
01302             UDPPut(pRRList[i].u32TTL.v[2]);
01303             UDPPut(pRRList[i].u32TTL.v[1]);
01304             UDPPut(pRRList[i].u32TTL.v[0]);
01305         }
01306         else
01307         {
01308             UDPPut(0);
01309             UDPPut(0);
01310             UDPPut(0);
01311             UDPPut(0);
01312         }
01313
01314         // Transfer data length (first add RAM and ROM payload)
01315         len.Val = pRRList[i].u16DataLength.Val +
01316                         _u8GetDNSNameLength(pRRList[i].u8DNSFirstLabelIdx);
01317         UDPPut(len.v[1]);
01318         UDPPut(len.v[0]);
01319
01320         // Transfer the RAM payload if available...
01321         if (pRRList[i].u16DataLength.Val)
01322             UDPPutArray(pRRList[i].pData, pRRList[i].u16DataLength.Val);
01323
01324         // Transfer the DNS payload if available...
01325         if (pRRList[i].u8DNSFirstLabelIdx != DNS_ROOT_LABEL)
01326             _PutDNSName(pRRList[i].u8DNSFirstLabelIdx);
01327     }
01328 }
01329
01330
01333
01334 static void _PutQuery(BOOL bProbe, BOOL bQU, DNS_QUERY * pQuery)
01335 {
01336     BYTE i = 0;
01337     _PutDNSName(pQuery->u8FirstLabelIdx);
01338
01339     // Type...
01340     if (bProbe==TRUE)
01341     {
01342         UDPPut(DNS_TYPE_ANY>>8);
01343         UDPPut(DNS_TYPE_ANY);
01344     }
01345     else
01346     {
01347         UDPPut(pQuery->u16Type.v[1]);
01348         UDPPut(pQuery->u16Type.v[0]);
01349     }
01350
01351     // Class...
01352     /*
01353     Taken from Internet draft:
01354     Repurposing of top bit of qclass in Question Section
01355
01356     In the Question Section of a Multicast DNS Query, the top bit of the
01357     qclass field is used to indicate that unicast responses are preferred
01358     for this particular question.
01359     */
01360
01361     UDPPut(bQU<<7); // Force unicast reponse, if requested.
01362     UDPPut(0x01);   // Class: IN (Internet)
01363 }
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: mdns.h Source File

mdns.h

Go to the documentation of this file.
00001
00002
00003
00041
00042
00043
00044
00045 #ifndef MDNS_H
00046 #define MDNS_H
00047
00049 // Defines
00051
00052 #ifdef MDNS_C
00053     #define PROTO
00054 #else
00055     #define PROTO extern
00056 #endif
00057
00058
00060 #define MDNS_PORT       5353u
00061
00063 #define DNS_TYPE_A              (0x0001u)
00065 #define DNS_TYPE_PTR            (0x000cu)
00067 #define DNS_TYPE_MX             (0x000fu)
00069 #define DNS_TYPE_SRV            (0x0021u)
00071 #define DNS_TYPE_TXT            (0x0010u)
00073 #define DNS_TYPE_ANY            (0x00FFu)
00074
00075
00077 // Typedefs
00079
00083 typedef enum _MDNS_STATE
00084 {
00085     MDNS_HAS_STOPPED = 0,
00086     MDNS_IS_STARTING_UP,
00087     MDNS_IS_RUNNING
00088 } MDNS_STATE;
00089
00090
00092 // Function prototypes
00094
00110 PROTO BOOL bInitMDNSResponder(void);
00111
00112
00126 PROTO void StartMDNSResponder(void);
00127
00128
00137 PROTO void StopMDNSResponder(void);
00138
00139
00147 PROTO void MDNSResponder(void);
00148
00149
00163 PROTO void MDNSProcessFrame(NODE_INFO *remoteNode, IP_ADDR *localIP);
00164
00165
00172 PROTO MDNS_STATE eGetMDNSState(void);
00185
00186
00206 PROTO void MDNSResolveService(char * pName, ROM char * pServiceName);
00207
00208
00216 PROTO void MDNSResolveName(char * pName);
00217
00218
00223 void MDNSStopResolving(void);
00224
00225
00242 BOOL bMDNSServiceIsResolved(IP_ADDR * pIP, WORD_VAL * pu16Port);
00243
00244
00257 BOOL bMDNSNameIsResolved(IP_ADDR * pIP);
00258
00261
00262 // Epilogue
00264
00265 #undef PROTO
00266
00267 #endif  // #ifndef MDNS_H
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: output.c Source File

output.c

Go to the documentation of this file.
00001
00002
00003
00013
00014
00015
00016     #define     OUTPUT_C
00017
00018     #include    "output.h"
00019
00020
00022 // Local Variables
00024
00025 static BYTE * _pu8LCD_row;
00026 static BYTE _u8LCD_contrast;
00027 static BYTE _u8LCD_progress;
00028 static BYTE _u8LED_blinking;
00029 static DWORD _u32BlinkTimer;
00030 static DWORD _u32LastProgTime;
00031 volatile WORD _u16LCDTime;
00032 static DWORD _u32DisplayTimer;
00033
00034
00036 // Local function prototypes
00038
00039 static void _writeToLCD(BYTE nValue, BOOL bRAM);
00040 static void _setLCDAddress(BYTE nCol, BYTE nRow);
00041 static void _startLCDTimer(WORD u16WaitValue);
00042 static void _initLCDTimer(void);
00043 static BOOL _isLCDTimerElapsed(void);
00044 void _peripheralTimerISR(void);
00045
00046
00048 // Function implementation
00050
00051 void OutInit(void)
00052 {
00053     BYTE i = 0;
00054
00055     // Init values for LCD, see the st7036 datasheet for details.
00056     BYTE initArray[] = { // Function set: 8 Bit | 2 rows | Inst table 1
00057                         0x39, 0x39,
00058
00059                         // BIAS set: 1/5 | 2 rows
00060                         0x14,
00061
00062                         // Follower control: Circuit on | 3,3 V boost
00063                         0x6D,
00064
00065                         // Contrast set (low byte), the contrast value is later
00066                         // ored to by the function _writeToLCD.
00067                         0x70,
00068
00069                         // ICON off | Booster circuit on | Contrast set (high
00070                         // byte), later ored to by the function _writeToLCD.
00071                         0x54,
00072
00073                         // Display On | No cursor | No cursor blinkink
00074                         0x0C,
00075
00076                         // Shift of entire display is not performed.
00077                         0x06,
00078
00079                         // Clear display.
00080                         0x01,
00081
00082                         // Function set: 8 Bit | 2 rows | Inst table 0
00083                         0x38,
00084
00085                         // Set CGRAM address to address 0x08.
00086                         0x48 };
00087
00088     BYTE patternArray[] = {0x18, 0x04, 0x02, 0x18, 0x1A, 0x1F, 0x1F, 0x0A,
00089                            0x03, 0x04, 0x08, 0x03, 0x0B, 0x1F, 0x1F, 0x0A,
00090                            0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00,
00091                            0x00, 0x0E, 0x1F, 0x1F, 0x1F, 0x0E, 0x00, 0x00,
00092                            0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04,
00093                            0x04, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04};
00094
00095     // Disable analog and comparator module
00096     ADCON1 = 0x0F;
00097     CMCON = 0x07;
00098
00099     // Initialize PORTF...
00100     // PORTF.RF0 - Not connected
00101     // PORTF.RF1 -> LCD_PWR (LCD power supply, high active )
00102     // PORTF.RF2 -> LCD_RS (select mode at LCD, register or ram access)
00103     // PORTF.RF3 -> /LCD_CSB (LCD chip select for SPI access)
00104     // PORTF.RF4 -> LCD_LED (Enables the backlight at LCD)
00105     // PORTF.RF5 -> /EEPROM_CS (Selects the EEPROM for SPI access, low active)
00106     // -> Configure the whole port as output.
00107
00108     PORTF = 0x28;   // Turn off all signals.
00109     Nop();
00110     TRISF = 0;      // Configure all bits of PORTF as outputs.
00111
00112
00113     // Initialize PORTB...
00114     // PORTB.RB0 -> /LED_PWR (LED of the power button, low active)
00115     // PORTB.RB1 -> /LED_F4 (LED of the F4 button, low active)
00116     // PORTB.RB2 -> /LED_F3 (LED of the F3 button, low active)
00117     // PORTB.RB3 -> /LED_F2 (LED of the F2 button, low active)
00118     // PORTB.RB4 - PORTB.RB7 not used by the display functions.
00119     // Only the lower 4 Bits of PORTB will be configured as outputs. The other
00120     // bits remain unintended.
00121
00122     PORTB = 0x0F;       // Switch off all the PORTB LEDs.
00123     Nop();
00124     TRISB &= 0xF0;
00125
00126
00127     // Initialize PORTC...
00128     // PORTC.RC0 -> /FL_LED (LED of the FL button, low active)
00129     // PORTC.RC1 -> /F1_LED (LED of the F1 button, low active)
00130     // PORTC.RC2 -> not connected
00131     // PORTC.RC3 -> LCD_CLK (SPI clock for communication with the LCD)
00132     // PORTC.RC4 <- SPI MISO (Not used by LCD)
00133     // PORTC.RC5 -> LCD_SI (SPI data line to LCD)
00134     // PORTC.RC6 -> /SEL_LED (LED of the SEL button, low active)
00135     // PORTC.RC7 -> /ACC_LED (LED of the ACC button, low active)
00136     // All bits are initialized as outputs, but RC4 is configured as input.
00137
00138     PORTC = 0xC3;       // Switch off all the PORTB LEDs.
00139     Nop();
00140     TRISC = 0x10;
00141
00142     _u8LED_blinking = 0;
00143
00144
00145     // Initilaize register for LCD operations:
00146     lcd_status = 0;
00147     _pu8LCD_row = 0;
00148     _u8LCD_progress = 16;
00149
00150
00151     // Set a well known contrast value.
00152     _u8LCD_contrast = 0x18;
00153
00154
00155     // The LCD uses an internal timer for all its access routines because the
00156     // display has no back communication channel and therefore the ouput
00157     // routines can not poll the busy flag of the LCD. It simply performs wait
00158     // cycles before sending the next data to the display.
00159     _initLCDTimer();
00160
00161     _startLCDTimer(10); // Wait for stabilized outputs before enabling the LCD.
00162     while(_isLCDTimerElapsed() == FALSE);
00163
00164     PORTFbits.RF1 = 1;  // Switch on LCD.
00165
00166
00167     // Wait some time (ca. 50 ms) before starting the init sequence of the
00168     // display (internal startup time of the display).
00169     _startLCDTimer(500);
00170
00171     // Init sequence
00172     for (i = 0; i < sizeof(initArray); i++)
00173     {
00174         while(_isLCDTimerElapsed() == FALSE);
00175         _writeToLCD(initArray[i], FALSE);
00176     }
00177
00178     // Send new symbols to display.
00180     for (i = 0; i <  sizeof(patternArray); i++)
00181     {
00182         while(_isLCDTimerElapsed() == FALSE);
00183         _writeToLCD(patternArray[i], TRUE);
00184     }
00185
00186     PORTFbits.RF4 = 1;  // Switch on LCD backlight.
00187 }
00188
00191
00192 void OutTriggerDisplay(void)
00193 {
00194     _u32DisplayTimer = TickGet();
00195
00196     if (sPCommonConfig.u8LCDLight == 0xFF)
00197     {
00198         OutSwitchLCDBacklight(TRUE);
00199     }
00200     else if (sPCommonConfig.u8LCDLight == 0)
00201     {
00202         OutSwitchLCDBacklight(FALSE);
00203     }
00204     else
00205     {
00206         _u32DisplayTimer += sPCommonConfig.u8LCDLight*TICKS_PER_SECOND;
00207         OutSwitchLCDBacklight(TRUE);
00208     }
00209 }
00210
00213
00214 void OutMain(void)
00215 {
00216     if (_u8LED_blinking && (_u32BlinkTimer < TickGet()))
00217     {
00218         OutSetLED(_u8LED_blinking, LED_TOGGLE);
00219         _u32BlinkTimer = TickGet() + LED_BLINK_INTERVAL * TICKS_PER_SECOND;
00220     }
00221
00222     // Is the LCD ready (Waiting time over)?
00223     if (_isLCDTimerElapsed() == FALSE)
00224     {
00225         return;
00226     }
00227
00228     // If commands for the display are pending, the LCD is busy and therefore
00229     // the display stays on!
00230     if (lcd_status)
00231     {
00232         OutTriggerDisplay();
00233     }
00234     else if ((_u32DisplayTimer < TickGet()) && sPCommonConfig.u8LCDLight)
00235     {
00236         OutSwitchLCDBacklight(FALSE);
00237     }
00238
00239     // Check the LCD command:
00240     if (lcd_status & LCD_CLR_MASK)
00241     {
00242         _pu8LCD_row = 0;
00243         lcd_status &= ~(LCD_CLR_MASK);
00244         _writeToLCD(0x01, FALSE);
00245     }
00246     else if (_pu8LCD_row)
00247     {
00248         if (*_pu8LCD_row == 0)
00249         {
00250             _pu8LCD_row = 0;
00251         }
00252         else
00253         {
00254             _writeToLCD(*_pu8LCD_row, TRUE);
00255             _pu8LCD_row++;
00256         }
00257     }
00258     else if (lcd_status & LCD_ROW1_MASK)
00259     {
00260         lcd_status &= ~LCD_ROW1_MASK;
00261         if (lcd_status & LCD_CENTER1_MASK)
00262         {
00263             lcd_addr1 = (LCD_CHARS_IN_A_ROW - strlen(lcdram_row1))>>1;
00264             lcd_status &= ~LCD_CENTER1_MASK;
00265         }
00266         if (strlen(lcdram_row1) == 0)
00267         {
00268             return;
00269         }
00270         _pu8LCD_row = lcdram_row1;
00271         _setLCDAddress(lcd_addr1, 0);
00272     }
00273 #ifdef LCD_WITH_2_ROWS
00274     else if (lcd_status & LCD_ROW2_MASK)
00275     {
00276         lcd_status &= ~LCD_ROW2_MASK;
00277         if (lcd_status & LCD_CENTER2_MASK)
00278         {
00279             lcd_addr2 = (LCD_CHARS_IN_A_ROW - strlen(lcdram_row2))>>1;
00280             lcd_status &= ~LCD_CENTER2_MASK;
00281         }
00282
00283         if (strlen(lcdram_row2) == 0)
00284         {
00285             return;
00286         }
00287         _pu8LCD_row = lcdram_row2;
00288         _u8LCD_progress = strlen(lcdram_row2);
00289         _u32LastProgTime = TickGet() + LCD_PROGRESS_TIME * TICKS_PER_SECOND;
00290         _setLCDAddress(lcd_addr2, 1);
00291     }
00292 #ifdef LCD_WITH_3_ROWS
00293     else if (lcd_status & LCD_ROW3_MASK)
00294     {
00295         lcd_status &= ~LCD_ROW3_MASK;
00296         // ToDo: Implement.
00297     }
00298 #endif
00299 #endif
00300     else if (lcd_status & LCD_CLR_PROG_MASK)
00301     {
00302         BYTE i;
00303         lcd_status &= ~LCD_CLR_PROG_MASK;
00304
00305         for (i = 0; i < 16; i++)
00306         {
00307             if (lcdram_row2[i] == '.')
00308             {
00309                 lcdram_row2[i] = 0;
00310                 lcd_status |= LCD_ROW2_MASK;
00311                 break;
00312             }
00313         }
00314     }
00315     else if (lcd_status & LCD_PROGRESS_MASK)
00316     {
00317         // Is it time for a new character?
00318         if (_u32LastProgTime < TickGet())
00319         {
00320             lcdram_row2[_u8LCD_progress++] = LCD_PROGRESS_CHAR;
00321             lcdram_row2[_u8LCD_progress] = 0;
00322             lcd_status |= LCD_ROW2_MASK;
00323             if (_u8LCD_progress > (15 - lcd_addr2))
00324             {
00325                 lcd_status &= ~LCD_PROGRESS_MASK;
00326             }
00327         }
00328     }
00329 }
00330
00333
00334 #ifdef DEBEXT_MODE
00335
00336 void OutDebugOut(BYTE nValue)
00337 {
00338     PORTCbits.RC0 = nValue & LED_FL ? 0 : 1;
00339     PORTCbits.RC1 = nValue & LED_F1 ? 0 : 1;
00340     PORTBbits.RB3 = nValue & LED_F2 ? 0 : 1;
00341     PORTBbits.RB2 = nValue & LED_F3 ? 0 : 1;
00342     PORTBbits.RB1 = nValue & LED_F4 ? 0 : 1;
00343     PORTBbits.RB0 = nValue & LED_PWR ? 0 : 1;
00344     PORTCbits.RC7 = nValue & LED_ACC ? 0 : 1;
00345     PORTCbits.RC6 = nValue & LED_SEL ? 0 : 1;
00346 }
00347
00348 #endif
00349
00352
00353 void OutSwitchOffLCD(void)
00354 {
00355     PORTF &= 0x2C;
00356 }
00357
00360
00361 void OutSwitchLCDBacklight(BOOL On)
00362 {
00363     if (On == FALSE)
00364     {
00365         PORTF &= 0x2E;
00366     }
00367     else
00368     {
00369         PORTF |= 0x10;
00370     }
00371 }
00372
00375
00376 BOOL OutIsLCDBusy(void)
00377 {
00378     if ((_isLCDTimerElapsed() == FALSE) || (lcd_status) || (_pu8LCD_row))
00379     {
00380         return TRUE;
00381     }
00382     else
00383     {
00384         return FALSE;
00385     }
00386 }
00387
00390
00391 void OutEnableCursor(BOOL On)
00392 {
00393     if (On == TRUE)
00394     {
00395         _writeToLCD(0x0E, FALSE);
00396     }
00397     else
00398     {
00399         _writeToLCD(0x0C, FALSE);
00400     }
00401 }
00402
00405
00406 void OutSetCursor(BYTE Column, BYTE Row)
00407 {
00408     _setLCDAddress(Column, Row);
00409 }
00410
00413
00414 void OutSwitchOffAllLEDs(void)
00415 {
00416     BYTE i;
00417
00418     for (i = LED_FL; i != 0; i = i<<1)
00419     {
00420         OutSetLED(i, LED_OFF);
00421     }
00422 }
00423
00426
00427 void OutSetLEDMask(BYTE LedMask, BYTE LedSwitchMask)
00428 {
00429     BYTE setmask = LedMask & LedSwitchMask;
00430     BYTE clearmask = LedMask & (~LedSwitchMask);
00431     OutSetLED(setmask, LED_ON);
00432     OutSetLED(clearmask, LED_OFF);
00433 }
00434
00437
00438 void OutSetLED(BYTE LedMask, eLED_Modes Mode)
00439 {
00440     BOOL ledOff = TRUE;
00441
00442     switch(Mode)
00443     {
00444     case LED_BLINK:
00445         _u8LED_blinking |= LedMask;
00446         _u32BlinkTimer = TickGet() + LED_BLINK_INTERVAL;
00447         break;
00448
00449     case LED_ON:
00450         ledOff = FALSE;
00451         // Intended fall through
00452
00453     case LED_OFF:
00454         _u8LED_blinking &= ~LedMask;
00455
00456         if (LedMask & LED_FL)
00457         {
00458             PORTCbits.RC0 = ledOff;
00459         }
00460         if (LedMask & LED_F1)
00461         {
00462             PORTCbits.RC1 = ledOff;
00463         }
00464         if (LedMask & LED_F2)
00465         {
00466             PORTBbits.RB3 = ledOff;
00467         }
00468         if (LedMask & LED_F3)
00469         {
00470             PORTBbits.RB2 = ledOff;
00471         }
00472         if (LedMask & LED_F4)
00473         {
00474             PORTBbits.RB1 = ledOff;
00475         }
00476         if (LedMask & LED_PWR)
00477         {
00478             PORTBbits.RB0 = ledOff;
00479         }
00480         if (LedMask & LED_ACC)
00481         {
00482             PORTCbits.RC7 = ledOff;
00483         }
00484         if (LedMask & LED_SEL)
00485         {
00486             PORTCbits.RC6 = ledOff;
00487         }
00488         break;
00489
00490     case LED_TOGGLE:
00491         if (LedMask & LED_FL)
00492         {
00493             PORTCbits.RC0 = ~PORTCbits.RC0;
00494         }
00495         if (LedMask & LED_F1)
00496         {
00497             PORTCbits.RC1 = ~PORTCbits.RC1;
00498         }
00499         if (LedMask & LED_F2)
00500         {
00501             PORTBbits.RB3 = ~PORTBbits.RB3;
00502         }
00503         if (LedMask & LED_F3)
00504         {
00505             PORTBbits.RB2 = ~PORTBbits.RB2;
00506         }
00507         if (LedMask & LED_F4)
00508         {
00509             PORTBbits.RB1 = ~PORTBbits.RB1;
00510         }
00511         if (LedMask & LED_PWR)
00512         {
00513             PORTBbits.RB0 = ~PORTBbits.RB0;
00514         }
00515         if (LedMask & LED_ACC)
00516         {
00517             PORTCbits.RC7 = ~PORTCbits.RC7;
00518         }
00519         if (LedMask & LED_SEL)
00520         {
00521             PORTCbits.RC6 = ~PORTCbits.RC6;
00522         }
00523     }
00524 }
00525
00528
00529 eLED_Modes OutGetLEDMode(BYTE Led)
00530 {
00531     BOOL ledOff = TRUE;
00532
00533     if (_u8LED_blinking & Led)
00534     {
00535         return LED_BLINK;
00536     }
00537
00538     if (Led & LED_FL)
00539     {
00540         ledOff = PORTCbits.RC0;
00541     }
00542
00543     if (Led & LED_F1)
00544     {
00545         ledOff = PORTCbits.RC1;
00546     }
00547
00548     if (Led & LED_F2)
00549     {
00550         ledOff = PORTBbits.RB3;
00551     }
00552
00553     if (Led & LED_F3)
00554     {
00555         ledOff = PORTBbits.RB2;
00556     }
00557
00558     if (Led & LED_F4)
00559     {
00560         ledOff = PORTBbits.RB1;
00561     }
00562
00563     if (Led & LED_PWR)
00564     {
00565         ledOff = PORTBbits.RB0;
00566     }
00567
00568     if (Led & LED_ACC)
00569     {
00570         ledOff = PORTCbits.RC7;
00571     }
00572
00573     if (Led & LED_SEL)
00574     {
00575         ledOff = PORTCbits.RC6;
00576     }
00577
00578     if (ledOff)
00579     {
00580         return LED_OFF;
00581     }
00582     else
00583     {
00584         return LED_ON;
00585     }
00586 }
00587
00590
00591 static void _writeToLCD(BYTE nValue, BOOL bRAM)
00592 {
00593     if (bRAM == FALSE)
00594     {
00595         if ((nValue & 0xF0) == 0x60)
00596         {
00597             // Wait 200 ms for stabilizing of the power supply when writing the
00598             // follower control to display.
00599             _startLCDTimer(2000);
00600         }
00601         else if ((nValue & 0xFC) == 0x00)
00602         {
00603             // Return Home and Clear Diplay need ca. 1,08 ms
00604             _startLCDTimer(11);
00605         }
00606         else
00607         {
00608             if ((nValue & 0xF0) == 0x70)
00609             {
00610                 // Oring the low nibble of the contrast value for setting the
00611                 // contrast low byte.
00612                 nValue = 0x70 | (_u8LCD_contrast & 0x0F);
00613             }
00614             else if ((nValue & 0xF0) == 0x50)
00615             {
00616                 nValue &= 0xFC;
00617                 nValue |= (_u8LCD_contrast >> 4) & 0x03;
00618             }
00619             _startLCDTimer(1);  // Wait 100 us.
00620         }
00621     }
00622     else
00623     {
00624         _startLCDTimer(1);  // Wait 100 us.
00625     }
00626
00627     // SPI-Configuration for LCD:
00628     // SPI Master | Clock = Fosc/64 | Enable | Clock idle state is high
00629     SSP1CON1 = 0x32;
00630     SSP1STAT = 0x00;    // CKE = 0
00631
00632     PORTFbits.RF2 = bRAM;
00633     PORTFbits.RF3 = 0;  // Select LCD.
00634     PIR1bits.SSP1IF = 0;
00635     SSP1BUF = nValue;   // Write value on SPI bus.
00636
00637     // Wait until SPI transmission is finished:
00638     while(PIR1bits.SSP1IF == 0);
00639
00640     PORTFbits.RF3 = 1;  // Deselect LCD.
00641
00642     return;
00643 }
00644
00647
00648 static void _setLCDAddress(BYTE nCol, BYTE nRow)
00649 {
00650
00651 #ifdef LCD_WITH_3_ROWS
00652     nCol &= 0x0F;
00653     if (nRow == 1)
00654     {
00655         nCol |= 0x10;
00656     }
00657     else if (nRow == 2)
00658     {
00659         nCol |= 0x20;
00660     }
00661 #endif
00662
00663 #ifdef LCD_WITH_2_ROWS
00664     nCol &= 0x3F;
00665     if (nRow == 1)
00666     {
00667         nCol |= 0x40;
00668     }
00669 #endif
00670
00671     _writeToLCD(nCol | 0x80, FALSE);
00672 }
00673
00676
00677 static void _initLCDTimer(void)
00678 {
00679     // Init the 100 us timer:
00680     T2CON = 0x03;   // Reset timer 2 (8 bit timer, 1:16 Prescaler).
00681     PR2 = (GetPeripheralClock() * 0.0001) / 16;     // Match register.
00682     IPR1bits.TMR2IP = 0;    // Low interrupt priority.
00683     PIE1bits.TMR2IE = 0;    // Disable the interrupt flag.
00684 }
00685
00688
00689 static void _startLCDTimer(WORD u16WaitValue)
00690 {
00691     PIE1bits.TMR2IE = 0;    // Disable the interrupt.
00692     _u16LCDTime = u16WaitValue;
00693     T2CONbits.TMR2ON = 0;   // Stop timer.
00694     TMR2 = 0;
00695     PIR1bits.TMR2IF = 0;    // Clearing the compare match interrupt flag.
00696     PIE1bits.TMR2IE = 1;    // Enable the interrupt.
00697
00698     T2CONbits.TMR2ON = 1;   // Start timer.
00699 }
00700
00703
00704 static BOOL _isLCDTimerElapsed(void)
00705 {
00706     if (PIE1bits.TMR2IE == 0)
00707     {
00708         return TRUE;
00709     }
00710
00711     return FALSE;
00712 }
00713
00716
00717 void OutConvertNameForDisplay(BYTE * pString)
00718 {
00719     BYTE i;
00720     for (i = 0; i < strlen(pString); i++)
00721     {
00722         switch(pString[i])
00723         {
00724         case 0xE4:
00725             pString[i] = '\x84';
00726             break;
00727
00728         case 0xFC:
00729             pString[i] = '\x81';
00730             break;
00731
00732         case 0xF6:
00733             pString[i] = '\x94';
00734             break;
00735
00736         case 0xDC:
00737             pString[i] = '\x9A';
00738             break;
00739
00740         case 0xC4:
00741             pString[i] = '\x8E';
00742             break;
00743
00744         case 0xD6:
00745             pString[i] = '\x99';
00746             break;
00747         }
00748     }
00749 }
00750
00753
00754 void OutInterruptHandler(void)
00755 {
00756     if (PIR1bits.TMR2IF == 1)
00757     {
00758         // Decrement LCD wait time...
00759         _u16LCDTime--;
00760
00761         if (_u16LCDTime == 0)
00762         {
00763             PIE1bits.TMR2IE = 0;    // Time is over, disable interrupt.
00764             T2CONbits.TMR2ON = 0;   // Disable timer.
00765         }
00766
00767         PIR1bits.TMR2IF = 0;    // Clearing the interrupt flag.
00768     }
00769 }
00770
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: output.h Source File

output.h

Go to the documentation of this file.
00001
00002
00003
00024
00025
00026
00027 #ifndef OUTPUT_H
00028
00029 #define OUTPUT_H
00030
00031 #include "GenericTypeDefs.h"
00032
00033 #ifdef OUTPUT_C
00034     #define PROTO
00035 #else
00036     #define PROTO extern
00037 #endif
00038
00039
00041 // Typedefs
00043
00048 typedef enum
00049 {
00050     LED_ON = 0,
00051     LED_OFF,
00052
00054     LED_BLINK,
00055     LED_TOGGLE
00056 } eLED_Modes;
00057
00059 // Defines
00061
00062 #define LCD_WITH_2_ROWS
00063
00067 #define LCD_CHARS_IN_A_ROW  16
00068
00081 #define LCD_CLR_MASK        0x01
00082 #define LCD_ROW1_MASK       0x02
00083 #define LCD_ROW2_MASK       0x04
00084
00086 #define LCD_ROW3_MASK       0x08
00087
00093 #define LCD_PROGRESS_MASK   0x10
00094
00099 #define LCD_CLR_PROG_MASK   0x20
00100
00101 #define LCD_CENTER1_MASK    0x40
00102 #define LCD_CENTER2_MASK    0x80
00103
00104
00106
00107 #define LCD_PROGRESS_CHAR   '.'
00108
00110 #define LCD_PROGRESS_TIME   1.5
00111
00118 #define LCD_IDLE_TIME       20
00119
00120
00127 #define LED_FL              0x01
00128 #define LED_F1              0x02
00129 #define LED_F2              0x04
00130 #define LED_F3              0x08
00131 #define LED_F4              0x10
00132 #define LED_PWR             0x20
00133 #define LED_ACC             0x40
00134 #define LED_SEL             0x80
00135
00141 #define LED_BLINK_INTERVAL  1u
00142
00144 // Variables
00146
00153     PROTO BYTE lcd_status;
00154
00155     PROTO BYTE lcd_addr1;
00156     PROTO BYTE lcd_addr2;
00157     PROTO char lcdram_row1[LCD_CHARS_IN_A_ROW+1]; // This both arrays must not
00158     PROTO char lcdram_row2[LCD_CHARS_IN_A_ROW+1]; // start at address 0!!!
00159
00160
00162 // Function prototypes
00164
00166
00179 void OutInit(void);
00180
00181
00183
00197 void OutMain(void);
00198
00199
00201
00218 void OutDebugOut(BYTE u8Value);
00219
00220
00222
00236 void OutSwitchOffLCD(void);
00237
00238
00240
00256 void OutSwitchLCDBacklight(BOOL On);
00257
00258
00260
00274 BOOL OutIsLCDBusy(void);
00275
00276
00278
00289 void OutEnableCursor(BOOL On);
00290
00291
00293
00306 void OutSetCursor(BYTE Column, BYTE Row);
00307
00308
00310
00323 void OutSwitchOffAllLEDs(void);
00324
00325
00327
00344 void OutSetLED(BYTE LedMask, eLED_Modes Mode);
00345
00346
00348
00367 void OutSetLEDMask(BYTE LedMask, BYTE LedSwitchMask);
00368
00369
00371
00385 void OutTriggerDisplay(void);
00386
00387
00389
00407 eLED_Modes OutGetLEDMode(BYTE Led);
00408
00409
00411
00423 void OutConvertNameForDisplay(BYTE * pString);
00424
00425
00426 void OutInterruptHandler(void);
00427
00428
00429
00430 #undef  PROTO
00431
00432 #include    "main.h"
00433
00434 #endif  // #ifndef OUTPUT_H
00435
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: Page Index

Related Pages

Here is a list of all related documentation pages:
  • Version tracking
  • The MoBaCon Software License (MBCSL)
  • Folder structure and project files
  • How to build
  • How to deploy
  • List of errors and feature requests
  • Todo List
Generated on Sun Nov 27 20:02:37 2011 for eWicht by doxygen 1.5.5


eWicht: HTTPPrint.h Source File

HTTPPrint.h

00001 /**************************************************************
00002  * HTTPPrint.h
00003  * Provides callback headers and resolution for user's custom
00004  * HTTP Application.
00005  *
00006  * This file is automatically generated by the MPFS Utility
00007  * ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR
00008  **************************************************************/
00009
00010 #ifndef __HTTPPRINT_H
00011 #define __HTTPPRINT_H
00012
00013 #include "TCPIP/TCPIP.h"
00014
00015 #if defined(STACK_USE_HTTP2_SERVER)
00016
00017 extern HTTP_CONN curHTTP;
00018 extern HTTP_STUB httpStubs[MAX_HTTP_CONNECTIONS];
00019 extern BYTE curHTTPID;
00020
00021 void HTTPPrint(DWORD callbackID);
00022 void HTTPPrint_header(WORD);
00023 void HTTPPrint_string(WORD);
00024 void HTTPPrint_language(void);
00025 void HTTPPrint_ledlight(void);
00026 void HTTPPrint_toggledir(void);
00027 void HTTPPrint_askforaddressmode(void);
00028 void HTTPPrint_ip(WORD);
00029 void HTTPPrint_serverurl(void);
00030 void HTTPPrint_version(WORD);
00031 void HTTPPrint_xmllanguage(void);
00032 void HTTPPrint_xmltoggle(void);
00033 void HTTPPrint_xmlip(void);
00034 void HTTPPrint_macaddress(void);
00035 void HTTPPrint_addressmode(void);
00036 void HTTPPrint_hostname(void);
00037 void HTTPPrint_mdns(void);
00038 void HTTPPrint_connection(void);
00039 void HTTPPrint_serverport(void);
00040
00041 void HTTPPrint(DWORD callbackID)
00042 {
00043     switch(callbackID)
00044     {
00045         case 0x00000000:
00046             HTTPIncFile((ROM BYTE*)"head.inc");
00047             break;
00048         case 0x00000001:
00049             HTTPPrint_header(STRTBLID_COMMON);
00050             break;
00051         case 0x00000002:
00052             HTTPPrint_string(STRTBLID_LANGUAGE);
00053             break;
00054         case 0x00000003:
00055             HTTPPrint_language();
00056             break;
00057         case 0x00000004:
00058             HTTPPrint_string(STRTBLID_LCD_BACKLIGHT);
00059             break;
00060         case 0x00000005:
00061             HTTPPrint_ledlight();
00062             break;
00063         case 0x00000006:
00064             HTTPPrint_string(STRTBLID_DIRECTION_MODE);
00065             break;
00066         case 0x00000007:
00067             HTTPPrint_toggledir();
00068             break;
00069         case 0x00000008:
00070             HTTPPrint_string(STRTBLID_SAVE);
00071             break;
00072         case 0x00000009:
00073             HTTPPrint_string(STRTBLID_RESET);
00074             break;
00075         case 0x0000000a:
00076             HTTPPrint_string(STRTBLID_IP_ALLOCATION);
00077             break;
00078         case 0x0000000b:
00079             HTTPPrint_askforaddressmode();
00080             break;
00081         case 0x0000000c:
00082             HTTPPrint_string(STRTBLID_IP_ADDRESS);
00083             break;
00084         case 0x0000000d:
00085             HTTPPrint_ip(VAR_IP_ADDRESS_EEPROM);
00086             break;
00087         case 0x0000000e:
00088             HTTPPrint_string(STRTBLID_SUBNETMASK);
00089             break;
00090         case 0x0000000f:
00091             HTTPPrint_ip(VAR_SUBNET_MASK_EEPROM);
00092             break;
00093         case 0x00000010:
00094             HTTPPrint_string(STRTBLID_GATEWAY_ADDRESS);
00095             break;
00096         case 0x00000011:
00097             HTTPPrint_ip(VAR_GATEWAY_ADDRESS_EEPROM);
00098             break;
00099         case 0x00000012:
00100             HTTPPrint_string(STRTBLID_SERVER_URL);
00101             break;
00102         case 0x00000013:
00103             HTTPPrint_serverurl();
00104             break;
00105         case 0x00000014:
00106             HTTPPrint_string(STRTBLID_RESTART_NEEDED);
00107             break;
00108         case 0x00000015:
00109             HTTPPrint_version(VAR_FIRMWARE_VERSION_MAJOR);
00110             break;
00111         case 0x00000016:
00112             HTTPPrint_version(VAR_FIRMWARE_VERSION_MINOR);
00113             break;
00114         case 0x00000017:
00115             HTTPPrint_xmllanguage();
00116             break;
00117         case 0x00000018:
00118             HTTPPrint_xmltoggle();
00119             break;
00120         case 0x00000019:
00121             HTTPPrint_xmlip();
00122             break;
00123         case 0x0000001a:
00124             HTTPPrint_header(STRTBLID_FILE);
00125             break;
00126         case 0x0000001b:
00127             HTTPPrint_string(STRTBLID_DOWNLOAD_CONFIG);
00128             break;
00129         case 0x0000001c:
00130             HTTPPrint_string(STRTBLID_OPEN);
00131             break;
00132         case 0x0000001d:
00133             HTTPPrint_string(STRTBLID_UPLOAD_CONFIG);
00134             break;
00135         case 0x0000001e:
00136             HTTPPrint_string(STRTBLID_UPLOAD);
00137             break;
00138         case 0x0000001f:
00139             HTTPPrint_header(STRTBLID_SYSTEMSTATE);
00140             break;
00141         case 0x00000020:
00142             HTTPPrint_string(STRTBLID_FIRMWARE_VERSION);
00143             break;
00144         case 0x00000023:
00145             HTTPPrint_string(STRTBLID_MAC_ADDRESS);
00146             break;
00147         case 0x00000024:
00148             HTTPPrint_macaddress();
00149             break;
00150         case 0x00000025:
00151             HTTPPrint_ip(VAR_IP_ADDRESS);
00152             break;
00153         case 0x00000026:
00154             HTTPPrint_addressmode();
00155             break;
00156         case 0x00000027:
00157             HTTPPrint_ip(VAR_SUBNET_MASK);
00158             break;
00159         case 0x00000028:
00160             HTTPPrint_ip(VAR_GATEWAY_ADDRESS);
00161             break;
00162         case 0x00000029:
00163             HTTPPrint_string(STRTBLID_NETWORK_NAME);
00164             break;
00165         case 0x0000002a:
00166             HTTPPrint_hostname();
00167             break;
00168         case 0x0000002b:
00169             HTTPPrint_string(STRTBLID_NAMESERVICE);
00170             break;
00171         case 0x0000002c:
00172             HTTPPrint_mdns();
00173             break;
00174         case 0x0000002d:
00175             HTTPPrint_string(STRTBLID_CONNECTION);
00176             break;
00177         case 0x0000002e:
00178             HTTPPrint_connection();
00179             break;
00180         case 0x0000002f:
00181             HTTPPrint_ip(VAR_CONNECTED_SERVER_IP);
00182             break;
00183         case 0x00000030:
00184             HTTPPrint_string(STRTBLID_PORT);
00185             break;
00186         case 0x00000031:
00187             HTTPPrint_serverport();
00188             break;
00189         case 0x00000032:
00190             HTTPPrint_string(STRTBLID_RESTART);
00191             break;
00192         case 0x00000033:
00193             HTTPPrint_string(STRTBLID_RESET_TO_FACTORY);
00194             break;
00195         case 0x00000034:
00196             HTTPPrint_version(VAR_FIRMWARE_VERSION_STRING);
00197             break;
00198         case 0x00000035:
00199             HTTPPrint_string(STRTBLID_BOOTLOADER_VERSION);
00200             break;
00201         case 0x00000036:
00202             HTTPPrint_version(VAR_BOOTLOADER_VERSION);
00203             break;
00204         default:
00205             // Output notification for undefined values
00206             TCPPutROMArray(sktHTTP, (ROM BYTE*)"!DEF", 4);
00207     }
00208
00209     return;
00210 }
00211
00212 void HTTPPrint_(void)
00213 {
00214     TCPPut(sktHTTP, '~');
00215     return;
00216 }
00217
00218 #endif
00219
00220 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: MPFSImg.c Source File

MPFSImg.c

00001 /***************************************************************
00002  * MPFSImg.c
00003  * Defines an MPFS2 image to be stored in program memory.
00004  *
00005  * NOT FOR HAND MODIFICATION
00006  * This file is automatically generated by the MPFS2 Utility
00007  * ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS2 GENERATOR
00008  * Generated Montag, 24. Januar 2011 22:29:51
00009  ***************************************************************/
00010
00011 #define __MPFSIMG_C
00012
00013 #if !defined(MPFS_USE_EEPROM) && !defined(MPFS_USE_SPI_FLASH)
00014
00015 #include "TCPIP/TCPIP.h"
00016 #if defined(STACK_USE_MPFS2)
00017
00018
00019 /**************************************
00020  * MPFS2 Image Data
00021  **************************************/
00022 #define DATACHUNK000000 \
00023     0x4d,0x50,0x46,0x53,0x02,0x01,0x0d,0x00,0xe8,0x2d,0x48,0x44,0xca,0x3f,0xff,0xff, /* MPFS.....-HD.?.. */ \
00024     0x4c,0x3b,0xff,0xff,0xea,0xca,0xff,0xff,0xe6,0xc7,0x0a,0xa3,0xff,0xff,0x74,0xe5, /* L;............t. */ \
00025     0xca,0xc6,0x40,0x01,0x00,0x00,0x9e,0x01,0x00,0x00,0x2b,0x00,0x00,0x00,0xef,0x6b, /* ..@.......+....k */ \
00026     0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x01,0x00,0x00,0xc9,0x01,0x00,0x00, /* .L......G....... */ \
00027     0x2c,0x00,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x01, /* ,....k.L......R. */ \
00028     0x00,0x00,0xf5,0x01,0x00,0x00,0x73,0x04,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00, /* ......s....k.L.. */ \
00029     0x00,0x00,0x06,0x00,0x5d,0x01,0x00,0x00,0x96,0x04,0x00,0x00,0xb8,0x00,0x00,0x00, /* ....]........... */ \
00030     0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0x01,0x00,0x00,0x4e,0x05, /* .k.L......^...N. */ \
00031     0x00,0x00,0xe2,0x00,0x00,0x00,0x05,0x67,0xef,0x4c,0x00,0x00,0x00,0x00,0x06,0x00, /* .......g.L...... */ \
00032     0x69,0x01,0x00,0x00,0xee,0x05,0x00,0x00,0x38,0x00,0x00,0x00,0x05,0x67,0xef,0x4c, /* i.......8....g.L */ \
00033     0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x01,0x00,0x00,0x26,0x06,0x00,0x00,0x96,0x01, /* ......j...&..... */ \
00034     0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x06,0x00,0x73,0x01,0x00,0x00, /* ...k.L......s... */ \
00035     0x1e,0x07,0x00,0x00,0x30,0x00,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00, /* ....0....k.L.... */ \
00036     0x00,0x00,0x74,0x01,0x00,0x00,0x4e,0x07,0x00,0x00,0x3a,0x01,0x00,0x00,0xef,0x6b, /* ..t...N...:....k */ \
00037     0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x7d,0x01,0x00,0x00,0x88,0x08,0x00,0x00, /* .L......}....... */ \
00038     0xf7,0x02,0x00,0x00,0x1e,0x7e,0xde,0x4c,0x00,0x00,0x00,0x00,0x06,0x00,0x87,0x01, /* .....~.L........ */ \
00039     0x00,0x00,0x39,0x0a,0x00,0x00,0xd8,0x00,0x00,0x00,0x1e,0x7e,0xde,0x4c,0x00,0x00, /* ..9........~.L.. */ \
00040     0x00,0x00,0x00,0x00,0x88,0x01,0x00,0x00,0x11,0x0b,0x00,0x00,0xc7,0x02,0x00,0x00, /* ................ */ \
00041     0xad,0xa9,0xef,0x4c,0x00,0x00,0x00,0x00,0x01,0x00,0x94,0x01,0x00,0x00,0xd8,0x0d, /* ...L............ */ \
00042     0x00,0x00,0x5a,0x03,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x01,0x00, /* ..Z....k.L...... */ \
00043     0x62,0x67,0x2e,0x67,0x69,0x66,0x00,0x62,0x75,0x6c,0x6c,0x65,0x74,0x2e,0x67,0x69, /* bg.gif.bullet.gi */ \
00044     0x66,0x00,0x63,0x6f,0x6d,0x6d,0x6f,0x6e,0x2e,0x68,0x74,0x6d,0x00,0x00,0x63,0x6f, /* f.common.htm..co */ \
00045     0x6e,0x66,0x69,0x67,0x2e,0x78,0x6d,0x6c,0x00,0x00,0x66,0x69,0x6c,0x65,0x2e,0x68, /* nfig.xml..file.h */ \
00046     0x74,0x6d,0x00,0x00,0x68,0x65,0x61,0x64,0x2e,0x69,0x6e,0x63,0x00,0x69,0x6e,0x64, /* tm..head.inc.ind */ \
00047     0x65,0x78,0x2e,0x68,0x74,0x6d,0x00,0x00,0x72,0x6f,0x63,0x72,0x61,0x69,0x6c,0x2e, /* ex.htm..rocrail. */ \
00048     0x78,0x73,0x64,0x00,0x73,0x74,0x79,0x6c,0x65,0x2e,0x63,0x73,0x73,0x00,0x47,0x49, /* xsd.style.css.GI */ \
00049     0x46,0x38,0x39,0x61,0x01,0x00,0x03,0x00,0x80,0x00,0x00,0x75,0x02,0x04,0x99,0x00, /* F89a.......u.... */ \
00050     0x00,0x21,0xf9,0x04,0x00,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00, /* .!.......,...... */ \
00051     0x03,0x00,0x00,0x02,0x02,0x0c,0x50,0x00,0x3b,0x47,0x49,0x46,0x38,0x39,0x61,0x03, /* ......P.;GIF89a. */ \
00052     0x00,0x03,0x00,0x80,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00, /* ............!... */ \
00053     0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x02,0x03, /* ....,........... */ \
00054     0x84,0x7f,0x05,0x00,0x3b,0xb1,0x1a,0xda,0x7a,0x45,0x79,0xdc,0x7e,0xec,0x2b,0x03, /* ....;...zEy.~.+. */ \
00055     0x8b,0x1b,0xd7,0x6e,0x0e,0xc7,0x57,0x14,0x81,0xab,0x57,0x4b,0x7f,0x8d,0x5b,0x51, /* ...n..W...WK..[Q */ \
00056     0x1e,0x77,0x0e,0xb7,0x48,0xf8,0x5d,0x65,0x5c,0x52,0x7c,0xda,0x73,0xa9,0x94,0x28, /* .w..H.]e\R|.s..( */ \
00057     0x60,0xb8,0x71,0xc0,0x25,0xc5,0x07,0xbc,0x41,0xe9,0x1d,0x9a,0x90,0x7e,0x2a,0xe3, /* `.q.%...A....~.. */ \
00058     0x26,0xe3,0xdb,0x9e,0x4b,0xa5,0x44,0xd1,0xd7,0x1c,0x51,0x09,0x0b,0xf6,0xcd,0xf8, /* &...K.D...Q..... */ \
00059     0x66,0xa8,0xe1,0xe3,0xdf,0x56,0xba,0x11,0x45,0x52,0xa8,0x6a,0xa5,0x21,0x47,0x14, /* f....V..ER.j.!G. */ \
00060     0x58,0x65,0x30,0x35,0x7c,0xfc,0x33,0xd8,0x37,0x83,0xdd,0x64,0xdc,0x64,0x7c,0xdb, /* Xe05|.3.7..d.d|. */ \
00061     0x73,0xa9,0x94,0x28,0xfa,0x9a,0x23,0x2a,0x61,0xc1,0xbe,0x19,0xdf,0x0c,0x6d,0x09, /* s..(..#.a.....m. */ \
00062     0xf2,0x7d,0x0c,0x31,0xa2,0x3e,0xe8,0x57,0x5b,0xe9,0x46,0x14,0x49,0xe9,0x6a,0xa8, /* .}.1.>.W[.F.I.j. */ \
00063     0xe4,0xe4,0x88,0xaa,0x56,0x1a,0x72,0x44,0x01,0xad,0x76,0x12,0xcd,0xc7,0xa2,0x0e, /* ....V.rD..v..... */ \
00064     0x17,0x05,0xb4,0x9a,0x65,0xab,0x60,0xdf,0x0c,0x76,0x93,0x71,0x93,0xf1,0x6d,0xcf, /* ....e.`..v.q..m. */ \
00065     0xa5,0x52,0xa2,0xe8,0x6b,0x8e,0xa8,0x84,0x05,0xfb,0x66,0x7c,0x33,0xd4,0xf0,0xf1, /* .R..k.....f|3... */ \
00066     0x6f,0x2b,0xdd,0x88,0x22,0xa9,0x57,0x2b,0x0d,0x39,0xa2,0xc0,0x2a,0x83,0xa9,0xe1, /* o+..".W+.9...... */ \
00067     0xe3,0x9f,0xc1,0xbe,0x19,0xec,0x26,0x83,0x5d,0x52,0x7c,0x32,0x88,0x0c,0x6d,0x09, /* ......&.]R|2..m. */ \
00068     0xf2,0x7d,0x0c,0x31,0xa2,0x14,0x49,0x39,0xfd,0x6a,0x2b,0xdd,0x88,0x02,0xb4,0x1a, /* .}.1..I9.j+..... */ \
00069     0x2a,0x39,0x39,0xa2,0x2a,0x3b,0xb4,0x25,0xc8,0xf7,0x31,0xc4,0x88,0x32,0xa3,0xe6, /* .99..;.%..1..2.. */ \
00070     0xd5,0x50,0xc9,0xc9,0x11,0x55,0x19,0x94,0xc9,0xa0,0x4c,0x06,0x23,0x32,0x18,0x16, /* .P...U....L.#2.. */ \
00071     0x37,0x2e,0x03,0x8b,0x1b,0xd7,0x6e,0x0e,0xc7,0x57,0x14,0x81,0xab,0x57,0x4b,0x7f, /* 7.....n..W...WK. */ \
00072     0x8d,0x5b,0x51,0x1e,0x77,0x0e,0xb7,0x48,0xf8,0x5d,0x65,0x5c,0x52,0x7c,0xda,0x73, /* .[Q.w..H.]e\R|.s */ \
00073     0xa9,0x94,0x28,0x60,0xb8,0x71,0xc0,0x25,0xc5,0x07,0xbc,0x41,0xe9,0x1d,0x9a,0x90, /* ..(`.q.%...A.... */ \
00074     0x7e,0x2a,0xe3,0x26,0xe3,0xdb,0x9e,0x4b,0xa5,0x44,0xd1,0xd7,0x1c,0x51,0x09,0x0b, /* ~..&...K.D...Q.. */ \
00075     0xf6,0xcd,0xf8,0x66,0xb0,0x6f,0x06,0xbb,0xc9,0xb8,0xc9,0xf8,0xb6,0xe7,0x52,0x29, /* ...f.o........R) */ \
00076     0x51,0xf4,0x35,0x47,0x54,0xc2,0x82,0x7d,0x33,0xbe,0x19,0xda,0x12,0xe4,0xfb,0x18, /* Q.5GT..}3....... */ \
00077     0x62,0x44,0x7d,0xd0,0xaf,0xb6,0xd2,0x8d,0x28,0xa2,0x1a,0x2a,0x39,0x39,0xa2,0xaa, /* bD}.....(...99.. */ \
00078     0x95,0x86,0x1c,0x51,0x60,0x10,0xd5,0x4e,0xa2,0xf9,0x58,0xd4,0xe1,0xa2,0xc0,0x20, /* ...Q`..N..X....  */ \
00079     0xaa,0x59,0x06,0xfb,0x66,0xb0,0x9b,0x8c,0x9b,0x8c,0x6f,0x7b,0x2e,0x95,0x12,0x45, /* .Y..f.....o{...E */ \
00080     0x5f,0x73,0x44,0x25,0x2c,0xd8,0x37,0xe3,0x9b,0xa1,0x2d,0x41,0xbe,0x8f,0x21,0x46, /* _sD%,.7...-A..!F */ \
00081     0xd4,0x07,0xfd,0x6a,0x2b,0xdd,0x88,0x52,0xd5,0x50,0xc9,0xc9,0x11,0x55,0xad,0x34, /* ...j+..R.P...U.4 */ \
00082     0xe4,0x88,0x02,0x83,0xa8,0x76,0x12,0xcd,0xc7,0xa2,0x0e,0x17,0x05,0x06,0x51,0xcd, /* .....v........Q. */ \
00083     0x32,0xd8,0x37,0x83,0xdd,0x64,0xdc,0x64,0x7c,0xdb,0x73,0xa9,0x94,0x28,0xfa,0x9a, /* 2.7..d.d|.s..(.. */ \
00084     0x23,0x2a,0x61,0xc1,0xbe,0x19,0xdf,0x0c,0x6d,0x09,0xf2,0x7d,0x0c,0x31,0xa2,0x3e, /* #.a.....m..}.1.> */ \
00085     0xe8,0x57,0x5b,0xe9,0x46,0x94,0xac,0x86,0x4a,0x4e,0x8e,0xa8,0x6a,0xa5,0x21,0x47, /* .W[.F...JN..j.!G */ \
00086     0x14,0x18,0x44,0xb5,0x93,0x68,0x3e,0x16,0x75,0xb8,0x28,0x30,0x88,0x6a,0x96,0xc1  /* ..D..h>.u.(0.j.. */
00087 #define DATACHUNK000001 \
00088     0xbe,0x19,0xec,0x26,0xe3,0x26,0xe3,0xdb,0x9e,0x4b,0xa5,0x44,0xd1,0xd7,0x1c,0x51, /* ...&.&...K.D...Q */ \
00089     0x09,0x0b,0xf6,0xcd,0xf8,0x66,0x68,0x4b,0x90,0xef,0x63,0x88,0x11,0xf5,0x41,0xbf, /* .....fhK..c...A. */ \
00090     0xda,0x4a,0x37,0xa2,0xd0,0xd5,0x50,0xc9,0xc9,0x11,0x55,0xad,0x34,0xe4,0x88,0x02, /* .J7...P...U.4... */ \
00091     0x0a,0x5e,0xed,0x24,0x9a,0x8f,0x45,0x1d,0x2e,0x0a,0x28,0x78,0x35,0xcb,0x60,0xdf, /* .^.$..E...(x5.`. */ \
00092     0x0c,0x76,0x93,0xc1,0x2e,0x29,0x3e,0x19,0x44,0x7b,0x2e,0x95,0x12,0x45,0x5f,0x73, /* .v...)>.D{...E_s */ \
00093     0x88,0xca,0x60,0x44,0x06,0x91,0xa1,0x2d,0x41,0xbe,0x8f,0x21,0x46,0x94,0x22,0x29, /* ..`D...-A..!F.") */ \
00094     0xa7,0x5f,0x6d,0xa5,0x1b,0x51,0x80,0x56,0x43,0x25,0x27,0x47,0x54,0x65,0x87,0xb6, /* ._m..Q.VC%'GTe.. */ \
00095     0x04,0xf9,0x3e,0x86,0x18,0x51,0x66,0xd4,0xbc,0x1a,0x2a,0x39,0x39,0xa2,0x2a,0x83, /* ..>..Qf....99... */ \
00096     0x11,0x19,0x0c,0x8b,0x1b,0x97,0xc1,0x56,0x43,0x33,0xd8,0x6a,0x68,0x06,0xa3,0xf0, /* .......VC3.jh... */ \
00097     0xc5,0x64,0x30,0xf8,0x1d,0x4f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* .d0..O.......... */ \
00098     0x00,0x00,0x01,0x00,0x00,0x00,0x74,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x9a,0x00, /* ......t......... */ \
00099     0x00,0x00,0x03,0x00,0x00,0x00,0xc3,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xf2,0x00, /* ................ */ \
00100     0x00,0x00,0x05,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x06,0x00,0x00,0x00,0x55,0x01, /* ....../.......U. */ \
00101     0x00,0x00,0x07,0x00,0x00,0x00,0x98,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0xb6,0x01, /* ................ */ \
00102     0x00,0x00,0x09,0x00,0x00,0x00,0x2d,0x02,0x00,0x00,0x0a,0x00,0x00,0x00,0x37,0x02, /* ......-.......7. */ \
00103     0x00,0x00,0x0b,0x00,0x00,0x00,0x57,0x02,0x00,0x00,0x0c,0x00,0x00,0x00,0x84,0x02, /* ......W......... */ \
00104     0x00,0x00,0x0d,0x00,0x00,0x00,0xc1,0x02,0x00,0x00,0x0e,0x00,0x00,0x00,0xee,0x02, /* ................ */ \
00105     0x00,0x00,0x0f,0x00,0x00,0x00,0x2b,0x03,0x00,0x00,0x10,0x00,0x00,0x00,0x58,0x03, /* ......+.......X. */ \
00106     0x00,0x00,0x11,0x00,0x00,0x00,0x95,0x03,0x00,0x00,0x12,0x00,0x00,0x00,0xc2,0x03, /* ................ */ \
00107     0x00,0x00,0x13,0x00,0x00,0x00,0x02,0x04,0x00,0x00,0x14,0x00,0x00,0x00,0x2e,0x04, /* ................ */ \
00108     0x00,0x00,0x08,0x00,0x00,0x00,0x4c,0x04,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x38, /* ......L........8 */ \
00109     0xda,0xf1,0x86,0x8e,0x51,0x1a,0xb7,0xa2,0xc0,0x90,0x20,0xab,0xc7,0x7a,0x7c,0xb5, /* ....Q..... ..z|. */ \
00110     0x45,0x89,0x02,0x30,0x0d,0x28,0x08,0xc0,0x00,0x83,0x00,0x10,0x08,0xb0,0x02,0x3c, /* E..0.(.........< */ \
00111     0xc3,0xe3,0x16,0xab,0x51,0x0d,0x1d,0xa3,0x34,0x6e,0x45,0x21,0xab,0xd1,0x8e,0x5b, /* ....Q...4nE!...[ */ \
00112     0x05,0x43,0x2b,0x2d,0x0a,0xfe,0x13,0x30,0xc6,0x40,0x83,0x06,0x8d,0x04,0x0d,0x14, /* .C+-...0.@...... */ \
00113     0x89,0x1b,0x14,0x03,0x07,0x09,0x12,0x8c,0x01,0x09,0x10,0x20,0x68,0x0f,0x1f,0x27, /* ........... h..' */ \
00114     0x41,0x68,0xab,0x2e,0xad,0x9f,0x6a,0xb4,0xd2,0x30,0x8b,0x03,0x54,0xba,0x51,0x84, /* Ah....j..0..T.Q. */ \
00115     0xf4,0x43,0x7b,0xf8,0x38,0x09,0x04,0xee,0xe5,0x35,0x6e,0x45,0x21,0x99,0xc1,0xbd, /* .C{.8....5nE!... */ \
00116     0x91,0x9a,0x23,0xd1,0x6a,0x2b,0xc3,0xe3,0xce,0xe1,0xb6,0xb9,0xb4,0x28,0x52,0xa2, /* ..#.j+.......(R. */ \
00117     0x46,0x54,0x35,0xf7,0xcb,0x35,0x0a,0x7e,0x51,0xd5,0xc7,0x51,0x28,0x3e,0xa2,0xaa, /* FT5..5.~Q..Q(>.. */ \
00118     0x5b,0x8d,0x81,0x8e,0x11,0x55,0x2c,0x83,0x79,0xdc,0x62,0x35,0x2a,0x01,0x3c,0x00, /* [....U,.y.b5..<. */ \
00119     0x00,0x00,0x15,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0xb5,0x00, /* ......=......... */ \
00120     0x00,0x00,0x17,0x00,0x00,0x00,0xc1,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0xcb,0x00, /* ................ */ \
00121     0x00,0x00,0x18,0x00,0x00,0x00,0xcd,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0xd6,0x00, /* ................ */ \
00122     0x00,0x00,0x13,0x00,0x00,0x00,0xb1,0x1a,0xda,0x7a,0x45,0x79,0xdc,0x7e,0xec,0x2b, /* .........zEy.~.+ */ \
00123     0xe3,0x92,0xe2,0xd3,0x9e,0x4b,0xa5,0x44,0x01,0xc3,0x8d,0x03,0x2e,0x29,0x3e,0xe0, /* .....K.D.....)>. */ \
00124     0x0d,0x4a,0xef,0xd0,0x84,0xf4,0x53,0x19,0x37,0x19,0xdf,0x0c,0xf6,0xcd,0x60,0x37, /* .J....S.7.....`7 */ \
00125     0x19,0xec,0x92,0xe2,0x93,0x21,0x1b,0x6e,0x06,0x2b,0xca,0xe3,0x16,0xab,0x51,0x48, /* .....!.n.+....QH */ \
00126     0xb4,0xe3,0x95,0x41,0x91,0x3f,0x6e,0x13,0x89,0x44,0x06,0xa3,0xc8,0x1f,0xb7,0x19, /* ...A.?n..D...... */ \
00127     0x4c,0x66,0x10,0x09,0xb0,0xa5,0x14,0x01,0x48,0x30,0x22,0x03,0x8b,0x1b,0xd7,0xd2, /* Lf......H0"..... */ \
00128     0x5f,0xe3,0x56,0x14,0x56,0xf3,0x41,0xc2,0xef,0xaa,0xdd,0x1c,0x8e,0xaf,0x28,0x02, /* _.V.V.A.......(. */ \
00129     0x57,0xaf,0x1e,0xeb,0x8f,0x21,0x46,0x94,0x23,0xf9,0x35,0x21,0xcd,0x19,0x16,0x37, /* W....!F.#.5!...7 */ \
00130     0x0e,0xc4,0xca,0xcb,0xca,0xb8,0xa4,0xf8,0xb4,0xe7,0x52,0x29,0x51,0xc0,0x70,0xe3, /* ..........R)Q.p. */ \
00131     0x80,0x4b,0x8a,0x0f,0x78,0x83,0xd2,0x3b,0x34,0x21,0xfd,0x54,0xc6,0x4d,0xc6,0x37, /* .K..x..;4!.T.M.7 */ \
00132     0x83,0x7d,0x33,0xd8,0x4d,0xc6,0x4d,0xc6,0x37,0x43,0x5b,0x82,0x7c,0x5b,0xe9,0x46, /* .}3.M.M.7C[.|[.F */ \
00133     0x94,0xc7,0x2d,0x56,0xa3,0xaa,0x95,0x86,0x1c,0x51,0xe0,0x20,0xab,0x8f,0x21,0x46, /* ..-V.....Q. ..!F */ \
00134     0x14,0x56,0xf3,0xa9,0x0c,0xca,0x64,0xb0,0x6f,0x06,0xbb,0xc9,0x60,0x97,0x14,0x9f, /* .V....d.o...`... */ \
00135     0x0c,0x22,0x43,0x5b,0x82,0x7c,0x1f,0x43,0x8c,0x28,0x45,0x52,0x4e,0xbf,0x1a,0x2a, /* ."C[.|.C.(ERN... */ \
00136     0x39,0x39,0xa2,0x90,0x48,0x64,0x65,0x30,0x22,0x83,0x61,0x71,0xe3,0x32,0xd8,0x6a, /* 99..Hde0".aq.2.j */ \
00137     0x68,0x06,0x5b,0x0d,0xcd,0x60,0x14,0xbe,0x98,0x0c,0x06,0xbf,0xe3,0x09,0x00,0x00, /* h.[..`.......... */ \
00138     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x3e,0x00, /* ..............>. */ \
00139     0x00,0x00,0x1b,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0xfa,0x00, /* ......m......... */ \
00140     0x00,0x00,0x1d,0x00,0x00,0x00,0x6c,0x01,0x00,0x00,0x1e,0x00,0x00,0x00,0x3c,0x21, /* ......l.......<! */ \
00141     0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x48,0x54,0x4d,0x4c,0x20,0x50,0x55,0x42, /* DOCTYPE HTML PUB */ \
00142     0x4c,0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,0x43,0x2f,0x2f,0x44,0x54,0x44, /* LIC "-//W3C//DTD */ \
00143     0x20,0x48,0x54,0x4d,0x4c,0x20,0x34,0x2e,0x30,0x31,0x2f,0x2f,0x45,0x4e,0x22,0x20, /*  HTML 4.01//EN"  */ \
00144     0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f, /* "http://www.w3.o */ \
00145     0x72,0x67,0x2f,0x54,0x52,0x2f,0x68,0x74,0x6d,0x6c,0x34,0x2f,0x73,0x74,0x72,0x69, /* rg/TR/html4/stri */ \
00146     0x63,0x74,0x2e,0x64,0x74,0x64,0x22,0x3e,0x0d,0x0a,0x3c,0x68,0x74,0x6d,0x6c,0x3e, /* ct.dtd">..<html> */ \
00147     0x3c,0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x6d,0x65,0x74,0x61,0x20,0x68,0x74, /* <head>..<meta ht */ \
00148     0x74,0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x43,0x6f,0x6e,0x74,0x65,0x6e, /* tp-equiv="Conten */ \
00149     0x74,0x2d,0x54,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x3d, /* t-Type" content= */ \
00150     0x22,0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72, /* "text/html; char */ \
00151     0x73,0x65,0x74,0x3d,0x49,0x53,0x4f,0x2d,0x38,0x38,0x35,0x39,0x2d,0x31,0x22,0x3e  /* set=ISO-8859-1"> */
00152 #define DATACHUNK000002 \
00153     0x0d,0x0a,0x3c,0x74,0x69,0x74,0x6c,0x65,0x3e,0x4d,0x6f,0x42,0x61,0x43,0x6f,0x6e, /* ..<title>MoBaCon */ \
00154     0x40,0x65,0x57,0x69,0x63,0x68,0x74,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x0d, /* @eWicht</title>. */ \
00155     0x0a,0x3c,0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,0x6c,0x3d,0x22,0x73,0x74,0x79,0x6c, /* .<link rel="styl */ \
00156     0x65,0x73,0x68,0x65,0x65,0x74,0x22,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x73,0x74, /* esheet" href="st */ \
00157     0x79,0x6c,0x65,0x2e,0x63,0x73,0x73,0x22,0x20,0x54,0x59,0x50,0x45,0x3d,0x22,0x74, /* yle.css" TYPE="t */ \
00158     0x65,0x78,0x74,0x2f,0x63,0x73,0x73,0x22,0x20,0x4d,0x45,0x44,0x49,0x41,0x3d,0x22, /* ext/css" MEDIA=" */ \
00159     0x73,0x63,0x72,0x65,0x65,0x6e,0x22,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x65,0x61,0x64, /* screen">..</head */ \
00160     0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x3e,0x3c,0x64,0x69,0x76,0x20,0x69,0x64, /* >..<body><div id */ \
00161     0x3d,0x22,0x73,0x69,0x74,0x65,0x22,0x3e,0xb1,0x1a,0xda,0x7a,0x45,0x79,0xdc,0x7e, /* ="site">...zEy.~ */ \
00162     0xec,0x2b,0xbb,0xe3,0x92,0xe2,0xd3,0x9e,0x4b,0xa5,0x44,0x01,0xc3,0x8d,0x03,0x2e, /* .+......K.D..... */ \
00163     0x29,0x3e,0xe0,0x4d,0x3b,0xc9,0x39,0x4d,0x48,0x3f,0x95,0x71,0x93,0xf1,0x6d,0xcf, /* )>.M;.9MH?.q..m. */ \
00164     0xa5,0x52,0xa2,0xe8,0x6b,0x8e,0xa8,0x84,0x05,0xfb,0x66,0x7c,0x33,0xd8,0x37,0x83, /* .R..k.....f|3.7. */ \
00165     0xdd,0x64,0xdc,0x64,0x7c,0xdb,0x73,0xa9,0x94,0x28,0xfa,0x9a,0x23,0x2a,0x61,0xc1, /* .d.d|.s..(..#.a. */ \
00166     0xbe,0x19,0xdf,0x0c,0xf6,0xcd,0x60,0x37,0x19,0x37,0x19,0xdf,0xf6,0x38,0x57,0x84, /* ......`7.7...8W. */ \
00167     0xb4,0xa2,0xc0,0x2b,0x01,0xb6,0x94,0x22,0x00,0x09,0xf6,0xcd,0x60,0x37,0x19,0x37, /* ...+..."....`7.7 */ \
00168     0x19,0xdf,0xf6,0x5c,0x2a,0x25,0x8a,0xbe,0xe6,0x88,0x4a,0x58,0xb0,0x6f,0xc6,0x37, /* ...\.%....JX.o.7 */ \
00169     0x83,0x7d,0x33,0xd8,0x4d,0xc6,0x4d,0xc6,0xb7,0x3d,0x97,0x4a,0x89,0xa2,0xaf,0x39, /* .}3.M.M..=.J...9 */ \
00170     0xa2,0x12,0x16,0xec,0x9b,0xf1,0xcd,0x06,0x00,0x00,0x83,0x7d,0x33,0xd8,0x4d,0xc6, /* ...........}3.M. */ \
00171     0x4d,0xc6,0xb7,0x3d,0x97,0x4a,0x89,0xa2,0xaf,0x39,0xa2,0x12,0x16,0xec,0x9b,0xf1, /* M..=.J...9...... */ \
00172     0xcd,0x60,0xdf,0x0c,0x76,0x93,0x71,0x93,0xf1,0x6d,0xcf,0xa5,0x52,0xa2,0xe8,0x6b, /* .`..v.q..m..R..k */ \
00173     0x8e,0xa8,0x84,0x05,0xfb,0x66,0x7c,0x33,0xd8,0x37,0x83,0xdd,0x64,0xdc,0x64,0x7c, /* .....f|3.7..d.d| */ \
00174     0xdb,0x73,0xa9,0x94,0x28,0xfa,0x9a,0x23,0x2a,0x61,0xc1,0xbe,0x19,0xdf,0x44,0x72, /* .s..(..#.a....Dr */ \
00175     0xdc,0x4b,0x1e,0xec,0x9b,0xc1,0x6e,0x32,0x6e,0x32,0xbe,0xed,0xb9,0x54,0x4a,0x14, /* .K....n2n2...TJ. */ \
00176     0x7d,0xcd,0x11,0x95,0xb0,0x60,0xdf,0x8c,0x6f,0x06,0xfb,0x66,0xb0,0x9b,0x8c,0x9b, /* }....`..o..f.... */ \
00177     0x8c,0x6f,0x7b,0x9c,0x2b,0x42,0x5a,0x51,0xe0,0x95,0x00,0x5b,0x4a,0x11,0x80,0x04, /* .o{.+BZQ...[J... */ \
00178     0xfb,0x66,0xb0,0x9b,0x8c,0x9b,0x8c,0x6f,0x7b,0x2e,0x95,0x12,0x45,0x5f,0x73,0x44, /* .f.....o{...E_sD */ \
00179     0x25,0x2c,0xd8,0x37,0xe3,0x9b,0xc1,0xbe,0x19,0xec,0x26,0xe3,0x26,0xe3,0xdb,0x9e, /* %,.7......&.&... */ \
00180     0x4b,0xa5,0x44,0xd1,0xd7,0x1c,0x51,0x09,0x0b,0xf6,0xcd,0xf8,0x66,0xb0,0x6f,0x06, /* K.D...Q.....f.o. */ \
00181     0xbb,0xc9,0xb8,0xc9,0xf8,0xb6,0xe7,0x52,0x29,0x51,0xf4,0x35,0x47,0x54,0xc2,0x82, /* .......R)Q.5GT.. */ \
00182     0x7d,0x33,0xbe,0x19,0xec,0x9b,0xc1,0x6e,0x32,0xd8,0x25,0xc5,0x27,0x03,0x8b,0x1b, /* }3.....n2.%.'... */ \
00183     0xd7,0x6e,0x0e,0xc7,0x57,0x14,0x6a,0x5e,0x2d,0xfd,0x35,0x6e,0x45,0x69,0xbb,0x83, /* .n..W.j^-.5nEi.. */ \
00184     0x46,0xc2,0xef,0x2a,0x43,0x5b,0x82,0x7c,0x1f,0x43,0x8c,0x28,0x45,0x52,0x4e,0xbf, /* F...C[.|.C.(ERN. */ \
00185     0xda,0x4a,0x37,0xa2,0xc0,0xaa,0xa1,0x92,0x93,0x23,0xaa,0x3a,0x3b,0xb4,0x25,0xc8, /* .J7......#.:;.%. */ \
00186     0xf7,0x31,0xc4,0x88,0x52,0x24,0xe5,0xf4,0xab,0xad,0x74,0x23,0x0a,0xbc,0x1a,0x2a, /* .1..R$....t#.... */ \
00187     0x39,0x39,0xa2,0x2a,0x83,0x61,0x71,0xe3,0x32,0xd8,0x6a,0x68,0x06,0x5b,0x0d,0xcd, /* 99...aq.2.jh.[.. */ \
00188     0x60,0x14,0xbe,0x98,0x0c,0x06,0xbf,0xe3,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* `............... */ \
00189     0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x20,0x00,0x00, /* .........O... .. */ \
00190     0x00,0x59,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x79,0x00,0x00,0x00,0x35,0x00,0x00, /* .Y...4...y...5.. */ \
00191     0x00,0x83,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0xc7,0x00,0x00,0x00,0x23,0x00,0x00, /* .....6.......#.. */ \
00192     0x00,0xd1,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x0c,0x00,0x00, /* .....$.......... */ \
00193     0x00,0xfb,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0xfd,0x00,0x00,0x00,0x26,0x00,0x00, /* .....%.......&.. */ \
00194     0x00,0x1e,0x01,0x00,0x00,0x0e,0x00,0x00,0x00,0x28,0x01,0x00,0x00,0x27,0x00,0x00, /* .........(...'.. */ \
00195     0x00,0x48,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x52,0x01,0x00,0x00,0x28,0x00,0x00, /* .H.......R...(.. */ \
00196     0x00,0x72,0x01,0x00,0x00,0x29,0x00,0x00,0x00,0x7c,0x01,0x00,0x00,0x2a,0x00,0x00, /* .r...)...|...... */ \
00197     0x00,0xa2,0x01,0x00,0x00,0x2b,0x00,0x00,0x00,0xac,0x01,0x00,0x00,0x2c,0x00,0x00, /* .....+.......,.. */ \
00198     0x00,0xf0,0x01,0x00,0x00,0x2d,0x00,0x00,0x00,0xfa,0x01,0x00,0x00,0x2e,0x00,0x00, /* .....-.......... */ \
00199     0x00,0x1a,0x02,0x00,0x00,0x0c,0x00,0x00,0x00,0x24,0x02,0x00,0x00,0x2f,0x00,0x00, /* .........$.../.. */ \
00200     0x00,0x44,0x02,0x00,0x00,0x30,0x00,0x00,0x00,0x4e,0x02,0x00,0x00,0x31,0x00,0x00, /* .D...0...N...1.. */ \
00201     0x00,0xab,0x02,0x00,0x00,0x32,0x00,0x00,0x00,0xd4,0x02,0x00,0x00,0x33,0x00,0x00, /* .....2.......3.. */ \
00202     0x00,0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xed,0xbd,0x07,0x60,0x1c, /* ..............`. */ \
00203     0x49,0x96,0x25,0x26,0x2f,0x6d,0xca,0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1, /* I.%&/m.{.J.J..t. */ \
00204     0x08,0x80,0x60,0x13,0x24,0xd8,0x90,0x40,0x10,0xec,0xc1,0x88,0xcd,0xe6,0x92,0xec, /* ..`.$..@........ */ \
00205     0x1d,0x69,0x47,0x23,0x29,0xab,0x2a,0x81,0xca,0x65,0x56,0x65,0x5d,0x66,0x16,0x40, /* .iG#)....eVe]f.@ */ \
00206     0xcc,0xed,0x9d,0xbc,0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xba, /* ......{....{.... */ \
00207     0x3b,0x9d,0x4e,0x27,0xf7,0xdf,0xff,0x3f,0x5c,0x66,0x64,0x01,0x6c,0xf6,0xce,0x4a, /* ;.N'...?\fd.l..J */ \
00208     0xda,0xc9,0x9e,0x21,0x80,0xaa,0xc8,0x1f,0x3f,0x7e,0x7c,0x1f,0x3f,0x22,0x1e,0xff, /* ...!....?~|.?".. */ \
00209     0x1e,0xef,0x16,0x65,0x7a,0x99,0xd7,0x4d,0x51,0x2d,0x3f,0xfb,0x68,0x77,0xbc,0xf3, /* ...ez..MQ-?.hw.. */ \
00210     0x51,0x9a,0x2f,0xa7,0xd5,0xac,0x58,0x5e,0x7c,0xf6,0xd1,0x57,0x6f,0x9e,0x6d,0x1f, /* Q./...X^|..Wo.m. */ \
00211     0x7c,0xf4,0x7b,0x1c,0xfd,0xc6,0xc9,0xe3,0x77,0xcd,0xa3,0x66,0x3a,0xcf,0x17,0x59, /* |.{.....w..f:..Y */ \
00212     0x4a,0x2f,0x2c,0x9b,0x47,0xef,0x9a,0xcf,0x3e,0x9a,0xb7,0xed,0xea,0xd1,0xdd,0xbb, /* J/,.G...>....... */ \
00213     0x57,0x57,0x57,0xe3,0xab,0x7b,0xe3,0xaa,0xbe,0xb8,0xbb,0xb7,0xb3,0xb3,0x7b,0xf7, /* WWW..{........{. */ \
00214     0xf7,0xfe,0xe2,0xf9,0x6b,0x6e,0x4a,0xa0,0xca,0x7c,0x91,0x2f,0xdb,0x67,0x55,0xbd, /* ....knJ..|./.gU. */ \
00215     0x78,0x9a,0x9f,0x67,0xeb,0xb2,0xfd,0xec,0xa3,0x5f,0xb4,0xce,0xca,0xe2,0xbc,0xc8, /* x..g....._...... */ \
00216     0x67,0x1f,0x11,0xdc,0x1f,0x03,0x60,0x6d,0x95,0x2e,0xb3,0x45,0xfe,0xd9,0x47,0xd3  /* g.....`m...E..G. */
00217 #define DATACHUNK000003 \
00218     0x6a,0xb1,0xa8,0x96,0xfc,0x25,0x7f,0x4b,0x7f,0xaf,0xca,0xfc,0xdd,0x9b,0xeb,0x55, /* j....%.K.......U */ \
00219     0xce,0x9f,0xf1,0x87,0x59,0xdb,0xd6,0xc5,0x64,0xdd,0xe6,0xfa,0x52,0x99,0x2d,0x2f, /* ....Y...d...R.-/ */ \
00220     0xd6,0xd9,0x45,0xfe,0x51,0xba,0x6e,0xe8,0xcf,0x6a,0xd5,0xd2,0x78,0xb2,0xf2,0xa3, /* ..E.Q.n..j..x... */ \
00221     0x74,0x66,0xba,0xdd,0x11,0x88,0xf2,0x7a,0x53,0x00,0xa6,0x03,0x29,0x9f,0xd6,0x79, /* tf.....zS...)..y */ \
00222     0x43,0x50,0xa7,0x78,0x35,0x9d,0x64,0x80,0x43,0x1f,0xae,0x97,0x4d,0x71,0xb1,0xcc, /* CP.x5.d.C...Mq.. */ \
00223     0x67,0x4f,0xae,0xdb,0xdc,0x80,0x90,0xe6,0x8b,0x62,0x79,0xb6,0x9c,0x96,0xeb,0xa6, /* gO.......by..... */ \
00224     0xb8,0xcc,0xd3,0xcb,0xac,0x5c,0xe7,0xe8,0xe5,0x6e,0xd8,0x26,0x7b,0xd7,0x6b,0xb3, /* .....\...n.&{.k. */ \
00225     0xeb,0xda,0x3c,0xbe,0x1b,0x76,0x6b,0x50,0xbc,0x1b,0xc3,0xf1,0xf1,0xef,0xba,0xbd, /* ..<..vkP........ */ \
00226     0xfd,0x55,0x93,0xa7,0x3b,0xe9,0x79,0x55,0xa7,0x9f,0xe7,0xf5,0x22,0x5b,0x8e,0xd2, /* .U..;.yU...."[.. */ \
00227     0x5d,0xfe,0xeb,0x74,0x79,0x51,0x16,0xcd,0x7c,0x7b,0x5b,0x49,0x74,0xd7,0xa7,0xd1, /* ]..tyQ..|{[It... */ \
00228     0x06,0xb2,0x4d,0x67,0x65,0x71,0x31,0x6f,0xff,0xbf,0x40,0xb6,0xbd,0xfb,0xf7,0x3f, /* ..Mgeq1o..@....? */ \
00229     0x84,0x70,0xcb,0xa2,0x4d,0x8b,0x26,0x6d,0xf2,0x69,0xb5,0x9c,0x35,0x63,0xa2,0xe2, /* .p..M.&m.i..5c.. */ \
00230     0x22,0xcf,0x96,0x4d,0x9a,0x95,0x57,0xd9,0x75,0x93,0x56,0xe7,0xe7,0xa3,0x94,0xba, /* "..M..W.u.V..... */ \
00231     0xe8,0x7c,0xba,0x7c,0x5f,0x8a,0xb6,0xd5,0xc5,0x45,0x49,0x6c,0xd8,0x52,0xf7,0x4c, /* .|.|_....EIl.R.L */ \
00232     0x88,0x49,0x55,0x95,0x04,0x72,0x98,0xc2,0xe7,0x59,0xd9,0x58,0x12,0x01,0xd5,0x67, /* .IU..r...Y.X...g */ \
00233     0xf8,0x40,0xf1,0x98,0x15,0x75,0x2e,0x94,0x65,0xc0,0x24,0x95,0x84,0x53,0xba,0x5a, /* .@...u..e.$..S.Z */ \
00234     0x37,0x73,0xfc,0xda,0xce,0x73,0x91,0xd6,0xbc,0x4e,0x09,0x87,0xb6,0x5a,0x8e,0xd3, /* 7s...s...N...Z.. */ \
00235     0x37,0xf5,0x7a,0xc3,0xcb,0xc5,0x79,0x3a,0xad,0xab,0xa6,0x31,0x6f,0xff,0x20,0xaf, /* 7.z...y:...1o. . */ \
00236     0xab,0x74,0x55,0x15,0xcb,0x76,0xfc,0xbe,0x23,0xcd,0xd6,0x6d,0x55,0xac,0xde,0x67, /* .tU..v..#..mU..g */ \
00237     0xa4,0x2d,0xa1,0x66,0xa6,0x30,0x06,0xb1,0xc9,0x6b,0xd2,0x44,0x1e,0xc4,0x6c,0x79, /* .-.f.0...k.D..ly */ \
00238     0xfd,0xd5,0xab,0xb3,0x2e,0xc0,0x0d,0x10,0xce,0xb3,0xa6,0x6d,0xda,0xac,0x6e,0xdf, /* ...........m..n. */ \
00239     0x07,0xad,0xde,0x04,0xbc,0x5e,0xe5,0xf9,0x2c,0x5d,0xaf,0x52,0x06,0x85,0x5f,0xb2, /* .....^..,].R.._. */ \
00240     0xe5,0x2c,0x25,0xbe,0x59,0x82,0x9c,0xa0,0x5c,0x95,0x0a,0xae,0xef,0x4d,0xb4,0x76, /* .,%.Y...\....M.v */ \
00241     0x5d,0x4f,0xaa,0x0f,0x42,0x8e,0x44,0x3d,0x9b,0x94,0x79,0xca,0x90,0xcc,0xec,0x6f, /* ]O..B.D=..y....o */ \
00242     0xc2,0x83,0x3f,0xea,0x28,0x51,0xfe,0x4c,0xd5,0x2e,0xff,0xed,0xfe,0xb4,0x5a,0x78, /* ..?.(Q.L......Zx */ \
00243     0x79,0x5e,0x5c,0xdc,0xa0,0x85,0x9b,0xfc,0x17,0xad,0x09,0x03,0x2b,0x67,0x1e,0x94, /* y^\.........+g.. */ \
00244     0x3a,0x3f,0xb7,0xaa,0x3c,0x25,0x91,0xff,0x72,0x3a,0x5d,0xd7,0x8d,0x27,0xe9,0x22, /* :?..<%..r:]..'." */ \
00245     0xaa,0x01,0x80,0x18,0xc1,0xd4,0x34,0x79,0x24,0x83,0xcc,0x2f,0x2f,0x86,0x29,0xb6, /* ......4y$..//.). */ \
00246     0x3b,0x36,0x0a,0xf6,0x16,0x23,0x17,0x2c,0xd8,0x5a,0x1d,0xfd,0xc6,0xc9,0xff,0x03, /* ;6...#.,.Z...... */ \
00247     0x48,0xc1,0x34,0x60,0x0e,0x07,0x00,0x00,0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00, /* H.4`............ */ \
00248     0x04,0x00,0xed,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d,0xca,0x7b,0x7f, /* .....`.I.%&/m.{. */ \
00249     0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60,0x13,0x24,0xd8,0x90,0x40,0x10, /* J.J..t...`.$..@. */ \
00250     0xec,0xc1,0x88,0xcd,0xe6,0x92,0xec,0x1d,0x69,0x47,0x23,0x29,0xab,0x2a,0x81,0xca, /* ........iG#).... */ \
00251     0x65,0x56,0x65,0x5d,0x66,0x16,0x40,0xcc,0xed,0x9d,0xbc,0xf7,0xde,0x7b,0xef,0xbd, /* eVe]f.@......{.. */ \
00252     0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xba,0x3b,0x9d,0x4e,0x27,0xf7,0xdf,0xff,0x3f,0x5c, /* ..{....;.N'...?\ */ \
00253     0x66,0x64,0x01,0x6c,0xf6,0xce,0x4a,0xda,0xc9,0x9e,0x21,0x80,0xaa,0xc8,0x1f,0x3f, /* fd.l..J...!....? */ \
00254     0x7e,0x7c,0x1f,0x3f,0x22,0xbe,0x95,0xfe,0xe2,0x45,0x56,0x5f,0x14,0xcb,0x47,0xe9, /* ~|.?"....EV_..G. */ \
00255     0xce,0xe1,0x2a,0x9b,0xcd,0x8a,0xe5,0x05,0x7e,0x2d,0x8b,0xa6,0xdd,0x6e,0xda,0xeb, /* ........~-...n.. */ \
00256     0x32,0x7f,0x94,0x2e,0xab,0x65,0x7e,0xf8,0x4b,0x7e,0xe3,0x64,0xde,0x2e,0xca,0xf4, /* 2....e~.K~.d.... */ \
00257     0x17,0x57,0x97,0x79,0x7d,0x5e,0x56,0x57,0xdb,0xd7,0x8f,0xd2,0x66,0x5a,0x57,0x65, /* .W.y}^VW....fZWe */ \
00258     0x89,0xef,0x7e,0xe3,0x64,0x52,0xcd,0xae,0x2d,0xb0,0x9d,0xd5,0xbb,0xc3,0x49,0x36, /* ..~.dR..-.....I6 */ \
00259     0x7d,0x7b,0x51,0x57,0xeb,0xe5,0xec,0xd1,0xba,0x2e,0xb7,0x3e,0x9a,0x5c,0x8c,0x2f, /* }{QW.......>.\./ */ \
00260     0x8a,0xf3,0x8f,0xee,0x1c,0xa6,0x93,0x8b,0x69,0x55,0x56,0xf5,0xa3,0xf4,0xc7,0x1f, /* ........iUV..... */ \
00261     0x3e,0xdc,0xa1,0xe7,0x30,0x3d,0xaf,0x96,0xd4,0x5d,0xf1,0x03,0xea,0x6d,0x77,0x67, /* >...0=...]...mwg */ \
00262     0x67,0xbc,0xb3,0xfb,0xbb,0xeb,0x67,0xe7,0xd9,0xa2,0x28,0xa9,0xa7,0xe3,0xba,0xc8, /* g.....g...(..... */ \
00263     0xca,0xd1,0xb7,0xf3,0xf2,0x32,0x6f,0x8b,0x69,0x36,0x6a,0xb2,0x65,0xb3,0xdd,0xe4, /* .....2o.i6j.e... */ \
00264     0x75,0x71,0x7e,0x98,0x2e,0x8a,0xe5,0xf6,0x55,0x31,0x6b,0xe7,0x8f,0xd2,0xfd,0xdd, /* uq~.....U1k..... */ \
00265     0x7c,0x01,0x74,0xda,0x59,0xfa,0x8b,0xf1,0xfe,0xa3,0xdd,0xdd,0xd5,0x3b,0x7d,0x39, /* |.t.Y........;}9 */ \
00266     0x75,0x6f,0xa7,0xfe,0xeb,0x82,0xcb,0x8f,0x3f,0xa3,0xe7,0xe4,0xe4,0x30,0x35,0x44, /* uo......?....05D */ \
00267     0xc0,0x8b,0x7b,0xf4,0x7f,0xfd,0x49,0x40,0xb3,0xf4,0x17,0x1b,0xbc,0x9f,0xf1,0x83, /* ..{...I@........ */ \
00268     0xcf,0x1e,0xcd,0x41,0x10,0xff,0x1b,0x8c,0x89,0x29,0x32,0xdf,0x4d,0x7f,0xb1,0x47, /* ...A.....)2.M..G */ \
00269     0x84,0x1f,0x9f,0x4e,0x65,0xb0,0xf3,0xbc,0xb8,0x98,0xb7,0x8f,0x3e,0x05,0x91,0xfc, /* ...Ne.......>... */ \
00270     0x81,0x8f,0xef,0x13,0xf2,0x7e,0x0f,0x84,0x4e,0x99,0xb7,0x6d,0x5e,0x6f,0x37,0xab, /* .....~..N..m^o7. */ \
00271     0x6c,0x0a,0xa4,0xc6,0xf7,0xa8,0x49,0x9b,0xbf,0x6b,0xb7,0xb3,0xb2,0xb8,0x58,0x3e, /* l.....I..k....X> */ \
00272     0x9a,0xe6,0x4b,0xfa,0xfa,0x90,0x30,0xc0,0xb8,0x4a,0xfd,0x74,0x52,0xb5,0x6d,0xb5, /* ..K...0..J.tR.m. */ \
00273     0x38,0x9c,0x54,0xf5,0x8c,0xde,0x6d,0xab,0xd5,0xa3,0xf4,0x1e,0x8d,0xa2,0xa9,0xca, /* 8.T...m......... */ \
00274     0x62,0x96,0xfe,0xf8,0xf9,0xf9,0xce,0xc1,0x4e,0x6e,0xbe,0x95,0xb6,0xb1,0x06,0x65, /* b.......Nn.....e */ \
00275     0xb1,0xcc,0xb7,0x7d,0x5c,0xc1,0x02,0x7b,0x66,0x8a,0xcd,0x8b,0x4a,0xf0,0xdf,0x38, /* ...}\..{f...J..8 */ \
00276     0xf9,0xf1,0xa6,0x68,0xf3,0xf4,0x17,0x7b,0xc8,0xa5,0x65,0x7e,0xde,0x1e,0x5a,0xf6, /* ...h...{..e~..Z. */ \
00277     0x4a,0xb3,0x75,0x5b,0x1d,0xea,0x44,0x3d,0xdc,0xf9,0xdd,0x3d,0x76,0xe3,0x91,0x0b, /* J.u[..D=...=v... */ \
00278     0x94,0x65,0x76,0x49,0x53,0x57,0x56,0x59,0xfb,0x88,0x5f,0x4f,0xe5,0x85,0x5d,0x0c, /* .evISWVY.._O..]. */ \
00279     0x3c,0xd5,0xae,0x79,0x44,0xe8,0xd8,0x83,0x70,0x20,0x10,0xf8,0x7d,0x3b,0x29,0x4c, /* <..yD...p ..};)L */ \
00280     0xdd,0x2b,0x19,0xc2,0xa4,0x2a,0x67,0xae,0x05,0xcd,0x4c,0x38,0xfe,0x5d,0x37,0x7e, /* .+....g...L8.]7~ */ \
00281     0x99,0x42,0x6f,0x6a,0x76,0x69,0xfe,0xbd,0x89,0x39,0x39,0xd9,0x81,0x80,0x38,0xea  /* .Bojvi...99...8. */
00282 #define DATACHUNK000004 \
00283     0xec,0x7e,0x4a,0xdf,0x77,0x67,0x6a,0xd7,0xcc,0xd4,0x2c,0x9f,0x56,0x75,0xd6,0x16, /* .~J.wgj...,.Vu.. */ \
00284     0xd5,0x52,0x45,0x69,0x56,0x34,0xab,0x32,0xbb,0x7e,0x34,0x29,0xab,0xe9,0x5b,0x3b, /* .REiV4.2.~4)..[; */ \
00285     0x86,0x03,0x42,0x80,0xe0,0xa4,0xf8,0xb9,0x27,0x0c,0xc7,0xa8,0x96,0x45,0x9a,0x8d, /* ..B.....'....E.. */ \
00286     0xb3,0x69,0x5b,0x5c,0xe6,0x01,0x3b,0x89,0x4c,0xad,0x4b,0xea,0x57,0xe4,0x8a,0x24, /* .i[\..;.L.K.W..$ */ \
00287     0x87,0x5e,0xbd,0xbf,0xf3,0xbb,0x53,0x2f,0xdb,0x75,0xbe,0xca,0xb3,0x56,0x91,0x36, /* .^....S/.u...V.6 */ \
00288     0xcc,0x34,0x48,0x0e,0xea,0x63,0x5d,0xda,0x99,0x05,0xdd,0x1f,0xa5,0x7b,0x20,0xb8, /* .4H..c]......{ . */ \
00289     0x12,0x5f,0x27,0xd9,0x6b,0x0b,0xac,0x94,0xbe,0x42,0x22,0x30,0xc8,0x0f,0x85,0x26, /* ._'.k....B"0...& */ \
00290     0x53,0xea,0x93,0xb8,0xbe,0x8b,0x2d,0x38,0xc8,0x67,0x0f,0xf0,0x8b,0x87,0xde,0xae, /* S.....-8.g...... */ \
00291     0x9d,0x41,0x95,0xdd,0x00,0x59,0xc0,0x8e,0x21,0x4b,0xfd,0x8d,0x9f,0x55,0xf5,0xe2, /* .A...Y..!K...U.. */ \
00292     0x4d,0x36,0x29,0xf3,0xdd,0x90,0xb9,0x55,0xf4,0x0c,0x4f,0x7a,0xe2,0x90,0x1a,0x10, /* M6)....U..Oz.... */ \
00293     0xac,0x05,0x85,0xcd,0xa8,0xef,0x32,0x5b,0x35,0x24,0xe6,0xe6,0x37,0x52,0x83,0xfc, /* ......2[5$..7R.. */ \
00294     0x55,0x84,0xf5,0x3a,0xdd,0x42,0x99,0x29,0x98,0x9a,0xd1,0xbd,0xf1,0x8d,0xf1,0x3c, /* U..:.B.).......< */ \
00295     0xcf,0xdc,0x4b,0x83,0x2c,0xde,0x7d,0x6b,0x96,0x37,0xd3,0xd4,0xa8,0x4e,0x21,0x9c, /* ..K.,.}k.7...N!. */ \
00296     0x08,0x96,0xaf,0x23,0x59,0xed,0x05,0xe8,0x91,0xa0,0x19,0x3a,0x42,0x90,0x83,0xaf, /* ...#Y......:B... */ \
00297     0xa3,0xfa,0x22,0x20,0x90,0x55,0xb8,0xfc,0xc7,0x46,0x9a,0x7c,0xb7,0x98,0xe5,0xaf, /* .." .U...F.|.... */ \
00298     0xe9,0xd5,0x9c,0x91,0x34,0xef,0xdd,0xa7,0xa6,0x0f,0xc0,0xf9,0xf2,0x13,0x0d,0x5f, /* ....4.........._ */ \
00299     0x2f,0xb2,0xb2,0xec,0xb7,0x84,0x3a,0xdf,0x57,0xb5,0xbe,0xcf,0x2d,0xd1,0xb6,0x2d, /* /.....:.W...-..- */ \
00300     0xca,0xfd,0x50,0xb3,0xc3,0x0c,0xa8,0x9e,0xda,0xbd,0xbf,0xa3,0x20,0xa9,0xd9,0xfd, /* ..P......... ... */ \
00301     0xae,0x9a,0xf7,0x0d,0x17,0x24,0xe0,0x97,0xfc,0x3f,0x02,0xa6,0x9e,0x8f,0x4f,0x07, /* .....$...?....O. */ \
00302     0x00,0x00                                                                        /* ..               */
00303
00304
00305 /**************************************
00306  * MPFS2 C linkable symbols
00307  **************************************/
00308 // For C18, these are split into seperate arrays because it speeds up compilation a lot.
00309 // For other compilers, the entire data array must be defined as a single variable to
00310 // ensure that the linker does not reorder the data chunks in Flash when compiler
00311 // optimizations are turned on.
00312 #if defined(__18CXX)
00313     ROM BYTE MPFS_Start[] = {DATACHUNK000000};
00314     ROM BYTE MPFS_000001[] = {DATACHUNK000001};
00315     ROM BYTE MPFS_000002[] = {DATACHUNK000002};
00316     ROM BYTE MPFS_000003[] = {DATACHUNK000003};
00317     ROM BYTE MPFS_000004[] = {DATACHUNK000004};
00318 #else
00319     ROM BYTE MPFS_Start[] = {DATACHUNK000000, DATACHUNK000001, DATACHUNK000002, DATACHUNK000003, DATACHUNK000004};
00320 #endif
00321
00322
00323 /**************************************************************
00324  * End of MPFS
00325  **************************************************************/
00326 #endif // #if defined(STACK_USE_MPFS2)
00327 #endif // #if !defined(MPFS_USE_EEPROM) && !defined(MPFS_USE_SPI_FLASH)
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: huffman.h Source File

huffman.h

00001
00002
00003 /**************************************
00004  * Huffman META data
00005 /**************************************/
00006
00007
00008 #define MAX_HUFFMAN_CODE_LENGTH (11u)
00009
00010 #define MAX_HUFFMAN_CODE_MASK   (0x0400u)
00011
00012 typedef unsigned short  HUFFMAN_CODE_TYPE;
00013
00014
00015 // Huffman code table structure:
00016 typedef struct {
00017     HUFFMAN_CODE_TYPE StartCode;
00018     unsigned char CodeLength;
00019     unsigned char CharacterIndex;
00020 } HuffmanCodeStruct;
00021
00022
00023 // Huffman code table:
00024 HuffmanCodeStruct HuffmanCode[] = {
00025     {0x0700, 0x03, 0x36},
00026     {0x0400, 0x04, 0x30},
00027     {0x0180, 0x05, 0x26},
00028     {0x00E0, 0x06, 0x21},
00029     {0x0050, 0x07, 0x18},
00030     {0x0030, 0x08, 0x14},
00031     {0x0014, 0x09, 0x0D},
00032     {0x0006, 0x0A, 0x06},
00033     {0x0000, 0x0B, 0x00},
00034 };
00035
00036
00037 // Huffman character table:
00038 unsigned char HuffmanCharacter[] = {
00039     0x28, 0x29, 0x39, 0x49, 0x4D, 0x4E, 0x26, 0x3B, 0x4F, 0x38,
00040     0x3F, 0x4C, 0x58, 0x33, 0x46, 0x54, 0x2D, 0x30, 0x57, 0x77,
00041     0x31, 0x32, 0x35, 0x7A, 0x76, 0x3A, 0x68, 0x34, 0x2E, 0x67,
00042     0x78, 0x79, 0x66, 0x6F, 0x70, 0x75, 0x62, 0x53, 0x2F, 0x6C,
00043     0x3D, 0x61, 0x73, 0x69, 0x72, 0x6E, 0x6D, 0x63, 0x3C, 0x3E,
00044     0x22, 0x20, 0x65, 0x64, 0x74
00045 };
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: projectdefs.h Source File

projectdefs.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00022
00023
00024 #ifndef PROJECTDEFS_H       // GUARD
00025
00026 #define PROJECTDEFS_H
00027
00028
00030 // Includes
00032
00033     #include    "appldefs.h"
00034
00035
00036 // ////////////////////////////////////////////////////////////////////////////
00037 // Defines
00038 // ////////////////////////////////////////////////////////////////////////////
00039
00042 #define PROJECT_ID                  ROCRAIL_PROJECT
00043
00044
00047 #define PROJECT_NAME                "Rocrail"
00048
00049
00051 #define PROJECT_SERVICE_NAME        "_rocrail"
00052
00053
00055 #define PROJECT_DEFAULT_PORT        (62842u)
00056
00058 #define PROJECT_SOCKET_CONFIGURATION            {TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 1140, 2000}
00059
00060
00062 #define PROJECT_LOCO_DIR_MODE_HAS_CHANGED       RocrailLocoDirModeHasChanged
00063
00065 #define PROJECT_INITIAL_INIT()
00066
00068 #define PROJECT_HANDLE_SERVER_CONNECTION        RocrailHandleServerConnection
00069
00071 #define PROJECT_PREPARE_CONNECTION              RocrailPrepareConnection
00072
00074 #define PROJECT_START_DISCONNECT                RocrailStartDisconnect
00075
00077 #define PROJECT_RESET_TO_FACTORY()
00078
00080 #define PROJECT_IS_CONNECTED                    RocrailIsConnected
00081
00083 #define PROJECT_MAIN                            RocrailMain
00084
00086 #define PROJECT_PROCESS_POST        WebIoProcessPost
00087
00089 #define PROJECT_WEBSITES        {STRTBLID_SYSTEMSTATE, "index.htm", NAV_CLOSE}, \
00090                                 {STRTBLID_COMMON, "common.htm", NAV_CLOSE},     \
00091                                 {STRTBLID_FILE, "file.htm", NAV_END},
00092
00093
00094 // ////////////////////////////////////////////////////////////////////////////
00095 // Typedefs
00096 // ////////////////////////////////////////////////////////////////////////////
00097
00098
00099
00100
00101 // ////////////////////////////////////////////////////////////////////////////
00102 // Includes
00103 // ////////////////////////////////////////////////////////////////////////////
00104
00105
00106 // ////////////////////////////////////////////////////////////////////////////
00107 // Function prototypes
00108 // ////////////////////////////////////////////////////////////////////////////
00109
00112 void RocrailLocoDirModeHasChanged(void);
00113
00114
00119 BOOL RocrailIsConnected(void);
00120
00121
00123 void RocrailStartDisconnect(void);
00124
00125
00127 void RocrailPrepareConnection(void);
00128
00131 APPL_CONNECTING_RETCODE RocrailHandleServerConnection(void);
00132
00133
00136 BOOL RocrailMain(void);
00137
00140 #endif  // #ifndef PROJECTDEFS_H
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: rocrail.c Source File

rocrail.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00015 #define     RR_C
00016
00017 // ////////////////////////////////////////////////////////////////////////////
00018 // Include
00019 // ////////////////////////////////////////////////////////////////////////////
00020
00021 #include    "stringtable.h"
00022 #include    "xml.h"
00023 #include    "sralloc.h"
00024 #include    "error.h"
00025 #include    "appl.h"
00026
00027 #include    "projectdefs.h"
00028
00029
00030 // ////////////////////////////////////////////////////////////////////////////
00031 // Local Defines
00032 // ////////////////////////////////////////////////////////////////////////////
00033
00034
00035 #define RR_MAX_ID_LENGTH        32
00036
00037 // RR_LOCOID_BUFFER_SIZE is at least two bytes longer than RR_MAX_ID_LENGTH
00038 // for the string termination and index byte!
00039 #define RR_LOCOID_BUFFER_SIZE   100
00040
00041
00042
00043 #if (RR_LOCOID_BUFFER_SIZE < (RR_MAX_ID_LENGTH+2))
00044     #error "The ID buffer must at least the size of one ID + 0 termination."
00045 #endif
00046
00047 // This valuers stores the count of attributes which are evaluated per lc element.
00048 #define RR_LOCO_ATTRIBUTES      7
00049
00050
00051 // ////////////////////////////////////////////////////////////////////////////
00052 // Local Typedefs
00053 // ////////////////////////////////////////////////////////////////////////////
00054
00055 typedef enum
00056 {
00057     RRC_CONNECT = 0,
00058     RRC_CONNECT_WAIT,
00059     RRC_CONNECTED,
00060     RRC_DELAY_CLOSING,
00061     RRC_CLOSING,
00062     RRC_WAIT_FOR_CLOSING,
00063     RRC_ERROR_CONNECT,
00064     RRC_CLOSED
00065 } SM_RR_CONNECTING;
00066
00067 typedef enum
00068 {
00069     RR_STARTUP = 0,
00070     RR_MAIN,
00071     RR_WAIT_FOR_VALID_LOCO_LIST,
00072     RR_WAIT_FOR_LOCO_LIST
00073 } SM_RR;
00074
00075 typedef enum
00076 {
00077     RR_PARSER_STATE_IDLE = 0,
00078     RR_PARSER_STATE_HEAD,
00079     RR_PARSER_STATE_XML,
00080     RR_PARSER_STATE_LC,
00081     RR_PARSER_STATE_FN,
00082     RR_PARSER_STATE_LCLIST,
00083     RR_PARSER_STATE_STATE,
00084     RR_PARSER_FLUSH
00085 } SM_RR_PARSER;
00086
00087
00088 typedef struct
00089 {
00090     BOOL bSearchDirection;
00091     BYTE u8StartPosition;
00092     BYTE u8CurrentIdPosition;
00093     BYTE au8IdBuffer[RR_LOCOID_BUFFER_SIZE];
00094 } sSearchControl;
00095
00096
00097 typedef struct __attribute__((__packed__))
00098 {
00099     BYTE au8IdBuffer[RR_MAX_ID_LENGTH+1];
00100     BOOL bNewData;
00101     BOOL bDirection;
00102     DWORD u32Functions;
00103     BYTE u8FuncGroup;
00104     WORD u16MaxV;
00105     WORD u16ActV;
00106     DWORD u32Address;
00107 } sLocoControl;
00108
00109
00110 // ////////////////////////////////////////////////////////////////////////////
00111 // Local variables
00112 // ////////////////////////////////////////////////////////////////////////////
00113
00114 static SM_RR_CONNECTING _eRRCsm;
00115 static SM_RR _eRRsm;
00116 static SM_RR_PARSER _eRRParserState;
00117
00118 static BYTE _u8Socket = INVALID_SOCKET;
00119
00120 static BYTE _u8NumberOfLocos;
00121
00122 static WORD _u16PayloadToProcess;
00123 static BYTE _u8XMLTreeDepth;
00124
00125 static sSearchControl * _pSearchControl;
00126 static sLocoControl * _pCurrentLoco;
00127 static BOOL _bLCListIsValid;
00128 static BOOL _bPowerIsOn;
00129 static BYTE _u8LastSelectedLoco;
00130
00131
00132 // ////////////////////////////////////////////////////////////////////////////
00133 // Local function prototypes
00134 // ////////////////////////////////////////////////////////////////////////////
00135
00136 static BOOL _bSendXMLCommand(ROM char * pCommand, char * pValue, BYTE ValueLength);
00137 static void _getLocoName(BYTE * au8IdBuffer, BYTE u8IdBufferSize, BYTE u8Index,
00138    BYTE * au8DestinationBuffer, BYTE u8BufferSize, BOOL * bCacheMissIndicator);
00139 static SM_RR_PARSER _parselclist(sSearchControl * pSearchControlStruct);
00140 static SM_RR_PARSER _parselc(sLocoControl * pLocoControlStruct);
00141 static SM_RR_PARSER _parsefn(sLocoControl * pLocoControlStruct);
00142 static BYTE _u8GetIdDistance(BOOL bDirection, BYTE StartPosition,
00143                                          BYTE CurrentPosition, BYTE Positions);
00144 static BOOL _bRemoveStringFromIdBuffer(BYTE Position, BYTE * Buffer, BYTE MaxBufferSize);
00145 static BYTE _u8GetRemainingSize(BYTE * Buffer, BYTE MaxBufferSize);
00146 static BOOL _bConvertToBoolean(BYTE * au8BoolString);
00147 static void _displayLCData(sLocoControl * pLoco);
00148 static BOOL _bGetLCInput(sLocoControl * pLoco, BOOL * pbNewDirection,
00149                                   WORD * pu16NewSpeed, BOOL * pbNewFunction);
00150 static BOOL _bGetFxInput(sLocoControl * pLoco, DWORD * pu32NewFuncMask);
00151 static void _sendNewFxData(TCP_SOCKET Socket, sLocoControl * pLoco, DWORD u32NewFuncMask);
00152 static void _sendNewLCData(TCP_SOCKET Socket, sLocoControl * pLoco,
00153                       BOOL bNewDirection, WORD u16NewSpeed, BOOL bNewFunction);
00154 static SM_RR_PARSER _parsestate(BOOL * pbPowerState);
00155 static void _displayPowerState(BOOL bPowerState);
00156
00157 // ////////////////////////////////////////////////////////////////////////////
00158 // ////////////////////////////////////////////////////////////////////////////
00159
00160 void RocrailPrepareConnection(void)
00161 {
00162     // Prepare socket:
00163     _u8Socket = INVALID_SOCKET;
00164
00165     // Prepare state machine stuff:
00166     _eRRCsm = RRC_CONNECT;
00167     _eRRsm = RR_STARTUP;
00168     _eRRParserState = RR_PARSER_STATE_IDLE;
00169
00170
00171     _u16PayloadToProcess = 0;
00172
00173     SRAMInitHeap();
00174
00175     _pSearchControl = NULL;
00176     _pCurrentLoco = NULL;
00177     _u8NumberOfLocos = 0;
00178     _u8LastSelectedLoco = 0;
00179
00180     _bLCListIsValid = FALSE;
00181     _bPowerIsOn = FALSE;
00182 }
00183
00184 // ////////////////////////////////////////////////////////////////////////////
00185 // ////////////////////////////////////////////////////////////////////////////
00186
00187 BOOL RocrailIsConnected(void)
00188 {
00189     if (_u8Socket != INVALID_SOCKET)
00190     {
00191         return TRUE;
00192     }
00193     else
00194     {
00195         return FALSE;
00196     }
00197 }
00198
00199 // ////////////////////////////////////////////////////////////////////////////
00200 // ////////////////////////////////////////////////////////////////////////////
00201
00202 BOOL RocrailMain(void)
00203 {
00204     WORD bytesToProcess;
00205
00206     if (TCPWasReset(_u8Socket))
00207     {
00208         _u8Socket = INVALID_SOCKET;
00209         RocrailStartDisconnect();
00210         return FALSE;
00211     }
00212
00213     bytesToProcess = TCPIsGetReady(_u8Socket);
00214
00215     if (bytesToProcess != 0)
00216     {
00217         switch(_eRRParserState)
00218         {
00219         case RR_PARSER_STATE_IDLE:
00220             InitXMLProcessor(XML_RR_HANDLE, _u8Socket);
00221             _u16PayloadToProcess = 0;
00222             _u8XMLTreeDepth = 0;
00223             _eRRParserState = RR_PARSER_STATE_HEAD;
00224             break;
00225
00226         case RR_PARSER_STATE_HEAD:
00227             while (bXMLWalkTheTree(XML_RR_HANDLE) == TRUE)
00228             {
00229                 if (eXMLGetState(XML_RR_HANDLE) == XML_ROOT_LEAVED)
00230                 {
00231                     _eRRParserState = RR_PARSER_STATE_XML;
00232                     break;
00233                 }
00234                 else if (bXMLCheckForNode(XML_RR_HANDLE, 1, (ROM char *)"xml") == TRUE)
00235                 {
00236                     // Fetch the size attribute:
00237                     bXMLSearchAttributeU16(XML_RR_HANDLE, (ROM char *)"size", &_u16PayloadToProcess);
00238                 }
00239             }
00240             break;
00241
00242         case RR_PARSER_STATE_XML:
00243             // Check for xml receiption...
00244             while (bXMLWalkTheTree(XML_RR_HANDLE) == TRUE)
00245             {
00246                 if (eXMLGetState(XML_RR_HANDLE) == XML_ROOT_LEAVED)
00247                 {
00248                     // Flush the rest of the frame and idle the parser.
00249                     _u16PayloadToProcess -= u16XMLGetProcessedBytes(XML_RR_HANDLE);
00250                     _eRRParserState = RR_PARSER_FLUSH;
00251                     break;
00252                 }
00253                 else if (bXMLCheckForNode(XML_RR_HANDLE, _u8XMLTreeDepth, (ROM char *)"lc"))
00254                 {
00255                     // loco information...
00256                     _eRRParserState = RR_PARSER_STATE_LC;
00257                     break;
00258                 }
00259                 else if (bXMLCheckForNode(XML_RR_HANDLE, _u8XMLTreeDepth, (ROM char *)"fn"))
00260                 {
00261                     // loco function information...
00262                     _eRRParserState = RR_PARSER_STATE_FN;
00263                     break;
00264                 }
00265                 else if (bXMLCheckForNode(XML_RR_HANDLE, _u8XMLTreeDepth, (ROM char *)"state"))
00266                 {
00267                     // state information (power, iid, consolemode, ...)
00268                     _eRRParserState = RR_PARSER_STATE_STATE;
00269                     break;
00270                 }
00271                 else if (bXMLCheckForNode(XML_RR_HANDLE, _u8XMLTreeDepth, (ROM char *)"lclist"))
00272                 {
00273                     // loco list information...
00274                     _eRRParserState = RR_PARSER_STATE_LCLIST;
00275                     break;
00276                 }
00277                 else if (bXMLCheckForNode(XML_RR_HANDLE, _u8XMLTreeDepth, (ROM char *)"plan"))
00278                 {
00279                     // plan information...
00280                     _u8XMLTreeDepth++;
00281                 }
00282
00283                 // Add more answer nodes here!
00284             }
00285             break;
00286
00287         case RR_PARSER_STATE_LC:
00288             _eRRParserState = _parselc(_pCurrentLoco);
00289             if (_eRRParserState == RR_PARSER_FLUSH)
00290             {
00291                 _u16PayloadToProcess -= u16XMLGetProcessedBytes(XML_RR_HANDLE);
00292             }
00293             break;
00294
00295         case RR_PARSER_STATE_FN:
00296             _eRRParserState = _parsefn(_pCurrentLoco);
00297             if (_eRRParserState == RR_PARSER_FLUSH)
00298             {
00299                 _u16PayloadToProcess -= u16XMLGetProcessedBytes(XML_RR_HANDLE);
00300             }
00301             break;
00302
00303         case RR_PARSER_STATE_LCLIST:
00304             _eRRParserState = _parselclist(_pSearchControl);
00305             if (_eRRParserState == RR_PARSER_FLUSH)
00306             {
00307                 _u16PayloadToProcess -= u16XMLGetProcessedBytes(XML_RR_HANDLE);
00308             }
00309             break;
00310
00311         case RR_PARSER_STATE_STATE:
00312             _eRRParserState = _parsestate(&_bPowerIsOn);
00313             _displayPowerState(_bPowerIsOn);
00314
00315             if (_eRRParserState == RR_PARSER_FLUSH)
00316             {
00317                 _u16PayloadToProcess -= u16XMLGetProcessedBytes(XML_RR_HANDLE);
00318             }
00319             break;
00320
00321         case RR_PARSER_FLUSH:
00322             if (_u16PayloadToProcess)
00323             {
00324                 WORD bytesToProcess = TCPIsGetReady(_u8Socket);
00325
00326                 if (bytesToProcess < _u16PayloadToProcess)
00327                 {
00328                     TCPDiscard(_u8Socket);
00329                     _u16PayloadToProcess -= bytesToProcess;
00330                     break;
00331                 }
00332
00333                 TCPGetArray(_u8Socket, NULL, _u16PayloadToProcess);
00334                 _u16PayloadToProcess = 0;
00335             }
00336             _eRRParserState = RR_PARSER_STATE_IDLE;
00337             break;
00338         }
00339     }
00340
00341
00342     if (bInputButtonPushed(PWR_BTN) == TRUE)
00343     {
00344         TCPPutROMString(_u8Socket, (ROM char *)"<?xml version=\"1.0\" encoding=\"UTF-8\"?><xmlh><xml size=\"");
00345
00346         if (_bPowerIsOn == FALSE)
00347         {
00348             // Switch on the power of the plant:
00349             TCPPutROMString(_u8Socket, "32\"/></xmlh><sys cmd=\"go\" informall=\"true\"/>");
00350         }
00351         else
00352         {
00353             // Switch off the power of the plant:
00354             TCPPutROMString(_u8Socket, "34\"/></xmlh><sys cmd=\"stop\" informall=\"true\"/>");
00355         }
00356
00357         InputButtonReset(PWR_BTN);
00358         return TRUE;
00359     }
00360
00361
00362     switch (_eRRsm)
00363     {
00364     case RR_STARTUP:
00365         InputButtonReset(ALL_BTN);
00366         OutSwitchOffAllLEDs();
00367         _eRRsm = RR_MAIN;
00368         break;
00369
00370     case RR_MAIN:
00371         if (_pCurrentLoco != NULL)
00372         {
00373             {
00374                 // Checking for a new speed or new driving direction:
00375                 BOOL newDirection;
00376                 WORD newSpeed;
00377                 BOOL newFuncValue;
00378
00379                 if (_bGetLCInput(_pCurrentLoco, &newDirection, &newSpeed, &newFuncValue) == TRUE)
00380                 {
00381                     // Something changed here on the loco!
00382                     _sendNewLCData(_u8Socket, _pCurrentLoco, newDirection, newSpeed, newFuncValue);
00383                     break;
00384                 }
00385             }
00386
00387             {
00388                 DWORD newFuncMask;
00389                 if (_bGetFxInput(_pCurrentLoco, &newFuncMask) == TRUE)
00390                 {
00391                     // Something changed here on the other loco functions!
00392                     _sendNewFxData(_u8Socket, _pCurrentLoco, newFuncMask);
00393                     break;
00394                 }
00395             }
00396
00397
00398             if (_pCurrentLoco->bNewData == TRUE)
00399             {
00400                 // Display the new loco data:
00401                 _displayLCData(_pCurrentLoco);
00402             }
00403         }
00404
00405         if ((_bLCListIsValid == TRUE) && bInputButtonPushed(SEL_BTN) == TRUE)
00406         {
00407             // Reset the button for new inputs:
00408             InputButtonReset(ALL_BTN);
00409
00410             lcd_addr1 = 0;
00411             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK;
00412
00413             if (_u8NumberOfLocos == 0)
00414             {
00415                 StrTbl_GetString(lcdram_row1, STRTBLID_NO_LOCO);
00416                 break;
00417             }
00418             StrTbl_GetString(lcdram_row1, STRTBLID_PLEASE_WAIT);
00419
00420             OutSetLED(LED_SEL, LED_ON);
00421
00422             InputEncoderInit(_u8LastSelectedLoco, 0, _u8NumberOfLocos-1, 0);
00423             _pSearchControl = (sSearchControl *)SRAMalloc(sizeof(sSearchControl));
00424
00425             if (_pSearchControl != NULL)
00426             {
00427                 memset(_pSearchControl, 0, sizeof(sSearchControl));
00428                 _bSendXMLCommand((ROM char *)"lclist", NULL, 0);
00429                 _eRRsm = RR_WAIT_FOR_VALID_LOCO_LIST;
00430             }
00431             else
00432             {
00433                 // Out of memory...
00434                 PrintCommonError(COMMON_ERROR_OUT_OF_MEMORY);
00435
00436                 // Trying to clean up the heap and start again...
00437                 _pCurrentLoco = NULL;
00438                 SRAMInitHeap();
00439                 _eRRsm = RR_STARTUP;
00440             }
00441         }
00442         break;
00443
00444     case RR_WAIT_FOR_VALID_LOCO_LIST:
00445         if (_pSearchControl->u8CurrentIdPosition == _u8NumberOfLocos)
00446         {
00447             InputForceChangedEncoderValue();
00448             _eRRsm = RR_WAIT_FOR_LOCO_LIST;
00449         }
00450         else if (bInputButtonPushed(SEL_BTN) == TRUE)
00451         {
00452             if (_pCurrentLoco)
00453             {
00454                 _pCurrentLoco->bNewData = TRUE;
00455             }
00456             else
00457             {
00458                 lcd_addr1 = 0;
00459                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK;
00460                 StrTbl_GetString(lcdram_row1, STRTBLID_NO_LOCO);
00461             }
00462             InputButtonReset(ALL_BTN);
00463             OutSetLED(LED_SEL, LED_OFF);
00464             _eRRsm = RR_MAIN;
00465         }
00466         break;
00467
00468     case RR_WAIT_FOR_LOCO_LIST:
00469         if (bInputButtonPushed(SEL_BTN) == TRUE)
00470         {
00471             if (_pCurrentLoco)
00472             {
00473                 _pCurrentLoco->bNewData = TRUE;
00474             }
00475             else
00476             {
00477                 lcd_addr1 = 0;
00478                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK;
00479                 StrTbl_GetString(lcdram_row1, STRTBLID_NO_LOCO);
00480             }
00481             InputButtonReset(ALL_BTN);
00482             OutSetLED(LED_SEL, LED_OFF);
00483             _eRRsm = RR_MAIN;
00484         }
00485         else if (bInputButtonPushed(ENC_BTN) == TRUE)
00486         {
00487             BOOL bFound = FALSE;
00488             BYTE stringIndex = 0;
00489             BYTE stringLength;
00490
00491             // User has selected a loco. Get further informations of this loco!
00492             _u8LastSelectedLoco = (BYTE)s16InputEncoderGetValue();
00493
00494             // Reset the buttons for new inputs:
00495             InputButtonReset(ALL_BTN);
00496             OutSetLED(LED_SEL, LED_OFF);
00497
00498             // Trying to find the requested index position...
00499             while (stringIndex < RR_LOCOID_BUFFER_SIZE)
00500             {
00501                 stringLength = _pSearchControl->au8IdBuffer[stringIndex];
00502
00503                 if (stringLength == 0)
00504                 {
00505                     break;
00506                 }
00507
00508                 if (_pSearchControl->au8IdBuffer[stringIndex+1] == _u8LastSelectedLoco)
00509                 {
00510                     bFound = TRUE;
00511                     break;
00512                 }
00513
00514                 stringIndex += stringLength + 1;
00515             }
00516
00517             if (bFound == TRUE)
00518             {
00519                 if (_pCurrentLoco == NULL)
00520                 {
00521                     _pCurrentLoco = (sLocoControl *)SRAMalloc(sizeof(sLocoControl));
00522
00523                     if (_pCurrentLoco == NULL)
00524                     {
00525                         // Out of memory...
00526                         PrintCommonError(COMMON_ERROR_OUT_OF_MEMORY);
00527
00528                         // Trying to clean up the heap and start again...
00529                         _pSearchControl = NULL;
00530                         SRAMInitHeap();
00531                         _eRRsm = RR_STARTUP;
00532                         break;
00533                     }
00534                 }
00535
00536                 memset(_pCurrentLoco, 0, sizeof(sLocoControl));
00537
00538                 // Filling the new loco struct:
00539                 memcpy(_pCurrentLoco->au8IdBuffer, (void *)&_pSearchControl->au8IdBuffer[stringIndex+2],stringLength-1);
00540
00541                 // Get the detailed loco properties of this loco....
00542                 _bSendXMLCommand((ROM char *)"lcprops", &_pSearchControl->au8IdBuffer[stringIndex+2], stringLength-1);
00543             }
00544             else
00545             {
00546                 // Error string not found!
00547                 PrintCommonError(COMMON_ERROR_ROCRAIL_LOCO_NOT_FOUND);
00548                 OutSetLED(LED_SEL, LED_OFF);
00549             }
00550             SRAMfree((BYTE *)_pSearchControl);
00551             _pSearchControl = NULL;
00552             _eRRsm = RR_MAIN;
00553         }
00554         else if (bInputEncoderValueChanged() == TRUE)
00555         {
00556             BYTE selected = (BYTE)s16InputEncoderGetValue();
00557             BYTE tmp[10];
00558             BOOL bCacheMissIndicator = FALSE;
00559
00560             lcd_addr1 = 0;
00561             StrTbl_GetString(lcdram_row1, STRTBLID_DATABASE);
00562
00563             // Right justify the current and max index:
00564             sprintf(tmp, (ROM char *)"%hhu/%hhu", selected+1, _u8NumberOfLocos);
00565             memset(&lcdram_row1[strlen(lcdram_row1)], ' ', LCD_CHARS_IN_A_ROW - strlen(lcdram_row1));
00566             strcpy(&lcdram_row1[LCD_CHARS_IN_A_ROW-strlen(tmp)], tmp);
00567
00568             lcd_addr2 = 0;
00569             _getLocoName(_pSearchControl->au8IdBuffer, RR_LOCOID_BUFFER_SIZE, selected, lcdram_row2, LCD_CHARS_IN_A_ROW+1, &bCacheMissIndicator);
00570             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
00571
00572             if (bCacheMissIndicator == TRUE)
00573             {
00574                 // Set a request for lclist
00575                 memset(_pSearchControl, 0, sizeof(sSearchControl));
00576                 _pSearchControl->u8StartPosition = selected;
00577                 _pSearchControl->bSearchDirection = InputEncoderGetDirection();
00578                 _bSendXMLCommand((ROM char *)"lclist", NULL, 0);
00579                 _eRRsm = RR_WAIT_FOR_VALID_LOCO_LIST;
00580             }
00581         }
00582
00583         break;
00584     }
00585
00586
00587     return TRUE;
00588 }
00589
00590 // ////////////////////////////////////////////////////////////////////////////
00591 // ////////////////////////////////////////////////////////////////////////////
00592
00593 static void _getLocoName(BYTE * au8IdBuffer, BYTE u8IdBufferSize, BYTE u8Index, BYTE * au8DestinationBuffer, BYTE u8BufferSize, BOOL * bCacheMissIndicator)
00594 {
00595     BYTE stringIndex = 0;
00596     BOOL bFound = FALSE;
00597
00598     if ((au8IdBuffer == NULL) || (au8DestinationBuffer == NULL) ||
00599         (u8BufferSize < 4) || (bCacheMissIndicator == NULL))
00600     {
00601         return;
00602     }
00603
00604     *bCacheMissIndicator = FALSE;
00605     memset(au8DestinationBuffer, 0, u8BufferSize);
00606
00607     // Trying to find the requested index position...
00608     while (stringIndex < u8IdBufferSize)
00609     {
00610         BYTE stringLength = au8IdBuffer[stringIndex];
00611
00612         if (stringLength == 0)
00613         {
00614             break;
00615         }
00616
00617         if (au8IdBuffer[stringIndex+1] == u8Index)
00618         {
00619             bFound = TRUE;
00620             break;
00621         }
00622
00623         stringIndex += stringLength + 1;
00624     }
00625
00626     if (bFound == FALSE)
00627     {
00628         // Cache miss!
00629         StrTbl_GetStringN(au8DestinationBuffer, u8BufferSize, STRTBLID_PLEASE_WAIT);
00630         au8DestinationBuffer[u8BufferSize-1] = 0;
00631         *bCacheMissIndicator = TRUE;
00632         return;
00633     }
00634
00635     {
00636         BYTE len = au8IdBuffer[stringIndex] - 1;
00637         if (len >= u8BufferSize)
00638         {
00639             // Buffer was to small, mark this with 3 dots at the end...
00640             len = u8BufferSize-3;
00641             au8DestinationBuffer[u8BufferSize-2] = '.';
00642             au8DestinationBuffer[u8BufferSize-3] = '.';
00643         }
00644
00645         memcpy((void *)au8DestinationBuffer, (void *)&au8IdBuffer[stringIndex+2], len);
00646     }
00647 }
00648
00649 // ////////////////////////////////////////////////////////////////////////////
00650 // ////////////////////////////////////////////////////////////////////////////
00651
00652 static BOOL _bSendXMLCommand(ROM char * pCommand, char * pValue, BYTE ValueLength)
00653 {
00654     WORD size = 0;
00655     BYTE buf[6];
00656
00657     if (!TCPIsPutReady(_u8Socket))
00658     {
00659         return FALSE;
00660     }
00661
00662     TCPPutROMString(_u8Socket, (ROM char *)"<?xml version=\"1.0\" encoding=\"UTF-8\"?><xmlh><xml size=\"");
00663
00664     size = strlenpgm(pCommand) + 16;
00665
00666     if (pValue)
00667     {
00668         size += 7 + ValueLength;
00669     }
00670     sprintf(buf, (ROM char *) "%hu", size);
00671
00672     TCPPutString(_u8Socket, buf);
00673     TCPPutROMString(_u8Socket, (ROM char *)"\"/></xmlh><model cmd=\"");
00674     TCPPutROMString(_u8Socket, pCommand);
00675     TCPPut(_u8Socket, '"');
00676
00677     if (pValue)
00678     {
00679         TCPPutROMString(_u8Socket, (ROM char *) " val=\"");
00680         TCPPutArray(_u8Socket, pValue, ValueLength);
00681         TCPPut(_u8Socket, '"');
00682     }
00683
00684     TCPPutROMString(_u8Socket, (ROM char *)"/>");
00685     TCPPut(_u8Socket, 0);
00686     TCPFlush(_u8Socket);
00687
00688     return TRUE;
00689 }
00690
00691 // ////////////////////////////////////////////////////////////////////////////
00692 // ////////////////////////////////////////////////////////////////////////////
00693
00694 APPL_CONNECTING_RETCODE RocrailHandleServerConnection(void)
00695 {
00696     switch(_eRRCsm)
00697     {
00698     case RRC_CONNECT:
00699         _u8Socket = TCPConnect(ApplGetServerNodeInfo(), ApplGetServerPort().Val);
00700
00701         if (_u8Socket == INVALID_SOCKET)
00702         {
00703              _eRRCsm = RRC_ERROR_CONNECT;
00704         }
00705         else
00706         {
00707              _eRRCsm = RRC_CONNECT_WAIT;
00708         }
00709         break;
00710
00711     case RRC_CONNECT_WAIT:
00712         if (TCPWasReset(_u8Socket) || (bInputButtonPushed(ENC_BTN) == TRUE))
00713         {
00714             _u8Socket = INVALID_SOCKET;
00715             _eRRCsm = RRC_CLOSING;
00716         }
00717         else if (TCPIsConnected(_u8Socket))
00718         {
00719             OutSwitchOffAllLEDs();
00720
00721             // Send a loco request to rr server:
00722             TCPPutROMString(_u8Socket, (ROM char *)"<?xml version=\"1.0\" encoding=\"UTF-8\"?><xmlh><xml size=\"");
00723             TCPPutROMString(_u8Socket, (ROM char *)"41\"/></xmlh><model cmd=\"plan\" disablemonitor=\"true\"/>");
00724             TCPFlush(_u8Socket);
00725
00726             _eRRCsm = RRC_CONNECTED;
00727         }
00728         break;
00729
00730     case RRC_CLOSING:
00731         if (_u8Socket != INVALID_SOCKET)
00732         {
00733             TCPDisconnect(_u8Socket);
00734         }
00735
00736         _eRRCsm = RRC_WAIT_FOR_CLOSING;
00737
00738         // Intented fall through.
00739
00740     case RRC_WAIT_FOR_CLOSING:
00741         if ((_u8Socket != INVALID_SOCKET) && TCPWasReset(_u8Socket))
00742         {
00743             _u8Socket = INVALID_SOCKET;
00744         }
00745
00746         if (_u8Socket == INVALID_SOCKET)
00747         {
00748             _eRRCsm = RRC_CLOSED;
00749         }
00750         break;
00751
00752     case RRC_CLOSED:
00753         return APPL_CR_CLOSED;
00754
00755     case RRC_CONNECTED:
00756         return APPL_CR_CONNECTED;
00757
00758     case RRC_ERROR_CONNECT:
00759         return APPL_CR_ERROR;
00760     }
00761
00762     return APPL_CR_IN_PROGRESS;
00763
00764 }
00765
00766 // ////////////////////////////////////////////////////////////////////////////
00767 // ////////////////////////////////////////////////////////////////////////////
00768
00769 void RocrailStartDisconnect(void)
00770 {
00771     _eRRCsm = RRC_CLOSING;
00772 }
00773
00774 // ////////////////////////////////////////////////////////////////////////////
00775 // ////////////////////////////////////////////////////////////////////////////
00776
00777 void RocrailLocoDirModeHasChanged(void)
00778 {
00779     if (_pCurrentLoco)
00780     {
00781         _pCurrentLoco->bNewData = TRUE;
00782     }
00783 }
00784
00785 // ////////////////////////////////////////////////////////////////////////////
00786 // ////////////////////////////////////////////////////////////////////////////
00787
00788 static SM_RR_PARSER _parsefn(sLocoControl * pLocoControlStruct)
00789 {
00790     sLocoControl tmpControl;
00791     BOOL idFound = FALSE;
00792
00793     if (pLocoControlStruct == NULL)
00794     {
00795         return RR_PARSER_FLUSH;
00796     }
00797
00798
00799     // Remember the "old data" in case not all attributes are given.
00800     memcpy((void *) &tmpControl, (void *) pLocoControlStruct, sizeof(tmpControl));
00801     tmpControl.u32Functions = 0;    // Set the function field to the default state.
00802
00803     while(1)
00804     {
00805         BYTE nameBuffer[10];
00806         BYTE attributeBuffer[RR_MAX_ID_LENGTH+1];
00807
00808         nameBuffer[sizeof(nameBuffer)-1] = 0;
00809         attributeBuffer[sizeof(attributeBuffer)-1] = 0;
00810
00811         if (bXMLGetNextAttribute(XML_RR_HANDLE,
00812                     nameBuffer, sizeof(nameBuffer),
00813                     attributeBuffer, sizeof(attributeBuffer)) == FALSE)
00814
00815         {
00816             break;
00817         }
00818
00819         if (nameBuffer[sizeof(nameBuffer)-1] != 0)
00820         {
00821             // nameBuffer overflow, throw this attribute away!
00822             continue;
00823         }
00824
00825         if (attributeBuffer[sizeof(attributeBuffer)-1] != 0)
00826         {
00827             // attributeBuffer overflow, throw this attribute away!
00828             continue;
00829         }
00830
00831         // Trying to match the attribute name to a well known loco field.
00832         if (strcmppgm2ram(nameBuffer, (ROM char *)"id") == 0)
00833         {
00834             // It is the id attribute! Compare with the given id!
00835             if (strcmp(attributeBuffer, tmpControl.au8IdBuffer) != 0)
00836             {
00837                 // Thats not the id field we are looking for!
00838                 return RR_PARSER_FLUSH;
00839             }
00840             idFound = TRUE;
00841         }
00842         else if (nameBuffer[0] == 'f')
00843         {
00844             BYTE func = (BYTE)atob(&nameBuffer[1]);
00845             DWORD mask = 0x01ul;
00846             while(func)
00847             {
00848                 mask = mask << 1;
00849                 func--;
00850             }
00851
00852             if (_bConvertToBoolean(attributeBuffer) == TRUE)
00853             {
00854                 tmpControl.u32Functions |= mask;
00855             }
00856             else
00857             {
00858                 tmpControl.u32Functions &= ~(mask);
00859             }
00860         }
00861     }
00862
00863     if (idFound == TRUE)
00864     {
00865         // Copy back the new data.
00866         memcpy((void *) pLocoControlStruct, (void *) &tmpControl, sizeof(sLocoControl));
00867
00868         // Mark as changed:
00869         pLocoControlStruct->bNewData = TRUE;
00870     }
00871
00872     return RR_PARSER_FLUSH;
00873 }
00874
00875 // ////////////////////////////////////////////////////////////////////////////
00876 // ////////////////////////////////////////////////////////////////////////////
00877
00878 static SM_RR_PARSER _parselc(sLocoControl * pLocoControlStruct)
00879 {
00880     sLocoControl tmpControl;
00881     BYTE attributesToFind = RR_LOCO_ATTRIBUTES;
00882     BOOL idFound = FALSE;
00883
00884     if (pLocoControlStruct == NULL)
00885     {
00886         return RR_PARSER_FLUSH;
00887     }
00888
00889
00890     // Remember the "old data" in case not all attributes are given.
00891     memcpy((void *) &tmpControl, (void *) pLocoControlStruct, sizeof(tmpControl));
00892
00893
00894     while(1)
00895     {
00896         BYTE nameBuffer[10];
00897         BYTE attributeBuffer[RR_MAX_ID_LENGTH+1];
00898
00899         nameBuffer[sizeof(nameBuffer)-1] = 0;
00900         attributeBuffer[sizeof(attributeBuffer)-1] = 0;
00901
00902         if (bXMLGetNextAttribute(XML_RR_HANDLE,
00903                     nameBuffer, sizeof(nameBuffer),
00904                     attributeBuffer, sizeof(attributeBuffer)) == FALSE)
00905
00906         {
00907             break;
00908         }
00909
00910         if (nameBuffer[sizeof(nameBuffer)-1] != 0)
00911         {
00912             // nameBuffer overflow, throw this attribute away!
00913             continue;
00914         }
00915
00916         if (attributeBuffer[sizeof(attributeBuffer)-1] != 0)
00917         {
00918             // attributeBuffer overflow, throw this attribute away!
00919             continue;
00920         }
00921
00922         // Trying to match the attribute name to a well known loco field.
00923         if (strcmppgm2ram(nameBuffer, (ROM char *)"id") == 0)
00924         {
00925             // It is the id attribute! Compare with the given id!
00926             if (strcmp(attributeBuffer, tmpControl.au8IdBuffer) != 0)
00927             {
00928                 // Thats not the id field we are looking for!
00929                 return RR_PARSER_FLUSH;
00930             }
00931             idFound = TRUE;
00932             attributesToFind--;
00933         }
00934         else if (strcmppgm2ram(nameBuffer, (ROM char *)"V") == 0)
00935         {
00936             // Speed attribute.
00937             tmpControl.u16ActV = (WORD) atoi(attributeBuffer);
00938             attributesToFind--;
00939         }
00940         else if (strcmppgm2ram(nameBuffer, (ROM char *)"V_max") == 0)
00941         {
00942             // Maxiumum speed attribute.
00943             tmpControl.u16MaxV = (WORD) atoi(attributeBuffer);
00944             attributesToFind--;
00945         }
00946         else if (strcmppgm2ram(nameBuffer, (ROM char *)"dir") == 0)
00947         {
00948             // Loco direction attribute.
00949             tmpControl.bDirection = _bConvertToBoolean(attributeBuffer);
00950             attributesToFind--;
00951         }
00952         else if (strcmppgm2ram(nameBuffer, (ROM char *)"addr") == 0)
00953         {
00954             // Digital address
00955             tmpControl.u32Address = (DWORD) atol(attributeBuffer);
00956             attributesToFind--;
00957         }
00958         else if (strcmppgm2ram(nameBuffer, (ROM char *)"fn") == 0)
00959         {
00960             // Function 0
00961             if (_bConvertToBoolean(attributeBuffer) == TRUE)
00962             {
00963                 tmpControl.u32Functions |= 0x01ul;
00964             }
00965             else
00966             {
00967                 tmpControl.u32Functions &= ~(0x01ul);
00968             }
00969             attributesToFind--;
00970         }
00971         else if (strcmppgm2ram(nameBuffer, (ROM char *)"fx") == 0)
00972         {
00973             // Function 1-X
00974             tmpControl.u32Functions &= 0x01;
00975             tmpControl.u32Functions |= ((DWORD)(atol(attributeBuffer))) << 1;
00976             attributesToFind--;
00977         }
00978
00979         if (attributesToFind == 0)
00980         {
00981             // All attributes found!
00982             break;
00983         }
00984     }
00985
00986     if (idFound == TRUE)
00987     {
00988         // Copy back the new data.
00989         memcpy((void *) pLocoControlStruct, (void *) &tmpControl, sizeof(sLocoControl));
00990
00991         // Mark as changed:
00992         pLocoControlStruct->bNewData = TRUE;
00993     }
00994
00995     return RR_PARSER_FLUSH;
00996 }
00997
00998 // ////////////////////////////////////////////////////////////////////////////
00999 // ////////////////////////////////////////////////////////////////////////////
01000
01001 static BOOL _bConvertToBoolean(BYTE * au8BoolString)
01002 {
01003     if (au8BoolString == NULL)
01004     {
01005         return FALSE;
01006     }
01007     else if ((au8BoolString[0] == '1') || (strcmppgm2ram(au8BoolString, (ROM char *)"true") == 0))
01008     {
01009         return TRUE;
01010     }
01011
01012     return FALSE;
01013 }
01014
01015 // ////////////////////////////////////////////////////////////////////////////
01016 // ////////////////////////////////////////////////////////////////////////////
01017
01018 static SM_RR_PARSER _parsestate(BOOL * pbPowerState)
01019 {
01020     if (pbPowerState == NULL)
01021     {
01022         return RR_PARSER_FLUSH;
01023     }
01024
01025     while(1)
01026     {
01027         BYTE nameBuffer[10];
01028         BYTE attributeBuffer[RR_MAX_ID_LENGTH+1];
01029
01030         nameBuffer[sizeof(nameBuffer)-1] = 0;
01031         attributeBuffer[sizeof(attributeBuffer)-1] = 0;
01032
01033         if (bXMLGetNextAttribute(XML_RR_HANDLE,
01034                     nameBuffer, sizeof(nameBuffer),
01035                     attributeBuffer, sizeof(attributeBuffer)) == FALSE)
01036
01037         {
01038             break;
01039         }
01040
01041         if (nameBuffer[sizeof(nameBuffer)-1] != 0)
01042         {
01043             // nameBuffer overflow, throw this attribute away!
01044             continue;
01045         }
01046
01047         if (attributeBuffer[sizeof(attributeBuffer)-1] != 0)
01048         {
01049             // attributeBuffer overflow, throw this attribute away!
01050             continue;
01051         }
01052
01053         // Trying to match the attribute name to a well known state field.
01054         if (strcmppgm2ram(nameBuffer, (ROM char *)"power") == 0)
01055         {
01056             // Power attribute.
01057             *pbPowerState = _bConvertToBoolean(attributeBuffer);
01058             break;
01059         }
01060     }
01061
01062     return RR_PARSER_FLUSH;
01063 }
01064
01065 // ////////////////////////////////////////////////////////////////////////////
01066 // ////////////////////////////////////////////////////////////////////////////
01067
01068 static SM_RR_PARSER _parselclist(sSearchControl * pSearchControlStruct)
01069 {
01070     while (bXMLWalkTheTree(XML_RR_HANDLE) == TRUE)
01071     {
01072         if (eXMLGetState(XML_RR_HANDLE) == XML_ROOT_LEAVED)
01073         {
01074             // Flush the rest of the frame:
01075             _bLCListIsValid = TRUE;
01076             return RR_PARSER_FLUSH;
01077         }
01078         else if (bXMLCheckForNodeWithoutDepth(XML_RR_HANDLE, (ROM char *)"lc"))
01079         {
01080             BYTE idBuffer[RR_MAX_ID_LENGTH+1];
01081             BYTE neededStringSize;
01082             BYTE remainingSpace;
01083
01084
01085             idBuffer[RR_MAX_ID_LENGTH] = 0;
01086             if (bXMLSearchAttribute(XML_RR_HANDLE, (ROM char *)"id", idBuffer, RR_MAX_ID_LENGTH+1) == FALSE)
01087             {
01088                 continue;
01089             }
01090
01091             if (idBuffer[RR_MAX_ID_LENGTH] != 0)
01092             {
01093                 // Id is too long!
01094                 continue;
01095             }
01096
01097             if (pSearchControlStruct == NULL)
01098             {
01099                 _u8NumberOfLocos++;
01100                 continue;
01101             }
01102
01103
01104             // Calculate the left size in buffer (minus one byte for the string length field and
01105             // one byte for the position field)
01106             neededStringSize = strlen(idBuffer) + 1;
01107             remainingSpace = _u8GetRemainingSize(pSearchControlStruct->au8IdBuffer, RR_LOCOID_BUFFER_SIZE);
01108
01109             while(remainingSpace < (neededStringSize+1))
01110             {
01111                 // No space left, free space in ID buffer!
01112                 BYTE currentDistance;
01113                 BYTE index = 0;
01114                 BOOL stringRemoved = FALSE;
01115
01116                 // No, try to make space for this one!
01117
01118                 // Step 1: Calculate the distance of the current id position in relation to
01119                 // the start position:
01120                 currentDistance = _u8GetIdDistance(pSearchControlStruct->bSearchDirection, pSearchControlStruct->u8StartPosition, pSearchControlStruct->u8CurrentIdPosition, _u8NumberOfLocos);
01121
01122                 // Find a string with a greater distance than this one:
01123                 while ((index < RR_LOCOID_BUFFER_SIZE) && pSearchControlStruct->au8IdBuffer[index])
01124                 {
01125                     BYTE position = pSearchControlStruct->au8IdBuffer[index+1];
01126                     BYTE distance = _u8GetIdDistance(pSearchControlStruct->bSearchDirection, pSearchControlStruct->u8StartPosition, position, _u8NumberOfLocos);
01127
01128                     if (currentDistance < distance)
01129                     {
01130                         // Remove the current string from buffer
01131                         _bRemoveStringFromIdBuffer(position, pSearchControlStruct->au8IdBuffer, RR_LOCOID_BUFFER_SIZE);
01132                         remainingSpace = _u8GetRemainingSize(pSearchControlStruct->au8IdBuffer, RR_LOCOID_BUFFER_SIZE);
01133                         stringRemoved = TRUE;
01134                         break;
01135                     }
01136                     index += pSearchControlStruct->au8IdBuffer[index] + 1;
01137                 }
01138
01139                 if (stringRemoved == FALSE)
01140                 {
01141                     // no deletable entry found, break this loop
01142                     break;
01143                 }
01144             }
01145
01146             if (remainingSpace >= (neededStringSize+1))
01147             {
01148                 BYTE bufferIndex = RR_LOCOID_BUFFER_SIZE - remainingSpace;
01149
01150                 // Now is space in the ID buffer. Store the id in the buffer.
01151                 pSearchControlStruct->au8IdBuffer[bufferIndex++] = neededStringSize;
01152                 pSearchControlStruct->au8IdBuffer[bufferIndex++] = pSearchControlStruct->u8CurrentIdPosition;
01153                 memcpy((void *)&pSearchControlStruct->au8IdBuffer[bufferIndex], (void *)idBuffer, neededStringSize-1);
01154             }
01155
01156             pSearchControlStruct->u8CurrentIdPosition++;
01157         }
01158     }
01159
01160     return RR_PARSER_STATE_LCLIST;
01161 }
01162
01163 // ////////////////////////////////////////////////////////////////////////////
01164 // ////////////////////////////////////////////////////////////////////////////
01165
01166 static BYTE _u8GetIdDistance(BOOL bDirection, BYTE StartPosition, BYTE CurrentPosition, BYTE Positions)
01167 {
01168     if ((CurrentPosition >= Positions) || ( StartPosition >= Positions))
01169     {
01170         return 0xFF;
01171     }
01172
01173
01174     // Examples use MaxPosition = 12 and StartPosition = 4
01175
01176     if (bDirection == TRUE)
01177     {
01178         // Backward...
01179         if (CurrentPosition > StartPosition)
01180         {
01181             // Example: CurrentPosition = 7: Distance = 9
01182             return (Positions - CurrentPosition + StartPosition);
01183         }
01184         else
01185         {
01186             // Example: CurrentPosition = 2: Distance = 2
01187             return (StartPosition - CurrentPosition);
01188         }
01189     }
01190     else
01191     {
01192         // Forward...
01193         if (CurrentPosition < StartPosition)
01194         {
01195             // Example: CurrentPosition = 2: Distance = 10
01196             return (Positions - StartPosition + CurrentPosition);
01197         }
01198         else
01199         {
01200             // Example: CurrentPosition = 7: Distance = 3
01201             return (CurrentPosition - StartPosition);
01202         }
01203     }
01204 }
01205
01206 // ////////////////////////////////////////////////////////////////////////////
01207 // ////////////////////////////////////////////////////////////////////////////
01208
01209 static BYTE _u8GetRemainingSize(BYTE * Buffer, BYTE MaxBufferSize)
01210 {
01211     BYTE * SourceBuffer;
01212     BYTE BufferFill;
01213
01214     if (Buffer == NULL)
01215     {
01216         return 0;
01217     }
01218
01219     BufferFill = 0;
01220
01221     while (BufferFill < MaxBufferSize)
01222     {
01223         BYTE stringLength = Buffer[BufferFill];
01224
01225         if (stringLength == 0)
01226         {
01227             return (MaxBufferSize - BufferFill);
01228         }
01229
01230         BufferFill += stringLength + 1; // Index to the next string.
01231     }
01232
01233     return 0;
01234 }
01235
01236 // ////////////////////////////////////////////////////////////////////////////
01237 // ////////////////////////////////////////////////////////////////////////////
01238
01239 static BOOL _bRemoveStringFromIdBuffer(BYTE Position, BYTE * Buffer, BYTE MaxBufferSize)
01240 {
01241     BYTE foundStringPointerIndex;
01242     BYTE index;
01243     BYTE BytesToCopy;
01244
01245     if (Buffer == NULL)
01246     {
01247         return FALSE;
01248     }
01249
01250
01251     // Step 1: Find the requested position in buffer and get the buffer fillment...
01252     foundStringPointerIndex = 0xFF;
01253     BytesToCopy = 0;
01254     index = 0;
01255
01256     while (index < MaxBufferSize)
01257     {
01258         BYTE stringLength = Buffer[index];
01259
01260         if (stringLength == 0)
01261         {
01262             break;
01263         }
01264
01265         stringLength++;     // Add the byte for string length.
01266
01267         if (Buffer[index+1] == Position)
01268         {
01269             foundStringPointerIndex = index;
01270         }
01271         else if (foundStringPointerIndex != 0xFF)
01272         {
01273             BytesToCopy += stringLength;
01274         }
01275
01276         index += stringLength;  // Index to the next string.
01277     }
01278
01279     if (foundStringPointerIndex == 0xFF)
01280     {
01281         return FALSE;
01282     }
01283
01284
01285
01286     // Step 2: Copy the content behind the string to the old string position:
01287     {
01288         BYTE * srcBuffer = &Buffer[Buffer[foundStringPointerIndex] + 1 + foundStringPointerIndex];
01289         while(BytesToCopy--)
01290         {
01291             Buffer[foundStringPointerIndex++] = *srcBuffer++;
01292         }
01293
01294         // Invalidate the rest of the buffer
01295         while(foundStringPointerIndex < MaxBufferSize)
01296         {
01297             Buffer[foundStringPointerIndex++] = 0;
01298         }
01299     }
01300
01301
01302     return TRUE;
01303 }
01304
01305 // ////////////////////////////////////////////////////////////////////////////
01306 // ////////////////////////////////////////////////////////////////////////////
01307
01308 static void _displayLCData(sLocoControl * pLoco)
01309 {
01310     SHORT speed;
01311     BYTE tmp[LCD_CHARS_IN_A_ROW+1];
01312
01313     if ((pLoco == NULL) || (OutIsLCDBusy() == TRUE))
01314     {
01315         return;
01316     }
01317
01318     _pCurrentLoco->bNewData = FALSE;
01319
01320     speed = pLoco->u16ActV;
01321     if ((sPApplConfig.sFlags.bToggleLocoDirMode == TOGGLEDIRMODE_ZERO) && (pLoco->bDirection == FALSE))
01322     {
01323         speed = -speed;
01324     }
01325
01326     if (pLoco->u8FuncGroup == 0)
01327     {
01328         sprintf(tmp, (ROM char *) "%-5lu        %3hd", pLoco->u32Address, speed);
01329
01330         if (pLoco->bDirection == TRUE)
01331         {
01332             tmp[7] = 0x01;
01333         }
01334         else
01335         {
01336             tmp[7] = 0x02;
01337         }
01338     }
01339     else if (pLoco->u8FuncGroup == 1)
01340     {
01341         strcpypgm2ram(tmp, (ROM char *)"F5   F6  F7   F8");
01342     }
01343     else
01344     {
01345         strcpypgm2ram(tmp, (ROM char *)"F9  F10  F11 F12");
01346     }
01347
01348
01349     if ((strncmp(lcdram_row2, tmp, LCD_CHARS_IN_A_ROW+1) != 0) ||
01350         (strncmp(lcdram_row1, pLoco->au8IdBuffer, LCD_CHARS_IN_A_ROW+1) != 0))
01351     {
01352         strncpy(lcdram_row1, pLoco->au8IdBuffer, LCD_CHARS_IN_A_ROW+1);
01353         lcdram_row1[LCD_CHARS_IN_A_ROW] = 0;
01354         strncpy(lcdram_row2, tmp, LCD_CHARS_IN_A_ROW+1);
01355         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
01356     }
01357
01358
01359     // Function mask (group dependent)
01360     {
01361         DWORD funcs = pLoco->u32Functions;
01362         BYTE led = funcs & 0x01;
01363
01364         // F1-F4 alternate function group dependent.
01365         if (pLoco->u8FuncGroup == 0)
01366         {
01367             led |= (funcs) & 0x1E;
01368         }
01369         else if (pLoco->u8FuncGroup == 1)
01370         {
01371             led |= (funcs >> 4) & 0x1E;
01372         }
01373         else
01374         {
01375             led |= (funcs >> 8) & 0x1E;
01376         }
01377
01378         OutSetLEDMask(LED_FL | LED_F1 | LED_F2 | LED_F3 | LED_F4, led);
01379     }
01380
01381
01382     if (IsEncoderTurning() == FALSE)
01383     {
01384         SHORT min = 0;
01385
01386         if (sPApplConfig.sFlags.bToggleLocoDirMode==TOGGLEDIRMODE_ZERO)
01387         {
01388             min = pLoco->u16MaxV;
01389             min = -min;
01390         }
01391
01392         InputEncoderInit(speed, min, pLoco->u16MaxV, ENC_NOCHANGE_MASK | ENC_ENDSTOP_MASK);
01393     }
01394 }
01395
01396 // ////////////////////////////////////////////////////////////////////////////
01397 // ////////////////////////////////////////////////////////////////////////////
01398
01399 static BOOL _bGetFxInput(sLocoControl * pLoco, DWORD * pu32NewState)
01400 {
01401     BOOL bChanged = FALSE;
01402     DWORD funcMask = 0;
01403
01404     if ((pLoco == NULL) || (pu32NewState == NULL))
01405     {
01406         return FALSE;
01407     }
01408
01409
01410     if (bInputButtonPushed(F1_BTN) == TRUE)
01411     {
01412         InputButtonReset(F1_BTN);
01413         funcMask = 0x02ul;
01414     }
01415     if (bInputButtonPushed(F2_BTN) == TRUE)
01416     {
01417         InputButtonReset(F2_BTN);
01418         funcMask |= 0x04ul;
01419     }
01420     if (bInputButtonPushed(F3_BTN) == TRUE)
01421     {
01422         InputButtonReset(F3_BTN);
01423         funcMask |= 0x08ul;
01424     }
01425     if (bInputButtonPushed(F4_BTN) == TRUE)
01426     {
01427         InputButtonReset(F4_BTN);
01428         funcMask |= 0x10ul;
01429     }
01430
01431     if (funcMask == 0)
01432     {
01433         return FALSE;
01434     }
01435
01436
01437     // Check the group!
01438     switch (pLoco->u8FuncGroup)
01439     {
01440     case 1:
01441         funcMask = funcMask << 4;
01442         break;
01443
01444     case 2:
01445         funcMask = funcMask << 8;
01446         break;
01447     }
01448
01449
01450     // Detect the new state (toggle the old state):
01451     *pu32NewState =  pLoco->u32Functions ^ funcMask;
01452
01453     return TRUE;
01454 }
01455
01456 // ////////////////////////////////////////////////////////////////////////////
01457 // ////////////////////////////////////////////////////////////////////////////
01458
01459 static BOOL _bGetLCInput(sLocoControl * pLoco, BOOL * pbNewDirection, WORD * pu16NewSpeed, BOOL * pbNewFunction)
01460 {
01461     BOOL bChanged = FALSE;
01462
01463     if ((pLoco == NULL) || (pbNewDirection == NULL) || (pu16NewSpeed == NULL) || (pbNewFunction == NULL))
01464     {
01465         return FALSE;
01466     }
01467
01468     *pbNewDirection = pLoco->bDirection;
01469     *pu16NewSpeed = pLoco->u16ActV;
01470
01471     if (pLoco->u32Functions & 0x01ul)
01472     {
01473         *pbNewFunction = TRUE;
01474     }
01475     else
01476     {
01477         *pbNewFunction = FALSE;
01478     }
01479
01480
01481     if (bInputEncoderValueChanged() == TRUE)
01482     {
01483         SHORT val = s16InputEncoderGetValue();
01484
01485         if (sPApplConfig.sFlags.bToggleLocoDirMode == TOGGLEDIRMODE_ZERO)
01486         {
01487             if ((InputEncoderGetDirection() == pLoco->bDirection) && (pLoco->u16ActV == 0))
01488             {
01489                 *pbNewDirection = !pLoco->bDirection;
01490                 val = 0;
01491             }
01492             else if (pLoco->bDirection == FALSE)
01493             {
01494                 val = -(val);
01495             }
01496         }
01497
01498         *pu16NewSpeed = val;
01499         bChanged = TRUE;
01500     }
01501
01502     // Checking the encoder push button:
01503     if (bInputButtonPushedOnce(ENC_BTN) == TRUE)
01504     {
01505         if (sPApplConfig.sFlags.bToggleLocoDirMode == TOGGLEDIRMODE_CLICK)
01506         {
01507             // Change the direction of the loco:
01508             *pbNewDirection = !pLoco->bDirection;
01509         }
01510
01511         *pu16NewSpeed = 0;
01512         bChanged = TRUE;
01513         InputButtonReset(ENC_BTN);
01514     }
01515
01516     // Checking the function button:
01517     if (bInputButtonPushed(FL_BTN) == TRUE)
01518     {
01519         if ((bInputButtonPushedLong(FL_BTN) == TRUE) && (pLoco->u8FuncGroup==0))
01520         {
01521             // Change the function view!
01522             pLoco->u8FuncGroup = 1;
01523             pLoco->bNewData = TRUE;     // Update the view.
01524         }
01525         else if (pLoco->u8FuncGroup==1)
01526         {
01527             pLoco->u8FuncGroup = 2;
01528             pLoco->bNewData = TRUE;     // Update the view.
01529         }
01530         else if (pLoco->u8FuncGroup==2)
01531         {
01532             pLoco->u8FuncGroup = 0;
01533             pLoco->bNewData = TRUE;     // Update the view.
01534         }
01535         else
01536         {
01537             // Toggle the current state.
01538             *pbNewFunction = !(*pbNewFunction);
01539             bChanged = TRUE;
01540         }
01541
01542         InputButtonReset(FL_BTN);
01543     }
01544
01545     return bChanged;
01546 }
01547
01548 // ////////////////////////////////////////////////////////////////////////////
01549 // ////////////////////////////////////////////////////////////////////////////
01550
01551 static void _sendNewFxData(TCP_SOCKET Socket, sLocoControl * pLoco, DWORD u32NewFuncMask)
01552 {
01553     WORD size;
01554     BYTE buffer[16];
01555     BYTE i = 0;
01556
01557     if (pLoco == NULL)
01558     {
01559         return;
01560     }
01561
01562
01564     // Step 1: Calculate the basic size of the packet:
01565     // <fn/>  = 5 characters
01566     //  id="" = 6 characters (+X)
01567     //          ------------
01568     //          11 characters
01569
01570
01571     size = 11;
01572     size += strlen(pLoco->au8IdBuffer); // X
01573
01574
01575     // Parse the function array for true (false values are not transmitted):
01576     // because they are default:
01577     {
01578         DWORD mask = u32NewFuncMask;
01579         for (i = 0; i < 32; i++)
01580         {
01581             if (mask & 0x01ul)
01582             {
01583                 size += 10; // " fX="true"
01584                 if (i >= 10)
01585                 {
01586                     // two digits are needed!
01587                     size++;
01588                 }
01589             }
01590             mask = mask >> 1;
01591         }
01592     }
01593
01594
01595
01597     // Step 2: Transfer the command packet to the TCP socket:
01598
01599     TCPPutROMString(Socket, (ROM char *)"<?xml version=\"1.0\" encoding=\"UTF-8\"?><xmlh><xml size=\"");
01600
01601     // Transmit the determined size of the command:
01602     sprintf(buffer, "%hu", size);
01603     TCPPutString(Socket, buffer);
01604
01605     // Transmit the loco id:
01606     TCPPutROMString(Socket, (ROM char *)"\"/></xmlh><fn id=\"");
01607     TCPPutString(Socket, pLoco->au8IdBuffer);
01608     TCPPut(Socket, '"');
01609
01610     // Transmit the changed (true) functions:
01611     for (i = 0; i < 32; i++)
01612     {
01613         if (u32NewFuncMask & 0x01ul)
01614         {
01615             sprintf(buffer, (ROM char *)" f%hhu=\"true\"", i);
01616             TCPPutString(Socket, buffer);
01617         }
01618         u32NewFuncMask = u32NewFuncMask >> 1;
01619     }
01620
01621
01622     TCPPutROMString(Socket, (ROM char *)"/>");
01623     TCPFlush(Socket);
01624 }
01625
01626 // ////////////////////////////////////////////////////////////////////////////
01627 // ////////////////////////////////////////////////////////////////////////////
01628
01629 static void _sendNewLCData(TCP_SOCKET Socket, sLocoControl * pLoco,
01630                        BOOL bNewDirection, WORD u16NewSpeed, BOOL bNewFunction)
01631 {
01632     WORD size;
01633     BYTE buffer[10];
01634
01635     if (pLoco == NULL)
01636     {
01637         return;
01638     }
01639
01640
01642     // Step 1: Calculate the basic size of the packet:
01643     // <lc/>    =   5 characters
01644     //  id="" =     6 characters (+X)
01645     //  V="" =      5 characters
01646     //  dir="" =    7 characters (+4: minimum true)
01647     //  fn="" =     6 characters (+4: minimum true)
01648     //          ------------
01649     //          29 characters + 8
01650
01651     size = 37;
01652     size += strlen(pLoco->au8IdBuffer); // X
01653
01654     // Determine the length of current speed:
01655     sprintf(buffer, "%hu", u16NewSpeed);
01656     size += strlen(buffer);
01657
01658     if (bNewDirection == FALSE)
01659     {
01660         // false is one byte longer than true:
01661         size++;
01662     }
01663
01664     if (bNewFunction == FALSE)
01665     {
01666         // false is one byte longer than true:
01667         size++;
01668     }
01669
01670
01672     // Step 2: Transfer the command packet to the TCP socket:
01673
01674     TCPPutROMString(Socket, (ROM char *)"<?xml version=\"1.0\" encoding=\"UTF-8\"?><xmlh><xml size=\"");
01675
01676     sprintf(buffer, "%hu", size);
01677     TCPPutString(Socket, buffer);
01678
01679
01680     // Transmit the loco id:
01681     TCPPutROMString(Socket, (ROM char *)"\"/></xmlh><lc id=\"");
01682     TCPPutString(Socket, pLoco->au8IdBuffer);
01683     TCPPut(Socket, '"');
01684
01685
01686     // Transmit the requested new speed:
01687     TCPPutROMString(Socket, (ROM char *)" V=\"");
01688     sprintf(buffer, "%hu", u16NewSpeed);
01689     TCPPutString(Socket, buffer);
01690     TCPPut(Socket, '"');
01691
01692
01693     // Transmit the requested new driving direction:
01694     TCPPutROMString(Socket, (ROM char *)" dir=\"");
01695     if (bNewDirection == TRUE)
01696     {
01697         TCPPutROMString(Socket, "true");
01698     }
01699     else
01700     {
01701         TCPPutROMString(Socket, "false");
01702     }
01703
01704     TCPPut(Socket, '"');
01705
01706
01707
01708
01709     TCPPutROMString(Socket, (ROM char *)" fn=\"");
01710     if (bNewFunction == TRUE)
01711     {
01712         TCPPutROMString(Socket, "true");
01713     }
01714     else
01715     {
01716         TCPPutROMString(Socket, "false");
01717     }
01718
01719     TCPPut(Socket, '"');
01720
01721
01722     TCPPutROMString(Socket, (ROM char *)"/>");
01723
01724     TCPFlush(Socket);
01725 }
01726
01727 // ////////////////////////////////////////////////////////////////////////////
01728 // ////////////////////////////////////////////////////////////////////////////
01729
01730 static void _displayPowerState(BOOL bPowerState)
01731 {
01732     if (bPowerState == FALSE)
01733     {
01734         OutSetLED(LED_PWR, LED_BLINK);
01735     }
01736     else
01737     {
01738         OutSetLED(LED_PWR, LED_ON);
01739     }
01740 }
01741
01742 // ////////////////////////////////////////////////////////////////////////////
01743 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: rocrail.h Source File

rocrail.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00015
00016 #ifndef RR_H
00017
00018     #define     RR_H
00019
00020
00021 // ////////////////////////////////////////////////////////////////////////////
00022 // Includes
00023 // ////////////////////////////////////////////////////////////////////////////
00024
00025     #include    "main.h"
00026
00027
00028 // ////////////////////////////////////////////////////////////////////////////
00029 // Defines
00030 // ////////////////////////////////////////////////////////////////////////////
00031
00032
00033 // ////////////////////////////////////////////////////////////////////////////
00034 // Typedefs
00035 // ////////////////////////////////////////////////////////////////////////////
00036
00037
00038
00039 // ////////////////////////////////////////////////////////////////////////////
00040 // Global variables
00041 // ////////////////////////////////////////////////////////////////////////////
00042
00043
00044
00045 // ////////////////////////////////////////////////////////////////////////////
00046 // Function prototypes
00047 // ////////////////////////////////////////////////////////////////////////////
00048
00049
00050
00051
00055 // ////////////////////////////////////////////////////////////////////////////
00056 // Epilogue
00057 // ////////////////////////////////////////////////////////////////////////////
00058
00059 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: HTTPPrint.h Source File

HTTPPrint.h

00001 /**************************************************************
00002  * HTTPPrint.h
00003  * Provides callback headers and resolution for user's custom
00004  * HTTP Application.
00005  *
00006  * This file is automatically generated by the MPFS Utility
00007  * ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR
00008  **************************************************************/
00009
00010 #ifndef __HTTPPRINT_H
00011 #define __HTTPPRINT_H
00012
00013 #include "TCPIP/TCPIP.h"
00014
00015 #if defined(STACK_USE_HTTP2_SERVER)
00016
00017 extern HTTP_CONN curHTTP;
00018 extern HTTP_STUB httpStubs[MAX_HTTP_CONNECTIONS];
00019 extern BYTE curHTTPID;
00020
00021 void HTTPPrint(DWORD callbackID);
00022 void HTTPPrint_header(WORD);
00023 void HTTPPrint_string(WORD);
00024 void HTTPPrint_protoreq(WORD);
00025 void HTTPPrint_eepromset(WORD);
00026 void HTTPPrint_setid(void);
00027 void HTTPPrint_setidx(void);
00028 void HTTPPrint_setname(void);
00029 void HTTPPrint_setaddress(void);
00030 void HTTPPrint_setdelay(void);
00031 void HTTPPrint_setbus(void);
00032 void HTTPPrint_setprotocol(void);
00033 void HTTPPrint_setminport(void);
00034 void HTTPPrint_setmaxport(void);
00035 void HTTPPrint_setprotos(WORD);
00036 void HTTPPrint_language(void);
00037 void HTTPPrint_ledlight(void);
00038 void HTTPPrint_toggledir(void);
00039 void HTTPPrint_askforaddressmode(void);
00040 void HTTPPrint_ip(WORD);
00041 void HTTPPrint_serverurl(void);
00042 void HTTPPrint_version(WORD);
00043 void HTTPPrint_xmllanguage(void);
00044 void HTTPPrint_xmltoggle(void);
00045 void HTTPPrint_xmlip(void);
00046 void HTTPPrint_xmllocoprotoreq(void);
00047 void HTTPPrint_xmllocostandard(void);
00048 void HTTPPrint_xmlaccprotoreq(void);
00049 void HTTPPrint_xmlaccstandard(void);
00050 void HTTPPrint_xmldelay(void);
00051 void HTTPPrint_xmlproto(WORD);
00052 void HTTPPrint_xmlset(WORD);
00053 void HTTPPrint_macaddress(void);
00054 void HTTPPrint_addressmode(void);
00055 void HTTPPrint_hostname(void);
00056 void HTTPPrint_mdns(void);
00057 void HTTPPrint_connection(void);
00058 void HTTPPrint_serverport(void);
00059 void HTTPPrint_setmaxspeed(void);
00060 void HTTPPrint_setfunction(WORD,WORD);
00061 void HTTPPrint_setsteps(void);
00062 void HTTPPrint_setfunctions(void);
00063 void HTTPPrint_askforproto(WORD);
00064 void HTTPPrint_locostandard(void);
00065 void HTTPPrint_accstandard(void);
00066 void HTTPPrint_askfordelay(void);
00067
00068 void HTTPPrint(DWORD callbackID)
00069 {
00070     switch(callbackID)
00071     {
00072         case 0x00000000:
00073             HTTPIncFile((ROM BYTE*)"head.inc");
00074             break;
00075         case 0x00000001:
00076             HTTPPrint_header(STRTBLID_ACC_PROTOCOLS);
00077             break;
00078         case 0x00000002:
00079             HTTPPrint_string(STRTBLID_ACTIVE);
00080             break;
00081         case 0x00000003:
00082             HTTPPrint_string(STRTBLID_NAME);
00083             break;
00084         case 0x00000004:
00085             HTTPPrint_string(STRTBLID_BUS);
00086             break;
00087         case 0x00000005:
00088             HTTPPrint_string(STRTBLID_PROTOCOL);
00089             break;
00090         case 0x00000006:
00091             HTTPPrint_string(STRTBLID_MIN_ADDRESS);
00092             break;
00093         case 0x00000007:
00094             HTTPPrint_string(STRTBLID_MAX_ADDRESS);
00095             break;
00096         case 0x00000008:
00097             HTTPPrint_string(STRTBLID_MIN_PORT);
00098             break;
00099         case 0x00000009:
00100             HTTPPrint_string(STRTBLID_MAX_PORT);
00101             break;
00102         case 0x0000000a:
00103             HTTPPrint_string(STRTBLID_MIN_CHARACTER);
00104             break;
00105         case 0x0000000b:
00106             HTTPPrint_protoreq(8);
00107             break;
00108         case 0x0000000c:
00109             HTTPPrint_protoreq(9);
00110             break;
00111         case 0x0000000d:
00112             HTTPPrint_protoreq(10);
00113             break;
00114         case 0x0000000e:
00115             HTTPPrint_protoreq(11);
00116             break;
00117         case 0x0000000f:
00118             HTTPPrint_protoreq(12);
00119             break;
00120         case 0x00000010:
00121             HTTPPrint_protoreq(13);
00122             break;
00123         case 0x00000011:
00124             HTTPPrint_protoreq(14);
00125             break;
00126         case 0x00000012:
00127             HTTPPrint_protoreq(15);
00128             break;
00129         case 0x00000013:
00130             HTTPPrint_string(STRTBLID_SAVE);
00131             break;
00132         case 0x00000014:
00133             HTTPPrint_string(STRTBLID_RESET);
00134             break;
00135         case 0x00000015:
00136             HTTPPrint_header(STRTBLID_ACC_DATABASE);
00137             break;
00138         case 0x00000016:
00139             HTTPPrint_string(STRTBLID_NUMBER);
00140             break;
00141         case 0x00000017:
00142             HTTPPrint_string(STRTBLID_ADDRESS);
00143             break;
00144         case 0x00000018:
00145             HTTPPrint_eepromset(16);
00146             break;
00147         case 0x00000019:
00148             HTTPPrint_eepromset(17);
00149             break;
00150         case 0x0000001a:
00151             HTTPPrint_eepromset(18);
00152             break;
00153         case 0x0000001b:
00154             HTTPPrint_eepromset(19);
00155             break;
00156         case 0x0000001c:
00157             HTTPPrint_setid();
00158             break;
00159         case 0x0000001d:
00160             HTTPPrint_setidx();
00161             break;
00162         case 0x0000001e:
00163             HTTPPrint_setname();
00164             break;
00165         case 0x0000001f:
00166             HTTPPrint_setaddress();
00167             break;
00168         case 0x00000020:
00169             HTTPPrint_string(STRTBLID_SET_PORT_DELAY);
00170             break;
00171         case 0x00000021:
00172             HTTPPrint_setdelay();
00173             break;
00174         case 0x00000022:
00175             HTTPPrint_string(STRTBLID_PROTOCOLDATA);
00176             break;
00177         case 0x00000023:
00178             HTTPPrint_string(STRTBLID_MANUAL);
00179             break;
00180         case 0x00000024:
00181             HTTPPrint_setbus();
00182             break;
00183         case 0x00000025:
00184             HTTPPrint_setprotocol();
00185             break;
00186         case 0x00000026:
00187             HTTPPrint_setminport();
00188             break;
00189         case 0x00000027:
00190             HTTPPrint_setmaxport();
00191             break;
00192         case 0x00000028:
00193             HTTPPrint_setprotos(8);
00194             break;
00195         case 0x00000029:
00196             HTTPPrint_setprotos(9);
00197             break;
00198         case 0x0000002a:
00199             HTTPPrint_setprotos(10);
00200             break;
00201         case 0x0000002b:
00202             HTTPPrint_setprotos(11);
00203             break;
00204         case 0x0000002c:
00205             HTTPPrint_setprotos(12);
00206             break;
00207         case 0x0000002d:
00208             HTTPPrint_setprotos(13);
00209             break;
00210         case 0x0000002e:
00211             HTTPPrint_setprotos(14);
00212             break;
00213         case 0x0000002f:
00214             HTTPPrint_setprotos(15);
00215             break;
00216         case 0x00000030:
00217             HTTPPrint_header(STRTBLID_COMMON);
00218             break;
00219         case 0x00000031:
00220             HTTPPrint_string(STRTBLID_LANGUAGE);
00221             break;
00222         case 0x00000032:
00223             HTTPPrint_language();
00224             break;
00225         case 0x00000033:
00226             HTTPPrint_string(STRTBLID_LCD_BACKLIGHT);
00227             break;
00228         case 0x00000034:
00229             HTTPPrint_ledlight();
00230             break;
00231         case 0x00000035:
00232             HTTPPrint_string(STRTBLID_DIRECTION_MODE);
00233             break;
00234         case 0x00000036:
00235             HTTPPrint_toggledir();
00236             break;
00237         case 0x00000037:
00238             HTTPPrint_string(STRTBLID_IP_ALLOCATION);
00239             break;
00240         case 0x00000038:
00241             HTTPPrint_askforaddressmode();
00242             break;
00243         case 0x00000039:
00244             HTTPPrint_string(STRTBLID_IP_ADDRESS);
00245             break;
00246         case 0x0000003a:
00247             HTTPPrint_ip(VAR_IP_ADDRESS_EEPROM);
00248             break;
00249         case 0x0000003b:
00250             HTTPPrint_string(STRTBLID_SUBNETMASK);
00251             break;
00252         case 0x0000003c:
00253             HTTPPrint_ip(VAR_SUBNET_MASK_EEPROM);
00254             break;
00255         case 0x0000003d:
00256             HTTPPrint_string(STRTBLID_GATEWAY_ADDRESS);
00257             break;
00258         case 0x0000003e:
00259             HTTPPrint_ip(VAR_GATEWAY_ADDRESS_EEPROM);
00260             break;
00261         case 0x0000003f:
00262             HTTPPrint_string(STRTBLID_SERVER_URL);
00263             break;
00264         case 0x00000040:
00265             HTTPPrint_serverurl();
00266             break;
00267         case 0x00000041:
00268             HTTPPrint_string(STRTBLID_RESTART_NEEDED);
00269             break;
00270         case 0x00000042:
00271             HTTPPrint_version(VAR_FIRMWARE_VERSION_MAJOR);
00272             break;
00273         case 0x00000043:
00274             HTTPPrint_version(VAR_FIRMWARE_VERSION_MINOR);
00275             break;
00276         case 0x00000044:
00277             HTTPPrint_xmllanguage();
00278             break;
00279         case 0x00000045:
00280             HTTPPrint_xmltoggle();
00281             break;
00282         case 0x00000046:
00283             HTTPPrint_xmlip();
00284             break;
00285         case 0x00000047:
00286             HTTPPrint_xmllocoprotoreq();
00287             break;
00288         case 0x00000048:
00289             HTTPPrint_xmllocostandard();
00290             break;
00291         case 0x00000049:
00292             HTTPPrint_xmlaccprotoreq();
00293             break;
00294         case 0x0000004a:
00295             HTTPPrint_xmlaccstandard();
00296             break;
00297         case 0x0000004b:
00298             HTTPPrint_xmldelay();
00299             break;
00300         case 0x0000004c:
00301             HTTPPrint_xmlproto(0);
00302             break;
00303         case 0x0000004d:
00304             HTTPPrint_xmlproto(1);
00305             break;
00306         case 0x0000004e:
00307             HTTPPrint_xmlproto(2);
00308             break;
00309         case 0x0000004f:
00310             HTTPPrint_xmlproto(3);
00311             break;
00312         case 0x00000050:
00313             HTTPPrint_xmlproto(4);
00314             break;
00315         case 0x00000051:
00316             HTTPPrint_xmlproto(5);
00317             break;
00318         case 0x00000052:
00319             HTTPPrint_xmlproto(6);
00320             break;
00321         case 0x00000053:
00322             HTTPPrint_xmlproto(7);
00323             break;
00324         case 0x00000054:
00325             HTTPPrint_xmlproto(8);
00326             break;
00327         case 0x00000055:
00328             HTTPPrint_xmlproto(9);
00329             break;
00330         case 0x00000056:
00331             HTTPPrint_xmlproto(10);
00332             break;
00333         case 0x00000057:
00334             HTTPPrint_xmlproto(11);
00335             break;
00336         case 0x00000058:
00337             HTTPPrint_xmlproto(12);
00338             break;
00339         case 0x00000059:
00340             HTTPPrint_xmlproto(13);
00341             break;
00342         case 0x0000005a:
00343             HTTPPrint_xmlproto(14);
00344             break;
00345         case 0x0000005b:
00346             HTTPPrint_xmlproto(15);
00347             break;
00348         case 0x0000005c:
00349             HTTPPrint_xmlset(0);
00350             break;
00351         case 0x0000005d:
00352             HTTPPrint_xmlset(1);
00353             break;
00354         case 0x0000005e:
00355             HTTPPrint_xmlset(2);
00356             break;
00357         case 0x0000005f:
00358             HTTPPrint_xmlset(3);
00359             break;
00360         case 0x00000060:
00361             HTTPPrint_xmlset(4);
00362             break;
00363         case 0x00000061:
00364             HTTPPrint_xmlset(5);
00365             break;
00366         case 0x00000062:
00367             HTTPPrint_xmlset(6);
00368             break;
00369         case 0x00000063:
00370             HTTPPrint_xmlset(7);
00371             break;
00372         case 0x00000064:
00373             HTTPPrint_xmlset(8);
00374             break;
00375         case 0x00000065:
00376             HTTPPrint_xmlset(9);
00377             break;
00378         case 0x00000066:
00379             HTTPPrint_xmlset(10);
00380             break;
00381         case 0x00000067:
00382             HTTPPrint_xmlset(11);
00383             break;
00384         case 0x00000068:
00385             HTTPPrint_xmlset(12);
00386             break;
00387         case 0x00000069:
00388             HTTPPrint_xmlset(13);
00389             break;
00390         case 0x0000006a:
00391             HTTPPrint_xmlset(14);
00392             break;
00393         case 0x0000006b:
00394             HTTPPrint_xmlset(15);
00395             break;
00396         case 0x0000006c:
00397             HTTPPrint_xmlset(16);
00398             break;
00399         case 0x0000006d:
00400             HTTPPrint_xmlset(17);
00401             break;
00402         case 0x0000006e:
00403             HTTPPrint_xmlset(18);
00404             break;
00405         case 0x0000006f:
00406             HTTPPrint_xmlset(19);
00407             break;
00408         case 0x00000070:
00409             HTTPPrint_header(STRTBLID_FILE);
00410             break;
00411         case 0x00000071:
00412             HTTPPrint_string(STRTBLID_DOWNLOAD_CONFIG);
00413             break;
00414         case 0x00000072:
00415             HTTPPrint_string(STRTBLID_OPEN);
00416             break;
00417         case 0x00000073:
00418             HTTPPrint_string(STRTBLID_UPLOAD_CONFIG);
00419             break;
00420         case 0x00000074:
00421             HTTPPrint_string(STRTBLID_UPLOAD);
00422             break;
00423         case 0x00000075:
00424             HTTPPrint_header(STRTBLID_SYSTEMSTATE);
00425             break;
00426         case 0x00000076:
00427             HTTPPrint_string(STRTBLID_FIRMWARE_VERSION);
00428             break;
00429         case 0x00000079:
00430             HTTPPrint_string(STRTBLID_MAC_ADDRESS);
00431             break;
00432         case 0x0000007a:
00433             HTTPPrint_macaddress();
00434             break;
00435         case 0x0000007b:
00436             HTTPPrint_ip(VAR_IP_ADDRESS);
00437             break;
00438         case 0x0000007c:
00439             HTTPPrint_addressmode();
00440             break;
00441         case 0x0000007d:
00442             HTTPPrint_ip(VAR_SUBNET_MASK);
00443             break;
00444         case 0x0000007e:
00445             HTTPPrint_ip(VAR_GATEWAY_ADDRESS);
00446             break;
00447         case 0x0000007f:
00448             HTTPPrint_string(STRTBLID_NETWORK_NAME);
00449             break;
00450         case 0x00000080:
00451             HTTPPrint_hostname();
00452             break;
00453         case 0x00000081:
00454             HTTPPrint_string(STRTBLID_NAMESERVICE);
00455             break;
00456         case 0x00000082:
00457             HTTPPrint_mdns();
00458             break;
00459         case 0x00000083:
00460             HTTPPrint_string(STRTBLID_CONNECTION);
00461             break;
00462         case 0x00000084:
00463             HTTPPrint_connection();
00464             break;
00465         case 0x00000085:
00466             HTTPPrint_ip(VAR_CONNECTED_SERVER_IP);
00467             break;
00468         case 0x00000086:
00469             HTTPPrint_string(STRTBLID_PORT);
00470             break;
00471         case 0x00000087:
00472             HTTPPrint_serverport();
00473             break;
00474         case 0x00000088:
00475             HTTPPrint_string(STRTBLID_RESTART);
00476             break;
00477         case 0x00000089:
00478             HTTPPrint_string(STRTBLID_RESET_TO_FACTORY);
00479             break;
00480         case 0x0000008a:
00481             HTTPPrint_header(STRTBLID_LOCO_PROTOCOLS);
00482             break;
00483         case 0x0000008b:
00484             HTTPPrint_string(STRTBLID_NO_OF_SPEED_STEPS);
00485             break;
00486         case 0x0000008c:
00487             HTTPPrint_string(STRTBLID_NO_OF_FUNCTIONS);
00488             break;
00489         case 0x0000008d:
00490             HTTPPrint_protoreq(0);
00491             break;
00492         case 0x0000008e:
00493             HTTPPrint_protoreq(1);
00494             break;
00495         case 0x0000008f:
00496             HTTPPrint_protoreq(2);
00497             break;
00498         case 0x00000090:
00499             HTTPPrint_protoreq(3);
00500             break;
00501         case 0x00000091:
00502             HTTPPrint_protoreq(4);
00503             break;
00504         case 0x00000092:
00505             HTTPPrint_protoreq(5);
00506             break;
00507         case 0x00000093:
00508             HTTPPrint_protoreq(6);
00509             break;
00510         case 0x00000094:
00511             HTTPPrint_protoreq(7);
00512             break;
00513         case 0x00000095:
00514             HTTPPrint_header(STRTBLID_LOCO_DATABASE);
00515             break;
00516         case 0x00000096:
00517             HTTPPrint_eepromset(0);
00518             break;
00519         case 0x00000097:
00520             HTTPPrint_eepromset(1);
00521             break;
00522         case 0x00000098:
00523             HTTPPrint_eepromset(2);
00524             break;
00525         case 0x00000099:
00526             HTTPPrint_eepromset(3);
00527             break;
00528         case 0x0000009a:
00529             HTTPPrint_eepromset(4);
00530             break;
00531         case 0x0000009b:
00532             HTTPPrint_eepromset(5);
00533             break;
00534         case 0x0000009c:
00535             HTTPPrint_eepromset(6);
00536             break;
00537         case 0x0000009d:
00538             HTTPPrint_eepromset(7);
00539             break;
00540         case 0x0000009e:
00541             HTTPPrint_eepromset(8);
00542             break;
00543         case 0x0000009f:
00544             HTTPPrint_eepromset(9);
00545             break;
00546         case 0x000000a0:
00547             HTTPPrint_eepromset(10);
00548             break;
00549         case 0x000000a1:
00550             HTTPPrint_eepromset(11);
00551             break;
00552         case 0x000000a2:
00553             HTTPPrint_eepromset(12);
00554             break;
00555         case 0x000000a3:
00556             HTTPPrint_eepromset(13);
00557             break;
00558         case 0x000000a4:
00559             HTTPPrint_eepromset(14);
00560             break;
00561         case 0x000000a5:
00562             HTTPPrint_eepromset(15);
00563             break;
00564         case 0x000000a6:
00565             HTTPPrint_string(STRTBLID_MAXSPEED);
00566             break;
00567         case 0x000000a7:
00568             HTTPPrint_setmaxspeed();
00569             break;
00570         case 0x000000a8:
00571             HTTPPrint_string(STRTBLID_FUNCTIONS);
00572             break;
00573         case 0x000000a9:
00574             HTTPPrint_string(STRTBLID_SWITCH);
00575             break;
00576         case 0x000000aa:
00577             HTTPPrint_setfunction(1,0);
00578             break;
00579         case 0x000000ab:
00580             HTTPPrint_setfunction(2,0);
00581             break;
00582         case 0x000000ac:
00583             HTTPPrint_setfunction(3,0);
00584             break;
00585         case 0x000000ad:
00586             HTTPPrint_setfunction(4,0);
00587             break;
00588         case 0x000000ae:
00589             HTTPPrint_setfunction(5,0);
00590             break;
00591         case 0x000000af:
00592             HTTPPrint_setfunction(6,0);
00593             break;
00594         case 0x000000b0:
00595             HTTPPrint_setfunction(7,0);
00596             break;
00597         case 0x000000b1:
00598             HTTPPrint_setfunction(8,0);
00599             break;
00600         case 0x000000b2:
00601             HTTPPrint_setfunction(9,0);
00602             break;
00603         case 0x000000b3:
00604             HTTPPrint_setfunction(10,0);
00605             break;
00606         case 0x000000b4:
00607             HTTPPrint_setfunction(11,0);
00608             break;
00609         case 0x000000b5:
00610             HTTPPrint_setfunction(12,0);
00611             break;
00612         case 0x000000b6:
00613             HTTPPrint_string(STRTBLID_PUSHBUTTON);
00614             break;
00615         case 0x000000b7:
00616             HTTPPrint_setfunction(1,1);
00617             break;
00618         case 0x000000b8:
00619             HTTPPrint_setfunction(2,1);
00620             break;
00621         case 0x000000b9:
00622             HTTPPrint_setfunction(3,1);
00623             break;
00624         case 0x000000ba:
00625             HTTPPrint_setfunction(4,1);
00626             break;
00627         case 0x000000bb:
00628             HTTPPrint_setfunction(5,1);
00629             break;
00630         case 0x000000bc:
00631             HTTPPrint_setfunction(6,1);
00632             break;
00633         case 0x000000bd:
00634             HTTPPrint_setfunction(7,1);
00635             break;
00636         case 0x000000be:
00637             HTTPPrint_setfunction(8,1);
00638             break;
00639         case 0x000000bf:
00640             HTTPPrint_setfunction(9,1);
00641             break;
00642         case 0x000000c0:
00643             HTTPPrint_setfunction(10,1);
00644             break;
00645         case 0x000000c1:
00646             HTTPPrint_setfunction(11,1);
00647             break;
00648         case 0x000000c2:
00649             HTTPPrint_setfunction(12,1);
00650             break;
00651         case 0x000000c3:
00652             HTTPPrint_setsteps();
00653             break;
00654         case 0x000000c4:
00655             HTTPPrint_setfunctions();
00656             break;
00657         case 0x000000c5:
00658             HTTPPrint_setprotos(0);
00659             break;
00660         case 0x000000c6:
00661             HTTPPrint_setprotos(1);
00662             break;
00663         case 0x000000c7:
00664             HTTPPrint_setprotos(2);
00665             break;
00666         case 0x000000c8:
00667             HTTPPrint_setprotos(3);
00668             break;
00669         case 0x000000c9:
00670             HTTPPrint_setprotos(4);
00671             break;
00672         case 0x000000ca:
00673             HTTPPrint_setprotos(5);
00674             break;
00675         case 0x000000cb:
00676             HTTPPrint_setprotos(6);
00677             break;
00678         case 0x000000cc:
00679             HTTPPrint_setprotos(7);
00680             break;
00681         case 0x000000cd:
00682             HTTPPrint_header(STRTBLID_SRCP);
00683             break;
00684         case 0x000000ce:
00685             HTTPPrint_string(STRTBLID_PROTOCOL_LOCO_REQUEST);
00686             break;
00687         case 0x000000cf:
00688             HTTPPrint_askforproto(TRUE);
00689             break;
00690         case 0x000000d0:
00691             HTTPPrint_string(STRTBLID_STANDARD_LOCO_PROTOCOL);
00692             break;
00693         case 0x000000d1:
00694             HTTPPrint_locostandard();
00695             break;
00696         case 0x000000d2:
00697             HTTPPrint_string(STRTBLID_PROTOCOL_ACC_REQUEST);
00698             break;
00699         case 0x000000d3:
00700             HTTPPrint_askforproto(FALSE);
00701             break;
00702         case 0x000000d4:
00703             HTTPPrint_string(STRTBLID_STANDARD_ACC_PROTOCOL);
00704             break;
00705         case 0x000000d5:
00706             HTTPPrint_accstandard();
00707             break;
00708         case 0x000000d6:
00709             HTTPPrint_string(STRTBLID_PORT_DELAY);
00710             break;
00711         case 0x000000d7:
00712             HTTPPrint_askfordelay();
00713             break;
00714         case 0x000000d9:
00715             HTTPPrint_version(VAR_FIRMWARE_VERSION_STRING);
00716             break;
00717         case 0x000000da:
00718             HTTPPrint_string(STRTBLID_BOOTLOADER_VERSION);
00719             break;
00720         case 0x000000db:
00721             HTTPPrint_version(VAR_BOOTLOADER_VERSION);
00722             break;
00723         default:
00724             // Output notification for undefined values
00725             TCPPutROMArray(sktHTTP, (ROM BYTE*)"!DEF", 4);
00726     }
00727
00728     return;
00729 }
00730
00731 void HTTPPrint_(void)
00732 {
00733     TCPPut(sktHTTP, '~');
00734     return;
00735 }
00736
00737 #endif
00738
00739 #endif
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: MPFSImg.c Source File

MPFSImg.c

00001 /***************************************************************
00002  * MPFSImg.c
00003  * Defines an MPFS2 image to be stored in program memory.
00004  *
00005  * NOT FOR HAND MODIFICATION
00006  * This file is automatically generated by the MPFS2 Utility
00007  * ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS2 GENERATOR
00008  * Generated Montag, 24. Januar 2011 22:29:08
00009  ***************************************************************/
00010
00011 #define __MPFSIMG_C
00012
00013 #if !defined(MPFS_USE_EEPROM) && !defined(MPFS_USE_SPI_FLASH)
00014
00015 #include "TCPIP/TCPIP.h"
00016 #if defined(STACK_USE_MPFS2)
00017
00018
00019 /**************************************
00020  * MPFS2 Image Data
00021  **************************************/
00022 #define DATACHUNK000000 \
00023     0x4d,0x50,0x46,0x53,0x02,0x01,0x1b,0x00,0x2a,0x71,0xff,0xff,0x6a,0xc2,0xff,0xff, /* MPFS.....q..j... */ \
00024     0x0a,0x17,0xff,0xff,0xe8,0x2d,0x48,0x44,0xca,0x3f,0xff,0xff,0x4c,0x3b,0xff,0xff, /* .....-HD.?..L;.. */ \
00025     0xea,0xca,0xff,0xff,0xe6,0xc7,0x0a,0xa3,0xff,0xff,0x2a,0x01,0xff,0xff,0x6a,0xab, /* ..............j. */ \
00026     0xff,0xff,0x0a,0xbb,0xff,0xff,0x8a,0xdb,0xff,0xff,0xf4,0x9f,0xca,0xc6,0x90,0x02, /* ................ */ \
00027     0x00,0x00,0x40,0x03,0x00,0x00,0xbd,0x01,0x00,0x00,0xf6,0x68,0xc4,0x4c,0x00,0x00, /* ..@........h.L.. */ \
00028     0x00,0x00,0x06,0x00,0x9d,0x02,0x00,0x00,0x2e,0x04,0x00,0x00,0xa8,0x00,0x00,0x00, /* ................ */ \
00029     0xf6,0x68,0xc4,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x9e,0x02,0x00,0x00,0xd6,0x04, /* .h.L............ */ \
00030     0x00,0x00,0x25,0x01,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x06,0x00, /* ..%....k.L...... */ \
00031     0xa7,0x02,0x00,0x00,0x7c,0x05,0x00,0x00,0x60,0x00,0x00,0x00,0xef,0x6b,0xc1,0x4c, /* ....|...`....k.L */ \
00032     0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x02,0x00,0x00,0xdc,0x05,0x00,0x00,0xc6,0x02, /* ................ */ \
00033     0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x06,0x00,0xb3,0x02,0x00,0x00, /* ...k.L.......... */ \
00034     0x66,0x07,0x00,0x00,0x08,0x01,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00, /* f........k.L.... */ \
00035     0x00,0x00,0xb4,0x02,0x00,0x00,0x6e,0x08,0x00,0x00,0x2b,0x00,0x00,0x00,0xef,0x6b, /* ......n...+....k */ \
00036     0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0xbb,0x02,0x00,0x00,0x99,0x08,0x00,0x00, /* .L.............. */ \
00037     0x2c,0x00,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0xc6,0x02, /* ,....k.L........ */ \
00038     0x00,0x00,0xc5,0x08,0x00,0x00,0x73,0x04,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00, /* ......s....k.L.. */ \
00039     0x00,0x00,0x06,0x00,0xd1,0x02,0x00,0x00,0x74,0x0b,0x00,0x00,0xb8,0x00,0x00,0x00, /* ........t....... */ \
00040     0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0x02,0x00,0x00,0x2c,0x0c, /* .k.L..........,. */ \
00041     0x00,0x00,0x38,0x01,0x00,0x00,0x18,0xa8,0xef,0x4c,0x00,0x00,0x00,0x00,0x06,0x00, /* ..8......L...... */ \
00042     0xdd,0x02,0x00,0x00,0x14,0x0d,0x00,0x00,0x80,0x01,0x00,0x00,0x18,0xa8,0xef,0x4c, /* ...............L */ \
00043     0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x02,0x00,0x00,0x94,0x0e,0x00,0x00,0x96,0x01, /* ................ */ \
00044     0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x06,0x00,0xe7,0x02,0x00,0x00, /* ...k.L.......... */ \
00045     0x8d,0x0f,0x00,0x00,0x30,0x00,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00, /* ....0....k.L.... */ \
00046     0x00,0x00,0xe8,0x02,0x00,0x00,0xbd,0x0f,0x00,0x00,0x3a,0x01,0x00,0x00,0xef,0x6b, /* ..........:....k */ \
00047     0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x02,0x00,0x00,0xf7,0x10,0x00,0x00, /* .L.............. */ \
00048     0xf7,0x02,0x00,0x00,0x3d,0x64,0xdd,0x4c,0x00,0x00,0x00,0x00,0x06,0x00,0xfb,0x02, /* ....=d.L........ */ \
00049     0x00,0x00,0xa0,0x12,0x00,0x00,0xd8,0x00,0x00,0x00,0x3d,0x64,0xdd,0x4c,0x00,0x00, /* ..........=d.L.. */ \
00050     0x00,0x00,0x00,0x00,0xfc,0x02,0x00,0x00,0x78,0x13,0x00,0x00,0xcb,0x01,0x00,0x00, /* ........x....... */ \
00051     0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x06,0x00,0x0a,0x03,0x00,0x00,0x74,0x14, /* .k.L..........t. */ \
00052     0x00,0x00,0xa8,0x00,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00, /* .......k.L...... */ \
00053     0x0b,0x03,0x00,0x00,0x1c,0x15,0x00,0x00,0x26,0x01,0x00,0x00,0xef,0x6b,0xc1,0x4c, /* ........&....k.L */ \
00054     0x00,0x00,0x00,0x00,0x06,0x00,0x15,0x03,0x00,0x00,0xc3,0x15,0x00,0x00,0xc0,0x00, /* ................ */ \
00055     0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x00, /* ...k.L.......... */ \
00056     0x83,0x16,0x00,0x00,0x1c,0x04,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00, /* .........k.L.... */ \
00057     0x06,0x00,0x22,0x03,0x00,0x00,0xd6,0x18,0x00,0x00,0xe0,0x01,0x00,0x00,0xef,0x6b, /* .."............k */ \
00058     0xc1,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x03,0x00,0x00,0xb6,0x1a,0x00,0x00, /* .L......#....... */ \
00059     0x45,0x02,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x06,0x00,0x2c,0x03, /* E....k.L......,. */ \
00060     0x00,0x00,0x0b,0x1c,0x00,0x00,0x70,0x00,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00, /* ......p....k.L.. */ \
00061     0x00,0x00,0x00,0x00,0x2d,0x03,0x00,0x00,0x7b,0x1c,0x00,0x00,0x75,0x05,0x00,0x00, /* ....-...{...u... */ \
00062     0x8b,0xa9,0xef,0x4c,0x00,0x00,0x00,0x00,0x01,0x00,0x36,0x03,0x00,0x00,0xf0,0x21, /* ...L......6....! */ \
00063     0x00,0x00,0x5a,0x03,0x00,0x00,0xef,0x6b,0xc1,0x4c,0x00,0x00,0x00,0x00,0x01,0x00, /* ..Z....k.L...... */ \
00064     0x61,0x63,0x63,0x70,0x72,0x6f,0x74,0x6f,0x2e,0x68,0x74,0x6d,0x00,0x00,0x61,0x63, /* accproto.htm..ac */ \
00065     0x63,0x73,0x2e,0x68,0x74,0x6d,0x00,0x00,0x61,0x63,0x63,0x73,0x65,0x74,0x2e,0x68, /* cs.htm..accset.h */ \
00066     0x74,0x6d,0x00,0x00,0x62,0x67,0x2e,0x67,0x69,0x66,0x00,0x62,0x75,0x6c,0x6c,0x65, /* tm..bg.gif.bulle */ \
00067     0x74,0x2e,0x67,0x69,0x66,0x00,0x63,0x6f,0x6d,0x6d,0x6f,0x6e,0x2e,0x68,0x74,0x6d, /* t.gif.common.htm */ \
00068     0x00,0x00,0x63,0x6f,0x6e,0x66,0x69,0x67,0x2e,0x78,0x6d,0x6c,0x00,0x00,0x66,0x69, /* ..config.xml..fi */ \
00069     0x6c,0x65,0x2e,0x68,0x74,0x6d,0x00,0x00,0x68,0x65,0x61,0x64,0x2e,0x69,0x6e,0x63, /* le.htm..head.inc */ \
00070     0x00,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x00,0x00,0x6c,0x6f,0x63,0x6f, /* .index.htm..loco */ \
00071     0x70,0x72,0x6f,0x74,0x6f,0x2e,0x68,0x74,0x6d,0x00,0x00,0x6c,0x6f,0x63,0x6f,0x73, /* proto.htm..locos */ \
00072     0x2e,0x68,0x74,0x6d,0x00,0x00,0x6c,0x6f,0x63,0x6f,0x73,0x65,0x74,0x2e,0x68,0x74, /* .htm..locoset.ht */ \
00073     0x6d,0x00,0x00,0x73,0x72,0x63,0x70,0x2e,0x68,0x74,0x6d,0x00,0x00,0x53,0x52,0x43, /* m..srcp.htm..SRC */ \
00074     0x50,0x2e,0x78,0x73,0x64,0x00,0x73,0x74,0x79,0x6c,0x65,0x2e,0x63,0x73,0x73,0x00, /* P.xsd.style.css. */ \
00075     0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59,0x46,0xd6,0x3f,0x08,0xdc,0x10,0x9c,0x60, /* ...6.c8YF.?....` */ \
00076     0x85,0xe3,0x21,0x9d,0xc2,0x75,0x9d,0x0b,0xac,0x16,0x27,0xa5,0x0b,0x0c,0xa3,0x0c, /* ..!..u....'..... */ \
00077     0x5e,0x1c,0x01,0x2f,0xe1,0x5f,0x05,0xaa,0x18,0xc7,0x94,0xd0,0x5a,0x3a,0x34,0x6e, /* ^../._......Z:4n */ \
00078     0x08,0x90,0x02,0x55,0x0c,0xcc,0xbf,0x9a,0xaf,0xf1,0xa1,0x5f,0xa2,0x5f,0x36,0xbe, /* ...U......._._6. */ \
00079     0xc6,0x87,0x7e,0x89,0x7e,0xd9,0xf8,0x1a,0x1f,0xfa,0x25,0xfa,0x65,0xe3,0x6b,0x7c, /* ..~.~.....%.e.k| */ \
00080     0xe8,0x97,0xe8,0x97,0x8d,0xaf,0xf1,0xa1,0x5f,0xa2,0x5f,0x36,0xbe,0xc6,0x87,0x7e, /* ........_._6...~ */ \
00081     0x89,0x7e,0xd9,0xf8,0x1a,0x1f,0xfa,0x25,0xfa,0x65,0xe3,0x6b,0x7c,0xe8,0x97,0xe8, /* .~.....%.e.k|... */ \
00082     0x97,0x8d,0x2f,0x6b,0xbe,0x1a,0x8e,0x29,0xa1,0xb5,0x74,0x38,0x13,0xc1,0x83,0x69, /* ../k...)..t8...i */ \
00083     0xcc,0xbf,0xc6,0x97,0x8d,0xaf,0xf1,0x65,0xe3,0x6b,0x1c,0x0c,0x81,0x40,0x40,0x82, /* .......e.k...@@. */ \
00084     0x00,0xb1,0x6c,0x7c,0x8d,0x2f,0x1b,0x5f,0xe3,0xcb,0xc6,0xd7,0xf8,0xb2,0xf1,0x35, /* ..l|./._.......5 */ \
00085     0xbe,0x6c,0x7c,0x8d,0x2f,0x1b,0x5f,0xd6,0x7c,0x59,0x81,0x2a,0xf6,0x51,0x9f,0x25, /* .l|./._.|Y...Q.% */ \
00086     0x29,0xba,0xbc,0x48,0x8a,0x49,0xd7,0x34,0x4a,0xd8,0x3a,0x27,0x05,0xc1,0xa4,0x03  /* )..H.I.4J.:'.... */
00087 #define DATACHUNK000001 \
00088     0xe1,0x1c,0x26,0x14,0xcd,0xa4,0xfb,0x67,0x49,0x8a,0x2e,0x2f,0x92,0x62,0xd2,0x0d, /* ..&....gI../.b.. */ \
00089     0xd3,0xac,0xce,0x61,0x42,0xd1,0x4c,0xba,0x7f,0x49,0x7d,0x09,0x81,0x1b,0xe2,0xcb, /* ...aB.L..I}..... */ \
00090     0xb0,0xb0,0x2f,0xc3,0xc2,0xbe,0x44,0xf1,0x40,0x7e,0x09,0x2f,0xa1,0x0e,0x00,0x00, /* ../...D.@~./.... */ \
00091     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x61,0x00, /* ..............a. */ \
00092     0x00,0x00,0x02,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x81,0x00, /* ......q......... */ \
00093     0x00,0x00,0x04,0x00,0x00,0x00,0x91,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0xa1,0x00, /* ................ */ \
00094     0x00,0x00,0x06,0x00,0x00,0x00,0xb1,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0xc1,0x00, /* ................ */ \
00095     0x00,0x00,0x08,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x1b,0x01, /* ................ */ \
00096     0x00,0x00,0x0a,0x00,0x00,0x00,0x49,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x49,0x01, /* ......I.......I. */ \
00097     0x00,0x00,0x0c,0x00,0x00,0x00,0x49,0x01,0x00,0x00,0x0d,0x00,0x00,0x00,0x49,0x01, /* ......I.......I. */ \
00098     0x00,0x00,0x0e,0x00,0x00,0x00,0x49,0x01,0x00,0x00,0x0f,0x00,0x00,0x00,0x49,0x01, /* ......I.......I. */ \
00099     0x00,0x00,0x10,0x00,0x00,0x00,0x49,0x01,0x00,0x00,0x11,0x00,0x00,0x00,0x49,0x01, /* ......I.......I. */ \
00100     0x00,0x00,0x12,0x00,0x00,0x00,0x79,0x01,0x00,0x00,0x13,0x00,0x00,0x00,0x96,0x01, /* ......y......... */ \
00101     0x00,0x00,0x14,0x00,0x00,0x00,0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59,0x46,0xd6, /* .........6.c8YF. */ \
00102     0x3f,0x08,0xdc,0x10,0x9c,0x60,0x85,0xe3,0x21,0x9d,0xc2,0x75,0x9d,0x0b,0xac,0x16, /* ?....`..!..u.... */ \
00103     0x27,0xa5,0x0b,0x0c,0xd3,0x08,0x78,0x09,0xff,0x2a,0x50,0xc5,0x38,0xa6,0x84,0xd6, /* '.....x...P.8... */ \
00104     0xd2,0xa1,0x71,0x43,0x80,0x14,0xa8,0x62,0x60,0xfe,0xd5,0x70,0x4c,0x09,0xad,0xa5, /* ..qC...b`..pL... */ \
00105     0xc3,0x99,0x08,0xff,0x1a,0x1f,0xfa,0x25,0xfa,0x65,0xe3,0x6b,0x7c,0xe8,0x97,0xe8, /* .......%.e.k|... */ \
00106     0x97,0x8d,0xaf,0xf1,0xa1,0x5f,0xa2,0x5f,0x36,0xbe,0xc6,0x87,0x7e,0x89,0x7e,0xd9, /* ....._._6...~.~. */ \
00107     0xf8,0x1a,0x5f,0x36,0xbe,0xac,0xf9,0xb2,0x02,0x55,0xec,0xa3,0x3e,0x4b,0x52,0x74, /* .._6.....U..>KRt */ \
00108     0x79,0x91,0x14,0x93,0xae,0x69,0x94,0xb0,0x75,0x4e,0x0a,0x82,0x49,0x07,0xc2,0x39, /* y....i..uN..I..9 */ \
00109     0x4c,0x28,0x9a,0x49,0xf7,0xcf,0x92,0x14,0x5d,0x5e,0x24,0xc5,0xa4,0x1b,0xa6,0x59, /* L(.I....]^$....Y */ \
00110     0x9d,0xc3,0x84,0xa2,0x99,0x74,0xff,0x92,0xfa,0x12,0x02,0x37,0xc4,0x97,0x61,0x61, /* .....t.....7..aa */ \
00111     0x5f,0x86,0x85,0x7d,0x89,0xe2,0x81,0xfc,0x12,0x5e,0x42,0x1d,0x00,0x00,0x00,0x00, /* _..}.....^B..... */ \
00112     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x6a,0x00,0x00,0x00, /* ............j... */ \
00113     0x16,0x00,0x00,0x00,0x7a,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x8a,0x00,0x00,0x00, /* ....z........... */ \
00114     0x03,0x00,0x00,0x00,0x9a,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0xb1,0x00,0x00,0x00, /* ................ */ \
00115     0x18,0x00,0x00,0x00,0xb1,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0xb1,0x00,0x00,0x00, /* ................ */ \
00116     0x1a,0x00,0x00,0x00,0xb1,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0xe1,0x00,0x00,0x00, /* ................ */ \
00117     0x13,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x0b,0x0b,0xe3,0x36, /* ...............6 */ \
00118     0xa4,0x63,0x38,0x59,0x46,0xd6,0x3f,0x08,0xdc,0x10,0x9c,0x60,0x85,0xe3,0x21,0x9d, /* .c8YF.?....`..!. */ \
00119     0xc2,0x75,0x9d,0x0b,0xac,0x16,0x27,0xa5,0x0b,0x0c,0xd3,0x08,0x78,0x09,0xff,0xe0, /* .u....'.....x... */ \
00120     0x90,0x07,0x5d,0xc2,0x21,0x3f,0x4b,0x52,0x74,0x79,0x91,0x14,0x93,0x0e,0xb7,0x11, /* ..].!?KRty...... */ \
00121     0x8c,0x74,0x4e,0x0a,0x82,0x49,0x07,0xb4,0x76,0x0e,0x13,0x8a,0x66,0xd2,0x9d,0xe7, /* .tN..I..v...f... */ \
00122     0x57,0x81,0x2a,0xc6,0x31,0x25,0xb4,0x96,0x0e,0x8d,0x1b,0x02,0xa4,0x40,0x15,0x83, /* W...1%.......@.. */ \
00123     0xe4,0x40,0xdb,0x60,0xa0,0x94,0xc0,0x98,0x7f,0x35,0x5f,0xe3,0xe0,0xcb,0xc6,0xd7, /* .@.`.....5_..... */ \
00124     0xf8,0xb2,0xf1,0x65,0xcd,0x57,0xf3,0x35,0x0e,0xbe,0x6c,0x7c,0x8d,0x2f,0x1b,0x5f, /* ...e.W.5..l|./._ */ \
00125     0xd6,0x7c,0x35,0x5f,0xe3,0xe0,0xcb,0xc6,0xd7,0x38,0x27,0xf4,0xb2,0xf1,0x65,0xcd, /* .|5_.....8'...e. */ \
00126     0x97,0x15,0xa8,0x62,0x5f,0x05,0xaa,0x18,0xc7,0x94,0xd0,0x5a,0x3a,0x34,0x6e,0x08, /* ...b_......Z:4n. */ \
00127     0x90,0x02,0x55,0x0c,0xcc,0xbf,0x9a,0xaf,0xf1,0x65,0xe3,0x6b,0x7c,0xe8,0x97,0xe8, /* ..U......e.k|... */ \
00128     0x97,0x8d,0xaf,0xf1,0xa1,0x5f,0xa2,0x5f,0x36,0xbe,0xc6,0x87,0x7e,0x89,0x7e,0xd9, /* ....._._6...~.~. */ \
00129     0xf8,0x1a,0x5f,0x36,0xbe,0xc6,0x97,0x8d,0x2f,0x6b,0xbe,0x1a,0x8e,0x29,0xa1,0xb5, /* .._6..../k...).. */ \
00130     0x74,0x38,0x13,0xe1,0x5f,0xe3,0xcb,0xc6,0xd7,0xf8,0xb2,0xf1,0x35,0x0e,0x86,0x40, /* t8.._.......5..@ */ \
00131     0x20,0x20,0x41,0x80,0x58,0x36,0xbe,0xc6,0x97,0x8d,0xaf,0xf1,0x65,0xe3,0x6b,0x7c, /*   A.X6......e.k| */ \
00132     0xd9,0xf8,0xb2,0xe6,0xab,0xf9,0x1a,0x9f,0x25,0x29,0xba,0xbc,0x48,0x8a,0x49,0x37, /* ........%)..H.I7 */ \
00133     0x22,0x2c,0xee,0x9c,0x14,0x04,0x93,0x0e,0x58,0xe7,0x30,0xa1,0x68,0x26,0x1d,0xa0, /* ",......X.0.h&.. */ \
00134     0x60,0xce,0x31,0x38,0xc3,0x00,0xce,0x42,0x3a,0x06,0x67,0x18,0xc0,0x59,0xf8,0x97, /* `.18...B:.g..Y.. */ \
00135     0x8d,0xaf,0xf1,0x65,0xe3,0x6b,0x7c,0xd9,0xf8,0x1a,0x5f,0x36,0xbe,0xc6,0x97,0x8d, /* ...e.k|..._6.... */ \
00136     0xaf,0xf1,0x65,0xe3,0xcb,0x9a,0x2f,0x2b,0x50,0xc5,0x3e,0x4b,0x52,0x74,0x79,0x91, /* ..e.../+P.>KRty. */ \
00137     0x14,0x93,0x0e,0xb7,0x11,0x8c,0x74,0x4e,0x0a,0x82,0x49,0x07,0x08,0xe7,0x30,0xa1, /* ......tN..I...0. */ \
00138     0x68,0x26,0xdd,0x79,0x7e,0xd4,0x67,0x49,0x8a,0x2e,0x2f,0x92,0x62,0xd2,0x35,0x8d, /* h&.y~.gI../.b.5. */ \
00139     0x12,0xb6,0xce,0x49,0x41,0x30,0xe9,0x40,0x38,0x87,0x09,0x45,0x33,0xe9,0xfe,0x59, /* ...IA0.@8..E3..Y */ \
00140     0x92,0xa2,0xcb,0x8b,0xa4,0x98,0x74,0xc3,0x34,0xab,0x73,0x98,0x50,0x34,0x93,0xee, /* ......t.4.s.P4.. */ \
00141     0x5f,0x52,0x5f,0x42,0xe0,0x86,0xf8,0x32,0x2c,0xec,0xcb,0xb0,0xb0,0x2f,0x51,0x3c, /* _R_B...2,..../Q< */ \
00142     0x90,0x5f,0xc2,0x4b,0xa8,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ._.K............ */ \
00143     0x00,0x00,0x15,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x68,0x00, /* ......=.......h. */ \
00144     0x00,0x00,0x1d,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xa2,0x00, /* ................ */ \
00145     0x00,0x00,0x1e,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0xbe,0x00, /* ................ */ \
00146     0x00,0x00,0x1f,0x00,0x00,0x00,0xd0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0xda,0x00, /* .......... ..... */ \
00147     0x00,0x00,0x21,0x00,0x00,0x00,0xef,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x1d,0x01, /* ..!......."..... */ \
00148     0x00,0x00,0x03,0x00,0x00,0x00,0x2d,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0x3d,0x01, /* ......-.......=. */ \
00149     0x00,0x00,0x05,0x00,0x00,0x00,0x4a,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x53,0x01, /* ......J.......S. */ \
00150     0x00,0x00,0x09,0x00,0x00,0x00,0x94,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,0xfb,0x01, /* ................ */ \
00151     0x00,0x00,0x23,0x00,0x00,0x00,0x04,0x02,0x00,0x00,0x24,0x00,0x00,0x00,0x0d,0x02  /* ..#.......$..... */
00152 #define DATACHUNK000002 \
00153     0x00,0x00,0x25,0x00,0x00,0x00,0x16,0x02,0x00,0x00,0x26,0x00,0x00,0x00,0x1f,0x02, /* ..%.......&..... */ \
00154     0x00,0x00,0x27,0x00,0x00,0x00,0x29,0x02,0x00,0x00,0x28,0x00,0x00,0x00,0x29,0x02, /* ..'...)...(...). */ \
00155     0x00,0x00,0x29,0x00,0x00,0x00,0x29,0x02,0x00,0x00,0x2a,0x00,0x00,0x00,0x29,0x02, /* ..)...).......). */ \
00156     0x00,0x00,0x2b,0x00,0x00,0x00,0x29,0x02,0x00,0x00,0x2c,0x00,0x00,0x00,0x29,0x02, /* ..+...)...,...). */ \
00157     0x00,0x00,0x2d,0x00,0x00,0x00,0x29,0x02,0x00,0x00,0x2e,0x00,0x00,0x00,0x29,0x02, /* ..-...).......). */ \
00158     0x00,0x00,0x2f,0x00,0x00,0x00,0x56,0x02,0x00,0x00,0x1d,0x00,0x00,0x00,0x82,0x02, /* ../...V......... */ \
00159     0x00,0x00,0x13,0x00,0x00,0x00,0x9f,0x02,0x00,0x00,0x14,0x00,0x00,0x00,0x47,0x49, /* ..............GI */ \
00160     0x46,0x38,0x39,0x61,0x01,0x00,0x03,0x00,0x80,0x00,0x00,0x75,0x02,0x04,0x99,0x00, /* F89a.......u.... */ \
00161     0x00,0x21,0xf9,0x04,0x00,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00, /* .!.......,...... */ \
00162     0x03,0x00,0x00,0x02,0x02,0x0c,0x50,0x00,0x3b,0x47,0x49,0x46,0x38,0x39,0x61,0x03, /* ......P.;GIF89a. */ \
00163     0x00,0x03,0x00,0x80,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00, /* ............!... */ \
00164     0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x02,0x03, /* ....,........... */ \
00165     0x84,0x7f,0x05,0x00,0x3b,0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59,0x46,0xd6,0x3f, /* ....;...6.c8YF.? */ \
00166     0x08,0xdc,0x10,0x9c,0x60,0x85,0xe3,0x21,0x9d,0xc2,0x75,0x9d,0x0b,0xac,0x16,0x27, /* ....`..!..u....' */ \
00167     0xa5,0x63,0x38,0x41,0xe0,0x24,0x02,0x5e,0xc2,0xbf,0x0a,0x54,0x31,0x8e,0x29,0xa1, /* .c8A.$.^...T1.). */ \
00168     0xb5,0x74,0x68,0xdc,0x10,0x20,0x05,0xaa,0x18,0x24,0x07,0xda,0x06,0x03,0xa5,0x04, /* .th.. ...$...... */ \
00169     0xc6,0xfc,0xab,0xf9,0x1a,0x1c,0x53,0x42,0x6b,0xe9,0xa0,0xb5,0x0a,0xca,0x0f,0xbe, /* ......SBk....... */ \
00170     0x6c,0x7c,0x8d,0x4f,0x33,0xc5,0xb0,0x72,0x52,0x10,0x4c,0x3a,0x8d,0x02,0x73,0xae, /* l|.O3..rR.L:..s. */ \
00171     0x2d,0xe0,0x4c,0x3a,0x98,0x7f,0xa9,0x99,0x62,0x58,0xbf,0x6c,0x7c,0x59,0xf3,0xd5, /* -.L:....bX.l|Y.. */ \
00172     0x7c,0x0d,0x8e,0x29,0xa1,0xb5,0x74,0xd0,0x5a,0x05,0xe5,0x07,0x5f,0x36,0xbe,0xc6, /* |..)..t.Z..._6.. */ \
00173     0x67,0x49,0x8a,0x2e,0x2f,0x92,0x62,0xd2,0xcb,0x80,0xd7,0x39,0x29,0x08,0x26,0x9d, /* gI../.b....9).&. */ \
00174     0x46,0xad,0x73,0x98,0x50,0x34,0x93,0xee,0x5c,0x5b,0xc0,0x99,0x74,0xa0,0x9c,0x13, /* F.s.P4..\[..t... */ \
00175     0x02,0xb8,0x62,0x24,0xb0,0xc2,0xa5,0x03,0xe5,0x3c,0xcf,0xf5,0xb2,0xf1,0x65,0xcd, /* ..b$.....<....e. */ \
00176     0x57,0xf3,0x35,0x38,0xa6,0x84,0xd6,0xd2,0x41,0x6b,0x15,0x94,0x1f,0x7c,0xd9,0xf8, /* W.58....Ak...|.. */ \
00177     0x1a,0x9f,0x66,0x8a,0x61,0xe5,0xa4,0x20,0x98,0x74,0x1a,0xad,0x73,0x6d,0x01,0x67, /* ..f.a.. .t..sm.g */ \
00178     0xd2,0xc1,0xfc,0x4b,0xcd,0x14,0xc3,0xfa,0x65,0xe3,0xcb,0x9a,0x2f,0x2b,0x50,0xc5, /* ...K....e.../+P. */ \
00179     0x3e,0xea,0xb3,0x24,0x45,0x97,0x17,0x49,0x31,0xe9,0x9a,0x46,0x09,0x5b,0xe7,0xa4, /* >..$E..I1..F.[.. */ \
00180     0x20,0x98,0x74,0x20,0x9c,0xc3,0x84,0xa2,0x99,0x74,0x3f,0x9f,0x25,0x29,0xba,0xbc, /*  .t .....t?.%).. */ \
00181     0x48,0x8a,0x49,0x37,0x4c,0xb3,0x3a,0x87,0x09,0x45,0x33,0xe9,0xfe,0xa1,0xe6,0x43, /* H.I7L.:..E3....C */ \
00182     0xcd,0x97,0xd4,0x97,0x10,0xb8,0x21,0x3e,0x08,0xdc,0x10,0x9c,0x60,0x85,0xe3,0x21, /* ......!>....`..! */ \
00183     0x9d,0xc2,0x75,0x9d,0x0b,0xac,0x16,0x27,0xa5,0x63,0x38,0x41,0xe0,0x24,0x02,0x5e, /* ..u....'.c8A.$.^ */ \
00184     0xc2,0xbf,0x0a,0x54,0x31,0x8e,0x29,0xa1,0xb5,0x74,0x68,0xdc,0x10,0x20,0x05,0xaa, /* ...T1.)..th.. .. */ \
00185     0x18,0x24,0x07,0xda,0x06,0x03,0xa5,0x04,0xc6,0xfc,0xab,0xf9,0x1a,0x1c,0x53,0x42, /* .$............SB */ \
00186     0x6b,0xe9,0xa0,0xb5,0x0a,0xca,0x0f,0xbe,0x6c,0x7c,0x8d,0x2f,0x1b,0x5f,0xd6,0x7c, /* k.......l|./._.| */ \
00187     0x35,0x5f,0x83,0x63,0x4a,0x68,0x2d,0x1d,0xb4,0x56,0x41,0xf9,0xc1,0x97,0x8d,0xaf, /* 5_.cJh-..VA..... */ \
00188     0xf1,0x59,0x92,0xa2,0xcb,0x8b,0xa4,0x98,0xf4,0x32,0xe0,0x75,0x4e,0x0a,0x82,0x49, /* .Y.......2.uN..I */ \
00189     0xa7,0x9c,0xc3,0x84,0xa2,0x99,0x74,0xe7,0xda,0x02,0xce,0xa4,0x83,0x81,0x70,0x4e, /* ......t.......pN */ \
00190     0x08,0xe0,0x8a,0x91,0xc0,0x0a,0x97,0x0e,0x06,0xc2,0x79,0x7e,0xd9,0xf8,0xb2,0xe6, /* ..........y~.... */ \
00191     0xab,0xf9,0x1a,0x1c,0x53,0x42,0x6b,0xe9,0xa0,0xb5,0x0a,0xca,0x0f,0xbe,0x6c,0x7c, /* ....SBk.......l| */ \
00192     0x8d,0xcf,0x92,0x14,0x5d,0x5e,0x24,0xc5,0xa4,0x97,0x01,0xaf,0x73,0x52,0x10,0x4c, /* ....]^$.....sR.L */ \
00193     0xba,0x76,0x0e,0x13,0x8a,0x66,0xd2,0x9d,0x6b,0x0b,0x38,0x93,0x0e,0x06,0xc2,0x39, /* .v...f..k.8....9 */ \
00194     0x21,0x80,0x2b,0x46,0x02,0x2b,0x5c,0x3a,0x18,0x08,0xe7,0xf9,0x65,0xe3,0xcb,0x9a, /* !.+F.+\:....e... */ \
00195     0xaf,0xe6,0x6b,0x70,0x4c,0x09,0xad,0xa5,0x83,0xd6,0x2a,0x28,0x3f,0xf8,0xb2,0xf1, /* ..kpL......(?... */ \
00196     0x35,0x3e,0x4b,0x52,0x74,0x79,0x91,0x14,0x93,0x5e,0x06,0xbc,0xce,0x49,0x41,0x30, /* 5>KRty...^...IA0 */ \
00197     0xe9,0xc2,0x39,0x4c,0x28,0x9a,0x49,0x77,0xae,0x2d,0xe0,0x4c,0x3a,0x18,0x08,0xe7, /* ..9L(.Iw.-.L:... */ \
00198     0x84,0x00,0xae,0x18,0x09,0xac,0x70,0xe9,0x60,0x20,0x9c,0xe7,0x97,0x8d,0x2f,0x6b, /* ......p.` ..../k */ \
00199     0xbe,0x9a,0xaf,0xc1,0x31,0x25,0xb4,0x96,0x0e,0x5a,0xab,0xa0,0xfc,0xe0,0xcb,0xc6, /* ....1%...Z...... */ \
00200     0xd7,0xf8,0x2c,0x49,0xd1,0xe5,0x45,0x52,0x4c,0x7a,0x19,0xf0,0x3a,0x27,0x05,0xc1, /* ..,I..ERLz..:'.. */ \
00201     0xa4,0x03,0x77,0x0e,0x13,0x8a,0x66,0xd2,0x9d,0x6b,0x0b,0x38,0x93,0x0e,0x14,0xa4, /* ..w...f..k.8.... */ \
00202     0x73,0x42,0x00,0x57,0x8c,0x04,0x56,0xb8,0x74,0xa0,0x20,0x9d,0xe7,0x97,0x8d,0x2f, /* sB.W..V.t. ..../ */ \
00203     0x6b,0xbe,0xac,0x40,0x15,0xfb,0x28,0x8e,0x29,0xa1,0xb5,0x74,0xd0,0x5a,0x05,0xc2, /* k..@..(.)..t.Z.. */ \
00204     0xbf,0xa4,0x3e,0xea,0xb3,0x24,0x45,0x97,0x17,0x49,0x31,0xe9,0x9a,0x46,0x09,0x5b, /* ..>..$E..I1..F.[ */ \
00205     0xe7,0xa4,0x20,0x98,0x74,0x20,0x9c,0xc3,0x84,0xa2,0x99,0x74,0x3f,0x9f,0x25,0x29, /* .. .t .....t?.%) */ \
00206     0xba,0xbc,0x48,0x8a,0x49,0x37,0x4c,0xb3,0x3a,0x87,0x09,0x45,0x33,0xe9,0xfe,0x25, /* ..H.I7L.:..E3..% */ \
00207     0xf5,0x25,0x04,0x6e,0x88,0x2f,0xc3,0xc2,0xbe,0x0c,0x0b,0xfb,0x12,0xc5,0x03,0xf9, /* .%.n./.......... */ \
00208     0x25,0xbc,0x84,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* %..:............ */ \
00209     0x30,0x00,0x00,0x00,0x74,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x9a,0x00,0x00,0x00, /* 0...t...1....... */ \
00210     0x32,0x00,0x00,0x00,0xc3,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0xf2,0x00,0x00,0x00, /* 2.......3....... */ \
00211     0x34,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x35,0x00,0x00,0x00,0x55,0x01,0x00,0x00, /* 4.../...5...U... */ \
00212     0x36,0x00,0x00,0x00,0x98,0x01,0x00,0x00,0x13,0x00,0x00,0x00,0xb6,0x01,0x00,0x00, /* 6............... */ \
00213     0x14,0x00,0x00,0x00,0x2d,0x02,0x00,0x00,0x37,0x00,0x00,0x00,0x37,0x02,0x00,0x00, /* ....-...7...7... */ \
00214     0x38,0x00,0x00,0x00,0x57,0x02,0x00,0x00,0x39,0x00,0x00,0x00,0x84,0x02,0x00,0x00, /* 8...W...9....... */ \
00215     0x3a,0x00,0x00,0x00,0xc1,0x02,0x00,0x00,0x3b,0x00,0x00,0x00,0xee,0x02,0x00,0x00, /* :.......;....... */ \
00216     0x3c,0x00,0x00,0x00,0x2b,0x03,0x00,0x00,0x3d,0x00,0x00,0x00,0x58,0x03,0x00,0x00  /* <...+...=...X... */
00217 #define DATACHUNK000003 \
00218     0x3e,0x00,0x00,0x00,0x95,0x03,0x00,0x00,0x3f,0x00,0x00,0x00,0xc2,0x03,0x00,0x00, /* >.......?....... */ \
00219     0x40,0x00,0x00,0x00,0x02,0x04,0x00,0x00,0x41,0x00,0x00,0x00,0x2e,0x04,0x00,0x00, /* @.......A....... */ \
00220     0x13,0x00,0x00,0x00,0x4c,0x04,0x00,0x00,0x14,0x00,0x00,0x00,0x03,0x70,0xe0,0x84, /* ....L........p.. */ \
00221     0xe2,0x30,0x66,0xb4,0xc5,0x49,0xe9,0x60,0x08,0x20,0x9d,0x33,0x12,0xc3,0xc3,0x92, /* .0f..I.`. .3.... */ \
00222     0xc0,0xa4,0x03,0x70,0x50,0x20,0x00,0x0a,0x30,0x80,0x81,0x00,0x30,0x80,0x82,0x39, /* ...pP ..0...0..9 */ \
00223     0x80,0x7f,0x18,0x4e,0x42,0x58,0x60,0x1c,0xc6,0x8c,0xb6,0x38,0x29,0x1d,0xe1,0x1c, /* ...NBX`....8)... */ \
00224     0x38,0xa1,0x48,0x0d,0x0e,0x5c,0x5b,0xe9,0xf0,0x96,0x02,0xcf,0x04,0x04,0x20,0x00, /* 8.H..\[....... . */ \
00225     0x81,0x00,0x04,0x50,0x08,0xdc,0x00,0x4b,0x48,0x20,0x81,0x04,0x4b,0x00,0x0d,0x20, /* ...P...KH ..K..  */ \
00226     0x00,0x03,0x8a,0xc1,0x19,0x21,0x00,0x6a,0x49,0x5d,0x41,0x62,0xcc,0x39,0x70,0x6d, /* .....!.jI]Ab.9pm */ \
00227     0xc1,0x49,0x1c,0x40,0x0a,0x82,0x69,0x4a,0x60,0x0c,0x14,0x83,0x33,0x42,0x00,0x06, /* .I.@..iJ`...3B.. */ \
00228     0xc7,0x44,0x2d,0x4e,0x4a,0x47,0x24,0x28,0x80,0x02,0xa0,0x80,0x45,0x00,0xd7,0xe1, /* .D-NJG$(....E... */ \
00229     0x1f,0x86,0x13,0x04,0x4e,0x72,0x25,0x48,0x60,0xb4,0x00,0xc6,0xa4,0x3b,0x57,0x58, /* ....Nr%H`....;WX */ \
00230     0x28,0x0b,0x0c,0x5e,0xe9,0xce,0x8b,0x03,0x03,0xa6,0x98,0x74,0xe7,0x5c,0x33,0x03, /* (..^.......t.\3. */ \
00231     0x63,0x46,0xba,0xe7,0xa7,0x0d,0x46,0x71,0x85,0x63,0x38,0x65,0xf0,0xe2,0x86,0x01, /* cF....Fq.c8e.... */ \
00232     0x24,0xcd,0x74,0xa5,0x3b,0x57,0x38,0x86,0xeb,0x0a,0x32,0x84,0x09,0xe9,0xce,0x05, /* $.t.;W8...2..... */ \
00233     0x86,0x51,0x06,0x2f,0x6e,0x18,0x40,0xd2,0x4c,0x57,0xba,0x73,0x81,0x61,0xba,0x82, /* .Q./n.@.LW.s.a.. */ \
00234     0x0c,0x61,0x42,0xba,0x73,0x81,0x61,0xc1,0x94,0x40,0x4a,0xf7,0xfc,0x12,0xc3,0x49, /* .aB.s.a..@J....I */ \
00235     0x08,0x0b,0xec,0x00,0x3c,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x3d,0x00,0x00,0x00, /* ....<...B...=... */ \
00236     0x43,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0xbe,0x00,0x00,0x00, /* C.......D....... */ \
00237     0x34,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0xca,0x00,0x00,0x00, /* 4.......E....... */ \
00238     0x46,0x00,0x00,0x00,0xd3,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xee,0x00,0x00,0x00, /* F.......@....... */ \
00239     0x47,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x11,0x01,0x00,0x00, /* G.......H....... */ \
00240     0x49,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x4a,0x00,0x00,0x00,0x2c,0x01,0x00,0x00, /* I... ...J...,... */ \
00241     0x4b,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x4c,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* K.../...L.../... */ \
00242     0x4d,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x4e,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* M.../...N.../... */ \
00243     0x4f,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x50,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* O.../...P.../... */ \
00244     0x51,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x52,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* Q.../...R.../... */ \
00245     0x53,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x54,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* S.../...T.../... */ \
00246     0x55,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x56,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* U.../...V.../... */ \
00247     0x57,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x58,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* W.../...X.../... */ \
00248     0x59,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x5a,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* Y.../...Z.../... */ \
00249     0x5b,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x5c,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* [.../...\.../... */ \
00250     0x5d,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x5e,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* ].../...^.../... */ \
00251     0x5f,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* _.../...`.../... */ \
00252     0x61,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x62,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* a.../...b.../... */ \
00253     0x63,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x64,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* c.../...d.../... */ \
00254     0x65,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x66,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* e.../...f.../... */ \
00255     0x67,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x68,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* g.../...h.../... */ \
00256     0x69,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x6a,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* i.../...j.../... */ \
00257     0x6b,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x6c,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* k.../...l.../... */ \
00258     0x6d,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x6e,0x00,0x00,0x00,0x2f,0x01,0x00,0x00, /* m.../...n.../... */ \
00259     0x6f,0x00,0x00,0x00,0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59,0x46,0xd6,0xbf,0x0a, /* o......6.c8YF... */ \
00260     0x54,0x31,0x8e,0x29,0xa1,0xb5,0x74,0x68,0xdc,0x10,0x20,0x05,0xaa,0x18,0x24,0x07, /* T1.)..th.. ...$. */ \
00261     0xda,0x06,0x03,0xa5,0x04,0xc6,0xfc,0xab,0xf9,0x1a,0x5f,0x36,0xbe,0xac,0xf9,0xb2, /* .........._6.... */ \
00262     0x02,0x55,0xec,0x13,0x1c,0x6e,0x18,0x84,0x74,0x0c,0x27,0x21,0x2c,0x30,0x04,0x70, /* .U...n..t.'!,0.p */ \
00263     0x42,0xf9,0x87,0xd2,0x2d,0x4e,0x1e,0x81,0x40,0x2c,0x51,0xba,0xc5,0xc9,0x2f,0xc5, /* B...-N..@,Q.../. */ \
00264     0x47,0x1d,0x90,0x24,0xaa,0x29,0x40,0x2d,0xa9,0x0f,0x02,0x37,0x04,0x17,0x58,0x2d, /* G..$.)@-...7..X- */ \
00265     0x4e,0x4a,0x87,0xb0,0x8a,0x21,0xe0,0x25,0x9c,0x13,0xac,0x70,0x3c,0xa4,0x53,0xb8, /* NJ...!.%...p<.S. */ \
00266     0xae,0x73,0x46,0x62,0x45,0x52,0x4c,0x3a,0x41,0xab,0x5a,0x4a,0x98,0x26,0x04,0x6e, /* .sFbERL:A.ZJ.&.n */ \
00267     0x08,0x80,0x86,0xa8,0xf0,0xaf,0x02,0x55,0x8c,0x63,0x4a,0x68,0x2d,0x1d,0x1a,0x37, /* .......U.cJh-..7 */ \
00268     0x04,0x48,0x81,0x2a,0x06,0xc9,0x81,0xb6,0xc1,0x40,0x29,0x81,0x31,0xff,0x6a,0xbe, /* .H.......@).1.j. */ \
00269     0xc6,0x97,0x8d,0x2f,0x6b,0xbe,0x9a,0xaf,0xf1,0x59,0x92,0xa2,0xcb,0x49,0x41,0x30, /* .../k....Y...IA0 */ \
00270     0xe9,0x18,0x4e,0x42,0x58,0x60,0xce,0xb5,0x05,0x9c,0x49,0x87,0x04,0xd2,0x79,0x91, /* ..NBX`....I...y. */ \
00271     0x14,0x93,0x0e,0x61,0x15,0xf3,0x0f,0x35,0x5f,0x36,0xbe,0xac,0xf9,0xb2,0x02,0x55, /* ...a...5_6.....U */ \
00272     0xec,0xa3,0x3e,0x4b,0x52,0x74,0x79,0x91,0x14,0x93,0xae,0x69,0x94,0xb0,0x75,0x0e, /* ..>KRty....i..u. */ \
00273     0x13,0x8a,0x66,0xd2,0x11,0x08,0x84,0x7f,0x49,0x7d,0x09,0x81,0x1b,0xe2,0xcb,0xb0, /* ..f.....I}...... */ \
00274     0xb0,0x2f,0xc3,0xc2,0xbe,0x44,0xf1,0x40,0x7e,0x09,0x2f,0xa1,0x0e,0x00,0x00,0x00, /* ./...D.@~./..... */ \
00275     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x3e,0x00,0x00, /* .........p...>.. */ \
00276     0x00,0x71,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0xfa,0x00,0x00, /* .q...m...r...... */ \
00277     0x00,0x73,0x00,0x00,0x00,0x6c,0x01,0x00,0x00,0x74,0x00,0x00,0x00,0x3c,0x21,0x44, /* .s...l...t...<!D */ \
00278     0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x48,0x54,0x4d,0x4c,0x20,0x50,0x55,0x42,0x4c, /* OCTYPE HTML PUBL */ \
00279     0x49,0x43,0x20,0x22,0x2d,0x2f,0x2f,0x57,0x33,0x43,0x2f,0x2f,0x44,0x54,0x44,0x20, /* IC "-//W3C//DTD  */ \
00280     0x48,0x54,0x4d,0x4c,0x20,0x34,0x2e,0x30,0x31,0x2f,0x2f,0x45,0x4e,0x22,0x20,0x22, /* HTML 4.01//EN" " */ \
00281     0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72  /* http://www.w3.or */
00282 #define DATACHUNK000004 \
00283     0x67,0x2f,0x54,0x52,0x2f,0x68,0x74,0x6d,0x6c,0x34,0x2f,0x73,0x74,0x72,0x69,0x63, /* g/TR/html4/stric */ \
00284     0x74,0x2e,0x64,0x74,0x64,0x22,0x3e,0x0d,0x0a,0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x3c, /* t.dtd">..<html>< */ \
00285     0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x6d,0x65,0x74,0x61,0x20,0x68,0x74,0x74, /* head>..<meta htt */ \
00286     0x70,0x2d,0x65,0x71,0x75,0x69,0x76,0x3d,0x22,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74, /* p-equiv="Content */ \
00287     0x2d,0x54,0x79,0x70,0x65,0x22,0x20,0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x3d,0x22, /* -Type" content=" */ \
00288     0x74,0x65,0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x3b,0x20,0x63,0x68,0x61,0x72,0x73, /* text/html; chars */ \
00289     0x65,0x74,0x3d,0x49,0x53,0x4f,0x2d,0x38,0x38,0x35,0x39,0x2d,0x31,0x22,0x3e,0x0d, /* et=ISO-8859-1">. */ \
00290     0x0a,0x3c,0x74,0x69,0x74,0x6c,0x65,0x3e,0x4d,0x6f,0x42,0x61,0x43,0x6f,0x6e,0x40, /* .<title>MoBaCon@ */ \
00291     0x65,0x57,0x69,0x63,0x68,0x74,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x0d,0x0a, /* eWicht</title>.. */ \
00292     0x3c,0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,0x6c,0x3d,0x22,0x73,0x74,0x79,0x6c,0x65, /* <link rel="style */ \
00293     0x73,0x68,0x65,0x65,0x74,0x22,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x73,0x74,0x79, /* sheet" href="sty */ \
00294     0x6c,0x65,0x2e,0x63,0x73,0x73,0x22,0x20,0x54,0x59,0x50,0x45,0x3d,0x22,0x74,0x65, /* le.css" TYPE="te */ \
00295     0x78,0x74,0x2f,0x63,0x73,0x73,0x22,0x20,0x4d,0x45,0x44,0x49,0x41,0x3d,0x22,0x73, /* xt/css" MEDIA="s */ \
00296     0x63,0x72,0x65,0x65,0x6e,0x22,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x65,0x61,0x64,0x3e, /* creen">..</head> */ \
00297     0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x3e,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d, /* ..<body><div id= */ \
00298     0x22,0x73,0x69,0x74,0x65,0x22,0x3e,0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59,0x46, /* "site">...6.c8YF */ \
00299     0xd6,0xcf,0xf9,0x2a,0x50,0xc5,0x38,0xa6,0x84,0xd6,0xd2,0xa1,0x71,0x43,0x80,0x14, /* ....P.8.....qC.. */ \
00300     0xa8,0x62,0x90,0x1c,0x94,0x10,0x4a,0x81,0x52,0x02,0x63,0xfe,0xd5,0x7c,0x0d,0x8e, /* .b....J.R.c..|.. */ \
00301     0x29,0xa1,0xb5,0x74,0xd0,0x5a,0x05,0xe5,0x07,0x5f,0x36,0xbe,0xc6,0x97,0x8d,0x2f, /* )..t.Z..._6..../ */ \
00302     0x6b,0xbe,0x9a,0xaf,0xc1,0x31,0x25,0xb4,0x96,0x0e,0x5a,0xab,0xa0,0xfc,0xe0,0xcb, /* k....1%...Z..... */ \
00303     0xc6,0xd7,0xf8,0xb2,0xf1,0x65,0xcd,0x57,0xf3,0x35,0x38,0x86,0x2b,0x4d,0x09,0x52, /* .....e.W.58.+M.R */ \
00304     0x3a,0xa4,0x1f,0x90,0x24,0xaa,0x29,0x40,0x2d,0x1b,0x5f,0xd6,0x7c,0x35,0x5f,0x83, /* :...$.)@-._.|5_. */ \
00305     0x63,0x4a,0x68,0x2d,0x1d,0xb4,0x56,0x41,0xf9,0xc1,0x97,0x8d,0xaf,0xf1,0x65,0xe3, /* cJh-..VA......e. */ \
00306     0xcb,0x9a,0xaf,0xe6,0x6b,0x70,0x4c,0x09,0xad,0xa5,0x83,0xd6,0x2a,0x28,0x3f,0xf8, /* ....kpL......(?. */ \
00307     0xb2,0xf1,0x35,0xce,0x01,0x00,0x00,0x5c,0x36,0xbe,0xac,0xf9,0x6a,0xbe,0x06,0xc7, /* ..5....\6...j... */ \
00308     0x94,0xd0,0x5a,0x3a,0x68,0xad,0x82,0xf2,0x83,0x2f,0x1b,0x5f,0xe3,0xcb,0xc6,0x97, /* ..Z:h..../._.... */ \
00309     0x35,0x5f,0xcd,0xd7,0xe0,0x98,0x12,0x5a,0x4b,0x07,0xad,0x55,0x50,0x7e,0xf0,0x65, /* 5_.....ZK..UP~.e */ \
00310     0xe3,0x6b,0x7c,0xd9,0xf8,0xb2,0xe6,0xab,0xf9,0x1a,0x1c,0x53,0x42,0x6b,0xe9,0xa0, /* .k|........SBk.. */ \
00311     0xb5,0x0a,0xca,0x0f,0xbe,0x6c,0x7c,0x8d,0x23,0x14,0x8e,0x09,0xb5,0x6c,0x7c,0x59, /* .....l|.#....l|Y */ \
00312     0xf3,0xd5,0x7c,0x0d,0x8e,0x29,0xa1,0xb5,0x74,0xd0,0x5a,0x05,0xe5,0x07,0x5f,0x36, /* ..|..)..t.Z..._6 */ \
00313     0xbe,0xc6,0x97,0x8d,0x2f,0x6b,0xbe,0x9a,0xaf,0xc1,0x31,0x5c,0x69,0x4a,0x90,0xd2, /* ..../k....1\iJ.. */ \
00314     0x21,0xfd,0x80,0x24,0x51,0x4d,0x01,0x6a,0xd9,0xf8,0xb2,0xe6,0xab,0xf9,0x1a,0x1c, /* !..$QM.j........ */ \
00315     0x53,0x42,0x6b,0xe9,0xa0,0xb5,0x0a,0xca,0x0f,0xbe,0x6c,0x7c,0x8d,0x2f,0x1b,0x5f, /* SBk.......l|./._ */ \
00316     0xd6,0x7c,0x35,0x5f,0x83,0x63,0x4a,0x68,0x2d,0x1d,0xb4,0x56,0x41,0xf9,0xc1,0x97, /* .|5_.cJh-..VA... */ \
00317     0x8d,0xaf,0xf1,0x65,0xe3,0xcb,0x9a,0xaf,0xe6,0x6b,0x70,0x4c,0x09,0xad,0xa5,0x83, /* ...e.....kpL.... */ \
00318     0xd6,0x2a,0x28,0x3f,0xf8,0xb2,0xf1,0x35,0xbe,0x6c,0x7c,0x59,0xf3,0x65,0x05,0xaa, /* ..(?...5.l|Y.e.. */ \
00319     0xd8,0x07,0x81,0x1b,0x82,0x13,0xac,0x70,0x3c,0xa4,0x03,0x63,0x75,0x2e,0xb0,0x5a, /* .......p<..cu..Z */ \
00320     0x9c,0x94,0x6e,0xc9,0x60,0xc0,0x11,0xf0,0x12,0xfe,0x59,0x92,0xa2,0xcb,0x8b,0xa4, /* ..n.`.....Y..... */ \
00321     0x98,0x74,0x4d,0xa3,0x84,0xad,0x73,0x52,0x10,0x4c,0x3a,0x98,0x73,0x98,0x50,0x34, /* .tM...sR.L:.s.P4 */ \
00322     0x93,0xee,0xfc,0x7c,0x96,0xa4,0xe8,0xf2,0x22,0x29,0x26,0x5d,0xd3,0x28,0x61,0xeb, /* ...|....")&].(a. */ \
00323     0x9c,0x14,0x04,0x93,0x0e,0xe9,0x1c,0x26,0x14,0xcd,0xa4,0xfb,0x97,0x10,0xb8,0x21, /* .......&.......! */ \
00324     0xbe,0x0c,0x0b,0xfb,0x32,0x2c,0xec,0x4b,0x14,0x0f,0xe4,0x97,0xf0,0x12,0xea,0x00, /* ....2,.K........ */ \
00325     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x75,0x00,0x00,0x00, /* ............u... */ \
00326     0x4f,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0xd9,0x00,0x00,0x00, /* O...v...Y....... */ \
00327     0x79,0x00,0x00,0x00,0xda,0x00,0x00,0x00,0x83,0x00,0x00,0x00,0xdb,0x00,0x00,0x00, /* y............... */ \
00328     0xc7,0x00,0x00,0x00,0x79,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x7a,0x00,0x00,0x00, /* ....y.......z... */ \
00329     0xf1,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0xfb,0x00,0x00,0x00,0x7b,0x00,0x00,0x00, /* ....9.......{... */ \
00330     0xfd,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x1e,0x01,0x00,0x00,0x3b,0x00,0x00,0x00, /* ....|.......;... */ \
00331     0x28,0x01,0x00,0x00,0x7d,0x00,0x00,0x00,0x48,0x01,0x00,0x00,0x3d,0x00,0x00,0x00, /* (...}...H...=... */ \
00332     0x52,0x01,0x00,0x00,0x7e,0x00,0x00,0x00,0x72,0x01,0x00,0x00,0x7f,0x00,0x00,0x00, /* R...~...r....... */ \
00333     0x7c,0x01,0x00,0x00,0x80,0x00,0x00,0x00,0xa2,0x01,0x00,0x00,0x81,0x00,0x00,0x00, /* |............... */ \
00334     0xac,0x01,0x00,0x00,0x82,0x00,0x00,0x00,0xf0,0x01,0x00,0x00,0x83,0x00,0x00,0x00, /* ................ */ \
00335     0xfa,0x01,0x00,0x00,0x84,0x00,0x00,0x00,0x1a,0x02,0x00,0x00,0x39,0x00,0x00,0x00, /* ............9... */ \
00336     0x24,0x02,0x00,0x00,0x85,0x00,0x00,0x00,0x44,0x02,0x00,0x00,0x86,0x00,0x00,0x00, /* $.......D....... */ \
00337     0x4e,0x02,0x00,0x00,0x87,0x00,0x00,0x00,0xab,0x02,0x00,0x00,0x88,0x00,0x00,0x00, /* N............... */ \
00338     0xd4,0x02,0x00,0x00,0x89,0x00,0x00,0x00,0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59, /* ...........6.c8Y */ \
00339     0x46,0xd6,0x3f,0x08,0xdc,0x10,0x9c,0x60,0x85,0xe3,0x21,0x9d,0xc2,0x75,0x9d,0x0b, /* F.?....`..!..u.. */ \
00340     0xac,0x16,0x27,0xa5,0x2b,0x1c,0xc3,0x29,0x83,0x17,0x47,0xc0,0x4b,0xf8,0x57,0x81, /* ..'.+..)..G.K.W. */ \
00341     0x2a,0xc6,0x31,0x25,0xb4,0x96,0x0e,0x8d,0x1b,0x02,0xa4,0x40,0x15,0x03,0xf3,0xaf, /* ..1%.......@.... */ \
00342     0xe6,0x6b,0x7c,0xe8,0x97,0xe8,0x97,0x8d,0xaf,0xf1,0xa1,0x5f,0xa2,0x5f,0x36,0xbe, /* .k|........_._6. */ \
00343     0xc6,0x87,0x7e,0x89,0x7e,0xd9,0xf8,0x1a,0x1f,0xfa,0x25,0xfa,0x65,0xe3,0x6b,0x7c, /* ..~.~.....%.e.k| */ \
00344     0xe8,0x97,0xe8,0x97,0x8d,0xaf,0xf1,0xa1,0x5f,0xa2,0x5f,0x36,0xbe,0xc6,0x87,0x7e, /* ........_._6...~ */ \
00345     0x89,0x7e,0xd9,0xf8,0x1a,0x1f,0xfa,0x25,0xfa,0x65,0xe3,0xcb,0x9a,0xaf,0x86,0x63, /* .~.....%.e.....c */ \
00346     0x4a,0x68,0x2d,0x1d,0xce,0x44,0xf0,0x60,0x1a,0xf3,0xaf,0xf1,0x65,0xe3,0x6b,0x7c  /* Jh-..D.`....e.k| */
00347 #define DATACHUNK000005 \
00348     0xd9,0xf8,0x1a,0x07,0x43,0x20,0x10,0x90,0x20,0x40,0x2c,0x1b,0x5f,0xe3,0xcb,0xc6, /* ....C .. @,._... */ \
00349     0xd7,0xf8,0xb2,0xf1,0x35,0xbe,0x6c,0x7c,0x8d,0x03,0x89,0x40,0x20,0xc0,0x20,0x01, /* ....5.l|...@ . . */ \
00350     0xb6,0x6c,0x7c,0x8d,0x03,0x89,0x40,0x20,0xc0,0x80,0x5a,0x36,0xbe,0xac,0xf9,0xb2, /* .l|...@ ..Z6.... */ \
00351     0x02,0x55,0xec,0xa3,0x3e,0x4b,0x52,0x74,0x79,0x91,0x14,0x93,0xae,0x69,0x94,0xb0, /* .U..>KRty....i.. */ \
00352     0x75,0x4e,0x0a,0x82,0x49,0x07,0xc2,0x39,0x4c,0x28,0x9a,0x49,0xf7,0xcf,0x92,0x14, /* uN..I..9L(.I.... */ \
00353     0x5d,0x5e,0x24,0xc5,0xa4,0x1b,0xa6,0x59,0x9d,0xc3,0x84,0xa2,0x99,0x74,0xff,0x92, /* ]^$....Y.....t.. */ \
00354     0xfa,0x12,0x02,0x37,0xc4,0x97,0x61,0x61,0x5f,0x86,0x85,0x7d,0x89,0xe2,0x81,0xfc, /* ...7..aa_..}.... */ \
00355     0x12,0x5e,0x42,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* .^B............. */ \
00356     0x8a,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x72,0x00,0x00,0x00, /* ....b.......r... */ \
00357     0x03,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x92,0x00,0x00,0x00, /* ................ */ \
00358     0x05,0x00,0x00,0x00,0xa2,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0xb2,0x00,0x00,0x00, /* ................ */ \
00359     0x07,0x00,0x00,0x00,0xc2,0x00,0x00,0x00,0x8b,0x00,0x00,0x00,0xd2,0x00,0x00,0x00, /* ................ */ \
00360     0x8c,0x00,0x00,0x00,0x1c,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,0x57,0x01,0x00,0x00, /* ............W... */ \
00361     0x8d,0x00,0x00,0x00,0x57,0x01,0x00,0x00,0x8e,0x00,0x00,0x00,0x57,0x01,0x00,0x00, /* ....W.......W... */ \
00362     0x8f,0x00,0x00,0x00,0x57,0x01,0x00,0x00,0x90,0x00,0x00,0x00,0x57,0x01,0x00,0x00, /* ....W.......W... */ \
00363     0x91,0x00,0x00,0x00,0x57,0x01,0x00,0x00,0x92,0x00,0x00,0x00,0x57,0x01,0x00,0x00, /* ....W.......W... */ \
00364     0x93,0x00,0x00,0x00,0x57,0x01,0x00,0x00,0x94,0x00,0x00,0x00,0x87,0x01,0x00,0x00, /* ....W........... */ \
00365     0x13,0x00,0x00,0x00,0xa4,0x01,0x00,0x00,0x14,0x00,0x00,0x00,0x0b,0x0b,0xe3,0x36, /* ...............6 */ \
00366     0xa4,0x63,0x38,0x59,0x46,0xd6,0x3f,0x08,0xdc,0x10,0x9c,0x60,0x85,0xe3,0x21,0x9d, /* .c8YF.?....`..!. */ \
00367     0xc2,0x75,0x9d,0x0b,0xac,0x16,0x27,0xa5,0x2b,0x1c,0xc3,0x35,0x02,0x5e,0xc2,0xbf, /* .u....'.+..5.^.. */ \
00368     0x0a,0x54,0x31,0x8e,0x29,0xa1,0xb5,0x74,0x68,0xdc,0x10,0x20,0x05,0xaa,0x18,0x98, /* .T1.)..th.. .... */ \
00369     0x7f,0x35,0x1c,0x53,0x42,0x6b,0xe9,0x70,0x26,0xc2,0xbf,0xc6,0x87,0x7e,0x89,0x7e, /* .5.SBk.p&....~.~ */ \
00370     0xd9,0xf8,0x1a,0x1f,0xfa,0x25,0xfa,0x65,0xe3,0x6b,0x7c,0xe8,0x97,0xe8,0x97,0x8d, /* .....%.e.k|..... */ \
00371     0xaf,0xf1,0xa1,0x5f,0xa2,0x5f,0x36,0xbe,0xc6,0x97,0x8d,0x2f,0x6b,0xbe,0xac,0x40, /* ..._._6..../k..@ */ \
00372     0x15,0xfb,0xa8,0xcf,0x92,0x14,0x5d,0x5e,0x24,0xc5,0xa4,0x6b,0x1a,0x25,0x6c,0x9d, /* ......]^$..k.%l. */ \
00373     0x93,0x82,0x60,0xd2,0x81,0x70,0x0e,0x13,0x8a,0x66,0xd2,0xfd,0xb3,0x24,0x45,0x97, /* ..`..p...f...$E. */ \
00374     0x17,0x49,0x31,0xe9,0x86,0x69,0x56,0xe7,0x30,0xa1,0x68,0x26,0xdd,0xbf,0xa4,0xbe, /* .I1..iV.0.h&.... */ \
00375     0x84,0xc0,0x0d,0xf1,0x65,0x58,0xd8,0x97,0x61,0x61,0x5f,0xa2,0x78,0x20,0xbf,0x84, /* ....eX..aa_.x .. */ \
00376     0x97,0x50,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x95, /* .P.............. */ \
00377     0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0x02, /* ...k.......{.... */ \
00378     0x00,0x00,0x00,0x8b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x9b,0x00,0x00,0x00,0x17, /* ................ */ \
00379     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x96,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x97, /* ................ */ \
00380     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x99, /* ................ */ \
00381     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x9a,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x9b, /* ................ */ \
00382     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x9c,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x9d, /* ................ */ \
00383     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x9e,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0x9f, /* ................ */ \
00384     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xa1, /* ................ */ \
00385     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xa2,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xa3, /* ................ */ \
00386     0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xa4,0x00,0x00,0x00,0xb2,0x00,0x00,0x00,0xa5, /* ................ */ \
00387     0x00,0x00,0x00,0xe2,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x14, /* ................ */ \
00388     0x00,0x00,0x00,0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59,0x46,0xd6,0x3f,0x08,0xdc, /* ......6.c8YF.?.. */ \
00389     0x10,0x9c,0x60,0x85,0xe3,0x21,0x9d,0xc2,0x75,0x9d,0x0b,0xac,0x16,0x27,0xa5,0x2b, /* ..`..!..u....'.+ */ \
00390     0x1c,0xc3,0x35,0x02,0x5e,0xc2,0x3f,0x38,0xe4,0x41,0x97,0x70,0xc8,0xcf,0x92,0x14, /* ..5.^.?8.A.p.... */ \
00391     0x5d,0x5e,0x24,0xc5,0xa4,0xc3,0x6d,0x04,0x23,0x9d,0x93,0x82,0x60,0xd2,0x01,0xad, /* ]^$...m.#...`... */ \
00392     0x9d,0xc3,0x84,0xa2,0x99,0x74,0xe7,0xf9,0x55,0xa0,0x8a,0x71,0x4c,0x09,0xad,0xa5, /* .....t..U..qL... */ \
00393     0x43,0xe3,0x86,0x00,0x29,0x50,0xc5,0x20,0x39,0xd0,0x36,0x18,0x28,0x25,0x30,0xe6, /* C...)P. 9.6.(%0. */ \
00394     0x5f,0xcd,0xd7,0xe0,0x98,0x12,0x5a,0x4b,0x07,0xad,0x55,0x50,0x7e,0xf0,0x65,0xe3, /* _.....ZK..UP~.e. */ \
00395     0x6b,0x7c,0xd9,0xf8,0xb2,0xe6,0xab,0xf9,0x1a,0x1c,0x53,0x42,0x6b,0xe9,0xa0,0xb5, /* k|........SBk... */ \
00396     0x0a,0xca,0x0f,0xbe,0x6c,0x7c,0x8d,0x2f,0x1b,0x5f,0xd6,0x7c,0x35,0x5f,0x83,0x63, /* ....l|./._.|5_.c */ \
00397     0x4a,0x68,0x2d,0x1d,0xb4,0x56,0x41,0xf9,0xc1,0x97,0x8d,0xaf,0x71,0x0e,0x70,0x22, /* Jh-..VA.....q.p" */ \
00398     0xe1,0xcb,0xc6,0x97,0x35,0x5f,0x56,0xa0,0x8a,0x7d,0x15,0xa8,0x62,0x1c,0x53,0x42, /* ....5_V..}..b.SB */ \
00399     0x6b,0xe9,0xd0,0xb8,0x21,0x40,0x0a,0x54,0x31,0x30,0x0e,0x8d,0x1b,0x02,0xa4,0x40, /* k...!@.T10.....@ */ \
00400     0x15,0x03,0xca,0x39,0x8a,0x9b,0x60,0x46,0x3a,0xa4,0x7f,0x35,0x5f,0x83,0xeb,0x22, /* ...9..`F:..5_.." */ \
00401     0x15,0x93,0x8e,0xe2,0x26,0x98,0x01,0x27,0x71,0x92,0xf9,0x97,0x8d,0xaf,0x71,0x68, /* ....&..'q.....qh */ \
00402     0xb0,0x65,0xe3,0x6b,0x1c,0x1a,0x72,0xd9,0xf8,0x1a,0x87,0x06,0x6a,0xd9,0xf8,0x1a, /* .e.k..r.....j... */ \
00403     0x87,0x86,0x5a,0x36,0xbe,0xc6,0xa1,0x41,0x2c,0x1b,0x5f,0xe3,0xd0,0x00,0x68,0xd9, /* ..Z6...A,._...h. */ \
00404     0xf8,0x1a,0x87,0x06,0xc0,0xcb,0xc6,0xd7,0x38,0x34,0xc0,0x96,0x8d,0xaf,0x71,0x68, /* ........84....qh */ \
00405     0x00,0x5b,0x36,0xbe,0xc6,0xa1,0xc1,0x80,0x5c,0x36,0xbe,0xc6,0xa1,0xc1,0xc0,0x96, /* .[6.....\6...... */ \
00406     0x8d,0xaf,0x71,0x68,0x30,0xc8,0x65,0xe3,0xcb,0x9a,0xaf,0xe6,0x6b,0x7c,0xd9,0xf8, /* ..qh0.e.....k|.. */ \
00407     0xb2,0xe6,0xab,0xf9,0x1a,0x5f,0x36,0xbe,0xac,0xf9,0xb2,0xe6,0xcb,0x0a,0x54,0xb1, /* ....._6.......T. */ \
00408     0xaf,0x02,0x55,0x8c,0x63,0x4a,0x68,0x2d,0x1d,0x1a,0x37,0x04,0x48,0x81,0x2a,0x06, /* ..U.cJh-..7.H... */ \
00409     0xe6,0x5f,0xcd,0xd7,0xf8,0xb2,0xf1,0x35,0x3e,0xf4,0x4b,0xf4,0xcb,0xc6,0xd7,0xf8, /* ._.....5>.K..... */ \
00410     0xd0,0x2f,0xd1,0x2f,0x1b,0x5f,0xe3,0x43,0xbf,0x44,0xbf,0x6c,0x7c,0x8d,0x0f,0xfd, /* ././._.C.D.l|... */ \
00411     0x12,0xfd,0xb2,0xf1,0x35,0x3e,0xf4,0x4b,0xf4,0xcb,0xc6,0x97,0x35,0x5f,0x0d,0xc7  /* ....5>.K....5_.. */
00412 #define DATACHUNK000006 \
00413     0x94,0xd0,0x5a,0x3a,0x9c,0x89,0xf0,0xaf,0xf1,0x65,0xe3,0x6b,0x7c,0xd9,0xf8,0x1a, /* ..Z:.....e.k|... */ \
00414     0x07,0x43,0x20,0x10,0x90,0x20,0x40,0x2c,0x1b,0x5f,0xe3,0xcb,0xc6,0xd7,0x38,0x90, /* .C .. @,._....8. */ \
00415     0x08,0x04,0x02,0x0c,0x12,0x60,0xcb,0xc6,0xd7,0x38,0x90,0x08,0x04,0x02,0x0c,0xa8, /* .....`...8...... */ \
00416     0x65,0xe3,0xcb,0x9a,0xaf,0xe6,0x6b,0x7c,0x96,0xa4,0xe8,0xf2,0x22,0x29,0x26,0xdd, /* e.....k|....")&. */ \
00417     0x88,0xb0,0xb8,0x73,0x52,0x10,0x4c,0x3a,0x60,0x9d,0xc3,0x84,0xa2,0x99,0x74,0x80, /* ...sR.L:`.....t. */ \
00418     0x82,0x39,0xc7,0xe0,0x0c,0x03,0x38,0x0b,0xe9,0x18,0x9c,0x61,0x00,0x67,0xe1,0x5f, /* .9....8....a.g._ */ \
00419     0x36,0xbe,0xc6,0x97,0x8d,0xaf,0xf1,0x65,0xe3,0x6b,0x7c,0xd9,0xf8,0x1a,0x5f,0x36, /* 6......e.k|..._6 */ \
00420     0xbe,0xc6,0x97,0x8d,0x2f,0x6b,0xbe,0xac,0x40,0x15,0xfb,0x2c,0x49,0xd1,0xe5,0x45, /* ..../k..@..,I..E */ \
00421     0x52,0x4c,0x3a,0xdc,0x46,0x30,0xd2,0x39,0x29,0x08,0x26,0x1d,0x20,0x9c,0xc3,0x84, /* RL:.F0.9).&. ... */ \
00422     0xa2,0x99,0x74,0xe7,0xf9,0x51,0x9f,0x25,0x29,0xba,0xbc,0x48,0x8a,0x49,0xd7,0x34, /* ..t..Q.%)..H.I.4 */ \
00423     0x4a,0xd8,0x3a,0x27,0x05,0xc1,0xa4,0x03,0xe1,0x1c,0x26,0x14,0xcd,0xa4,0xfb,0x67, /* J.:'......&....g */ \
00424     0x49,0x8a,0x2e,0x2f,0x92,0x62,0xd2,0x0d,0xd3,0xac,0xce,0x61,0x42,0xd1,0x4c,0xba, /* I../.b.....aB.L. */ \
00425     0x7f,0x49,0x7d,0x09,0x81,0x1b,0xe2,0xcb,0xb0,0xb0,0x2f,0xc3,0xc2,0xbe,0x44,0xf1, /* .I}......./...D. */ \
00426     0x40,0x7e,0x09,0x2f,0xa1,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* @~./............ */ \
00427     0x00,0x00,0x95,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x69,0x00, /* ......>.......i. */ \
00428     0x00,0x00,0x1d,0x00,0x00,0x00,0xa7,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xb1,0x00, /* ................ */ \
00429     0x00,0x00,0x1e,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0xdb,0x00, /* ................ */ \
00430     0x00,0x00,0x1f,0x00,0x00,0x00,0xfb,0x00,0x00,0x00,0xa6,0x00,0x00,0x00,0x05,0x01, /* ................ */ \
00431     0x00,0x00,0xa7,0x00,0x00,0x00,0x1c,0x01,0x00,0x00,0xa8,0x00,0x00,0x00,0x01,0x02, /* ................ */ \
00432     0x00,0x00,0xa9,0x00,0x00,0x00,0x06,0x02,0x00,0x00,0xaa,0x00,0x00,0x00,0x06,0x02, /* ................ */ \
00433     0x00,0x00,0xab,0x00,0x00,0x00,0x06,0x02,0x00,0x00,0xac,0x00,0x00,0x00,0x06,0x02, /* ................ */ \
00434     0x00,0x00,0xad,0x00,0x00,0x00,0x06,0x02,0x00,0x00,0xae,0x00,0x00,0x00,0x06,0x02, /* ................ */ \
00435     0x00,0x00,0xaf,0x00,0x00,0x00,0x06,0x02,0x00,0x00,0xb0,0x00,0x00,0x00,0x06,0x02, /* ................ */ \
00436     0x00,0x00,0xb1,0x00,0x00,0x00,0x06,0x02,0x00,0x00,0xb2,0x00,0x00,0x00,0x06,0x02, /* ................ */ \
00437     0x00,0x00,0xb3,0x00,0x00,0x00,0x06,0x02,0x00,0x00,0xb4,0x00,0x00,0x00,0x06,0x02, /* ................ */ \
00438     0x00,0x00,0xb5,0x00,0x00,0x00,0x13,0x02,0x00,0x00,0xb6,0x00,0x00,0x00,0x18,0x02, /* ................ */ \
00439     0x00,0x00,0xb7,0x00,0x00,0x00,0x18,0x02,0x00,0x00,0xb8,0x00,0x00,0x00,0x18,0x02, /* ................ */ \
00440     0x00,0x00,0xb9,0x00,0x00,0x00,0x18,0x02,0x00,0x00,0xba,0x00,0x00,0x00,0x18,0x02, /* ................ */ \
00441     0x00,0x00,0xbb,0x00,0x00,0x00,0x18,0x02,0x00,0x00,0xbc,0x00,0x00,0x00,0x18,0x02, /* ................ */ \
00442     0x00,0x00,0xbd,0x00,0x00,0x00,0x18,0x02,0x00,0x00,0xbe,0x00,0x00,0x00,0x18,0x02, /* ................ */ \
00443     0x00,0x00,0xbf,0x00,0x00,0x00,0x18,0x02,0x00,0x00,0xc0,0x00,0x00,0x00,0x18,0x02, /* ................ */ \
00444     0x00,0x00,0xc1,0x00,0x00,0x00,0x18,0x02,0x00,0x00,0xc2,0x00,0x00,0x00,0x2a,0x02, /* ................ */ \
00445     0x00,0x00,0x22,0x00,0x00,0x00,0x58,0x02,0x00,0x00,0x03,0x00,0x00,0x00,0x68,0x02, /* .."...X.......h. */ \
00446     0x00,0x00,0x04,0x00,0x00,0x00,0x78,0x02,0x00,0x00,0x05,0x00,0x00,0x00,0x88,0x02, /* ......x......... */ \
00447     0x00,0x00,0x8b,0x00,0x00,0x00,0x98,0x02,0x00,0x00,0x8c,0x00,0x00,0x00,0xdd,0x02, /* ................ */ \
00448     0x00,0x00,0x0a,0x00,0x00,0x00,0x51,0x03,0x00,0x00,0x23,0x00,0x00,0x00,0x5a,0x03, /* ......Q...#...Z. */ \
00449     0x00,0x00,0x24,0x00,0x00,0x00,0x63,0x03,0x00,0x00,0x25,0x00,0x00,0x00,0x6c,0x03, /* ..$...c...%...l. */ \
00450     0x00,0x00,0xc3,0x00,0x00,0x00,0x75,0x03,0x00,0x00,0xc4,0x00,0x00,0x00,0x7f,0x03, /* ......u......... */ \
00451     0x00,0x00,0xc5,0x00,0x00,0x00,0x7f,0x03,0x00,0x00,0xc6,0x00,0x00,0x00,0x7f,0x03, /* ................ */ \
00452     0x00,0x00,0xc7,0x00,0x00,0x00,0x7f,0x03,0x00,0x00,0xc8,0x00,0x00,0x00,0x7f,0x03, /* ................ */ \
00453     0x00,0x00,0xc9,0x00,0x00,0x00,0x7f,0x03,0x00,0x00,0xca,0x00,0x00,0x00,0x7f,0x03, /* ................ */ \
00454     0x00,0x00,0xcb,0x00,0x00,0x00,0x7f,0x03,0x00,0x00,0xcc,0x00,0x00,0x00,0xac,0x03, /* ................ */ \
00455     0x00,0x00,0x1d,0x00,0x00,0x00,0xd8,0x03,0x00,0x00,0x13,0x00,0x00,0x00,0xf5,0x03, /* ................ */ \
00456     0x00,0x00,0x14,0x00,0x00,0x00,0x0b,0x0b,0xe3,0x36,0xa4,0x63,0x38,0x59,0x46,0xd6, /* .........6.c8YF. */ \
00457     0x3f,0x08,0xdc,0x10,0x9c,0x60,0x85,0xe3,0x21,0x9d,0xc2,0x75,0x9d,0x0b,0xac,0x16, /* ?....`..!..u.... */ \
00458     0x27,0xa5,0x6b,0x83,0x51,0x08,0x78,0x09,0x3f,0xe7,0x7c,0x15,0xa8,0x62,0x1c,0x53, /* '.k.Q.x.?.|..b.S */ \
00459     0x42,0x6b,0xe9,0xd0,0xb8,0x21,0x40,0x0a,0x54,0x31,0x48,0x0e,0xb4,0x0d,0x06,0x4a, /* Bk...!@.T1H....J */ \
00460     0x09,0x8c,0xf9,0x57,0xf3,0x35,0x38,0xa6,0x84,0xd6,0xd2,0x41,0x6b,0x15,0x94,0x1f, /* ...W.58....Ak... */ \
00461     0x7c,0xd9,0xf8,0x1a,0x9f,0x66,0x8a,0x61,0xe5,0xa4,0x20,0x98,0x74,0x1a,0x05,0x8c, /* |....f.a.. .t... */ \
00462     0x73,0x6d,0x01,0x67,0xd2,0xc1,0xfc,0x4b,0xcd,0x14,0xc3,0xfa,0x65,0xe3,0xcb,0x9a, /* sm.g...K....e... */ \
00463     0xaf,0xe6,0x6b,0x70,0x4c,0x09,0xad,0xa5,0x83,0xd6,0x2a,0x28,0x3f,0xf8,0xb2,0xf1, /* ..kpL......(?... */ \
00464     0x35,0x3e,0xcd,0x14,0xc3,0xca,0x49,0x41,0x30,0xe9,0x34,0x0a,0x40,0x9c,0x6b,0x0b, /* 5>....IA0.4.@.k. */ \
00465     0x38,0x93,0x0e,0xe6,0x5f,0x6a,0xa6,0x18,0xd6,0x2f,0x1b,0x5f,0xd6,0x7c,0x35,0x5f, /* 8..._j.../._.|5_ */ \
00466     0x83,0x63,0x4a,0x68,0x2d,0x1d,0xb4,0x56,0x41,0xf9,0xc1,0x97,0x8d,0xaf,0xf1,0x69, /* .cJh-..VA......i */ \
00467     0xa6,0x18,0x56,0x4e,0x0a,0x82,0x49,0xa7,0x51,0x40,0x3b,0xd7,0x16,0x70,0x26,0x1d, /* ..VN..I.Q@;..p&. */ \
00468     0xcc,0xbf,0xd4,0x4c,0x31,0xac,0x5f,0x36,0xbe,0xac,0xf9,0x6a,0xbe,0x06,0xc7,0x94, /* ...L1._6...j.... */ \
00469     0xd0,0x5a,0x3a,0x68,0xad,0x82,0xf2,0x83,0x2f,0x1b,0x5f,0xe3,0xd3,0x4c,0x31,0xac, /* .Z:h..../._..L1. */ \
00470     0x9c,0x14,0x04,0x93,0x4e,0xa3,0x00,0xcc,0xb9,0xb6,0x80,0x33,0xe9,0x60,0xfe,0xa5, /* ....N......3.`.. */ \
00471     0x66,0x8a,0x61,0xfd,0xb2,0xf1,0x65,0xcd,0x57,0xf3,0x35,0x38,0xa6,0x84,0xd6,0xd2, /* f.a...e.W.58.... */ \
00472     0x41,0x6b,0x15,0x94,0x1f,0x7c,0xd9,0xf8,0x1a,0xe7,0x84,0x5e,0x36,0xbe,0xac,0x39, /* Ak...|.....^6..9 */ \
00473     0xe7,0x7c,0x59,0x81,0x2a,0x76,0xce,0xf9,0xa8,0xcf,0x92,0x14,0x5d,0x5e,0x24,0xc5, /* .|Y..v......]^$. */ \
00474     0xa4,0x6b,0x1a,0x25,0x6c,0x9d,0x93,0x82,0x60,0xd2,0x81,0x70,0x0e,0x13,0x8a,0x66, /* .k.%l...`..p...f */ \
00475     0xd2,0xfd,0x9c,0xf3,0x59,0x92,0xa2,0xcb,0x8b,0xa4,0x98,0x74,0xc3,0x34,0xab,0x73, /* ....Y......t.4.s */ \
00476     0x98,0x50,0x34,0x93,0xee,0x5f,0x52,0x5f,0x42,0xe0,0x86,0xf8,0x32,0x2c,0xec,0xcb  /* .P4.._R_B...2,.. */
00477 #define DATACHUNK000007 \
00478     0xb0,0xb0,0x2f,0x51,0x3c,0x90,0x5f,0xc2,0x4b,0xa8,0x03,0x00,0x00,0x00,0x00,0x00, /* ../Q<._.K....... */ \
00479     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcd,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0xce, /* ...........u.... */ \
00480     0x00,0x00,0x00,0x9b,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0xc4,0x00,0x00,0x00,0xd0, /* ................ */ \
00481     0x00,0x00,0x00,0xea,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x13,0x01,0x00,0x00,0xd2, /* ................ */ \
00482     0x00,0x00,0x00,0x39,0x01,0x00,0x00,0xd3,0x00,0x00,0x00,0x62,0x01,0x00,0x00,0xd4, /* ...9.......b.... */ \
00483     0x00,0x00,0x00,0x88,0x01,0x00,0x00,0xd5,0x00,0x00,0x00,0xb1,0x01,0x00,0x00,0xd6, /* ................ */ \
00484     0x00,0x00,0x00,0xbb,0x01,0x00,0x00,0xd7,0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x13, /* ................ */ \
00485     0x00,0x00,0x00,0x1e,0x02,0x00,0x00,0x14,0x00,0x00,0x00,0x1f,0x8b,0x08,0x00,0x00, /* ................ */ \
00486     0x00,0x00,0x00,0x04,0x00,0xed,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d, /* ........`.I.%&/m */ \
00487     0xca,0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60,0x13,0x24,0xd8, /* .{.J.J..t...`.$. */ \
00488     0x90,0x40,0x10,0xec,0xc1,0x88,0xcd,0xe6,0x92,0xec,0x1d,0x69,0x47,0x23,0x29,0xab, /* .@.........iG#). */ \
00489     0x2a,0x81,0xca,0x65,0x56,0x65,0x5d,0x66,0x16,0x40,0xcc,0xed,0x9d,0xbc,0xf7,0xde, /* ...eVe]f.@...... */ \
00490     0x7b,0xef,0xbd,0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xba,0x3b,0x9d,0x4e,0x27,0xf7,0xdf, /* {....{....;.N'.. */ \
00491     0xff,0x3f,0x5c,0x66,0x64,0x01,0x6c,0xf6,0xce,0x4a,0xda,0xc9,0x9e,0x21,0x80,0xaa, /* .?\fd.l..J...!.. */ \
00492     0xc8,0x1f,0x3f,0x7e,0x7c,0x1f,0x3f,0x22,0x1e,0xff,0x1e,0xef,0x16,0x65,0x7a,0x99, /* ..?~|.?".....ez. */ \
00493     0xd7,0x4d,0x51,0x2d,0x3f,0xfb,0x68,0x77,0xbc,0xf3,0x51,0x9a,0x2f,0xa7,0xd5,0xac, /* .MQ-?.hw..Q./... */ \
00494     0x58,0x5e,0x7c,0xf6,0xd1,0x57,0x6f,0x9e,0x6d,0x1f,0x7c,0xf4,0x7b,0x1c,0xfd,0xc6, /* X^|..Wo.m.|.{... */ \
00495     0xc9,0xe3,0x77,0xcd,0xa3,0x66,0x3a,0xcf,0x17,0x59,0x4a,0x2f,0x2c,0x9b,0x47,0xef, /* ..w..f:..YJ/,.G. */ \
00496     0x9a,0xcf,0x3e,0x9a,0xb7,0xed,0xea,0xd1,0xdd,0xbb,0x57,0x57,0x57,0xe3,0xab,0x7b, /* ..>.......WWW..{ */ \
00497     0xe3,0xaa,0xbe,0xb8,0xbb,0xb7,0xb3,0xb3,0x7b,0xf7,0xf7,0xfe,0xe2,0xf9,0x6b,0x6e, /* ........{.....kn */ \
00498     0x4a,0xa0,0xca,0x7c,0x91,0x2f,0xdb,0x67,0x55,0xbd,0x78,0x9a,0x9f,0x67,0xeb,0xb2, /* J..|./.gU.x..g.. */ \
00499     0xfd,0xec,0xa3,0x5f,0xb4,0xce,0xca,0xe2,0xbc,0xc8,0x67,0x1f,0x11,0xdc,0x1f,0x03, /* ..._......g..... */ \
00500     0x60,0x6d,0x95,0x2e,0xb3,0x45,0xfe,0xd9,0x47,0xd3,0x6a,0xb1,0xa8,0x96,0xfc,0x25, /* `m...E..G.j....% */ \
00501     0x7f,0x4b,0x7f,0xaf,0xca,0xfc,0xdd,0x9b,0xeb,0x55,0xce,0x9f,0xf1,0x87,0x59,0xdb, /* .K.......U....Y. */ \
00502     0xd6,0xc5,0x64,0xdd,0xe6,0xfa,0x52,0x99,0x2d,0x2f,0xd6,0xd9,0x45,0xfe,0x51,0xba, /* ..d...R.-/..E.Q. */ \
00503     0x6e,0xe8,0xcf,0x6a,0xd5,0xd2,0x78,0xb2,0xf2,0xa3,0x74,0x66,0xba,0xdd,0x11,0x88, /* n..j..x...tf.... */ \
00504     0xf2,0x7a,0x53,0x00,0xa6,0x03,0x29,0x9f,0xd6,0x79,0x43,0x50,0xa7,0x78,0x35,0x9d, /* .zS...)..yCP.x5. */ \
00505     0x64,0x80,0x43,0x1f,0xae,0x97,0x4d,0x71,0xb1,0xcc,0x67,0x4f,0xae,0xdb,0xdc,0x80, /* d.C...Mq..gO.... */ \
00506     0x90,0xe6,0x8b,0x62,0x79,0xb6,0x9c,0x96,0xeb,0xa6,0xb8,0xcc,0xd3,0xcb,0xac,0x5c, /* ...by..........\ */ \
00507     0xe7,0xe8,0xe5,0x6e,0xd8,0x26,0x7b,0xd7,0x6b,0xb3,0xeb,0xda,0x3c,0xbe,0x1b,0x76, /* ...n.&{.k...<..v */ \
00508     0x6b,0x50,0xbc,0x1b,0xc3,0xf1,0xf1,0xef,0xba,0xbd,0xfd,0x55,0x93,0xa7,0x3b,0xe9, /* kP.........U..;. */ \
00509     0x79,0x55,0xa7,0x9f,0xe7,0xf5,0x22,0x5b,0x8e,0xd2,0x5d,0xfe,0xeb,0x74,0x79,0x51, /* yU...."[..]..tyQ */ \
00510     0x16,0xcd,0x7c,0x7b,0x5b,0x49,0x74,0xd7,0xa7,0xd1,0x06,0xb2,0x4d,0x67,0x65,0x71, /* ..|{[It.....Mgeq */ \
00511     0x31,0x6f,0xff,0xbf,0x40,0xb6,0xbd,0xfb,0xf7,0x3f,0x84,0x70,0xcb,0xa2,0x4d,0x8b, /* 1o..@....?.p..M. */ \
00512     0x26,0x6d,0xf2,0x69,0xb5,0x9c,0x35,0x63,0xa2,0xe2,0x22,0xcf,0x96,0x4d,0x9a,0x95, /* &m.i..5c.."..M.. */ \
00513     0x57,0xd9,0x75,0x93,0x56,0xe7,0xe7,0xa3,0x94,0xba,0xe8,0x7c,0xba,0x7c,0x5f,0x8a, /* W.u.V......|.|_. */ \
00514     0xb6,0xd5,0xc5,0x45,0x49,0x6c,0xd8,0x52,0xf7,0x4c,0x88,0x49,0x55,0x95,0x04,0x72, /* ...EIl.R.L.IU..r */ \
00515     0x98,0xc2,0xe7,0x59,0xd9,0x58,0x12,0x01,0xd5,0x67,0xf8,0x40,0xf1,0x98,0x15,0x75, /* ...Y.X...g.@...u */ \
00516     0x2e,0x94,0x65,0xc0,0x24,0x95,0x84,0x53,0xba,0x5a,0x37,0x73,0xfc,0xda,0xce,0x73, /* ..e.$..S.Z7s...s */ \
00517     0x91,0xd6,0xbc,0x4e,0x09,0x87,0xb6,0x5a,0x8e,0xd3,0x37,0xf5,0x7a,0xc3,0xcb,0xc5, /* ...N...Z..7.z... */ \
00518     0x79,0x3a,0xad,0xab,0xa6,0x31,0x6f,0xff,0x20,0xaf,0xab,0x74,0x55,0x15,0xcb,0x76, /* y:...1o. ..tU..v */ \
00519     0xfc,0xbe,0x23,0xcd,0xd6,0x6d,0x55,0xac,0xde,0x67,0xa4,0x2d,0xa1,0x66,0xa6,0x30, /* ..#..mU..g.-.f.0 */ \
00520     0x06,0xb1,0xc9,0x6b,0xd2,0x44,0x1e,0xc4,0x6c,0x79,0xfd,0xd5,0xab,0xb3,0x2e,0xc0, /* ...k.D..ly...... */ \
00521     0x0d,0x10,0xce,0xb3,0xa6,0x6d,0xda,0xac,0x6e,0xdf,0x07,0xad,0xde,0x04,0xbc,0x5e, /* .....m..n......^ */ \
00522     0xe5,0xf9,0x2c,0x5d,0xaf,0x52,0x06,0x85,0x5f,0xb2,0xe5,0x2c,0x25,0xbe,0x59,0x82, /* ..,].R.._..,%.Y. */ \
00523     0x9c,0xa0,0x5c,0x95,0x0a,0xae,0xef,0x4d,0xb4,0x76,0x5d,0x4f,0xaa,0x0f,0x42,0x8e, /* ..\....M.v]O..B. */ \
00524     0x44,0x3d,0x9b,0x94,0x79,0xca,0x90,0xcc,0xec,0x6f,0xc2,0x83,0x3f,0xea,0x28,0x51, /* D=..y....o..?.(Q */ \
00525     0xfe,0x4c,0xd5,0x2e,0xff,0xed,0xfe,0xb4,0x5a,0x78,0x79,0x5e,0x5c,0xdc,0xa0,0x85, /* .L......Zxy^\... */ \
00526     0x9b,0xfc,0x17,0xad,0x09,0x03,0x2b,0x67,0x1e,0x94,0x3a,0x3f,0xb7,0xaa,0x3c,0x25, /* ......+g..:?..<% */ \
00527     0x91,0xff,0x72,0x3a,0x5d,0xd7,0x8d,0x2f,0xe9,0xbd,0xd6,0x4d,0x3d,0x5d,0xbd,0x4f, /* ..r:]../...M=].O */ \
00528     0xdb,0x55,0x5d,0xb5,0x55,0xe7,0x85,0x94,0x34,0x87,0xf9,0x6b,0xd7,0xe9,0x8b,0xe8, /* .U].U...4..k.... */ \
00529     0xfb,0xb3,0xc9,0xa6,0x97,0x1f,0x5a,0x3e,0xbb,0xdb,0x1b,0x69,0x6c,0x66,0xd5,0x86, /* ......Z>...ilf.. */ \
00530     0x7a,0x73,0x0b,0xe5,0xb4,0xbc,0x18,0x9e,0xda,0xdd,0xb1,0xb1,0x04,0x5f,0x6f,0x8a, /* zs..........._o. */ \
00531     0x66,0x59,0x9b,0xbd,0xa7,0x99,0xc4,0xbf,0x43,0x18,0xd6,0x34,0x44,0x52,0x18,0xb3, /* fY......C..4DR.. */ \
00532     0x4d,0xf2,0xa5,0x24,0xbf,0x01,0x80,0xc7,0xad,0x2f,0xf1,0xc2,0xb4,0x2a,0x53,0x69, /* M..$...../....Si */ \
00533     0x89,0x86,0x33,0x36,0x58,0x05,0xe9,0xe3,0x82,0x1c,0x81,0x1f,0xe0,0xd3,0xac,0x65, /* ..36X..........e */ \
00534     0x65,0xf4,0xfa,0xd5,0xc9,0x4b,0x15,0xac,0x74,0xab,0x18,0xe7,0xe9,0x8b,0x74,0xf7, /* e....K..t.....t. */ \
00535     0xce,0x7b,0x8b,0xd8,0x64,0xdd,0x0c,0x21,0xf4,0xee,0x67,0xd1,0x84,0x7d,0x88,0x55, /* .{..d..!..g..}.U */ \
00536     0xe7,0x81,0x13,0xde,0xe9,0x72,0xbd,0x98,0x7c,0x0d,0xad,0x92,0xcd,0x66,0xde,0xa4, /* .....r..|....f.. */ \
00537     0x18,0xbc,0x5f,0xcf,0x2b,0x28,0xc2,0xc1,0xb9,0x39,0x9e,0xcd,0x08,0x49,0x98,0x3e, /* .._.+(...9...I.> */ \
00538     0xa6,0xfe,0x2c,0xbf,0x2c,0xa6,0xf9,0x7b,0xf7,0x4d,0xb4,0xd8,0xd4,0xbd,0xd7,0xdf, /* ..,.,..{.M...... */ \
00539     0x17,0x34,0xe7,0x8b,0xf5,0x82,0xcc,0x0d,0xd9,0x1f,0xa8,0xb0,0xec,0x9b,0x41,0x20, /* .4............A  */ \
00540     0x7b,0x77,0x5b,0x04,0xb2,0x77,0x3f,0x1b,0x08,0x34,0x6d,0xbe,0x6a,0x22,0xfd,0xfb, /* {w[..w?..4m.j".. */ \
00541     0x7c,0xe3,0xcc,0x0a,0xb7,0x46,0x8f,0x59,0x5a,0x92,0x64,0x7c,0xdd,0x4e,0x69,0xd4  /* |....F.YZ.d|.Ni. */
00542 #define DATACHUNK000008 \
00543     0x0d,0xe0,0xbd,0xcf,0xb8,0xf9,0x85,0x34,0x23,0xef,0x26,0x5d,0xc3,0x1d,0x12,0x6e, /* .......4#.&]...n */ \
00544     0x23,0x51,0x6b,0xd2,0x69,0x56,0x4e,0xd7,0x65,0xd6,0xd2,0xf7,0x93,0x6c,0xfa,0x96, /* #Qk.iVN.e....l.. */ \
00545     0x2d,0x9c,0x43,0xf7,0xfd,0x85,0xf0,0x7c,0xbd,0x9c,0xde,0x86,0x26,0x2f,0x04,0x05, /* -.C....|....&/.. */ \
00546     0x22,0x07,0xde,0x80,0xb0,0x7c,0x03,0xb4,0x11,0x1f,0x6c,0x91,0x35,0x6f,0x23,0x18, /* "....|....l.5o#. */ \
00547     0x3c,0xaf,0x96,0x6a,0xd6,0x04,0x83,0xd3,0x6c,0x3a,0x4f,0x27,0x70,0x0e,0xc9,0x4d, /* <..j....l:O'p..M */ \
00548     0x9a,0x13,0x29,0x28,0x34,0x29,0x67,0x64,0x25,0x56,0xc4,0x1a,0xa4,0x6c,0x1b,0x83, /* ..)(4)gd%V...l.. */ \
00549     0x8c,0x41,0x30,0xdd,0x7a,0x42,0xad,0x77,0x46,0xe9,0x33,0xfa,0x3f,0x1c,0x83,0xa6, /* .A0.zB.wF.3.?... */ \
00550     0x22,0x9f,0xec,0xce,0x38,0xf5,0xfc,0xb6,0x11,0x81,0x52,0xa5,0x66,0x5f,0x23,0xd0, /* "...8.....R.f_#. */ \
00551     0xac,0xfd,0x98,0xfe,0x82,0x62,0xda,0x5c,0x15,0xed,0x74,0x1e,0x38,0x6d,0xc3,0xef, /* .....b.\..t.8m.. */ \
00552     0xc0,0xeb,0x33,0x6e,0xde,0xfb,0x92,0x84,0xa4,0x74,0x55,0x05,0x6e,0xd1,0xd0,0x8c, /* ..3n.....tU.n... */ \
00553     0xf4,0xa4,0x14,0xef,0xb1,0xca,0xce,0x96,0x69,0x36,0x9d,0x92,0xbc,0x54,0xf5,0xf5, /* ........i6...T.. */ \
00554     0xd7,0x9d,0x1a,0x62,0xdb,0xdb,0xe2,0xd1,0x15,0xd6,0x6f,0x14,0x8f,0x59,0x5e,0x66, /* ...b......o..Y^f */ \
00555     0xd7,0x5f,0xd3,0x2e,0x94,0x1e,0x07,0x49,0xb3,0x98,0x3d,0xd8,0xfe,0x20,0x83,0xb0, /* ._.....I..=.. .. */ \
00556     0xca,0xa7,0x14,0x23,0x4f,0x53,0xc6,0x93,0x25,0xa2,0x3f,0x68,0xa1,0xc8,0x24,0x27, /* ...#OS..%.?h..$' */ \
00557     0x9a,0x18,0x4e,0xe2,0xf8,0xe0,0xfc,0x3c,0xdd,0xda,0xde,0x55,0x76,0x5a,0x2f,0xcb, /* ..N....<...UvZ/. */ \
00558     0x62,0x51,0x90,0x5c,0x6f,0x94,0xe1,0xaf,0xe7,0x80,0xb0,0xc3,0x26,0xef,0xf7,0x5f, /* bQ.\o.......&.._ */ \
00559     0x8f,0xd3,0x1d,0x92,0xc4,0x4e,0x04,0x0c,0x12,0x11,0xe4,0x66,0x57,0xd8,0xa3,0xca, /* .....N.....fW... */ \
00560     0x2b,0x79,0x87,0x99,0x80,0x45,0x72,0x65,0xbc,0x0b,0x0a,0x6b,0x10,0x5c,0x18,0x19, /* +y...Ere...k.\.. */ \
00561     0xd4,0xe8,0x8d,0x00,0x89,0x3c,0x91,0x1f,0xbf,0x9c,0x65,0xf5,0xcc,0xbe,0xf0,0xde, /* .....<....e..... */ \
00562     0xfc,0x82,0xee,0x0c,0x94,0x21,0x0c,0xdf,0x8f,0x8b,0x26,0xb7,0xf2,0x2a,0xb6,0xf7, /* .....!....&..... */ \
00563     0x6e,0x11,0x19,0x3f,0xf8,0x00,0x4e,0xfb,0x72,0x99,0x1b,0xf3,0x77,0xf6,0x94,0x94, /* n..?..N.r...w... */ \
00564     0x5f,0x5d,0x2d,0xf8,0x0f,0x1e,0xb0,0xe8,0x44,0xa2,0x9f,0xf1,0xb6,0x53,0x4a,0x32, /* _]-.....D....SJ2 */ \
00565     0xb4,0xe3,0xd4,0x72,0x17,0x5c,0x50,0x8c,0x88,0x3e,0xda,0xd3,0x8f,0x5e,0x8b,0xff, /* ...r.\P..>...^.. */ \
00566     0x76,0x42,0x6a,0xf5,0xfd,0xc5,0x92,0x58,0xfc,0x1b,0xe1,0x0e,0x27,0x2a,0x3f,0x3c, /* vBj....X....'.?< */ \
00567     0x16,0xa1,0x3e,0x7f,0x4e,0x38,0xc4,0xd3,0x33,0x83,0x1c,0xe2,0x85,0x42,0xdf,0x1c, /* ..>.N8..3....B.. */ \
00568     0x8b,0x18,0x22,0x17,0xf9,0x7b,0x30,0xca,0xd7,0xa0,0xaa,0xe8,0xea,0x6f,0x84,0xa4, /* .."..{0......o.. */ \
00569     0x3f,0x04,0xd5,0x7d,0xc2,0x31,0xaf,0xa7,0xb8,0x63,0x5a,0xbb,0xf9,0xb9,0x56,0xdb, /* ?..}.1...cZ...V. */ \
00570     0x14,0xfb,0x0a,0x84,0x3e,0x00,0x25,0xea,0x0d,0xa1,0x3d,0x07,0x9f,0xef,0x17,0x21, /* ....>.%...=....! */ \
00571     0x17,0x46,0x2e,0x7e,0xa8,0x71,0xd9,0x6d,0x52,0x8b,0x2e,0xd8,0x7f,0xbf,0x09,0xff, /* .F.~.q.mR....... */ \
00572     0x46,0xa7,0x44,0x62,0xeb,0x1f,0xcd,0xca,0x07,0x2b,0xad,0xaf,0x37,0x2b,0x02,0x8a, /* F.Db.....+..7+.. */ \
00573     0xd7,0x2d,0x8e,0x7e,0xe3,0xe4,0xff,0x01,0x43,0xd4,0xf1,0x1d,0x18,0x19,0x00,0x00, /* .-.~....C....... */ \
00574     0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xed,0xbd,0x07,0x60,0x1c,0x49, /* .............`.I */ \
00575     0x96,0x25,0x26,0x2f,0x6d,0xca,0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08, /* .%&/m.{.J.J..t.. */ \
00576     0x80,0x60,0x13,0x24,0xd8,0x90,0x40,0x10,0xec,0xc1,0x88,0xcd,0xe6,0x92,0xec,0x1d, /* .`.$..@......... */ \
00577     0x69,0x47,0x23,0x29,0xab,0x2a,0x81,0xca,0x65,0x56,0x65,0x5d,0x66,0x16,0x40,0xcc, /* iG#)....eVe]f.@. */ \
00578     0xed,0x9d,0xbc,0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xba,0x3b, /* .....{....{....; */ \
00579     0x9d,0x4e,0x27,0xf7,0xdf,0xff,0x3f,0x5c,0x66,0x64,0x01,0x6c,0xf6,0xce,0x4a,0xda, /* .N'...?\fd.l..J. */ \
00580     0xc9,0x9e,0x21,0x80,0xaa,0xc8,0x1f,0x3f,0x7e,0x7c,0x1f,0x3f,0x22,0xbe,0x95,0xfe, /* ..!....?~|.?"... */ \
00581     0xe2,0x45,0x56,0x5f,0x14,0xcb,0x47,0xe9,0xce,0xe1,0x2a,0x9b,0xcd,0x8a,0xe5,0x05, /* .EV_..G......... */ \
00582     0x7e,0x2d,0x8b,0xa6,0xdd,0x6e,0xda,0xeb,0x32,0x7f,0x94,0x2e,0xab,0x65,0x7e,0xf8, /* ~-...n..2....e~. */ \
00583     0x4b,0x7e,0xe3,0x64,0xde,0x2e,0xca,0xf4,0x17,0x57,0x97,0x79,0x7d,0x5e,0x56,0x57, /* K~.d.....W.y}^VW */ \
00584     0xdb,0xd7,0x8f,0xd2,0x66,0x5a,0x57,0x65,0x89,0xef,0x7e,0xe3,0x64,0x52,0xcd,0xae, /* ....fZWe..~.dR.. */ \
00585     0x2d,0xb0,0x9d,0xd5,0xbb,0xc3,0x49,0x36,0x7d,0x7b,0x51,0x57,0xeb,0xe5,0xec,0xd1, /* -.....I6}{QW.... */ \
00586     0xba,0x2e,0xb7,0x3e,0x9a,0x5c,0x8c,0x2f,0x8a,0xf3,0x8f,0xee,0x1c,0xa6,0x93,0x8b, /* ...>.\./........ */ \
00587     0x69,0x55,0x56,0xf5,0xa3,0xf4,0xc7,0x1f,0x3e,0xdc,0xa1,0xe7,0x30,0x3d,0xaf,0x96, /* iUV.....>...0=.. */ \
00588     0xd4,0x5d,0xf1,0x03,0xea,0x6d,0x77,0x67,0x67,0xbc,0xb3,0xfb,0xbb,0xeb,0x67,0xe7, /* .]...mwgg.....g. */ \
00589     0xd9,0xa2,0x28,0xa9,0xa7,0xe3,0xba,0xc8,0xca,0xd1,0xb7,0xf3,0xf2,0x32,0x6f,0x8b, /* ..(..........2o. */ \
00590     0x69,0x36,0x6a,0xb2,0x65,0xb3,0xdd,0xe4,0x75,0x71,0x7e,0x98,0x2e,0x8a,0xe5,0xf6, /* i6j.e...uq~..... */ \
00591     0x55,0x31,0x6b,0xe7,0x8f,0xd2,0xfd,0xdd,0x7c,0x01,0x74,0xda,0x59,0xfa,0x8b,0xf1, /* U1k.....|.t.Y... */ \
00592     0xfe,0xa3,0xdd,0xdd,0xd5,0x3b,0x7d,0x39,0x75,0x6f,0xa7,0xfe,0xeb,0x82,0xcb,0x8f, /* .....;}9uo...... */ \
00593     0x3f,0xa3,0xe7,0xe4,0xe4,0x30,0x35,0x44,0xc0,0x8b,0x7b,0xf4,0x7f,0xfd,0x49,0x40, /* ?....05D..{...I@ */ \
00594     0xb3,0xf4,0x17,0x1b,0xbc,0x9f,0xf1,0x83,0xcf,0x1e,0xcd,0x41,0x10,0xff,0x1b,0x8c, /* ...........A.... */ \
00595     0x89,0x29,0x32,0xdf,0x4d,0x7f,0xb1,0x47,0x84,0x1f,0x9f,0x4e,0x65,0xb0,0xf3,0xbc, /* .)2.M..G...Ne... */ \
00596     0xb8,0x98,0xb7,0x8f,0x3e,0x05,0x91,0xfc,0x81,0x8f,0xef,0x13,0xf2,0x7e,0x0f,0x84, /* ....>........~.. */ \
00597     0x4e,0x99,0xb7,0x6d,0x5e,0x6f,0x37,0xab,0x6c,0x0a,0xa4,0xc6,0xf7,0xa8,0x49,0x9b, /* N..m^o7.l.....I. */ \
00598     0xbf,0x6b,0xb7,0xb3,0xb2,0xb8,0x58,0x3e,0x9a,0xe6,0x4b,0xfa,0xfa,0x90,0x30,0xc0, /* .k....X>..K...0. */ \
00599     0xb8,0x4a,0xfd,0x74,0x52,0xb5,0x6d,0xb5,0x38,0x9c,0x54,0xf5,0x8c,0xde,0x6d,0xab, /* .J.tR.m.8.T...m. */ \
00600     0xd5,0xa3,0xf4,0x1e,0x8d,0xa2,0xa9,0xca,0x62,0x96,0xfe,0xf8,0xf9,0xf9,0xce,0xc1, /* ........b....... */ \
00601     0x4e,0x6e,0xbe,0x95,0xb6,0xb1,0x06,0x65,0xb1,0xcc,0xb7,0x7d,0x5c,0xc1,0x02,0x7b, /* Nn.....e...}\..{ */ \
00602     0x66,0x8a,0xcd,0x8b,0x4a,0xf0,0xdf,0x38,0xf9,0xf1,0xa6,0x68,0xf3,0xf4,0x17,0x7b, /* f...J..8...h...{ */ \
00603     0xc8,0xa5,0x65,0x7e,0xde,0x1e,0x5a,0xf6,0x4a,0xb3,0x75,0x5b,0x1d,0xea,0x44,0x3d, /* ..e~..Z.J.u[..D= */ \
00604     0xdc,0xf9,0xdd,0x3d,0x76,0xe3,0x91,0x0b,0x94,0x65,0x76,0x49,0x53,0x57,0x56,0x59, /* ...=v....evISWVY */ \
00605     0xfb,0x88,0x5f,0x4f,0xe5,0x85,0x5d,0x0c,0x3c,0xd5,0xae,0x79,0x44,0xe8,0xd8,0x83, /* .._O..].<..yD... */ \
00606     0x70,0x20,0x10,0xf8,0x7d,0x3b,0x29,0x4c,0xdd,0x2b,0x19,0xc2,0xa4,0x2a,0x67,0xae  /* p ..};)L.+....g. */
00607 #define DATACHUNK000009 \
00608     0x05,0xcd,0x4c,0x38,0xfe,0x5d,0x37,0x7e,0x99,0x42,0x6f,0x6a,0x76,0x69,0xfe,0xbd, /* ..L8.]7~.Bojvi.. */ \
00609     0x89,0x39,0x39,0xd9,0x81,0x80,0x38,0xea,0xec,0x7e,0x4a,0xdf,0x77,0x67,0x6a,0xd7, /* .99...8..~J.wgj. */ \
00610     0xcc,0xd4,0x2c,0x9f,0x56,0x75,0xd6,0x16,0xd5,0x52,0x45,0x69,0x56,0x34,0xab,0x32, /* ..,.Vu...REiV4.2 */ \
00611     0xbb,0x7e,0x34,0x29,0xab,0xe9,0x5b,0x3b,0x86,0x03,0x42,0x80,0xe0,0xa4,0xf8,0xb9, /* .~4)..[;..B..... */ \
00612     0x27,0x0c,0xc7,0xa8,0x96,0x45,0x9a,0x8d,0xb3,0x69,0x5b,0x5c,0xe6,0x01,0x3b,0x89, /* '....E...i[\..;. */ \
00613     0x4c,0xad,0x4b,0xea,0x57,0xe4,0x8a,0x24,0x87,0x5e,0xbd,0xbf,0xf3,0xbb,0x53,0x2f, /* L.K.W..$.^....S/ */ \
00614     0xdb,0x75,0xbe,0xca,0xb3,0x56,0x91,0x36,0xcc,0x34,0x48,0x0e,0xea,0x63,0x5d,0xda, /* .u...V.6.4H..c]. */ \
00615     0x99,0x05,0xdd,0x1f,0xa5,0x7b,0x20,0xb8,0x12,0x5f,0x27,0xd9,0x6b,0x0b,0xac,0x94, /* .....{ .._'.k... */ \
00616     0xbe,0x42,0x22,0x30,0xc8,0x0f,0x85,0x26,0x53,0xea,0x93,0xb8,0xbe,0x8b,0x2d,0x38, /* .B"0...&S.....-8 */ \
00617     0xc8,0x67,0x0f,0xf0,0x8b,0x87,0xde,0xae,0x9d,0x41,0x95,0xdd,0x00,0x59,0xc0,0x8e, /* .g.......A...Y.. */ \
00618     0x21,0x4b,0xfd,0x8d,0x9f,0x55,0xf5,0xe2,0x4d,0x36,0x29,0xf3,0xdd,0x90,0xb9,0x55, /* !K...U..M6)....U */ \
00619     0xf4,0x0c,0x4f,0x7a,0xe2,0x90,0x1a,0x10,0xac,0x05,0x85,0xcd,0xa8,0xef,0x32,0x5b, /* ..Oz..........2[ */ \
00620     0x35,0x24,0xe6,0xe6,0x37,0x52,0x83,0xfc,0x55,0x84,0xf5,0x3a,0xdd,0x42,0x99,0x29, /* 5$..7R..U..:.B.) */ \
00621     0x98,0x9a,0xd1,0xbd,0xf1,0x8d,0xf1,0x3c,0xcf,0xdc,0x4b,0x83,0x2c,0xde,0x7d,0x6b, /* .......<..K.,.}k */ \
00622     0x96,0x37,0xd3,0xd4,0xa8,0x4e,0x21,0x9c,0x08,0x96,0xaf,0x23,0x59,0xed,0x05,0xe8, /* .7...N!....#Y... */ \
00623     0x91,0xa0,0x19,0x3a,0x42,0x90,0x83,0xaf,0xa3,0xfa,0x22,0x20,0x90,0x55,0xb8,0xfc, /* ...:B....." .U.. */ \
00624     0xc7,0x46,0x9a,0x7c,0xb7,0x98,0xe5,0xaf,0xe9,0xd5,0x9c,0x91,0x34,0xef,0xdd,0xa7, /* .F.|........4... */ \
00625     0xa6,0x0f,0xc0,0xf9,0xf2,0x13,0x0d,0x5f,0x2f,0xb2,0xb2,0xec,0xb7,0x84,0x3a,0xdf, /* ......._/.....:. */ \
00626     0x57,0xb5,0xbe,0xcf,0x2d,0xd1,0xb6,0x2d,0xca,0xfd,0x50,0xb3,0xc3,0x0c,0xa8,0x9e, /* W...-..-..P..... */ \
00627     0xda,0xbd,0xbf,0xa3,0x20,0xa9,0xd9,0xfd,0xae,0x9a,0xf7,0x0d,0x17,0x24,0xe0,0x97, /* .... ........$.. */ \
00628     0xfc,0x3f,0x02,0xa6,0x9e,0x8f,0x4f,0x07,0x00,0x00                                /* .?....O...       */
00629
00630
00631 /**************************************
00632  * MPFS2 C linkable symbols
00633  **************************************/
00634 // For C18, these are split into seperate arrays because it speeds up compilation a lot.
00635 // For other compilers, the entire data array must be defined as a single variable to
00636 // ensure that the linker does not reorder the data chunks in Flash when compiler
00637 // optimizations are turned on.
00638 #if defined(__18CXX)
00639     ROM BYTE MPFS_Start[] = {DATACHUNK000000};
00640     ROM BYTE MPFS_000001[] = {DATACHUNK000001};
00641     ROM BYTE MPFS_000002[] = {DATACHUNK000002};
00642     ROM BYTE MPFS_000003[] = {DATACHUNK000003};
00643     ROM BYTE MPFS_000004[] = {DATACHUNK000004};
00644     ROM BYTE MPFS_000005[] = {DATACHUNK000005};
00645     ROM BYTE MPFS_000006[] = {DATACHUNK000006};
00646     ROM BYTE MPFS_000007[] = {DATACHUNK000007};
00647     ROM BYTE MPFS_000008[] = {DATACHUNK000008};
00648     ROM BYTE MPFS_000009[] = {DATACHUNK000009};
00649 #else
00650     ROM BYTE MPFS_Start[] = {DATACHUNK000000, DATACHUNK000001, DATACHUNK000002, DATACHUNK000003, DATACHUNK000004, DATACHUNK000005, DATACHUNK000006, DATACHUNK000007, DATACHUNK000008, DATACHUNK000009};
00651 #endif
00652
00653
00654 /**************************************************************
00655  * End of MPFS
00656  **************************************************************/
00657 #endif // #if defined(STACK_USE_MPFS2)
00658 #endif // #if !defined(MPFS_USE_EEPROM) && !defined(MPFS_USE_SPI_FLASH)
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: huffman.h Source File

huffman.h

00001
00002
00003 /**************************************
00004  * Huffman META data
00005 /**************************************/
00006
00007
00008 #define MAX_HUFFMAN_CODE_LENGTH (13u)
00009
00010 #define MAX_HUFFMAN_CODE_MASK   (0x1000u)
00011
00012 typedef unsigned short  HUFFMAN_CODE_TYPE;
00013
00014
00015 // Huffman code table structure:
00016 typedef struct {
00017     HUFFMAN_CODE_TYPE StartCode;
00018     unsigned char CodeLength;
00019     unsigned char CharacterIndex;
00020 } HuffmanCodeStruct;
00021
00022
00023 // Huffman code table:
00024 HuffmanCodeStruct HuffmanCode[] = {
00025     {0x1400, 0x03, 0x3F},
00026     {0x0E00, 0x04, 0x3C},
00027     {0x0600, 0x05, 0x34},
00028     {0x0280, 0x06, 0x2D},
00029     {0x0180, 0x07, 0x29},
00030     {0x00A0, 0x08, 0x22},
00031     {0x0060, 0x09, 0x1E},
00032     {0x0038, 0x0A, 0x19},
00033     {0x0014, 0x0B, 0x10},
00034     {0x000C, 0x0C, 0x0C},
00035     {0x0000, 0x0D, 0x00},
00036 };
00037
00038
00039 // Huffman character table:
00040 unsigned char HuffmanCharacter[] = {
00041     0x28, 0x29, 0x36, 0x37, 0x42, 0x43, 0x44, 0x49, 0x4D, 0x4E,
00042     0x52, 0x58, 0x39, 0x3F, 0x45, 0x71, 0x2D, 0x38, 0x6B, 0x77,
00043     0x26, 0x3B, 0x41, 0x4C, 0x50, 0x7A, 0x4F, 0x30, 0x33, 0x57,
00044     0x67, 0x78, 0x35, 0x54, 0x53, 0x31, 0x3A, 0x66, 0x32, 0x34,
00045     0x46, 0x76, 0x68, 0x2E, 0x79, 0x62, 0x63, 0x6F, 0x6D, 0x6E,
00046     0x70, 0x75, 0x65, 0x20, 0x61, 0x3D, 0x6C, 0x73, 0x72, 0x69,
00047     0x22, 0x64, 0x2F, 0x74, 0x3C, 0x3E
00048 };
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: projectdefs.h Source File

projectdefs.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00023
00024 #ifndef PROJECTDEFS_H
00025
00026 #define     PROJECTDEFS_H
00027
00029 // Includes
00031
00032 #include    "appldefs.h"
00033
00034
00036 // Defines
00038
00040 #define PROJECT_ID              SRCP_PROJECT
00041
00043 #define PROJECT_NAME            "srcp"
00044
00046 #define PROJECT_SERVICE_NAME    "_srcp"
00047
00049 #define PROJECT_DEFAULT_PORT    (4303u)
00050
00052 #define SRCP_NAME_MAXLEN        16
00053
00055 #define SRCP_PROTO_MAXLEN       3
00056
00058 #define SRCP_SERVERCACHE_ID     0xFE
00059
00061 #define SRCP_EEPROMSET_ID       0xFF
00062
00064 #define MAX_PROTO_SLOTS         8
00065
00067 #define MAX_SRCP_FUNCTIONS      13
00068
00070 #define MAX_SRCP_SPEEDSTEPS     128
00071
00073 #define SRCP_EEPROMSET_COUNT    32
00074
00076 #define SRCP_GLEEPROMSET_COUNT  16
00077
00079 #define SRCP_GAEEPROMSET_COUNT  4
00080
00082 #define SRCP_EEPROMSET_IDX_MASK 0x0F
00083
00085 #define SRCP_EEPROMSET_GA_MASK  0x10
00086
00087
00092 #define SRCP_CONFIG_EEPROM_ADD      (0x0200u)
00093
00094
00099 #define SRCP_PROTOS_EEPROM_ADD      (0x0300u)
00100
00101
00106 #define SRCP_SETS_EEPROM_ADD        (0x0800u)
00107
00108
00109
00111 #define PROJECT_SOCKET_CONFIGURATION    {TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 300, 1500}, \
00112                                         {TCP_PURPOSE_DEFAULT, TCP_ETH_RAM, 300, 1000}
00113
00115 #define PROJECT_INITIAL_INIT                    SRCPInitialInit
00116
00118 #define PROJECT_LOCO_DIR_MODE_HAS_CHANGED       SRCPLocoDirModeHasChanged
00119
00121 #define PROJECT_HANDLE_SERVER_CONNECTION        SRCPHandleServerConnection
00122
00124 #define PROJECT_RESET_TO_FACTORY                SRCPRestoreToFactory
00125
00127 #define PROJECT_PREPARE_CONNECTION              SRCPPrepareConnection
00128
00130 #define PROJECT_START_DISCONNECT                SRCPStartDisconnect
00131
00133 #define PROJECT_IS_CONNECTED                    SRCPIsConnected
00134
00136 #define PROJECT_MAIN                            SRCPMain
00137
00139 #define PROJECT_WEBSITES        {STRTBLID_SYSTEMSTATE, "index.htm", NAV_CLOSE},         \
00140                                 {STRTBLID_COMMON, "common.htm", NAV_CLOSE},             \
00141                                 {STRTBLID_SRCP, "srcp.htm", NAV_SUBNAV},                \
00142                                 {STRTBLID_LOCO_PROTOCOLS, "locoproto.htm", NAV_CLOSE},  \
00143                                 {STRTBLID_LOCO_DATABASE, "locos.htm", NAV_CLOSE},       \
00144                                 {STRTBLID_ACC_PROTOCOLS, "accproto.htm", NAV_CLOSE},    \
00145                                 {STRTBLID_ACC_DATABASE, "accs.htm", NAV_SUBNAVEND},     \
00146                                 {STRTBLID_FILE, "file.htm", NAV_END},
00147
00148
00150 // Typedefs
00152
00159 typedef struct __attribute__((__packed__))
00160 {
00162     struct
00163     {
00165         BYTE        bGLAskForLock : 1;
00166
00168         BYTE        bGAAskForLock : 1;
00169
00171         BYTE        bGLLock : 1;
00172
00174         BYTE        bGALock : 1;
00175
00177         BYTE        bGLAskForProto : 1;
00178
00180         BYTE        bGAAskForProto : 1;
00181
00182     } sFlags;
00183
00185     BYTE        u8Reserved1;
00186
00189     BYTE        u8DefaultGLProtoId;
00190
00192     BYTE        u8Reserved2;
00193
00195     BYTE        u8DefaultGAProtoId;
00196
00199     LONG        s32GADelay;
00200 } SPSRCPCONFIG;
00201
00202
00205 typedef struct __attribute__((__packed__)) _PERS_PROTOCOL_CONFIG
00206 {
00207     WORD u16MinAdd;
00208     WORD u16MaxAdd;
00209
00211     struct
00212     {
00213         BOOL bGL;
00214         BOOL bActive;
00215     } sFlags;
00216
00217     BYTE u8Bus;
00218     BYTE au8Desc[SRCP_NAME_MAXLEN+1];
00219     BYTE au8Proto[SRCP_PROTO_MAXLEN+1];
00220
00222     union
00223     {
00225         struct
00226         {
00227             BYTE u8MaxSteps;
00228             BYTE u8NrFunc;
00229         } sGL;
00230
00232         struct
00233         {
00234             BYTE u8MinP;
00235             BYTE u8MaxP;
00236         } sGA;
00237     } uSpec;
00238 } SPPROTOCOL;
00239
00240
00242 typedef struct __attribute__((__packed__))
00243 {
00245     struct
00246     {
00247         BOOL bGL;
00248         BOOL bActive;
00249     } sFlags;
00250
00252     BYTE    au8Name[SRCP_NAME_MAXLEN+1];
00253
00255     DWORD   u32Address;
00256
00258     BYTE    u8BusNr;
00259
00261     BYTE    au8Proto[SRCP_PROTO_MAXLEN+1];
00262
00264     union
00265     {
00267         struct
00268         {
00269             BYTE u8MaxSteps;
00270             BYTE u8NrFunc;
00271             WORD u16MaxV;
00272
00273             DWORD u32FuncToggleMask;
00274         } sGL;
00275
00277         struct
00278         {
00279             BYTE u8MinP;
00280             BYTE u8MaxP;
00281             long s32Delay;
00282         } sGA;
00283     } uSpec;
00284     BYTE    u8Reserved[15];
00285 } SPSET;
00286
00287
00288 // ////////////////////////////////////////////////////////////////////////////
00289 // Function prototypes
00290 // ////////////////////////////////////////////////////////////////////////////
00291
00293 void SRCPRestoreToFactory(void);
00294
00295
00300 BOOL SRCPIsConnected(void);
00301
00302
00306 void SRCPInitialInit(void);
00307
00308
00310 void SRCPStartDisconnect(void);
00311
00312
00314 void SRCPPrepareConnection(void);
00315
00316
00319 APPL_CONNECTING_RETCODE SRCPHandleServerConnection(void);
00320
00321
00324 BOOL SRCPMain(void);
00325
00328 void SRCPLocoDirModeHasChanged(void);
00329
00332 #endif  // #ifndef SRCPDEFS_H
Generated on Sun Nov 27 20:02:38 2011 for eWicht by doxygen 1.5.5


eWicht: srcp.c Source File

srcp.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00014     #define     SRCP_C
00015
00016
00017 // ////////////////////////////////////////////////////////////////////////////
00018 // Includes
00019 // ////////////////////////////////////////////////////////////////////////////
00020
00021     #include    "srcp.h"
00022     #include    "stringtable.h"
00023     #include    "dialog.h"
00024     #include    "sralloc.h"
00025     #include    "error.h"
00026
00027
00028 // ////////////////////////////////////////////////////////////////////////////
00029 // Local Defines
00030 // ////////////////////////////////////////////////////////////////////////////
00031
00032 // Maximum SRCP device, which can be configured in parallel (eWicht cache)
00033 #define MAX_SRCP_DEVICES            6
00034
00035 // Entries in the server cache (currently only for GLs)
00036 #define SERVER_CACHE_ENTRIES        11
00037
00038
00039 #define DEVICE_PRM_PTR(deviceptr)  ((BYTE *)(&deviceptr[1]))
00040 #define DEVICE_PROTO_PTR(devptr)   ((BYTE *)(DEVICE_PRM_PTR(devptr) + offsetof(sGL, au8Proto)))
00041 #define DEVICE_NAME_PTR(devptr)    ((BYTE *)(DEVICE_PRM_PTR(devptr) + offsetof(sGL, au8Name)))
00042
00043
00044 // ////////////////////////////////////////////////////////////////////////////
00045 // Local enumerator typedefs
00046 // ////////////////////////////////////////////////////////////////////////////
00047
00048 // SRCP Handshake return codes
00049 typedef enum
00050 {
00051     SRCP_HR_ERROR = 0,
00052     SRCP_HR_IN_PROGRESS,
00053     SRCP_HR_FINISHED
00054 } SRCP_HANDSHAKE_RETCODE;
00055
00056
00057 // States of SRCP in "Operating Mode"
00058 typedef enum
00059 {
00060     SRCP_STARTUP = 0,
00061     SRCP_MAIN,
00062     SRCP_PREPARE_MAIN,
00063     SRCP_SELECT_EEPROM_SET_TO_SAVE,
00064     SRCP_ENTER_NAME,
00065     SRCP_SELECT_PROTOCOL,
00066     SRCP_PROTOCOL_SELECTED,
00067     SRCP_SELECT_DEVICE_ADDRESS,
00068     SRCP_SELECT_SERVER_CACHE,
00069     SRCP_SELECT_EEPROMSET,
00070     SRCP_INIT_DEVICE,
00071     SRCP_WAIT_FOR_IDLE_DEVICE,
00072     SRCP_INIT_POWER,
00073     SRCP_WAIT_FOR_IDLE_POWER_DEVICE,
00074     SRCP_ERROR,
00075     SRCP_ACK_ERROR
00076 } SRCP_SM;
00077
00078
00079 // States of SRCP in the "Handshaking Mode"
00080 typedef enum
00081 {
00082     SRCP_HS_WAIT_FOR_WELCOME = 0,
00083     SRCP_HS_SET_VERSION,
00084     SRCP_HS_WAIT_VERSION,
00085     SRCP_HS_SET_MODE,
00086     SRCP_HS_WAIT_MODE,
00087     SRCP_HS_GO,
00088     SRCP_HS_WAIT_GO,
00089     SRCP_HS_GOING,
00090     SRCP_HS_ERROR
00091 } SRCP_HANDSHAKE_SM;
00092
00093
00094 // SRCP device groups
00095 typedef enum
00096 {
00097     SRCP_DT_NOT_DEFINED = 0,
00098     SRCP_DT_GL,
00099     SRCP_DT_SM,
00100     SRCP_DT_GA,
00101     SRCP_DT_FB,
00102     SRCP_DT_TIME,
00103     SRCP_DT_POWER,
00104     SRCP_DT_SERVER,
00105     SRCP_DT_SESSION,
00106     SRCP_DT_LOCK,
00107     SRCP_DT_DESCRIPTION
00108 } SRCP_DEVTYPE;
00109
00110
00111 // SRCP commands
00112 typedef enum
00113 {
00114     SRCP_CMD_INFO = 0,
00115     SRCP_CMD_GET,
00116     SRCP_CMD_SET,
00117     SRCP_CMD_INIT,
00118     SRCP_CMD_TERM,
00119     SRCP_CMD_CHECK,
00120     SRCP_CMD_WAIT,
00121     SRCP_CMD_RESET,
00122     SRCP_CMD_VERIFY,
00123     SRCP_CMD_GETDESC
00124 } SRCP_COMMANDS;
00125
00126
00127 // Enumerator for system device states
00128 typedef enum
00129 {
00130 // The unsynchronized states:
00131     SRCP_DS_DISABLED = 0,   // Doing nothing.
00132     SRCP_DS_UNKNOWN,        // Initial state of each new device.
00133
00134 // The synchronized states:
00135     SRCP_DS_NOT_DEFINED,    // Server does not know anything.
00136     SRCP_DS_IDLE            // The destination state!
00137 } SRCP_DEVICESTATE;
00138
00139
00140 typedef enum
00141 {
00142     SRCPC_SM_CONNECT_COMMAND = 0,
00143     SRCPC_SM_CONNECT_WAIT_COMMAND,
00144     SRCPC_SM_CONNECTED_COMMAND,
00145     SRCPC_SM_CONNECT_WAIT_INFO,
00146     SRCPC_SM_CONNECTED_INFO,
00147     SRCPC_SM_CONNECTED,
00148     SRCPC_SM_DELAY_CLOSING,
00149     SRCPC_SM_CLOSING,
00150     SRCPC_SM_WAIT_FOR_CLOSING,
00151     SRCPC_SM_ERROR_CONNECT,
00152     SRCPC_SM_CLOSED
00153 } SM_SRCP_CONNECTING;
00154
00155
00156 // ////////////////////////////////////////////////////////////////////////////
00157 // Local structure typedefs
00158 // ////////////////////////////////////////////////////////////////////////////
00159
00160 typedef struct __attribute__((__packed__)) srcpsocket_struct
00161 {
00162     BYTE        u8Socket;
00163     BOOL        bCommand;
00164 } SSRCPSOCKET;
00165
00166
00167 typedef struct __attribute__((__packed__)) _srcpnet_state
00168 {
00169     SSRCPSOCKET sCommand;
00170     SSRCPSOCKET sInfo;
00171 } SSRCPSTATE;
00172
00173
00174 typedef struct __attribute__((__packed__))
00175 {
00176     BYTE u8Bus;
00177     SRCP_DEVTYPE eDevType;
00178
00179     union
00180     {
00181         struct
00182         {
00183             DWORD u32Addr;
00184             BYTE au8Proto[4];
00185             BYTE u8Port;
00186         } sGA;
00187
00188         struct
00189         {
00190             DWORD u32Addr;
00191             BYTE au8Proto[4];
00192             SHORT s16MaxV;
00193             BYTE u8MaxSteps;
00194             BYTE u8NrFunc;
00195             DWORD u32FuncAllocMask;
00196         } sGL;
00197
00198         struct
00199         {
00200             DWORD u32Addr;
00201             SRCP_DEVTYPE eDevType;
00202         } sLock;
00203     } uStat;
00204
00205     union
00206     {
00207         BOOL bPowerState;   // TRUE means ON, FALSE means OFF
00208         struct
00209         {
00210             BYTE u8Value;
00211                 #define     GAPORT_INACTIVE 0x00
00212                 #define     GAPORT_ACTIVE   0x01
00213         } sGA;
00214
00215         struct
00216         {
00217             BYTE u8Dir;
00218                 #define     DIR_BACKWARD    0x00
00219                 #define     DIR_FORWARD     0x01
00220                 #define     DIR_ESTOP       0x02
00221                 #define     DIR_UNCHANGED   0x03
00222             SHORT s16ActV;
00223             DWORD u32FuncBitField;
00224             BYTE u8FuncGroup;   // The displayed function group (0=1-4,1=5-8,2=9-12)
00225             SHORT s16ServerV;   // This value indicates the servers speed.
00226         } sGL;
00227
00228         struct
00229         {
00230             DWORD u32SessionId;
00231         } sLock;
00232     } uDyn;
00233 } SRCP_PRM;
00234
00235
00236 typedef struct __attribute__((__packed__))
00237 {
00238     DWORD   u32Seconds;
00239     WORD    u16Milliseconds;
00240 } SRCP_TIME;
00241
00242
00243 typedef struct __attribute__((__packed__))
00244 {
00245     SRCP_DEVTYPE eDevType;
00246     SRCP_DEVICESTATE eDevState;
00247     WORD u16LastErrorCode;
00248     SRCP_TIME sLastUpdate;
00249     struct
00250     {
00251         BYTE bNewData : 1;
00252     } sFlags;
00253     BYTE u8Bus;
00254     // Device specific (sPower, sLock, sGA, sGL)
00255     // structure starts here.
00256 } SRCP_DEVICE;
00257
00258
00259 typedef struct __attribute__((__packed__))
00260 {
00261     BOOL bPowerState;   // TRUE means ON, FALSE means OFF
00262 } sPower;
00263
00264
00265 typedef struct __attribute__((__packed__))
00266 {
00267     DWORD u32Addr;  // This field is fixed to this position!!!
00268     DWORD u32Duration;
00269     DWORD u32SessionId;
00270     SRCP_DEVTYPE eDevType;
00271 } sLock;
00272
00273
00274 typedef struct __attribute__((__packed__))
00275 {
00276     DWORD u32Addr;  // This field is fixed to this position!
00277     BYTE au8Proto[SRCP_PROTO_MAXLEN+1];// This field is fixed to this position!
00278     BYTE au8Name[SRCP_NAME_MAXLEN+1]; // This field is fixed to this position!
00279     BYTE u8MinPort;
00280     BYTE u8MaxPort;
00281     BYTE u8Port;
00282     DWORD s32Delay;
00283     BYTE u8Value;
00284         #define     GAPORT_INACTIVE 0x00
00285         #define     GAPORT_ACTIVE   0x01
00286 } sGA;
00287
00288
00289 typedef struct __attribute__((__packed__))
00290 {
00291     DWORD u32Addr;  // This field is fixed to this position!
00292     BYTE au8Proto[SRCP_PROTO_MAXLEN+1];// This field is fixed to this position!
00293     BYTE au8Name[SRCP_NAME_MAXLEN+1]; // This field is fixed to this position!
00294     BYTE u8MaxSteps;
00295     BYTE u8NrFunc;
00296     SHORT s16MaxV;
00297     struct
00298     {
00299         BYTE u5Res : 5;
00300         BYTE bUnit : 1;
00301         BYTE u2Dir : 2;
00302             #define     DIR_BACKWARD    0x00
00303             #define     DIR_FORWARD     0x01
00304             #define     DIR_ESTOP       0x02
00305             #define     DIR_UNCHANGED   0x03
00306     } sGLFlags;
00307
00308     SHORT s16ActV;
00309     DWORD u32FuncBitField;
00310     DWORD u32FuncAllocMask;
00311     DWORD u32FuncToggleMask;
00312     BYTE u8FuncGroup;   // The displayed function group (0=1-4,1=5-8,2=9-12)
00313     SHORT s16ServerV;   // This value indicates the servers speed.
00314 } sGL;
00315
00316
00317 typedef struct __attribute__((__packed__))
00318 {
00319     BYTE    u8BusNr;
00320     DWORD   u32Address;
00321     BYTE    au8Proto[SRCP_PROTO_MAXLEN+1];
00322     BYTE    u8MaxSteps;
00323     BYTE    u8NrFunc;
00324 } sServerCacheEntry;
00325
00326
00327 typedef struct __attribute__((__packed__))
00328 {
00329     BYTE    u8BusNr;
00330     DWORD   u32Address;
00331     BYTE    au8Proto[SRCP_PROTO_MAXLEN+1];
00332     BYTE    au8Name[SRCP_NAME_MAXLEN+1];
00333
00334     union
00335     {
00336         struct
00337         {
00338             BYTE u8MaxSteps;
00339             BYTE u8NrFunc;
00340             WORD u16MaxV;
00341             DWORD u32FunctionToggleMask;
00342         } sGLSpec;
00343
00344         struct
00345         {
00346             BYTE u8MinP;
00347             BYTE u8MaxP;
00348             long s32Delay;
00349         } sGASpec;
00350     } uSpec;
00351 } sStaticDeviceData;
00352
00353
00354 // ////////////////////////////////////////////////////////////////////////////
00355 // Local variables
00356 // ////////////////////////////////////////////////////////////////////////////
00357
00358 static SSRCPSTATE _sSRCPState;
00359
00360 static SRCP_SM _eSRCPsm;
00361
00362 static SRCP_COMMANDS _eLastSentCommand;
00363
00364 static SM_SRCP_CONNECTING _eSRCPCsm;
00365
00366 // This variable stores the index (for _apsDevices) of the device which has
00367 // sent the last command.
00368 static SRCP_DEVICE * _pLastCommandDevice;
00369
00370 SRCP_DEVICE * _apsDevices[MAX_SRCP_DEVICES];
00371
00372 static BOOL _bSrvReqIsInProgress;
00373 static DWORD _bServerRequestTime;
00374
00375 static SRCP_DEVICE * _psNewDevice;
00376 static BYTE _u8LastEEPROMSetIdx;
00377
00378 static SRCP_DEVICE * _psActualDevice;
00379
00380 static SRCP_HANDSHAKE_SM _eHSState; // State for handshaking
00381
00382 static BYTE _u8LastSelectedProtoId;
00383 static sStaticDeviceData _sNewDeviceStaticData;
00384
00385 static BYTE _au8ActiveProtos[MAX_PROTO_SLOTS+2]; // One more for server cache.
00386 static sServerCacheEntry * _apsSelectCache;
00387 static BYTE * _pActiveEEPROMSetList;
00388
00389 #pragma udata SRCPGLCache
00390 static sServerCacheEntry _asServerCache[SERVER_CACHE_ENTRIES];
00391 #pragma udata
00392
00393
00394 // ////////////////////////////////////////////////////////////////////////////
00395 // Local function prototypes
00396 // ////////////////////////////////////////////////////////////////////////////
00397
00398 // Connection and handshake functions
00399 void _startHandShake(void);
00400 SRCP_HANDSHAKE_RETCODE _eHandShake(SSRCPSOCKET * hSRCP);
00401
00402
00403 // View functions
00404 static void _updateView(SRCP_DEVICE * pDev);
00405 static void _displayNoData(void);
00406 static void _displayGLData(SRCP_DEVICE * pDev);
00407 static void _displayGAData(SRCP_DEVICE * pDev);
00408 static void _displayPower(SRCP_DEVICE * pDev);
00409 static void _showServerError(WORD u16Code);
00410
00411
00412 // Input functions
00413 static void _updateInput(SRCP_DEVICE * pDev);
00414 static BOOL _bGetGLInput(sGL * pGL);
00415 static BOOL _bGetGAInput(SRCP_DEVICE * pPrm);
00416
00417
00418 // SRCP message functions
00419 static BOOL _startParsing(BYTE u8Socket, SRCP_TIME * psTime, WORD * pu16Code);
00420 static BOOL _bParseLine(BYTE u8Socket, WORD u16Code, SRCP_PRM * pPrm);
00421 static BOOL _bTCPDevType(WORD u16Code, SRCP_DEVTYPE * pDev, BYTE * au8Buf);
00422 static void _answerReceived(SRCP_DEVICE* pDev, WORD u16Code, SRCP_TIME* pTime);
00423 static BOOL _bSendSRCPMessage(SRCP_COMMANDS eCommand, SRCP_DEVICE * pDev);
00424 static BOOL _bDevTypeTCP(SRCP_DEVTYPE eDevType, SRCP_COMMANDS eCommand);
00425 static BOOL _bLookForEnd(BYTE u8Socket);
00426 static BOOL _bGetNextWord(BYTE u8Socket, BYTE * pu8Buf, BYTE u8BufSize,
00427                                                                   BOOL * bEnd);
00428
00429 // Device functions
00430 static void _deviceSM(SRCP_DEVICE * pDev);
00431 static BOOL _bIsDeviceMatching(SRCP_DEVICE * psDevice, SRCP_PRM * pPrm);
00432 static SRCP_DEVICE * _pGetPowerDevice(BYTE u8Bus);
00433 static void _updateData(SRCP_DEVICE * pDev, WORD u16Code, SRCP_PRM * pNewPrm);
00434 static SRCP_DEVICE* _psAddDevice(SRCP_DEVTYPE eDevType, BYTE u8Bus, void*pPrm);
00435 static BOOL _bIsInitAllowed(SRCP_DEVTYPE eDevType);
00436 static SHORT _s16computeRealSpeed(SHORT s16MaxV, SHORT s16ServerMaxV,
00437                                                          SHORT s16ServerSpeed);
00438 static SRCP_DEVICE * _psInitializeNewDevice(SRCP_DEVTYPE eDevType, BYTE u8Bus,
00439                                             void * pPrm);
00440 static DWORD _u32GetAddress(SRCP_DEVICE * psDevice);
00441 static void _refreshDeviceList(void);
00442 static SRCP_DEVICE * _pTakeOverDevice(SRCP_DEVICE * pDevice);
00443 static SRCP_DEVICE * _pGetLatestGL(void);
00444 static SRCP_DEVICE * _pGetLatestGA(void);
00445 static void _fillPrmGL(sGL * psNewGL, sStaticDeviceData * psStaticData);
00446 static void _fillPrmGA(sGA * psNewGA, sStaticDeviceData * psStaticData);
00447 static void _getInitData(SRCP_DEVICE * pDev, char * pString);
00448
00449
00450 // Protocol parameter functions
00451 static void _getProtoName(BYTE u8ProtoId, BYTE * pString);
00452 static void _getProtoMinMax(BYTE u8ProtoId, WORD* pu16MinAdd,
00453                                                              WORD* pu16MaxAdd);
00454 static BYTE _u8GenerateActiveProtoList(BOOL bGL, BYTE u8Default);
00455 static void _getProtoFromEEPROM(BYTE u8ProtoId, SPPROTOCOL * psProto);
00456 static BOOL _bGetStaticParameterFromProto(BYTE u8ProtoId, sStaticDeviceData * psPrm);
00457
00458
00459 // EEPROM set functions
00460 static BYTE _u8AddEntryToEEPROM(BYTE u8RawQuickIdx, SRCP_DEVICE * pDevice);
00461 static BOOL _bCheckForSelectedSet(sStaticDeviceData * psDeviceData, BOOL bEncoder);
00462 static void _storeNameToEEPROM(BYTE u8EEPROMSetIdx, BYTE *pName);
00463 static BYTE _prepareEEPROMSetInput(BOOL bGL);
00464 static void _destructEEPROMSet(void);
00465
00466
00467 // Server cache functions
00468 static void _UpdateServerCache(SRCP_PRM * pPrm, BOOL bAdd);
00469 static BOOL _bPrepareServerCacheInput(void);
00470 static BOOL _bGetStaticParameterFromCache(BYTE u8CacheId, sStaticDeviceData * psPrm);
00471 static void _destructServerCache(void);
00472
00473
00474 // ////////////////////////////////////////////////////////////////////////////
00475 // ////////////////////////////////////////////////////////////////////////////
00476
00477 void SRCP_CancelInputProtoDialog(void)
00478 {
00479     if ((_eSRCPsm == SRCP_SELECT_PROTOCOL)||
00480         (_eSRCPsm == SRCP_SELECT_DEVICE_ADDRESS))
00481     {
00482         InputButtonReset(ALL_BTN);
00483         _eSRCPsm = SRCP_PREPARE_MAIN;
00484     }
00485 }
00486
00487 // ////////////////////////////////////////////////////////////////////////////
00488 // ////////////////////////////////////////////////////////////////////////////
00489
00490 void SRCP_CancelInputSetDialog(void)
00491 {
00492     if (_eSRCPsm == SRCP_SELECT_EEPROMSET)
00493     {
00494         InputButtonReset(ALL_BTN);
00495         _eSRCPsm = SRCP_PREPARE_MAIN;
00496     }
00497 }
00498
00499 // ////////////////////////////////////////////////////////////////////////////
00500 // ////////////////////////////////////////////////////////////////////////////
00501
00502 void SRCPRestoreToFactory(void)
00503 {
00504     SPPROTOCOL lococonf;
00505     BYTE i = 0;
00506     SPSET eepromset;
00507     WORD address;
00508
00509
00510     // ////////////////////////////////////////////////////////////////////////
00511     // Restoring srcp configuration data:
00512     memset((void *)&sPSRCPConfig, 0, sizeof(SPSRCPCONFIG));
00513     // The server cache is standard:
00514     sPSRCPConfig.u8DefaultGLProtoId = SRCP_SERVERCACHE_ID;
00515     sPSRCPConfig.u8DefaultGAProtoId = MAX_PROTO_SLOTS;
00516     sPSRCPConfig.sFlags.bGAAskForProto = TRUE;
00517     sPSRCPConfig.sFlags.bGLAskForProto = TRUE;
00518     sPSRCPConfig.s32GADelay = 500;  // in milliseconds.
00519
00520     XEEWriteArray(SRCP_CONFIG_EEPROM_ADD, (BYTE *)&sPSRCPConfig, sizeof(SPSRCPCONFIG));
00521
00522
00523     // ////////////////////////////////////////////////////////////////////////
00524     // Restoring loco protocol specific data:
00525
00526     strcpypgm2ram(lococonf.au8Desc, (ROM char *)"Old Motorola");
00527     strcpypgm2ram(lococonf.au8Proto, (ROM char *)"M 1");
00528     lococonf.sFlags.bGL = TRUE;
00529     lococonf.sFlags.bActive = TRUE;
00530     lococonf.u8Bus = 1;
00531     lococonf.u16MinAdd = 1;
00532     lococonf.u16MaxAdd = 80;
00533     lococonf.uSpec.sGL.u8MaxSteps = 14;
00534     lococonf.uSpec.sGL.u8NrFunc = 1;
00535     XEEWriteArray(EEPROM_GLS, (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00536
00537
00538     strcpypgm2ram(lococonf.au8Desc, (ROM char *)"New Motorola 1");
00539     strcpypgm2ram(lococonf.au8Proto, (ROM char *)"M 2");
00540     lococonf.sFlags.bGL = TRUE;
00541     lococonf.sFlags.bActive = TRUE;
00542     lococonf.u8Bus = 1;
00543     lococonf.u16MinAdd = 1;
00544     lococonf.u16MaxAdd = 255;
00545     lococonf.uSpec.sGL.u8MaxSteps = 28;
00546     lococonf.uSpec.sGL.u8NrFunc = 5;
00547     XEEWriteArray(EEPROM_GLS + 1*sizeof(SPPROTOCOL), (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00548
00549
00550     strcpypgm2ram(lococonf.au8Desc, (ROM char * )"NMRA Base");
00551     strcpypgm2ram(lococonf.au8Proto, (ROM char * )"N 1");
00552     lococonf.sFlags.bGL = TRUE;
00553     lococonf.sFlags.bActive = TRUE;
00554     lococonf.u8Bus = 2;
00555     lococonf.u16MinAdd = 1;
00556     lococonf.u16MaxAdd = 99;
00557     lococonf.uSpec.sGL.u8MaxSteps = 14;
00558     lococonf.uSpec.sGL.u8NrFunc = 0;
00559     XEEWriteArray(EEPROM_GLS + 2*sizeof(SPPROTOCOL), (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00560
00561
00562     strcpypgm2ram(lococonf.au8Desc, (ROM char *) "NMRA Extended 2");
00563     strcpypgm2ram(lococonf.au8Proto, (ROM char *) "N 1");
00564     lococonf.sFlags.bGL = TRUE;
00565     lococonf.sFlags.bActive = TRUE;
00566     lococonf.u8Bus = 2;
00567     lococonf.u16MinAdd = 1;
00568     lococonf.u16MaxAdd = 99;
00569     lococonf.uSpec.sGL.u8MaxSteps = 28;
00570     lococonf.uSpec.sGL.u8NrFunc = 5;
00571     XEEWriteArray(EEPROM_GLS + 3*sizeof(SPPROTOCOL), (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00572
00573
00574     // Delete the other protocol slots.
00575     memset(&lococonf, 0, sizeof(SPPROTOCOL));
00576     lococonf.sFlags.bGL = TRUE;
00577
00578     for (i = 4; i < MAX_PROTO_SLOTS; i++)
00579     {
00580         XEEWriteArray(EEPROM_GLS + i*sizeof(SPPROTOCOL), (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00581     }
00582
00583
00584     // ////////////////////////////////////////////////////////////////////////
00585     // Restoring accessory protocol specific data:
00586     strcpypgm2ram(lococonf.au8Desc, (ROM char *) "Motorola");
00587     strcpypgm2ram(lococonf.au8Proto, (ROM char *) "M");
00588     lococonf.sFlags.bGL = FALSE;
00589     lococonf.sFlags.bActive = TRUE;
00590     lococonf.u8Bus = 5;
00591     lococonf.u16MinAdd = 1;
00592     lococonf.u16MaxAdd = 324;
00593     lococonf.uSpec.sGA.u8MinP = 0;
00594     lococonf.uSpec.sGA.u8MaxP = 1;
00595     XEEWriteArray(EEPROM_GAS, (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00596
00597     strcpypgm2ram(lococonf.au8Desc, (ROM char *) "NMRA-DCC");
00598     strcpypgm2ram(lococonf.au8Proto, (ROM char *) "N");
00599     lococonf.sFlags.bGL = FALSE;
00600     lococonf.sFlags.bActive = TRUE;
00601     lococonf.u8Bus = 6;
00602     lococonf.u16MinAdd = 1;
00603     lococonf.u16MaxAdd = 511;
00604     lococonf.uSpec.sGA.u8MinP = 0;
00605     lococonf.uSpec.sGA.u8MaxP = 1;
00606
00607     XEEWriteArray(EEPROM_GAS + sizeof(SPPROTOCOL), (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00608
00609     // Delete the other protocol slots.
00610     memset(&lococonf, 0, sizeof(SPPROTOCOL));
00611
00612     for (i = 2; i < MAX_PROTO_SLOTS; i++)
00613     {
00614         XEEWriteArray(EEPROM_GAS + i*sizeof(SPPROTOCOL), (BYTE *)&lococonf, sizeof(SPPROTOCOL));
00615     }
00616
00617
00618     // Prepare the quick set area.
00619     memset(&eepromset, 0, sizeof(SPSET));
00620     eepromset.sFlags.bGL = TRUE;
00621     address = SRCP_SETS_EEPROM_ADD;
00622     for (i = 0; i < SRCP_GLEEPROMSET_COUNT; i++)
00623     {
00624         XEEWriteArray(address, (BYTE *)&eepromset, sizeof(SPSET));
00625         address += sizeof(SPSET);
00626     }
00627
00628     eepromset.sFlags.bGL = FALSE;
00629     for (i = 0; i < SRCP_GAEEPROMSET_COUNT; i++)
00630     {
00631         XEEWriteArray(address, (BYTE *)&eepromset, sizeof(SPSET));
00632         address += sizeof(SPSET);
00633     }
00634
00635 }
00636
00637 // ////////////////////////////////////////////////////////////////////////////
00638 // ////////////////////////////////////////////////////////////////////////////
00639
00640 void SRCPLocoDirModeHasChanged(void)
00641 {
00642     if ((_psActualDevice) && (_psActualDevice->eDevType == SRCP_DT_GL))
00643     {
00644         _psActualDevice->sFlags.bNewData = TRUE;
00645     }
00646 }
00647
00648 // ////////////////////////////////////////////////////////////////////////////
00649 // ////////////////////////////////////////////////////////////////////////////
00650
00651 void SRCPInitialInit(void)
00652 {
00653     // Get configuration data from EEPROM...
00654     XEEReadArray(SRCP_CONFIG_EEPROM_ADD, (BYTE*)&sPSRCPConfig, sizeof(SPSRCPCONFIG));
00655
00656     _sSRCPState.sCommand.u8Socket = INVALID_SOCKET;
00657     _sSRCPState.sInfo.u8Socket = INVALID_SOCKET;
00658 }
00659
00660 // ////////////////////////////////////////////////////////////////////////////
00661 // ////////////////////////////////////////////////////////////////////////////
00662
00663 BOOL SRCPMain(void)
00664 {
00665     // Check for Command and Info messages and feed the device state machine.
00666
00667     SRCP_TIME time;
00668     WORD code;
00669     BYTE i = 0;
00670
00671
00672     // ////////////////////////////////////////////////////////////////////////
00673     // Checking for a hanging server communication...
00674     if ((_bSrvReqIsInProgress == TRUE)&&(_bServerRequestTime < TickGet()))
00675     {
00676         _bSrvReqIsInProgress = FALSE;
00677     }
00678
00679
00680     // ////////////////////////////////////////////////////////////////////////
00681     // Check the command socket!
00682     if (TCPWasReset(_sSRCPState.sCommand.u8Socket))
00683     {
00684         _sSRCPState.sCommand.u8Socket = INVALID_SOCKET;
00685         SRCPStartDisconnect();
00686         return FALSE;
00687     }
00688
00689     if (TCPIsGetReady(_sSRCPState.sCommand.u8Socket))
00690     {
00691         if (_pLastCommandDevice && _startParsing(_sSRCPState.sCommand.u8Socket, &time, &code))
00692         {
00693             SRCP_PRM prm;
00694             BOOL ret;
00695
00696             // We are pretty sure, that the incoming packet belongs to the
00697             // device the last command was sent to. This will not be
00698             // checked here!
00699             _bSrvReqIsInProgress = FALSE;  // Acknowledge the sent command.
00700             _answerReceived(_pLastCommandDevice, code, &time);
00701
00702             if (_bParseLine(_sSRCPState.sCommand.u8Socket,code, &prm))
00703             {
00704                 // Update the data.
00705                 _updateData(_pLastCommandDevice, code, &prm);
00706             }
00707         }
00708
00709         // Only one command answer is expected. Throw away the rest of the
00710         // frame.
00711         TCPDiscard(_sSRCPState.sCommand.u8Socket);
00712     }
00713
00714
00715     // ////////////////////////////////////////////////////////////////////////
00716     // Check the info socket!
00717     if(TCPWasReset(_sSRCPState.sInfo.u8Socket))
00718     {
00719         _sSRCPState.sInfo.u8Socket = INVALID_SOCKET;
00720         SRCPStartDisconnect();
00721         return FALSE;
00722     }
00723     while (TCPIsGetReady(_sSRCPState.sInfo.u8Socket))
00724     {
00725         // Check all the lines which are included in the received frame.
00726
00727         // Obtain the time and the code!
00728         if (_startParsing(_sSRCPState.sInfo.u8Socket, &time, &code))
00729         {
00730             SRCP_PRM prm;
00731             if (_bParseLine(_sSRCPState.sInfo.u8Socket, code, &prm))
00732             {
00733                 // Update the internal list cache of server devices.
00734                 if (code == 101)
00735                 {
00736                     // Add to cache.
00737                     _UpdateServerCache(&prm, TRUE);
00738                 }
00739                 else if (code == 102)
00740                 {
00741                     // Remove from cache.
00742                     _UpdateServerCache(&prm, FALSE);
00743                 }
00744
00745                 // Search for a matching device in the device list.
00746                 for(i = 0; i < MAX_SRCP_DEVICES; i++)
00747                 {
00748                     if (_bIsDeviceMatching(_apsDevices[i], &prm))
00749                     {
00750                         _answerReceived(_apsDevices[i], code, &time);
00751                         _updateData(_apsDevices[i], code, &prm);
00752                     }
00753                 }
00754             }
00755         }
00756     }
00757
00758
00759     // ////////////////////////////////////////////////////////////////////////
00760     // Execute all the state machines of the devices if we can send new
00761     // commands.
00762     i = 0;
00763     while((_bSrvReqIsInProgress == FALSE)&&(i < MAX_SRCP_DEVICES))
00764     {
00765         _deviceSM(_apsDevices[i++]);
00766     }
00767
00768
00769     // ////////////////////////////////////////////////////////////////////////
00770     // Check for the power device. This view and input is independent from the
00771     // SRCP state machine. So the power state can be controlled also in error
00772     // states and in the input dialog states.
00773     if (_psActualDevice)
00774     {
00775         SRCP_DEVICE * pPowerDev = _pGetPowerDevice(_psActualDevice->u8Bus);
00776
00777         if (pPowerDev==NULL)
00778         {
00779             // The power device was disabled! The actual device is strongly
00780             // linked to this power device and can only be used with a well
00781             // configured power device. Disable the actual device.
00782
00783             _psActualDevice->eDevState = SRCP_DS_DISABLED;
00784         }
00785         else
00786         {
00787             sPower * pPwr = (sPower*)(&pPowerDev[1]);
00788             _updateView(pPowerDev);
00789
00790             if (pPowerDev->eDevState == SRCP_DS_DISABLED)
00791             {
00792                 // The power device was disabled! The actual device is strongly
00793                 // linked to this power device and can only be used with a well
00794                 // configured power device. Disable the actual device.
00795
00796                 _psActualDevice->eDevState = SRCP_DS_DISABLED;
00797             }
00798             else if (bInputButtonPushed(PWR_BTN) == TRUE)
00799             {
00800                 // Toggle the power state.
00801                 pPwr->bPowerState = !(pPwr->bPowerState);
00802                 if (_bSendSRCPMessage(SRCP_CMD_SET, pPowerDev) == TRUE)
00803                 {
00804                     InputButtonReset(PWR_BTN);
00805                 }
00806
00807                 // Retoggle the power state to stay synchronized with the view.
00808                 // The new state comes via an INFO message and updates the
00809                 // view.
00810                 pPwr->bPowerState = !(pPwr->bPowerState);
00811             }
00812         }
00813     }
00814
00815
00816     // ////////////////////////////////////////////////////////////////////////
00817     // The Global SRCP Input and View State Machine
00818     switch (_eSRCPsm)
00819     {
00820     case SRCP_STARTUP:
00821         // This state is only called once after connect and handshake.
00822         InputButtonReset(ALL_BTN);
00823         OutSwitchOffAllLEDs();
00824         _eSRCPsm = SRCP_MAIN;
00825         break;
00826
00827     case SRCP_MAIN:
00828         if (_psActualDevice)
00829         {
00830             if ((_psActualDevice->eDevType == SRCP_DT_GL) && bInputButtonPushedLong(SEL_BTN))
00831             {
00832                 // The loco select button was pushed for a long time, the user
00833                 // wants to store the loco as a quick or loco db set in eeprom.
00834                 InputButtonReset(ALL_BTN);
00835                 InputEncoderInit(4, 0, SRCP_GLEEPROMSET_COUNT-1, 0);
00836                 _eSRCPsm = SRCP_SELECT_EEPROM_SET_TO_SAVE;
00837                 break;
00838             }
00839             else if ((_psActualDevice->eDevType == SRCP_DT_GA) && bInputButtonPushedLong(ACC_BTN))
00840             {
00841                 // The accessory select button was pushed for a long time, the user
00842                 // wants to store the acc at a quick set in eeprom.
00843                 InputButtonReset(ALL_BTN);
00844                 InputEncoderInit(0, 0, SRCP_GAEEPROMSET_COUNT-1, 0);
00845                 _eSRCPsm = SRCP_SELECT_EEPROM_SET_TO_SAVE;
00846                 break;
00847             }
00848         }
00849
00850         if (bInputButtonPushed(SEL_BTN) == TRUE)
00851         {
00852             BYTE protoCount;
00853
00854             // Reset the button for new inputs:
00855             InputButtonReset(ALL_BTN);
00856             OutSetLED(LED_SEL, LED_ON);
00857
00858             if (_psActualDevice && (_psActualDevice->eDevType==SRCP_DT_GA))
00859             {
00860                 // Switch over to the last known GL set.
00861                 if (_pGetLatestGL())
00862                 {
00863                     _psNewDevice = _pGetLatestGL();
00864                     _eSRCPsm = SRCP_WAIT_FOR_IDLE_DEVICE;
00865                     break;
00866                 }
00867             }
00868
00869             protoCount = _u8GenerateActiveProtoList(TRUE, sPSRCPConfig.u8DefaultGLProtoId);
00870             if (protoCount==0)
00871             {
00872                 // We never should come in here (at least the server cache is
00873                 // selectable).
00874                 OutSetLED(LED_SEL, LED_OFF);
00875                 break;
00876             }
00877
00878             if ((sPSRCPConfig.sFlags.bGLAskForProto == TRUE) && (protoCount>1))
00879             {
00880                 InputEncoderInit(0, 0, protoCount-1, 0);
00881                 InputButtonReset(ENC_BTN);
00882                 _eSRCPsm = SRCP_SELECT_PROTOCOL;
00883             }
00884             else
00885             {
00886                 _u8LastSelectedProtoId = sPSRCPConfig.u8DefaultGLProtoId;
00887                 _eSRCPsm = SRCP_PROTOCOL_SELECTED;
00888             }
00889
00890             break;
00891         }
00892         else if (bInputButtonPushed(ACC_BTN) == TRUE)
00893         {
00894             BYTE protoCount;
00895
00896             // Reset the button for new inputs:
00897             InputButtonReset(ALL_BTN);
00898             OutSetLED(LED_ACC, LED_ON);
00899
00900             if (_psActualDevice && (_psActualDevice->eDevType==SRCP_DT_GL))
00901             {
00902                 // Switch over to the last known GA set.
00903                 if (_pGetLatestGA())
00904                 {
00905                     _psNewDevice = _pGetLatestGA();
00906                     _eSRCPsm = SRCP_WAIT_FOR_IDLE_DEVICE;
00907                     break;
00908                 }
00909             }
00910
00911             protoCount = _u8GenerateActiveProtoList(FALSE, sPSRCPConfig.u8DefaultGAProtoId);
00912             if (protoCount == 0)
00913             {
00914                 // No entry in the protocol list! Finish up!
00915                 OutSetLED(LED_ACC, LED_OFF);
00916                 break;
00917             }
00918
00919             if ((sPSRCPConfig.sFlags.bGAAskForProto == TRUE) && (protoCount>1))
00920             {
00921                 InputEncoderInit(0, 0, protoCount-1, 0);
00922                 InputButtonReset(ENC_BTN);
00923                 _eSRCPsm = SRCP_SELECT_PROTOCOL;
00924             }
00925             else
00926             {
00927                 _u8LastSelectedProtoId = sPSRCPConfig.u8DefaultGAProtoId;
00928                 _eSRCPsm = SRCP_PROTOCOL_SELECTED;
00929             }
00930
00931             break;
00932         }
00933
00934
00935         // Is there a configured device for view?
00936         if (_psActualDevice == NULL)
00937         {
00938             break;
00939         }
00940
00941         if (_psActualDevice->eDevState == SRCP_DS_DISABLED)
00942         {
00943             // The device is disabled (terminated)!
00944             _displayNoData();
00945             _psActualDevice = NULL;
00946             break;
00947         }
00948
00949         // Check for changed view of the actual device.
00950         _updateView(_psActualDevice);
00951
00952         _updateInput(_psActualDevice);
00953
00954         break;
00955
00956     case SRCP_SELECT_EEPROM_SET_TO_SAVE:
00957         _u8LastEEPROMSetIdx = 0xFF;
00958         if (bInputButtonPushed(F1_BTN) == TRUE)
00959         {
00960             _u8LastEEPROMSetIdx = 0;
00961         }
00962         else if (bInputButtonPushed(F2_BTN) == TRUE)
00963         {
00964             _u8LastEEPROMSetIdx = 1;
00965         }
00966         else if (bInputButtonPushed(F3_BTN) == TRUE)
00967         {
00968             _u8LastEEPROMSetIdx = 2;
00969         }
00970         else if (bInputButtonPushed(F4_BTN) == TRUE)
00971         {
00972             _u8LastEEPROMSetIdx = 3;
00973         }
00974         else if (bInputButtonPushedOnce(ENC_BTN) == TRUE)
00975         {
00976             _u8LastEEPROMSetIdx = (BYTE) s16InputEncoderGetValue();
00977         }
00978
00979         if (_u8LastEEPROMSetIdx != 0xFF)
00980         {
00981             BOOL ret;
00982
00983             ret = bInitInputDialog(DEVICE_NAME_PTR(_psActualDevice),
00984                                    DIALOG_ALL_LETTERS, 0,
00985                                    SRCP_NAME_MAXLEN,
00986                                    DIALOG_ESC_FLAG | DIALOG_DESCRIPTION_FLAG |
00987                                    DIALOG_NEXT_FLAG | DIALOG_BACKSPACE_FLAG);
00988
00989             if (ret == TRUE)
00990             {
00991                 _eSRCPsm = SRCP_ENTER_NAME;
00992             }
00993             else
00994             {
00995                 _eSRCPsm = SRCP_MAIN;
00996             }
00997         }
00998         else if (bInputEncoderValueChanged() == TRUE)
00999         {
01000             BYTE setidx = s16InputEncoderGetValue();
01001             lcd_addr1 = 0;
01002             StrTbl_GetString(lcdram_row1, STRTBLID_DATABASE);
01003             // The second row is for the set id.
01004             sprintf(lcdram_row2, StrTbl_cau8GetStringPointer(STRTBLID_POSITION_X), setidx+1);
01005             lcd_addr2 = 0;
01006             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
01007         }
01008         break;
01009
01010     case SRCP_ENTER_NAME:
01011         if (bHandleInputDialog()==TRUE)
01012         {
01013             BYTE * pName = DEVICE_NAME_PTR(_psActualDevice);
01014             if (FiniDialog(pName) == DIALOG_FINI_OK)
01015             {
01016                 // Store the current device into the quick storage.
01017                 _u8LastEEPROMSetIdx = _u8AddEntryToEEPROM(_u8LastEEPROMSetIdx, _psActualDevice);
01018
01019                 // Remember the new name.
01020                 _storeNameToEEPROM(_u8LastEEPROMSetIdx, pName);
01021             }
01022             _eSRCPsm = SRCP_PREPARE_MAIN;
01023         }
01024         break;
01025
01026     case SRCP_SELECT_PROTOCOL:
01027         // Thats the protocol dialog. The user chooses one of the preconfigured
01028         // protocols.
01029         if (_bCheckForSelectedSet(&_sNewDeviceStaticData, FALSE) == TRUE)
01030         {
01031             // Quick select (via the FX-buttons):
01032             _eSRCPsm = SRCP_INIT_DEVICE;
01033         }
01034         else if (bInputButtonPushed(ENC_BTN) == TRUE)
01035         {
01036             _u8LastSelectedProtoId = _au8ActiveProtos[s16InputEncoderGetValue()];
01037             _eSRCPsm = SRCP_PROTOCOL_SELECTED;
01038         }
01039         else if (bInputEncoderValueChanged() == TRUE)
01040         {
01041             BYTE selected = s16InputEncoderGetValue();
01042             lcd_addr1 = 0;
01043             StrTbl_GetString(lcdram_row1, STRTBLID_PROTOCOL);
01044             // The second row is for the protocol name
01045             if (_au8ActiveProtos[selected]==SRCP_SERVERCACHE_ID)
01046             {
01047                 StrTbl_GetString(lcdram_row2, STRTBLID_SERVER_CACHE);
01048             }
01049             else if (_au8ActiveProtos[selected]==SRCP_EEPROMSET_ID)
01050             {
01051                 StrTbl_GetString(lcdram_row2, STRTBLID_DATABASE);
01052             }
01053             else
01054             {
01055                 _getProtoName(_au8ActiveProtos[selected], lcdram_row2);
01056             }
01057             lcd_addr2 = 0;
01058             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
01059         }
01060         else if (bInputButtonPushed(ACC_BTN) == TRUE)
01061         {
01062             if (OutGetLEDMode(LED_ACC) == LED_ON)
01063             {
01064                 InputButtonReset(ACC_BTN);
01065             }
01066             _eSRCPsm = SRCP_PREPARE_MAIN;
01067         }
01068         else if (bInputButtonPushed(SEL_BTN) == TRUE)
01069         {
01070             if (OutGetLEDMode(LED_SEL) == LED_ON)
01071             {
01072                 InputButtonReset(SEL_BTN);
01073             }
01074             _eSRCPsm = SRCP_PREPARE_MAIN;
01075         }
01076         break;
01077
01078     case SRCP_PROTOCOL_SELECTED:
01079         switch(_u8LastSelectedProtoId)
01080         {
01081         case SRCP_SERVERCACHE_ID:
01082             if (_bPrepareServerCacheInput() == TRUE)
01083             {
01084                 _eSRCPsm = SRCP_SELECT_SERVER_CACHE;
01085             }
01086             else
01087             {
01088                 // \todo For test: Force to get into this state!
01089                 _eSRCPsm = SRCP_ERROR;
01090             }
01091             break;
01092
01093         case SRCP_EEPROMSET_ID:
01094         {
01095             BOOL bGL = FALSE;
01096             BYTE entries;
01097             if (OutGetLEDMode(LED_SEL) == LED_ON)
01098             {
01099                 bGL = TRUE;
01100             }
01101
01102             entries = _prepareEEPROMSetInput(bGL);
01103
01104             if (entries == 0)
01105             {
01106                 _eSRCPsm = SRCP_ERROR;
01107             }
01108             else
01109             {
01110                 // Initialize the encoder.
01111                 InputButtonReset(ENC_BTN);
01112                 InputEncoderInit(0, 0, entries-1, 0);
01113                 _eSRCPsm = SRCP_SELECT_EEPROMSET;
01114             }
01115
01116             break;
01117         }
01118
01119         default:
01120             if (_bGetStaticParameterFromProto(_u8LastSelectedProtoId, &_sNewDeviceStaticData) == TRUE)
01121             {
01122                 // Fetch the address from user.
01123                 WORD min, max;
01124                 _getProtoMinMax(_u8LastSelectedProtoId, &min, &max);
01125                 InputEncoderInit(1, min, max, 0);
01126
01127                 lcd_addr1 = 0;
01128                 StrTbl_GetString(lcdram_row1, STRTBLID_ADDRESS);
01129                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK;
01130
01131                 InputButtonReset(ENC_BTN);
01132                 _eSRCPsm = SRCP_SELECT_DEVICE_ADDRESS;
01133             }
01134             else
01135             {
01136                 // \todo For test: Force to get into this state!
01137                 _eSRCPsm = SRCP_ERROR;
01138             }
01139         }
01140         break;
01141
01142
01143     case SRCP_SELECT_DEVICE_ADDRESS:
01144         // Thats the address setting dialog!
01145         if (_bCheckForSelectedSet(&_sNewDeviceStaticData, FALSE) == TRUE)
01146         {
01147             // One of the quick buttons was pushed!
01148             _eSRCPsm = SRCP_INIT_DEVICE;
01149         }
01150         else if (bInputButtonPushedOnce(ENC_BTN) == TRUE)
01151         {
01152             // Selection!
01153             _sNewDeviceStaticData.u32Address = s16InputEncoderGetValue();
01154             _eSRCPsm = SRCP_INIT_DEVICE;
01155         }
01156         else if (bInputEncoderValueChanged() == TRUE)
01157         {
01158             sprintf(lcdram_row2, (ROM char *) "%5hu", s16InputEncoderGetValue());
01159             lcd_status |= LCD_ROW2_MASK;
01160         }
01161         else if (bInputButtonPushed(ACC_BTN) == TRUE)
01162         {
01163             if (OutGetLEDMode(LED_ACC) == LED_ON)
01164             {
01165                 InputButtonReset(ACC_BTN);
01166             }
01167             _eSRCPsm = SRCP_PREPARE_MAIN;
01168         }
01169         else if (bInputButtonPushed(SEL_BTN) == TRUE)
01170         {
01171             if (OutGetLEDMode(LED_SEL) == LED_ON)
01172             {
01173                 InputButtonReset(SEL_BTN);
01174             }
01175             _eSRCPsm = SRCP_PREPARE_MAIN;
01176         }
01177         break;
01178
01179
01180     case SRCP_SELECT_EEPROMSET:
01181         if (_bCheckForSelectedSet(&_sNewDeviceStaticData, TRUE) == TRUE)
01182         {
01183             // Quick select (via the FX or the Encoder-buttons):
01184             _eSRCPsm = SRCP_INIT_DEVICE;
01185         }
01186         else if (bInputEncoderValueChanged() == TRUE)
01187         {
01188             SPSET set;
01189             BYTE setidx = _pActiveEEPROMSetList[s16InputEncoderGetValue()];
01190
01191             // The first row indicates what should be input.
01192             lcd_addr1 = 0;
01193             StrTbl_GetString(lcdram_row1, STRTBLID_DATABASE);
01194
01195             // The second row is for eeprom set name.
01196             XEEReadArray(SRCP_SETS_EEPROM_ADD + (sizeof(SPSET) * setidx), (BYTE *)&set, sizeof(SPSET));
01197
01198             strncpy(lcdram_row2, set.au8Name, LCD_CHARS_IN_A_ROW);
01199             lcdram_row2[LCD_CHARS_IN_A_ROW] = 0;
01200             lcd_addr2 = 0;
01201             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
01202         }
01203         else if (bInputButtonPushed(ACC_BTN) == TRUE)
01204         {
01205             if (OutGetLEDMode(LED_ACC) == LED_ON)
01206             {
01207                 InputButtonReset(ACC_BTN);
01208             }
01209             _eSRCPsm = SRCP_PREPARE_MAIN;
01210         }
01211         else if (bInputButtonPushed(SEL_BTN) == TRUE)
01212         {
01213             if (OutGetLEDMode(LED_SEL) == LED_ON)
01214             {
01215                 InputButtonReset(SEL_BTN);
01216             }
01217             _eSRCPsm = SRCP_PREPARE_MAIN;
01218         }
01219
01220         if (_eSRCPsm != SRCP_SELECT_EEPROMSET)
01221         {
01222             // Leaving this state? Destructing the list.
01223             _destructEEPROMSet();
01224         }
01225         break;
01226
01227
01228     case SRCP_SELECT_SERVER_CACHE:
01229         if (_bCheckForSelectedSet(&_sNewDeviceStaticData, FALSE) == TRUE)
01230         {
01231             // Quick select (via the FX-buttons):
01232             _eSRCPsm = SRCP_INIT_DEVICE;
01233         }
01234         else if (bInputButtonPushed(ENC_BTN) == TRUE)
01235         {
01236             // Copy the cache data to the initialization structure.
01237             _bGetStaticParameterFromCache(s16InputEncoderGetValue(),&_sNewDeviceStaticData);
01238             _eSRCPsm = SRCP_INIT_DEVICE;
01239         }
01240         else if (bInputEncoderValueChanged() == TRUE)
01241         {
01242             BYTE idx = s16InputEncoderGetValue();
01243
01244             // The first row indicates what should be input.
01245             lcd_addr1 = 0;
01246             StrTbl_GetString(lcdram_row1, STRTBLID_BUS_ADDRESS);
01247
01248             // The second row is for the address and bus number.
01249             sprintf(lcdram_row2, (ROM char *) "%-3hhu        %5lu", _apsSelectCache[idx].u8BusNr, _apsSelectCache[idx].u32Address);
01250             lcd_addr2 = 0;
01251             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_ROW2_MASK;
01252         }
01253         else if (bInputButtonPushed(ACC_BTN) == TRUE)
01254         {
01255             if (OutGetLEDMode(LED_ACC) == LED_ON)
01256             {
01257                 InputButtonReset(ACC_BTN);
01258             }
01259             _eSRCPsm = SRCP_PREPARE_MAIN;
01260         }
01261         else if (bInputButtonPushed(SEL_BTN) == TRUE)
01262         {
01263             if (OutGetLEDMode(LED_SEL) == LED_ON)
01264             {
01265                 InputButtonReset(SEL_BTN);
01266             }
01267             _eSRCPsm = SRCP_PREPARE_MAIN;
01268         }
01269
01270         if (_eSRCPsm != SRCP_SELECT_SERVER_CACHE)
01271         {
01272             // Leaving this state? Destructing the cache.
01273             _destructServerCache();
01274         }
01275         break;
01276
01277
01278     case SRCP_INIT_DEVICE:
01279         if (OutGetLEDMode(LED_ACC) == LED_ON)
01280         {
01281             sGA newGA;
01282             _fillPrmGA(&newGA, &_sNewDeviceStaticData);
01283             _psNewDevice = _psAddDevice(SRCP_DT_GA, _sNewDeviceStaticData.u8BusNr, (void *)&newGA);
01284         }
01285         else
01286         {
01287             sGL newGL;
01288             _fillPrmGL(&newGL, &_sNewDeviceStaticData);
01289             _psNewDevice = _psAddDevice(SRCP_DT_GL, _sNewDeviceStaticData.u8BusNr, (void *)&newGL);
01290         }
01291
01292         if (_psNewDevice == NULL)
01293         {
01294             PrintCommonError(COMMON_ERROR_OUT_OF_MEMORY);
01295             _eSRCPsm = SRCP_ERROR;
01296             break;
01297         }
01298
01299         _eSRCPsm = SRCP_WAIT_FOR_IDLE_DEVICE;
01300         // Intended fall through.
01301
01302
01303     case SRCP_WAIT_FOR_IDLE_DEVICE:
01304         if (_psNewDevice->u16LastErrorCode)
01305         {
01306             _showServerError(_psNewDevice->u16LastErrorCode);
01307             // Acknowledge the error:
01308             _psNewDevice->u16LastErrorCode = 0;
01309             _psNewDevice->eDevState = SRCP_DS_DISABLED;
01310             _eSRCPsm = SRCP_ERROR;
01311             break;
01312         }
01313         else if (_psNewDevice->eDevState != SRCP_DS_IDLE)
01314         {
01315             break;
01316         }
01317
01318         _eSRCPsm = SRCP_INIT_POWER;
01319         // Intended fall through.
01320
01321
01322     case SRCP_INIT_POWER:
01323     {
01324         // After we know the protocol and the SRCP bus number (as protocol
01325         // parameter), we can check for a configured POWER device on that bus.
01326         sPower prm;
01327         prm.bPowerState = FALSE;
01328
01329         // Append the power device to the device list (the function
01330         // _psAddDevice automatically checks for already configured power
01331         // device).
01332         if (_psAddDevice(SRCP_DT_POWER, _psNewDevice->u8Bus, (void*)&prm) == NULL)
01333         {
01334             PrintCommonError(COMMON_ERROR_OUT_OF_MEMORY);
01335             _eSRCPsm = SRCP_ERROR;
01336             break;
01337         }
01338
01339         _eSRCPsm = SRCP_WAIT_FOR_IDLE_POWER_DEVICE;
01340         // Intented fall through.
01341     }
01342
01343
01344     case SRCP_WAIT_FOR_IDLE_POWER_DEVICE:
01345     {
01346         // Check whether the power device is already idle (initialized).
01347         SRCP_DEVICE * pPowerDev;
01348
01349
01350         // Step 1: Fetch the power device from the device list.
01351         pPowerDev = _pGetPowerDevice(_psNewDevice->u8Bus);
01352         if (pPowerDev==NULL)
01353         {
01354             // We never should come in here!
01355             PrintCommonError(COMMON_ERROR_SRCP_NO_POWER_DEVICE);
01356             _eSRCPsm = SRCP_ERROR;
01357             break;
01358         }
01359
01360
01361         // Step 2: Check for errors on the power device.
01362         if (pPowerDev->u16LastErrorCode)
01363         {
01364             _showServerError(pPowerDev->u16LastErrorCode);
01365             pPowerDev->u16LastErrorCode = 0;    // Acknowledge the error.
01366             _eSRCPsm = SRCP_ERROR;
01367             pPowerDev->eDevState = SRCP_DS_DISABLED;
01368             _psNewDevice->eDevState = SRCP_DS_DISABLED;
01369             break;
01370         }
01371
01372
01373         // Step 3:
01374         // Check the state of power device (should become idle in short time).
01375         if (pPowerDev->eDevState == SRCP_DS_IDLE)
01376         {
01377             // We can switch from the old to this new device.
01378             _psActualDevice = _pTakeOverDevice(_psNewDevice);
01379             _eSRCPsm = SRCP_PREPARE_MAIN;
01380         }
01381
01382         break;
01383     }
01384
01385
01386     case SRCP_ERROR:
01387         InputButtonReset(ALL_BTN);
01388         _eSRCPsm = SRCP_ACK_ERROR;
01389         break;
01390
01391
01392     case SRCP_ACK_ERROR:
01393         if (bInputButtonPushed(ALL_BTN)==FALSE)
01394         {
01395             break;
01396         }
01397         // Intented fall through.
01398
01399
01400     case SRCP_PREPARE_MAIN:
01401         if (_psActualDevice == NULL)
01402         {
01403             _displayNoData();
01404         }
01405         else
01406         {
01407             OutSetLED(LED_ACC | LED_SEL, LED_OFF);
01408
01409             lcd_addr1 = 0;
01410             strncpy(lcdram_row1, DEVICE_NAME_PTR(_psActualDevice), LCD_CHARS_IN_A_ROW);
01411             lcdram_row1[LCD_CHARS_IN_A_ROW] = 0;
01412             lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK;
01413             lcdram_row2[0] = 0;
01414
01415             if (_psActualDevice->eDevType == SRCP_DT_GA)
01416             {
01417                 sGA * pGA = (sGA *)(&_psActualDevice[1]);
01418                 InputEncoderInit(pGA->u8Port, pGA->u8MinPort, pGA->u8MaxPort, ENC_ENDSTOP_MASK);
01419             }
01420             else if (_psActualDevice->eDevType == SRCP_DT_GL)
01421             {
01422                 sGL * pGL = (sGL *)(&_psActualDevice[1]);
01423                 pGL->s16ActV = pGL->s16ServerV;
01424             }
01425
01426             // Mark for new data to ensure updating the view.
01427             _psActualDevice->sFlags.bNewData = TRUE;
01428         }
01429
01430         _eSRCPsm = SRCP_MAIN;
01431         if (bInputButtonPushed(SEL_BTN) || bInputButtonPushed(ACC_BTN))
01432         {
01433             // The user wants to configure a new device. Go straight to the
01434             // dialog.
01435             break;
01436         }
01437
01438         InputButtonReset(ALL_BTN);
01439         break;
01440     }
01441
01442     // All SRCP stuff was handled correctly. Show to application with a TRUE
01443     // return value.
01444     return TRUE;
01445 }
01446
01447 // ////////////////////////////////////////////////////////////////////////////
01448 // ////////////////////////////////////////////////////////////////////////////
01449
01450 static SHORT _s16computeRealSpeed(SHORT s16MaxV, SHORT s16ServerMaxV, SHORT s16ServerSpeed)
01451 {
01452     if (s16MaxV == s16ServerMaxV)
01453     {
01454         return s16ServerSpeed;
01455     }
01456     else
01457     {
01458         return (SHORT)(((float)s16ServerSpeed / s16ServerMaxV) * s16MaxV);
01459     }
01460 }
01461
01462
01463 // ////////////////////////////////////////////////////////////////////////////
01464 // ////////////////////////////////////////////////////////////////////////////
01465
01478 static BOOL _bGetNextWord(BYTE u8Socket, BYTE * au8Buf, BYTE u8BufSize, BOOL * bEnd)
01479 {
01480     BYTE i = 0;
01481     BYTE data = 0;
01482     u8BufSize = u8BufSize-1;    // Leave space for the termination character.
01483
01484     if (*bEnd == TRUE)
01485     {
01486         return FALSE;
01487     }
01488
01489     // Step 1: Throw away all prepending whitespaces (semicolon, space, tab)
01490     // characters.
01491     do
01492     {
01493         if (TCPGet(u8Socket, &data) == FALSE)
01494         {
01495             return FALSE;
01496         }
01497     } while(data==';' || data==' ' || data==9);
01498
01499
01500     // Step 2: Get the word to the next whitespace or line end.
01501     do
01502     {
01503         if (data == '\n')
01504         {
01505             if (i && au8Buf[i-1] == 92)
01506             {
01507                 // Is the line end escaped, than handle this character group
01508                 // (\CRLF or \LF) as whitespace!
01509                 i = i-1;
01510             }
01511             else
01512             {
01513                 // We have reached the end of the line:
01514                 *bEnd = TRUE;
01515             }
01516
01517             // Maybe after this line is another line!
01518             break;
01519         }
01520
01521         if ((i < u8BufSize)&&(data>=32)&&(data<=127))
01522         {
01523             // Store the data if buffer space is left.
01524             au8Buf[i++] = data;
01525         }
01526
01527         if (TCPGet(u8Socket, &data) == FALSE)
01528         {
01529             return FALSE;
01530         }
01531
01532     } while(data != ';' && data != ' ' && data != 9);
01533
01534     au8Buf[i] = 0;      // end as string
01535
01536     return TRUE;
01537 }
01538
01539 // ////////////////////////////////////////////////////////////////////////////
01540 // ////////////////////////////////////////////////////////////////////////////
01541
01542 static BOOL _bLookForEnd(BYTE u8Socket)
01543 {
01544     BYTE data;
01545
01546     while (TCPGet(u8Socket, &data))
01547     {
01548         if (data == 92)
01549         {
01550             // Backslash found!
01551             // Handle the following (CR)LF as whitespace.
01552             if(TCPGet(u8Socket, &data))
01553             {
01554                 if (data==0x0d)
01555                 {
01556                     if (TCPGet(u8Socket, &data) == FALSE)
01557                     {
01558                         return FALSE;
01559                     }
01560                 }
01561             }
01562             else
01563             {
01564                 return FALSE;
01565             }
01566         }
01567         else if (data == 0x0a)
01568         {
01569             return TRUE;
01570         }
01571     }
01572
01573     return FALSE;
01574 }
01575
01576 // ////////////////////////////////////////////////////////////////////////////
01577 // ////////////////////////////////////////////////////////////////////////////
01578
01579 void SRCP_GetProtoFromEEPROM(BYTE u8ProtoId, SPPROTOCOL * psProto)
01580 {
01581     XEEReadArray(SRCP_PROTOS_EEPROM_ADD + (sizeof(SPPROTOCOL) * u8ProtoId), (BYTE *)psProto, sizeof(SPPROTOCOL));
01582 }
01583
01584
01585 // ////////////////////////////////////////////////////////////////////////////
01586 // ////////////////////////////////////////////////////////////////////////////
01587
01588 void SRCP_WriteSetToEEPROM(BYTE u8SetIdx, SPSET * psSet)
01589 {
01590     XEEWriteArray(SRCP_SETS_EEPROM_ADD + (sizeof(SPSET) * u8SetIdx), (BYTE *)psSet, sizeof(SPSET));
01591 }
01592
01593 // ////////////////////////////////////////////////////////////////////////////
01594 // ////////////////////////////////////////////////////////////////////////////
01595
01596 void SRCP_GetSetFromEEPROM(BYTE u8SetIdx, SPSET * psSet)
01597 {
01598     XEEReadArray(SRCP_SETS_EEPROM_ADD + (sizeof(SPSET) * u8SetIdx), (BYTE *)psSet, sizeof(SPSET));
01599 }
01600
01601 // ////////////////////////////////////////////////////////////////////////////
01602 // ////////////////////////////////////////////////////////////////////////////
01603
01604 static void _getProtoFromEEPROM(BYTE u8ProtoId, SPPROTOCOL * psProto)
01605 {
01606     // For the internal access only the content data will be used.
01607     XEEReadArray(SRCP_PROTOS_EEPROM_ADD + (sizeof(SPPROTOCOL) * u8ProtoId), (BYTE *)psProto, sizeof(SPPROTOCOL));
01608 }
01609
01610 // ////////////////////////////////////////////////////////////////////////////
01611 // ////////////////////////////////////////////////////////////////////////////
01612
01613 void SRCP_WriteProtoToEEPROM(BYTE u8ProtoId, SPPROTOCOL * psProto)
01614 {
01615     SPPROTOCOL proto;
01616     SRCP_GetProtoFromEEPROM(u8ProtoId, &proto);
01617
01618     if (memcmp((void *)&proto, (void*)psProto, sizeof(SPPROTOCOL)))
01619     {
01620         XEEWriteArray(SRCP_PROTOS_EEPROM_ADD+(sizeof(SPPROTOCOL) * u8ProtoId), (BYTE *)psProto, sizeof(SPPROTOCOL));
01621     }
01622 }
01623
01624 // ////////////////////////////////////////////////////////////////////////////
01625 // ////////////////////////////////////////////////////////////////////////////
01626
01627 static void _displayNoData(void)
01628 {
01629     StrTbl_GetString(lcdram_row1, STRTBLID_NO_DEVICE);
01630     lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK;
01631     OutSwitchOffAllLEDs();
01632 }
01633
01634 // ////////////////////////////////////////////////////////////////////////////
01635 // ////////////////////////////////////////////////////////////////////////////
01636
01637 static void _displayGLData(SRCP_DEVICE * pDev)
01638 {
01639     BYTE i = 0;
01640     BYTE tmplcd[17];
01641     sGL * pGL = (sGL *)(&pDev[1]);
01642
01643     if (pGL->u8FuncGroup == 0)
01644     {
01645         SHORT min = 0;
01646         SHORT speed = pGL->s16ActV;
01647
01648         if (pGL->s16MaxV != pGL->u8MaxSteps)
01649         {
01650             speed = _s16computeRealSpeed(pGL->s16MaxV, pGL->u8MaxSteps, pGL->s16ActV);
01651         }
01652
01653         sprintf(tmplcd, (ROM char *) "%-5lu       %3hd", pGL->u32Addr, speed);
01654
01655         if (pGL->s16ActV != pGL->s16ServerV)
01656         {
01657             if (pGL->s16ActV > pGL->s16ServerV)
01658             {
01659                 tmplcd[15] = 0x05;
01660             }
01661             else
01662             {
01663                 tmplcd[15] = 0x06;
01664             }
01665         }
01666         else
01667         {
01668             tmplcd[15] = 0x20;
01669         }
01670
01671         if (pGL->sGLFlags.u2Dir == DIR_FORWARD)
01672         {
01673             tmplcd[7] = 0x01;
01674         }
01675         else if (pGL->sGLFlags.u2Dir == DIR_BACKWARD)
01676         {
01677             tmplcd[7] = 0x02;
01678         }
01679
01680         tmplcd[16] = 0;
01681
01682
01683         if (IsEncoderTurning() == FALSE)
01684         {
01685             speed = pGL->s16ActV;
01686             if (sPApplConfig.sFlags.bToggleLocoDirMode == TOGGLEDIRMODE_ZERO)
01687             {
01688                 if (pGL->sGLFlags.u2Dir == DIR_BACKWARD)
01689                 {
01690                     speed = -(speed);
01691                 }
01692                 min = pGL->u8MaxSteps;
01693                 min = -min;
01694             }
01695
01696             InputEncoderInit(speed, min, pGL->u8MaxSteps, ENC_NOCHANGE_MASK | ENC_ENDSTOP_MASK);
01697         }
01698     }
01699     else if (pGL->u8FuncGroup == 1)
01700     {
01701         strcpypgm2ram(tmplcd, (ROM char *)"F5              ");
01702         if (pGL->u8NrFunc > 6)
01703         {
01704             tmplcd[5] = 'F';
01705             tmplcd[6] = '6';
01706         }
01707         if (pGL->u8NrFunc > 7)
01708         {
01709             tmplcd[9] = 'F';
01710             tmplcd[10] = '7';
01711         }
01712         if (pGL->u8NrFunc > 8)
01713         {
01714             tmplcd[14] = 'F';
01715             tmplcd[15] = '8';
01716         }
01717     }
01718     else
01719     {
01720         strcpypgm2ram(tmplcd, (ROM char *)"F9              ");
01721         if (pGL->u8NrFunc > 10)
01722         {
01723             tmplcd[5] = 'F';
01724             tmplcd[6] = '1';
01725             tmplcd[7] = '0';
01726         }
01727         if (pGL->u8NrFunc > 11)
01728         {
01729             tmplcd[9] = 'F';
01730             tmplcd[10] = '1';
01731             tmplcd[11] = '1';
01732         }
01733         if (pGL->u8NrFunc > 12)
01734         {
01735             tmplcd[13] = 'F';
01736             tmplcd[14] = '1';
01737             tmplcd[15] = '2';
01738         }
01739     }
01740
01741
01742     if (strcmp(tmplcd, lcdram_row2))
01743     {
01744         lcd_addr2 = 0;
01745         lcd_status |= LCD_ROW2_MASK;
01746         strcpy(lcdram_row2, tmplcd);
01747     }
01748
01749
01750     // Function mask (group dependent)
01751     {
01752         DWORD funcs = pGL->u32FuncBitField & pGL->u32FuncAllocMask;
01753
01754         // F0 is always displayed at the F0 button:
01755         BYTE led = funcs & 0x01;
01756
01757         // F1-F4 alternate function group dependent.
01758         if (pGL->u8FuncGroup == 0)
01759         {
01760             led |= funcs & 0x1E;
01761         }
01762         else if (pGL->u8FuncGroup == 1)
01763         {
01764             led |= (funcs >> 4) & 0x1E;
01765         }
01766         else
01767         {
01768             led |= (funcs >> 8) & 0x1E;
01769         }
01770
01771         OutSetLEDMask(LED_FL | LED_F1 | LED_F2 | LED_F3 | LED_F4, led);
01772     }
01773 }
01774
01775 // ////////////////////////////////////////////////////////////////////////////
01776 // ////////////////////////////////////////////////////////////////////////////
01777
01778 static void _displayGAData(SRCP_DEVICE * pDev)
01779 {
01780     sGA * pGA = (sGA *)(&pDev[1]);
01781
01782     lcd_addr2 = 0;
01783     sprintf(lcdram_row2, (ROM char *) "%-5lu        %3hhu", pGA->u32Addr, pGA->u8Port);
01784     lcd_status |= LCD_ROW2_MASK;
01785
01786     InputEncoderSetValue(pGA->u8Port, FALSE);
01787
01788     if (pGA->u8Value == 0)
01789     {
01790         lcdram_row2[7] = 0x03;
01791     }
01792     else
01793     {
01794         lcdram_row2[7] = 0x04;
01795     }
01796
01797     OutSetLED(LED_FL|LED_F1|LED_F2|LED_F3|LED_F4, LED_OFF);
01798 }
01799
01800 // ////////////////////////////////////////////////////////////////////////////
01801 // ////////////////////////////////////////////////////////////////////////////
01802
01803 static void _displayPower(SRCP_DEVICE * pDev)
01804 {
01805     sPower * pPwr = (sPower *)(&pDev[1]);
01806
01807     if ((OutGetLEDMode(LED_PWR) != LED_BLINK)&&(pPwr->bPowerState==FALSE))
01808     {
01809         OutSetLED(LED_PWR, LED_BLINK);
01810     }
01811     else if ((OutGetLEDMode(LED_PWR) != LED_ON)&&(pPwr->bPowerState))
01812     {
01813         OutSetLED(LED_PWR, LED_ON);
01814     }
01815 }
01816
01817 // ////////////////////////////////////////////////////////////////////////////
01818 // ////////////////////////////////////////////////////////////////////////////
01819
01820 static BOOL _bGetGLInput(sGL * pGL)
01821 {
01822     BOOL bChanged = FALSE;
01823     DWORD functionActive = pGL->u32FuncBitField;    // Get the current function flag field.
01824     DWORD functionToggle = pGL->u32FuncToggleMask;
01825     DWORD functionMask;
01826
01827
01828     if (pGL == NULL)
01829     {
01830         return FALSE;
01831     }
01832
01833     if (bInputEncoderValueChanged() == TRUE)
01834     {
01835         SHORT val = s16InputEncoderGetValue();
01836
01837         if (sPApplConfig.sFlags.bToggleLocoDirMode == TOGGLEDIRMODE_ZERO)
01838         {
01839             if (pGL->s16ActV == 0)
01840             {
01841                 if ((InputEncoderGetDirection() == FALSE) && (pGL->sGLFlags.u2Dir == DIR_BACKWARD))
01842                 {
01843                     pGL->sGLFlags.u2Dir = DIR_FORWARD;
01844                     val = 0;
01845                 }
01846                 else if ((InputEncoderGetDirection() == TRUE) && (pGL->sGLFlags.u2Dir == DIR_FORWARD))
01847                 {
01848                     pGL->sGLFlags.u2Dir = DIR_BACKWARD;
01849                     val = 0;
01850                 }
01851             }
01852
01853             if (val < 0)
01854             {
01855                 val = -(val);
01856             }
01857         }
01858
01859         pGL->s16ActV = val;
01860         bChanged = TRUE;
01861     }
01862     if (bInputButtonPushedOnce(ENC_BTN) == TRUE)
01863     {
01864         if (sPApplConfig.sFlags.bToggleLocoDirMode == TOGGLEDIRMODE_CLICK)
01865         {
01866             // Change the direction of the loco:
01867             switch (pGL->sGLFlags.u2Dir)
01868             {
01869             case DIR_FORWARD:
01870                 pGL->sGLFlags.u2Dir = DIR_BACKWARD;
01871                 break;
01872
01873             case DIR_BACKWARD:
01874                 pGL->sGLFlags.u2Dir = DIR_FORWARD;
01875                 break;
01876             }
01877         }
01878
01879         pGL->s16ActV = 0;
01880         bChanged = TRUE;
01881         InputButtonReset(ENC_BTN);
01882     }
01883
01884
01885     // Preparing the toggle mask for the actual function group.
01886     functionActive &= ~functionToggle;  // Mask out the toggle bits.
01887     functionMask = 0x02;
01888
01889     if (pGL->u8FuncGroup==1)
01890     {
01891         functionMask = functionMask << 4;
01892     }
01893     else if (pGL->u8FuncGroup == 2)
01894     {
01895         functionMask = functionMask << 8;
01896     }
01897
01898
01899     // Function F1
01900     if ((functionToggle & functionMask) && bInputButtonPressed(F1_BTN))
01901     {
01902         functionActive |= functionMask;
01903         InputButtonReset(F1_BTN);
01904     }
01905     else if (((functionToggle & functionMask) == 0) && bInputButtonPushed(F1_BTN))
01906     {
01907         functionActive ^= functionMask;
01908         InputButtonReset(F1_BTN);
01909     }
01910     functionMask = functionMask << 1;
01911
01912
01913
01914     // Function F2
01915     if ((functionToggle & functionMask) && bInputButtonPressed(F2_BTN))
01916     {
01917         functionActive |= functionMask;
01918         InputButtonReset(F2_BTN);
01919     }
01920     else if (((functionToggle & functionMask) == 0) && bInputButtonPushed(F2_BTN))
01921     {
01922         functionActive ^= functionMask;
01923         InputButtonReset(F2_BTN);
01924     }
01925     functionMask = functionMask << 1;
01926
01927
01928
01929     // Function F3
01930     if ((functionToggle & functionMask) && bInputButtonPressed(F3_BTN))
01931     {
01932         functionActive |= functionMask;
01933         InputButtonReset(F3_BTN);
01934     }
01935     else if (((functionToggle & functionMask) == 0) && bInputButtonPushed(F3_BTN))
01936     {
01937         functionActive ^= functionMask;
01938         InputButtonReset(F3_BTN);
01939     }
01940     functionMask = functionMask << 1;
01941
01942
01943
01944     // Function F4
01945     if ((functionToggle & functionMask) && bInputButtonPressed(F4_BTN))
01946     {
01947         functionActive |= functionMask;
01948         InputButtonReset(F4_BTN);
01949     }
01950     else if (((functionToggle & functionMask) == 0) && bInputButtonPushed(F4_BTN))
01951     {
01952         functionActive ^= functionMask;
01953         InputButtonReset(F4_BTN);
01954     }
01955
01956
01957     // Function F0
01958     if (bInputButtonPushed(FL_BTN) == TRUE)
01959     {
01960         if ((bInputButtonPushedLong(FL_BTN) == TRUE)&&(pGL->u8NrFunc > 5)&&
01961             (pGL->u8FuncGroup == 0))
01962         {
01963             // Change the function view!
01964             pGL->u8FuncGroup = 1;
01965         }
01966         else if (pGL->u8FuncGroup == 1)
01967         {
01968             if (pGL->u8NrFunc > 9)
01969             {
01970                 pGL->u8FuncGroup = 2;
01971             }
01972             else
01973             {
01974                 pGL->u8FuncGroup = 0;
01975             }
01976         }
01977         else if (pGL->u8FuncGroup == 2)
01978         {
01979             pGL->u8FuncGroup = 0;
01980         }
01981         else
01982         {
01983             functionActive ^= 0x01;
01984         }
01985
01986         InputButtonReset(FL_BTN);
01987         bChanged = TRUE;
01988     }
01989
01990     if (pGL->u32FuncBitField != functionActive)
01991     {
01992         pGL->u32FuncBitField = functionActive;
01993         pGL->u32FuncBitField &= pGL->u32FuncAllocMask;
01994         bChanged = TRUE;
01995     }
01996
01997     return bChanged;
01998 }
01999
02002
02003 static BOOL _bGetGAInput(SRCP_DEVICE * pDev)
02004 {
02005     BOOL bChanged = FALSE;
02006     sGA * pGA = (sGA *)(&pDev[1]);
02007
02008     if (bInputButtonPushedOnce(ENC_BTN) == TRUE)
02009     {
02010         // Change the port value of the GA:
02011         pGA->u8Value = !(pGA->u8Value);
02012         InputButtonReset(ENC_BTN);
02013         bChanged = TRUE;
02014     }
02015     if (bInputEncoderValueChanged() == TRUE)
02016     {
02017         SRCP_PRM prm;
02018         BYTE i = 0;
02019
02020         // Switch to another port!
02021         pGA->u8Port = (BYTE) s16InputEncoderGetValue();
02022         pDev->eDevState = SRCP_DS_UNKNOWN;
02023         pDev->sFlags.bNewData = TRUE;
02024     }
02025
02026     return bChanged;
02027 }
02028
02031
02032 static void _showServerError(WORD u16Code)
02033 {
02034     StrTbl_GetString(lcdram_row1, STRTBLID_SERVER_REPORTS);
02035     sprintf(lcdram_row2,
02036             StrTbl_cau8GetStringPointer(STRTBLID_ERRORCODE),
02037             u16Code);
02038     lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
02039                  LCD_ROW2_MASK | LCD_CENTER2_MASK;
02040
02041     OutSwitchOffAllLEDs();
02042 }
02043
02046
02047 static BOOL _bSendSRCPMessage(SRCP_COMMANDS eCommand, SRCP_DEVICE * pDev)
02048 {
02049     BYTE buf[50];
02050     BOOL bAddress = FALSE;
02051
02052     if (pDev==NULL)
02053     {
02054         return FALSE;
02055     }
02056
02057     // Check for undefined messages and devices....
02058     if ((eCommand==SRCP_CMD_INFO)||(pDev->eDevType==SRCP_DT_NOT_DEFINED))
02059     {
02060         return FALSE;
02061     }
02062
02063     // Is there already a SRCP message in progress?
02064     if (_bSrvReqIsInProgress==TRUE)
02065     {
02066         return FALSE;
02067     }
02068
02069     // Check for a free TCP channel.
02070     if (!TCPIsPutReady(_sSRCPState.sCommand.u8Socket))
02071     {
02072         return FALSE;
02073     }
02074
02075     // Step 1: Transfer the message string.
02076     switch(eCommand)
02077     {
02078         case SRCP_CMD_GET:
02079             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"GET");
02080             break;
02081
02082         case SRCP_CMD_SET:
02083             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"SET");
02084             break;
02085
02086         case SRCP_CMD_INIT:
02087             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"INIT");
02088             break;
02089
02090         case SRCP_CMD_TERM:
02091             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"TERM");
02092             break;
02093
02094         case SRCP_CMD_CHECK:
02095             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"CHECK");
02096             break;
02097
02098         case SRCP_CMD_WAIT:
02099             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"WAIT");
02100             break;
02101
02102         case SRCP_CMD_RESET:
02103             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"RESET");
02104             break;
02105     }
02106
02107
02108     // Step 2: Transfer the bus number.
02109     sprintf(buf, (ROM char *) " %hhu ", pDev->u8Bus);
02110     TCPPutString(_sSRCPState.sCommand.u8Socket, buf);
02111
02112
02113     // Step 3: Transfer the device type string.
02114     bAddress = _bDevTypeTCP(pDev->eDevType, eCommand);
02115
02116
02117     // Step 4: Check for the lock device and transfer the device type to lock.
02118     if (pDev->eDevType == SRCP_DT_LOCK)
02119     {
02120         sLock * pLock = (sLock *)(&pDev[1]);
02121         TCPPut(_sSRCPState.sCommand.u8Socket, ' ');
02122         bAddress = _bDevTypeTCP(pLock->eDevType, eCommand);
02123     }
02124
02125
02126     // Step 5: Transfer the address.
02127     if (bAddress == TRUE)
02128     {
02129         // The address is always located at the same field position regardless
02130         // of the device type.
02131         sprintf(buf, (ROM char *) " %lu", _u32GetAddress(pDev));
02132         TCPPutString(_sSRCPState.sCommand.u8Socket, buf);
02133     }
02134
02135
02136     // Step 6: Generate a parameter list (if necessary).
02137     buf[0] = 0;     // Clear the working buffer.
02138     switch(pDev->eDevType)
02139     {
02140         case SRCP_DT_GL:
02141         {
02142             sGL * pGL = (sGL *)(&pDev[1]);
02143             if (eCommand==SRCP_CMD_INIT)
02144             {
02145                 _getInitData(pDev, buf);
02146             }
02147             else if ((eCommand==SRCP_CMD_CHECK)||(eCommand==SRCP_CMD_SET))
02148             {
02149                 DWORD mask = pGL->u32FuncBitField;
02150                 BYTE i = pGL->sGLFlags.u2Dir;
02151                 BYTE bufindex = sprintf(buf, (ROM char *) "%hhu %hu %hu", i, pGL->s16ActV, pGL->u8MaxSteps);
02152
02153                 for (i=0; i < pGL->u8NrFunc; i++)
02154                 {
02155                     if (mask &0x01)
02156                     {
02157                         strcpypgm2ram(&buf[bufindex], (ROM char *)" 1");
02158                     }
02159                     else
02160                     {
02161                         strcpypgm2ram(&buf[bufindex], (ROM char *)" 0");
02162                     }
02163                     mask = mask >> 1;
02164                     bufindex+=2;
02165                 }
02166             }
02167             break;
02168         }
02169
02170         case SRCP_DT_GA:
02171         {
02172             sGA * pGA = (sGA *)(&pDev[1]);
02173             if (eCommand == SRCP_CMD_INIT)
02174             {
02175                 _getInitData(pDev, buf);
02176             }
02177             else if (eCommand==SRCP_CMD_GET)
02178             {
02179                 sprintf(buf, (ROM char *) "%hhu", pGA->u8Port);
02180             }
02181             else if ((eCommand==SRCP_CMD_CHECK)||(eCommand==SRCP_CMD_SET))
02182             {
02183                 LONG delay = 1;
02184                 if (pGA->u8Value)
02185                 {
02186                     delay = pGA->s32Delay;
02187                 }
02188
02189                 sprintf(buf, (ROM char *)"%hhu %hhu %ld", pGA->u8Port, pGA->u8Value, delay);
02190             }
02191             break;
02192         }
02193
02194         case SRCP_DT_POWER:
02195             if (eCommand == SRCP_CMD_SET)
02196             {
02197                 sPower * pPwr = (sPower*)(&pDev[1]);
02198                 if (pPwr->bPowerState == TRUE)
02199                 {
02200                     strcpypgm2ram(buf, (ROM char *)"ON");
02201                 }
02202                 else
02203                 {
02204                     strcpypgm2ram(buf, (ROM char *)"OFF");
02205                 }
02206             }
02207             break;
02208
02209         case SRCP_DT_LOCK:
02210             if (eCommand == SRCP_CMD_SET)
02211             {
02212                 sLock * pLock = (sLock *)(&pDev[1]);
02213                 sprintf(buf, (ROM char *) " %u", pLock->u32Duration);
02214             }
02215             break;
02216
02217         // ToDo:
02218         // Add the parameter lists for other devices like FB and SM.
02219     }
02220
02221
02222     if (strlen(buf))
02223     {
02224         TCPPut(_sSRCPState.sCommand.u8Socket, ' ');
02225         TCPPutString(_sSRCPState.sCommand.u8Socket, buf);
02226     }
02227
02228
02229
02230     // Step 7: Complete the transfer with linefeed and flush.
02231     TCPPut(_sSRCPState.sCommand.u8Socket, '\n');
02232     TCPFlush(_sSRCPState.sCommand.u8Socket);
02233
02234     // Remember the last sent command (which command from which device)
02235     _eLastSentCommand = eCommand;
02236     _pLastCommandDevice = pDev;
02237     _bSrvReqIsInProgress = TRUE;
02238     _bServerRequestTime = TickGet() + 2 * TICKS_PER_SECOND;
02239
02240     return TRUE;
02241 }
02242
02245
02246 static BOOL _bDevTypeTCP(SRCP_DEVTYPE eDevType, SRCP_COMMANDS eCommand)
02247 {
02248     if (eCommand == SRCP_CMD_GETDESC)
02249     {
02250         TCPPutROMString(_sSRCPState.sCommand.u8Socket,
02251                         (ROM char *)"DESCRIPTION");
02252     }
02253
02254     switch(eDevType)
02255     {
02256         case SRCP_DT_GL:
02257             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char*)"GL");
02258             return TRUE;    // Address is needed.
02259
02260         case SRCP_DT_GA:
02261             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"GA");
02262             return TRUE;    // Address is needed.
02263
02264         case SRCP_DT_POWER:
02265             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"POWER");
02266             break;
02267
02268         case SRCP_DT_LOCK:
02269             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"LOCK");
02270             break;
02271
02272         case SRCP_DT_SM:
02273             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"SM");
02274             if ((eCommand == SRCP_CMD_SET)||
02275                 (eCommand == SRCP_CMD_CHECK)||
02276                 (eCommand == SRCP_CMD_GET)||
02277                 (eCommand == SRCP_CMD_VERIFY))
02278             {
02279                 return TRUE;    // Address is needed.
02280             }
02281             break;
02282
02283         case SRCP_DT_FB:
02284             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"FB");
02285             if ((eCommand == SRCP_CMD_WAIT)||
02286                 (eCommand == SRCP_CMD_GET))
02287             {
02288                 return TRUE;    // Address is needed.
02289             }
02290             break;
02291
02292         case SRCP_DT_TIME:
02293             TCPPutROMString(_sSRCPState.sCommand.u8Socket, (ROM char *)"TIME");
02294             break;
02295
02296         case SRCP_DT_SERVER:
02297             TCPPutROMString(_sSRCPState.sCommand.u8Socket,(ROM char *)"SERVER");
02298             break;
02299
02300         case SRCP_DT_SESSION:
02301             TCPPutROMString(_sSRCPState.sCommand.u8Socket,(ROM char*)"SESSION");
02302             return TRUE;    // Address is needed.
02303
02304         case SRCP_DT_DESCRIPTION:
02305             TCPPutROMString(_sSRCPState.sCommand.u8Socket,
02306                                                     (ROM char *)"DESCRIPTION");
02307             break;
02308     }
02309
02310     return FALSE;
02311 }
02312
02313 // ////////////////////////////////////////////////////////////////////////////
02314 // ////////////////////////////////////////////////////////////////////////////
02315
02316 /*
02317 When calling this function, the caller must ensure that received packet is
02318 definitly for this device! That is not checked here!
02319 This function processes the packet and handles the state transitions caused
02320 due the packet code.
02321 */
02322 static void _answerReceived(SRCP_DEVICE *pDev, WORD u16Code, SRCP_TIME * pTime)
02323 {
02324     if ((pDev == NULL) || (pDev->eDevState == SRCP_DS_DISABLED))
02325     {
02326         return;
02327     }
02328
02329
02330     // If the time of the message is older than the last update than we are
02331     // doing nothing.
02332     if (pDev->sLastUpdate.u32Seconds > pTime->u32Seconds)
02333     {
02334         return;
02335     }
02336
02337     if ((pDev->sLastUpdate.u32Seconds == pTime->u32Seconds) &&
02338         (pDev->sLastUpdate.u16Milliseconds > pTime->u16Milliseconds))
02339     {
02340         return;
02341     }
02342
02343     // Remember the time of this message
02344     pDev->sLastUpdate.u32Seconds = pTime->u32Seconds;
02345     pDev->sLastUpdate.u16Milliseconds = pTime->u16Milliseconds;
02346
02347     switch(u16Code)
02348     {
02349         // 100 (After INIT), 101
02350         // This INFO codes has the meaning of an existing device. The server
02351         // knows the (initialized) device and sends the parameters of this
02352         // device. The device state machine is always IDLE than.
02353         case 100:
02354         case 101:
02355             pDev->eDevState = SRCP_DS_IDLE;
02356             break;
02357
02358         // 102 (After TERM). The server does not know this device anymore.
02359         case 102:
02360             pDev->eDevState = SRCP_DS_DISABLED;
02361             break;
02362
02363         // 200 (After any successful executed command).
02364         case 200:
02365             // If it is OK to a TERM command, than the device is in an
02366             // uninitialized state.
02367             if(_eLastSentCommand == SRCP_CMD_TERM)
02368             {
02369                 pDev->eDevState = SRCP_DS_DISABLED;
02370             }
02371             // If it is OK to a INIT command, than the device is in the
02372             // idle (initialized) state.
02373             else if(_eLastSentCommand == SRCP_CMD_INIT)
02374             {
02375                 pDev->sFlags.bNewData = TRUE;   // To ensure that the view is refreshed.
02376                 pDev->eDevState = SRCP_DS_IDLE;
02377             }
02378             break;
02379
02380         case 416:
02381             // ERROR no data
02382             // no information at all is available.
02383             if (_eLastSentCommand == SRCP_CMD_GET)
02384             {
02385                 pDev->eDevState = SRCP_DS_NOT_DEFINED;
02386                 break;
02387             }
02388
02389         default:
02390             // Action:
02391             // Store this error in the structure.
02392             pDev->u16LastErrorCode = u16Code;
02393             pDev->eDevState = SRCP_DS_DISABLED;
02394     }
02395 }
02396
02397 // ////////////////////////////////////////////////////////////////////////////
02398 // ////////////////////////////////////////////////////////////////////////////
02399
02400 static void _deviceSM(SRCP_DEVICE * pDev)
02401 {
02402     // This state machine includes no state transitions.
02403     // All the actions are done state related.
02404     // Precondition for calling this function: The command socket must be free!
02405
02406     if (pDev == NULL)
02407     {
02408         return;
02409     }
02410
02411     switch(pDev->eDevState)
02412     {
02413     case SRCP_DS_UNKNOWN:
02414         _bSendSRCPMessage(SRCP_CMD_GET, pDev);
02415         // The answer to this message results in a state change processed by
02416         // the function _answerReceived.
02417         break;
02418
02419     case SRCP_DS_NOT_DEFINED:
02420         // Synchronized with server, the server does not know anything about
02421         // this device... Try to initialize the device.
02422         if (_bIsInitAllowed(pDev->eDevType)&&(pDev->u16LastErrorCode==0))
02423         {
02424             _bSendSRCPMessage(SRCP_CMD_INIT, pDev);
02425         }
02426         break;
02427
02428     case SRCP_DS_IDLE:
02429         // Add some generic idle handler code here.
02430         break;
02431     }
02432 }
02433
02434 // ////////////////////////////////////////////////////////////////////////////
02435 // ////////////////////////////////////////////////////////////////////////////
02436
02437 static void _updateData(SRCP_DEVICE * pDev, WORD u16Code, SRCP_PRM * pNewPrm)
02438 {
02439     BYTE size;
02440
02441     if (pDev == NULL)
02442     {
02443         return;
02444     }
02445
02446     // Only INFO (GET replies) messages will be checked here.
02447     if (u16Code != 100)
02448     {
02449         return;
02450     }
02451
02452     switch(pDev->eDevType)
02453     {
02454     case SRCP_DT_GL:
02455     {
02456         sGL * pGL = (sGL *)(&pDev[1]);
02457         DWORD mask;
02458         DWORD funcmask;
02459
02460         // Speed handling...
02461
02462         // Set the local maximum speed step to that from server.
02463         pGL->u8MaxSteps = pNewPrm->uStat.sGL.s16MaxV;
02464
02465         // The element 's16ServerV' is always consistent with the server.
02466         pGL->s16ServerV = pNewPrm->uDyn.sGL.s16ActV;
02467
02468         if (IsEncoderTurning() == FALSE)
02469         {
02470             pGL->s16ActV = pGL->s16ServerV;
02471         }
02472
02473         if (pGL->sGLFlags.u2Dir != (pNewPrm->uDyn.sGL.u8Dir & 0x03))
02474         {
02475             pGL->sGLFlags.u2Dir = pNewPrm->uDyn.sGL.u8Dir & 0x03;
02476         }
02477
02478         mask = pGL->u32FuncAllocMask & pNewPrm->uStat.sGL.u32FuncAllocMask;
02479
02480         funcmask=mask&(pGL->u32FuncBitField^pNewPrm->uDyn.sGL.u32FuncBitField);
02481
02482         if (mask & (pGL->u32FuncBitField ^ pNewPrm->uDyn.sGL.u32FuncBitField))
02483         {
02484             pGL->u32FuncBitField &= ~mask;
02485             pGL->u32FuncBitField |= mask & pNewPrm->uDyn.sGL.u32FuncBitField;
02486         }
02487
02488         pDev->sFlags.bNewData = TRUE;
02489
02490         break;
02491     }
02492
02493     case SRCP_DT_GA:
02494         {
02495             sGA * pGA = (sGA *)(&pDev[1]);
02496             if (pGA->u8Value != pNewPrm->uDyn.sGA.u8Value)
02497             {
02498                 pDev->sFlags.bNewData = TRUE;
02499                 pGA->u8Value = pNewPrm->uDyn.sGA.u8Value;
02500             }
02501             break;
02502         }
02503     case SRCP_DT_POWER:
02504         {
02505             sPower * pPwr = (sPower *)(&pDev[1]);
02506             if (pPwr->bPowerState != pNewPrm->uDyn.bPowerState)
02507             {
02508                 pDev->sFlags.bNewData = TRUE;
02509                 pPwr->bPowerState = pNewPrm->uDyn.bPowerState;
02510             }
02511             break;
02512         }
02513     }
02514 }
02515
02516 // ////////////////////////////////////////////////////////////////////////////
02517 // ////////////////////////////////////////////////////////////////////////////
02518
02519 static BOOL _bIsDeviceMatching(SRCP_DEVICE * psDevice, SRCP_PRM * pPrm)
02520 {
02521     BYTE size;
02522     void * pSrcPrm;
02523
02524     if ((psDevice == NULL) || (pPrm == NULL))
02525     {
02526         return FALSE;
02527     }
02528
02529     if (psDevice->eDevType != pPrm->eDevType)
02530     {
02531         return FALSE;
02532     }
02533
02534     if (psDevice->u8Bus != pPrm->u8Bus)
02535     {
02536         return FALSE;
02537     }
02538
02539     if (psDevice->eDevState == SRCP_DS_DISABLED)
02540     {
02541         return FALSE;
02542     }
02543
02544     // Check the device dependent parameters.
02545     if (pPrm->eDevType == SRCP_DT_POWER)
02546     {
02547         return TRUE;
02548     }
02549
02550     pSrcPrm = (void *)(&psDevice[1]);
02551
02552     switch(pPrm->eDevType)
02553     {
02554     case SRCP_DT_LOCK:
02555         {
02556             sLock * pLockSrc = (sLock *)pSrcPrm;
02557
02558             if (pPrm->uStat.sLock.eDevType != pLockSrc->eDevType)
02559             {
02560                 return FALSE;
02561             }
02562
02563             if (pPrm->uStat.sLock.u32Addr != pLockSrc->u32Addr)
02564             {
02565                 return FALSE;
02566             }
02567         }
02568         break;
02569
02570     case SRCP_DT_GA:
02571         {
02572             sGA * pGASrc = (sGA *)pSrcPrm;
02573
02574             if (pPrm->uStat.sGA.u8Port != pGASrc->u8Port)
02575             {
02576                 return FALSE;
02577             }
02578
02579             if (pPrm->uStat.sGA.u32Addr != pGASrc->u32Addr)
02580             {
02581                 return FALSE;
02582             }
02583         }
02584         break;
02585
02586     case SRCP_DT_GL:
02587         {
02588             sGL * pGLSrc = (sGL *)pSrcPrm;
02589
02590             if (pPrm->uStat.sGL.u32Addr != pGLSrc->u32Addr)
02591             {
02592                 return FALSE;
02593             }
02594         }
02595         break;
02596     }
02597
02598     return TRUE;
02599 }
02600
02601 // ////////////////////////////////////////////////////////////////////////////
02602 // ////////////////////////////////////////////////////////////////////////////
02603
02604 static SRCP_DEVICE * _pGetPowerDevice(BYTE u8Bus)
02605 {
02606     BYTE i;
02607     for (i = 0; i < MAX_SRCP_DEVICES; i++)
02608     {
02609         if (_apsDevices[i] && (u8Bus == _apsDevices[i]->u8Bus) &&
02610             (SRCP_DT_POWER == _apsDevices[i]->eDevType))
02611         {
02612             return _apsDevices[i];
02613         }
02614     }
02615
02616     // Not found!
02617     return NULL;
02618 }
02619
02620 // ////////////////////////////////////////////////////////////////////////////
02621 // ////////////////////////////////////////////////////////////////////////////
02622
02623 #define FREQUENT_SRCP_DEVICE_OFFSET     2
02624
02625 static SRCP_DEVICE* _psAddDevice(SRCP_DEVTYPE eDevType, BYTE u8Bus, void* pPrm)
02626 {
02627     BYTE i, j;
02628     DWORD checkAddress = 0;
02629
02630     if(pPrm == NULL)
02631     {
02632         return NULL;
02633     }
02634
02635     _refreshDeviceList();
02636
02637     if ((eDevType == SRCP_DT_GL)||(eDevType == SRCP_DT_GA)||(eDevType == SRCP_DT_LOCK))
02638     {
02639         checkAddress = *((DWORD *)(pPrm));
02640     }
02641
02642
02643     // Step 1: Check if the device is already in the list!
02644     for (i = FREQUENT_SRCP_DEVICE_OFFSET; i < MAX_SRCP_DEVICES; i++)
02645     {
02646         if (_apsDevices[i] == NULL)
02647         {
02648             // Empty device slot found, after refreshing the list it is the
02649             // last one!
02650             break;
02651         }
02652         if (_apsDevices[i]->u8Bus != u8Bus)
02653         {
02654             continue;
02655         }
02656         if (_apsDevices[i]->eDevType != eDevType)
02657         {
02658             continue;
02659         }
02660         if (_u32GetAddress(_apsDevices[i]) != checkAddress)
02661         {
02662             continue;
02663         }
02664
02665         // Device found!
02666         // Younger this device to prevent removing from device
02667         // list. Update the stack positions of all other devices.
02668
02669         if (i>FREQUENT_SRCP_DEVICE_OFFSET)
02670         {
02671             // Temporary store the pointer:
02672             SRCP_DEVICE * pDev = _apsDevices[i];
02673
02674             // Older all devices which were before the found device.
02675             for (j = i; j > FREQUENT_SRCP_DEVICE_OFFSET; j--)
02676             {
02677                 _apsDevices[j] = _apsDevices[j-1];
02678             }
02679
02680             _apsDevices[j] = pDev;
02681         }
02682
02683         return _apsDevices[j];
02684     }
02685
02686
02687     // Step 2: Free the oldest device in list.
02688     if (_apsDevices[MAX_SRCP_DEVICES-1])
02689     {
02690         SRAMfree((BYTE *)_apsDevices[MAX_SRCP_DEVICES-1]);
02691         _apsDevices[MAX_SRCP_DEVICES-1] = NULL;
02692     }
02693
02694
02695     // Step 3: Older all devices which were before the found device.
02696     for (j = (MAX_SRCP_DEVICES-1); j > FREQUENT_SRCP_DEVICE_OFFSET; j--)
02697     {
02698         _apsDevices[j] = _apsDevices[j-1];
02699     }
02700
02701
02702     // Step 4: Get a new device structure.
02703     _apsDevices[j] = _psInitializeNewDevice(eDevType, u8Bus, pPrm);
02704
02705     return _apsDevices[j];
02706 }
02707
02708 // ////////////////////////////////////////////////////////////////////////////
02709 // ////////////////////////////////////////////////////////////////////////////
02710
02711 static BOOL _startParsing(BYTE u8Socket, SRCP_TIME * psTime, WORD * pu16Code)
02712 {
02713     BYTE wb[16];
02714     BOOL end = FALSE;
02715
02716     if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02717     {
02718         // Get the time...
02719         char * pDot = strrchr(wb, '.');
02720         if (pDot)
02721         {
02722             *pDot++ = 0;
02723             psTime->u32Seconds = (DWORD) atol(wb);
02724             psTime->u16Milliseconds = (WORD) atoi(pDot);
02725         }
02726         else
02727         {
02728             goto _startParsingError;
02729         }
02730     }
02731     else
02732     {
02733         goto _startParsingError;
02734     }
02735
02736     if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02737     {
02738         *pu16Code = atoi(wb);
02739         if (*pu16Code == 110)
02740         {
02741             *pu16Code = 100;
02742         }
02743     }
02744     else
02745     {
02746         goto _startParsingError;
02747     }
02748
02749     // Throw away the message classification string. We just use the code
02750     // for checking the device states.
02751     if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02752     {
02753         return TRUE;
02754     }
02755
02756
02757 _startParsingError:
02758     if (end==FALSE)
02759     {
02760         // The end of line was not found. Look for the line end (or the frame
02761         // end) in the remaining frame data. Maybe other lines will follow up.
02762         _bLookForEnd(u8Socket);
02763     }
02764     return FALSE;
02765 }
02766
02767 // ////////////////////////////////////////////////////////////////////////////
02768 // ////////////////////////////////////////////////////////////////////////////
02769
02770 static BOOL _bParseLine(BYTE u8Socket, WORD u16Code, SRCP_PRM * pPrm)
02771 {
02772     BYTE wb[16];
02773     BOOL end = FALSE;
02774     BOOL valid = FALSE;
02775     BOOL address = FALSE;
02776     memset(pPrm, 0, sizeof(SRCP_PRM));
02777
02778     // Only INFO messages store device related data.
02779     if (u16Code >= 200)
02780     {
02781         goto _parseForLineEnd;
02782     }
02783
02784
02785     // Step 1: Fetch the bus number from the received message.
02786     if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02787     {
02788         pPrm->u8Bus = (BYTE) atoi(wb);
02789     }
02790     else
02791     {
02792         goto _parseForLineEnd;
02793     }
02794
02795
02796     // Step 2: Fetch the device type string from the received message.
02797     if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end)==FALSE)
02798     {
02799         goto _parseForLineEnd;
02800     }
02801
02802     address = _bTCPDevType(u16Code, &pPrm->eDevType, wb);
02803
02804     if (pPrm->eDevType == SRCP_DT_NOT_DEFINED)
02805     {
02806         goto _parseForLineEnd;
02807     }
02808
02809
02810     // Step 3: Get the device if locked.
02811     if (pPrm->eDevType == SRCP_DT_LOCK)
02812     {
02813         if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end)==FALSE)
02814         {
02815             goto _parseForLineEnd;
02816         }
02817
02818         address = _bTCPDevType(u16Code, &pPrm->uStat.sLock.eDevType, wb);
02819
02820         if (pPrm->eDevType == SRCP_DT_NOT_DEFINED)
02821         {
02822             goto _parseForLineEnd;
02823         }
02824     }
02825
02826
02827     // Step 4: Parse for the address.
02828     if (address==TRUE)
02829     {
02830         if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end)==FALSE)
02831         {
02832             goto _parseForLineEnd;
02833         }
02834
02835         // All address parameters are at the same field position.
02836         pPrm->uStat.sGL.u32Addr = (DWORD) atol(wb);
02837     }
02838
02839
02840     // Step 5: Fetch the device type specific static and dynamic data from the
02841     // received message.
02842     if (u16Code == 101)
02843     {
02844         // Device is initialized! Maybe its worth parsing the line for our
02845         // server cache.
02846         if (pPrm->eDevType != SRCP_DT_GL)
02847         {
02848             // Only GL devices are currently stored in the cache.
02849             valid = TRUE;
02850             goto _parseForLineEnd;
02851         }
02852
02853         // Get the protocol specifier:
02854         if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02855         {
02856             // Only M and N protocols are supported at the moment.
02857             if ((wb[0] != 'N') && (wb[0] != 'M'))
02858             {
02859                 goto _parseForLineEnd;
02860             }
02861
02862             pPrm->uStat.sGL.au8Proto[0] = wb[0];
02863             pPrm->uStat.sGL.au8Proto[1] = ' ';
02864         }
02865
02866         // Get the protocol version:
02867         if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02868         {
02869             // Protocol version is not checked here!
02870             pPrm->uStat.sGL.au8Proto[2] = wb[0];
02871         }
02872
02873         // Get the number of decoder speed steps:
02874         if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02875         {
02876             pPrm->uStat.sGL.u8MaxSteps = atob(wb);
02877         }
02878
02879         // Get the number of decoder functions:
02880         if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02881         {
02882             pPrm->uStat.sGL.u8NrFunc = atob(wb);
02883         }
02884     }
02885
02886     if (u16Code != 100)
02887     {
02888         valid = TRUE;
02889         goto _parseForLineEnd;
02890     }
02891
02892
02893     switch(pPrm->eDevType)
02894     {
02895         case SRCP_DT_GL:
02896         {
02897             DWORD mask = 0x01;
02898             BYTE i;
02899
02900             // Get the drive mode.
02901             if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02902             {
02903                 pPrm->uDyn.sGL.u8Dir = atob(wb);
02904             }
02905
02906             // Get the actual speed.
02907             if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02908             {
02909                 pPrm->uDyn.sGL.s16ActV = atoi(wb);
02910             }
02911
02912             // Get the maximum speed.
02913             if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02914             {
02915                 pPrm->uStat.sGL.s16MaxV = atoi(wb);
02916             }
02917
02918             // Get the function values.
02919             for (i = 0; i < MAX_SRCP_FUNCTIONS; i++, mask=mask<<1)
02920             {
02921                 if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02922                 {
02923                     if (wb[0] == '=')
02924                     {
02925                         continue;
02926                     }
02927                     if (wb[0] == '1')
02928                     {
02929                         pPrm->uDyn.sGL.u32FuncBitField |= mask;
02930                     }
02931                     pPrm->uStat.sGL.u32FuncAllocMask |= mask;
02932                 }
02933                 else
02934                 {
02935                     break;
02936                 }
02937             }
02938             break;
02939         }
02940
02941         case SRCP_DT_GA:
02942             if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02943                 pPrm->uStat.sGA.u8Port = atob(wb);
02944
02945             if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end))
02946                 pPrm->uDyn.sGA.u8Value = atob(wb);
02947             break;
02948
02949         case SRCP_DT_POWER:
02950             if (_bGetNextWord(u8Socket, wb, sizeof(wb), &end)==FALSE)
02951                 goto _parseForLineEnd;
02952
02953             if (strncmppgm2ram(wb,(ROM char *)"ON",sizeof(wb)-1)==0)
02954                 pPrm->uDyn.bPowerState = TRUE;
02955             else
02956                 pPrm->uDyn.bPowerState = FALSE;
02957             break;
02958     }
02959
02960     valid = TRUE;
02961
02962 _parseForLineEnd:
02963     if (end==FALSE)
02964     {
02965         // The end of line was not found. Look for the line end (or the frame
02966         // end) in the remaining frame data.
02967         _bLookForEnd(u8Socket);
02968     }
02969     return valid;
02970 }
02971
02972 // ////////////////////////////////////////////////////////////////////////////
02973 // ////////////////////////////////////////////////////////////////////////////
02974
02975 static BOOL _bTCPDevType(WORD u16Code, SRCP_DEVTYPE * pDev, BYTE * au8Buf)
02976 {
02977     if (strcmppgm2ram(au8Buf,(ROM char *)"FB")==0)
02978     {
02979         *pDev = SRCP_DT_FB;
02980         if (u16Code==100)
02981             return TRUE;
02982     }
02983     else if (strcmppgm2ram(au8Buf,(ROM char *)"GA")==0)
02984     {
02985         *pDev = SRCP_DT_GA;
02986         return TRUE;
02987     }
02988     if (strcmppgm2ram(au8Buf, (ROM char *) "GL")== 0)
02989     {
02990         *pDev = SRCP_DT_GL;
02991         return TRUE;
02992     }
02993     else if (strcmppgm2ram(au8Buf,(ROM char *)"SM")==0)
02994     {
02995         *pDev = SRCP_DT_SM;
02996         if (u16Code==100)
02997             return TRUE;
02998     }
02999     else if (strcmppgm2ram(au8Buf,(ROM char *)"LOCK")==0)
03000         *pDev = SRCP_DT_LOCK;
03001     else if (strcmppgm2ram(au8Buf,(ROM char *)"POWER")==0)
03002         *pDev = SRCP_DT_POWER;
03003     else if (strcmppgm2ram(au8Buf,(ROM char *)"SESSION")==0)
03004     {
03005         *pDev = SRCP_DT_SESSION;
03006         return TRUE;
03007     }
03008     else if (strcmppgm2ram(au8Buf,(ROM char *)"DESCRIPTION")==0)
03009         *pDev = SRCP_DT_DESCRIPTION;
03010     else if (strcmppgm2ram(au8Buf,(ROM char *)"TIME")==0)
03011         *pDev = SRCP_DT_TIME;
03012     else if (strcmppgm2ram(au8Buf,(ROM char *)"SERVER")==0)
03013         *pDev = SRCP_DT_SERVER;
03014
03015     return FALSE;
03016 }
03017
03018 // ////////////////////////////////////////////////////////////////////////////
03019 // ////////////////////////////////////////////////////////////////////////////
03020
03021 static void _getProtoName(BYTE u8ProtoId, BYTE * pString)
03022 {
03023     // Get data from EEPROM!
03024     SPPROTOCOL conf;
03025     _getProtoFromEEPROM(u8ProtoId, &conf);
03026     strncpy(pString, conf.au8Desc, SRCP_NAME_MAXLEN);
03027     conf.au8Desc[SRCP_NAME_MAXLEN] = 0;
03028     OutConvertNameForDisplay(pString);
03029 }
03030
03031 // ////////////////////////////////////////////////////////////////////////////
03032 // ////////////////////////////////////////////////////////////////////////////
03033
03034 static BYTE _u8GenerateActiveProtoList(BOOL bGL, BYTE u8Default)
03035 {
03036     BYTE i = 0;
03037     BYTE protostart, protomax;
03038     BYTE count = 0;
03039     SPPROTOCOL conf;
03040
03041
03042     // Step 1: Get the device dependent margins for protocol.
03043     if (bGL == TRUE)
03044     {
03045         protostart = 0;
03046         protomax = MAX_PROTO_SLOTS;
03047     }
03048     else
03049     {
03050         protostart = MAX_PROTO_SLOTS;
03051         protomax = MAX_PROTO_SLOTS * 2;
03052     }
03053
03054
03055     // Step 2: Looking for the default protocol and add it to the list.
03056     if ((bGL == TRUE) && (u8Default == SRCP_SERVERCACHE_ID))
03057     {
03058         _au8ActiveProtos[count++] = SRCP_SERVERCACHE_ID;
03059     }
03060     else if (u8Default == SRCP_EEPROMSET_ID)
03061     {
03062         _au8ActiveProtos[count++] = SRCP_EEPROMSET_ID;
03063     }
03064     else
03065     {
03066         // Get data from EEPROM!
03067         _getProtoFromEEPROM(u8Default, &conf);
03068         if (conf.sFlags.bActive == TRUE)
03069         {
03070             _au8ActiveProtos[count++] = u8Default;
03071         }
03072     }
03073
03074
03075     if (u8Default != SRCP_EEPROMSET_ID)
03076     {
03077         _au8ActiveProtos[count++] = SRCP_EEPROMSET_ID;
03078     }
03079
03080     if ((bGL==TRUE)&&(u8Default != SRCP_SERVERCACHE_ID))
03081     {
03082         _au8ActiveProtos[count++] = SRCP_SERVERCACHE_ID;
03083     }
03084
03085
03086     for (i = protostart; i < protomax; i++)
03087     {
03088         if (u8Default == i)
03089         {
03090             // The default protocol is already in the list.
03091             continue;
03092         }
03093
03094         // Get data from EEPROM!
03095         _getProtoFromEEPROM(i, &conf);
03096
03097         if (conf.sFlags.bActive == TRUE)
03098         {
03099             _au8ActiveProtos[count++] = i;
03100         }
03101     }
03102
03103     return count;
03104 }
03105
03106 // ////////////////////////////////////////////////////////////////////////////
03107 // ////////////////////////////////////////////////////////////////////////////
03108
03109 static void _getProtoMinMax(BYTE u8ProtoId, WORD* pu16MinAdd, WORD* pu16MaxAdd)
03110 {
03111     // Get data from EEPROM!
03112     SPPROTOCOL conf;
03113     _getProtoFromEEPROM(u8ProtoId, &conf);
03114     *pu16MinAdd = conf.u16MinAdd;
03115     *pu16MaxAdd = conf.u16MaxAdd;
03116 }
03117
03118 // ////////////////////////////////////////////////////////////////////////////
03119 // ////////////////////////////////////////////////////////////////////////////
03120
03121 static BOOL _bGetStaticParameterFromCache(BYTE u8CacheId, sStaticDeviceData * psPrm)
03122 {
03123     if (_apsSelectCache == NULL)
03124     {
03125         PrintCommonError(COMMON_ERROR_NULL_POINTER);
03126         return FALSE;
03127     }
03128
03129     memset((void*)psPrm, 0, sizeof(sStaticDeviceData));
03130
03131
03132     // Copy proto data.
03133     strncpy(psPrm->au8Proto, _apsSelectCache[u8CacheId].au8Proto, SRCP_PROTO_MAXLEN);
03134     psPrm->u8BusNr = _apsSelectCache[u8CacheId].u8BusNr;
03135     psPrm->u32Address = _apsSelectCache[u8CacheId].u32Address;
03136     psPrm->uSpec.sGLSpec.u8MaxSteps = _apsSelectCache[u8CacheId].u8MaxSteps;
03137     psPrm->uSpec.sGLSpec.u8NrFunc = _apsSelectCache[u8CacheId].u8NrFunc;
03138
03139     return TRUE;
03140 }
03141
03142 // ////////////////////////////////////////////////////////////////////////////
03143 // ////////////////////////////////////////////////////////////////////////////
03144
03145 static void _destructServerCache(void)
03146 {
03147     if (_apsSelectCache)
03148     {
03149         SRAMfree((BYTE*)_apsSelectCache);
03150         _apsSelectCache = NULL;
03151     }
03152 }
03153
03154 // ////////////////////////////////////////////////////////////////////////////
03155 // ////////////////////////////////////////////////////////////////////////////
03156
03157 static BOOL _bGetStaticParameterFromProto(BYTE u8ProtoId, sStaticDeviceData * psPrm)
03158 {
03159     SPPROTOCOL conf;
03160
03161     // Get data from EEPROM!
03162     _getProtoFromEEPROM(u8ProtoId, &conf);
03163
03164     if ((conf.sFlags.bActive == FALSE)||(psPrm == NULL))
03165     {
03166         PrintCommonError(COMMON_ERROR_LOADING_SRCP_PROTOCOL);
03167         return FALSE;
03168     }
03169
03170     memset((void*)psPrm, 0, sizeof(sStaticDeviceData));
03171
03172     // Copy proto data.
03173     strncpy(psPrm->au8Proto, conf.au8Proto, SRCP_PROTO_MAXLEN);
03174     psPrm->u8BusNr = conf.u8Bus;
03175
03176     if (conf.sFlags.bGL == TRUE)
03177     {
03178         psPrm->uSpec.sGLSpec.u8MaxSteps = conf.uSpec.sGL.u8MaxSteps;
03179         psPrm->uSpec.sGLSpec.u8NrFunc = conf.uSpec.sGL.u8NrFunc;
03180     }
03181     else
03182     {
03183         psPrm->uSpec.sGASpec.u8MinP = conf.uSpec.sGA.u8MinP;
03184         psPrm->uSpec.sGASpec.u8MaxP = conf.uSpec.sGA.u8MaxP;
03185     }
03186
03187     return TRUE;
03188 }
03189
03190 // ////////////////////////////////////////////////////////////////////////////
03191 // ////////////////////////////////////////////////////////////////////////////
03192
03193 static void _fillPrmGL(sGL * psNewGL, sStaticDeviceData * psStaticData)
03194 {
03195     if ((psNewGL == NULL) || (psStaticData == NULL))
03196     {
03197         return;
03198     }
03199
03200     memset(psNewGL, 0, sizeof(sGL));
03201
03202     // Copy the proto data into the device structure:
03203     strncpy(psNewGL->au8Proto, psStaticData->au8Proto, SRCP_PROTO_MAXLEN);
03204     strncpy(psNewGL->au8Name, psStaticData->au8Name, SRCP_NAME_MAXLEN);
03205     psNewGL->u32Addr = psStaticData->u32Address;
03206     psNewGL->u8MaxSteps = psStaticData->uSpec.sGLSpec.u8MaxSteps;
03207     psNewGL->u8NrFunc = psStaticData->uSpec.sGLSpec.u8NrFunc;
03208     psNewGL->s16MaxV = psStaticData->uSpec.sGLSpec.u16MaxV;
03209
03210     // Prepare other stuff like function mask and so on.
03211     {
03212         BYTE i = 0;
03213         DWORD mask = 0x01;
03214
03215         for (i = 0; i < MAX_SRCP_FUNCTIONS, i < psNewGL->u8NrFunc; i++, mask=mask<<1)
03216         {
03217             psNewGL->u32FuncAllocMask |= mask;
03218         }
03219
03220         psNewGL->u32FuncToggleMask = psStaticData->uSpec.sGLSpec.u32FunctionToggleMask;
03221     }
03222
03223     if (psNewGL->s16MaxV == 0)
03224     {
03225         psNewGL->s16MaxV = psNewGL->u8MaxSteps;
03226     }
03227     else
03228     {
03229         // Show a unit if a maximum speed is configured.
03230         psNewGL->sGLFlags.bUnit = TRUE;
03231     }
03232
03233     psNewGL->sGLFlags.u2Dir = DIR_FORWARD;
03234 }
03235
03236 // ////////////////////////////////////////////////////////////////////////////
03237 // ////////////////////////////////////////////////////////////////////////////
03238
03239 static void _fillPrmGA(sGA * psNewGA, sStaticDeviceData * psStaticData)
03240 {
03241     if ((psNewGA == NULL) || (psStaticData == NULL))
03242     {
03243         return;
03244     }
03245
03246     memset(psNewGA, 0, sizeof(sGA));
03247
03248     // Copy the proto data into the device structure:
03249     strncpy(psNewGA->au8Name, psStaticData->au8Name, SRCP_NAME_MAXLEN);
03250     strncpy(psNewGA->au8Proto, psStaticData->au8Proto, SRCP_PROTO_MAXLEN);
03251     psNewGA->u32Addr = psStaticData->u32Address;
03252     psNewGA->u8MinPort = psStaticData->uSpec.sGASpec.u8MinP;
03253     psNewGA->u8MaxPort = psStaticData->uSpec.sGASpec.u8MaxP;
03254
03255     if (psStaticData->uSpec.sGASpec.s32Delay == 0)
03256     {
03257         psNewGA->s32Delay = sPSRCPConfig.s32GADelay;
03258     }
03259     else
03260     {
03261         psNewGA->s32Delay = psStaticData->uSpec.sGASpec.s32Delay;
03262     }
03263
03264     psNewGA->u8Port = psNewGA->u8MinPort;
03265 }
03266
03267 // ////////////////////////////////////////////////////////////////////////////
03268 // ////////////////////////////////////////////////////////////////////////////
03269
03270 static void _getInitData(SRCP_DEVICE * pDev, char * pString)
03271 {
03272     if (pDev == NULL)
03273     {
03274         pString[0] = 0;
03275         return;
03276     }
03277
03278     if (pDev->eDevType == SRCP_DT_GA)
03279     {
03280         sGA * pGA = (sGA *)(&pDev[1]);
03281         strcpy(pString, pGA->au8Proto);
03282     }
03283     else if (pDev->eDevType == SRCP_DT_GL)
03284     {
03285         sGL * pGL = (sGL *)(&pDev[1]);
03286         strcpy(pString, pGL->au8Proto);
03287
03288         if (strrchr(pString,'M') || strrchr(pString,'N'))
03289         {
03290             // Add parameters (max speed steps and number of functions) to the
03291             // initialization string if it is a NMRA or Motorola Decoder like
03292             // described in the SRCP Spec.
03293             sprintf(&pString[strlen(pString)],(ROM char *)" %hhu %hhu", pGL->u8MaxSteps, pGL->u8NrFunc);
03294         }
03295     }
03296 }
03297
03298 // ////////////////////////////////////////////////////////////////////////////
03299 // ////////////////////////////////////////////////////////////////////////////
03300
03301 void _startHandShake(void)
03302 {
03303     _eHSState = SRCP_HS_WAIT_FOR_WELCOME;
03304 }
03305
03306 // ////////////////////////////////////////////////////////////////////////////
03308 // ////////////////////////////////////////////////////////////////////////////
03309
03310 SRCP_HANDSHAKE_RETCODE _eHandShake(SSRCPSOCKET * hSRCP)
03311 {
03312     BYTE socket = hSRCP->u8Socket;
03313     WORD code = 0;
03314     SRCP_TIME time;
03315
03316     switch (_eHSState)
03317     {
03318     case SRCP_HS_WAIT_FOR_WELCOME:
03319
03320         // For the welcome message we can not use the SRCP parse functions
03321         // because the message format is completly different.
03322
03323         if (TCPIsGetReady(socket))
03324         {
03325             // received a frame...
03326             BYTE buf[11];
03327             BOOL end = FALSE;
03328             BOOL valid = FALSE;
03329
03330             // We still wait for the welcome message with the supported
03331             // SRCP versions of the server.
03332             while (_bGetNextWord(socket,buf,sizeof(buf),&end))
03333             {
03334                 // Looking for the keyword SRCP or SRCPOTHER. The value of
03335                 // this key (the following SRCP word) is the supported
03336                 // version.
03337                 if ((strncmppgm2ram(buf, (ROM char *) "SRCP", 10)==0)||
03338                     (strncmppgm2ram(buf, (ROM char *) "SRCPOTHER", 10)==0))
03339                 {
03340                     if(_bGetNextWord(socket,buf,10,&end)==FALSE)
03341                     {
03342                         break;
03343                     }
03344
03345                     // eWicht only supports SRCP version 0.8 at this
03346                     // time. Add more code here for other versions.
03347                     if (strncmppgm2ram(buf,(ROM char *)"0.8",3)==0)
03348                     {
03349                         valid = TRUE;
03350                         break;
03351                     }
03352                 }
03353             }
03354
03355             if (valid == TRUE)
03356             {
03357                 // eWicht supports this server version, got to the next
03358                 // state.
03359                 _eHSState = SRCP_HS_SET_VERSION;
03360             }
03361             else
03362             {
03363                 // Unsupported SCRP version, close this session.
03364                 StrTbl_GetString(lcdram_row1, STRTBLID_SERVERVERSION);
03365                 StrTbl_GetString(lcdram_row2, STRTBLID_UNKNOWN);
03366                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03367                              LCD_ROW2_MASK | LCD_CENTER2_MASK;
03368                 _eHSState = SRCP_HS_ERROR;
03369             }
03370
03371             TCPDiscard(socket);
03372         }
03373         break;
03374
03375     case SRCP_HS_SET_VERSION:
03376         if (TCPIsPutReady(socket))
03377         {
03378             // Send the SRCP version to server. As we have seen in the welcome
03379             // message, the server supports it, but we explicitly send the set
03380             // message to prevent errors.
03381             TCPPutROMString(socket, (ROM char *) "SET PROTOCOL SRCP 0.8\n");
03382             TCPFlush(socket);
03383
03384             _eHSState = SRCP_HS_WAIT_VERSION;
03385         }
03386         break;
03387
03388     case SRCP_HS_SET_MODE:
03389         if (TCPIsPutReady(socket))
03390         {
03391             // Send the SRCP connection mode to server.
03392             // It depends on the socket given to this function.
03393
03394             TCPPutROMString(socket, (ROM char*) "SET CONNECTIONMODE SRCP ");
03395             if (hSRCP->bCommand == TRUE)
03396                 TCPPutROMString(socket, (ROM char*) "COMMAND\n");
03397             else
03398                 TCPPutROMString(socket, (ROM char*) "INFO\n");
03399             TCPFlush(socket);
03400
03401             _eHSState = SRCP_HS_WAIT_MODE;
03402         }
03403         break;
03404
03405     case SRCP_HS_GO:
03406         if (TCPIsPutReady(hSRCP->u8Socket))
03407         {
03408             TCPPutROMString(hSRCP->u8Socket, (ROM char *) "GO\n");
03409             TCPFlush(hSRCP->u8Socket);
03410
03411             _eHSState = SRCP_HS_WAIT_GO;
03412         }
03413         break;
03414
03415     case SRCP_HS_WAIT_VERSION:
03416     case SRCP_HS_WAIT_MODE:
03417     case SRCP_HS_WAIT_GO:
03418     {
03419         BOOL ret;
03420         if (TCPIsGetReady(socket)==0)
03421             break;
03422
03423         // received a frame...
03424         ret = _startParsing(socket, &time, &code);
03425         TCPDiscard(socket);
03426         if (ret==FALSE)
03427             break;
03428
03429         switch(code)
03430         {
03431             case 200:
03432                 _eHSState = SRCP_HS_GOING;
03433                 break;
03434
03435             case 201:
03436                 _eHSState = SRCP_HS_SET_MODE;
03437                 break;
03438
03439             case 202:
03440                 _eHSState = SRCP_HS_GO;
03441                 break;
03442
03443             case 400:
03444                 // Oops! The server says in its welcome message, that
03445                 // he supports this SRCP version but than the server
03446                 // NAKs the explicitly version set?! Sounds like an
03447                 // implementation error in the server...
03448                 StrTbl_GetString(lcdram_row1, STRTBLID_SRVVERSION);
03449                 StrTbl_GetString(lcdram_row2, STRTBLID_UNKNOWN);
03450                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03451                              LCD_ROW2_MASK | LCD_CENTER2_MASK;
03452                 _eHSState = SRCP_HS_ERROR;
03453                 break;
03454
03455             case 401:
03456                 StrTbl_GetString(lcdram_row1, STRTBLID_SRVMODE);
03457                 StrTbl_GetString(lcdram_row2, STRTBLID_UNKNOWN);
03458                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03459                              LCD_ROW2_MASK | LCD_CENTER2_MASK;
03460                 _eHSState = SRCP_HS_ERROR;
03461                 break;
03462
03463             case 402:
03464                 StrTbl_GetString(lcdram_row1, STRTBLID_SRVUNSUFFICIENT_DATA1);
03465                 StrTbl_GetString(lcdram_row2, STRTBLID_SRVUNSUFFICIENT_DATA2);
03466                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03467                              LCD_ROW2_MASK | LCD_CENTER2_MASK;
03468                 _eHSState = SRCP_HS_ERROR;
03469                 break;
03470
03471             case 403:
03472                 StrTbl_GetString(lcdram_row1, STRTBLID_SRVUNKNOWN_COMMAND1);
03473                 StrTbl_GetString(lcdram_row2, STRTBLID_SRVUNKNOWN_COMMAND2);
03474                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03475                              LCD_ROW2_MASK | LCD_CENTER2_MASK;
03476                 _eHSState = SRCP_HS_ERROR;
03477                 break;
03478
03479             case 500:
03480                 StrTbl_GetString(lcdram_row1, STRTBLID_SRVNO_RESSOURCES1);
03481                 StrTbl_GetString(lcdram_row2, STRTBLID_SRVNO_RESSOURCES2);
03482                 lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03483                              LCD_ROW2_MASK | LCD_CENTER2_MASK;
03484                 _eHSState = SRCP_HS_ERROR;
03485                 break;
03486         }
03487         break;
03488     }
03489
03490     case SRCP_HS_ERROR:
03491         return SRCP_HR_ERROR;
03492
03493     case SRCP_HS_GOING:
03494         return SRCP_HR_FINISHED;
03495     }
03496
03497     return SRCP_HR_IN_PROGRESS;
03498 }
03499
03500 // ////////////////////////////////////////////////////////////////////////////
03501 // ////////////////////////////////////////////////////////////////////////////
03502
03503 static BOOL _bIsInitAllowed(SRCP_DEVTYPE eDevType)
03504 {
03505     if ((eDevType==SRCP_DT_SESSION)||
03506         (eDevType==SRCP_DT_SERVER)||
03507         (eDevType==SRCP_DT_DESCRIPTION)||
03508         (eDevType==SRCP_DT_LOCK))
03509     {
03510         return FALSE;
03511     }
03512
03513     return TRUE;
03514 }
03515
03516 // ////////////////////////////////////////////////////////////////////////////
03517 // ////////////////////////////////////////////////////////////////////////////
03518
03519 static void _updateInput(SRCP_DEVICE * pDev)
03520 {
03521     // Is there a configured device for input?
03522     if (pDev == NULL)
03523     {
03524         return;     // No!
03525     }
03526
03527     if (pDev->eDevState == SRCP_DS_DISABLED)
03528     {
03529         return;
03530     }
03531
03532     // Is a server request already running?
03533     if (_bSrvReqIsInProgress == TRUE)
03534     {
03535         return;
03536     }
03537
03538     if (pDev->eDevType == SRCP_DT_GL)
03539     {
03540         sGL tmp;
03541         sGL * pGL = (sGL *)(&pDev[1]);
03542
03543         // Temporary save the server consistent data.
03544         memcpy((void*)&tmp, (void*)pGL, sizeof(sGL));
03545
03546         if (_bGetGLInput(pGL) == TRUE)
03547         {
03548             tmp.s16ActV = pGL->s16ActV;
03549             tmp.u8FuncGroup = pGL->u8FuncGroup;
03550
03551             _bSendSRCPMessage(SRCP_CMD_SET, pDev);
03552
03553             // Restore the old data to stay consistent with the server.
03554             // The recently sent data will processed by the server and comes
03555             // back via an INFO message.
03556             memcpy((void*)pGL, (void*)&tmp, sizeof(sGL));
03557         }
03558     }
03559     else if (pDev->eDevType == SRCP_DT_GA)
03560     {
03561         sGA tmp;
03562         sGA * pGA = (sGA *)(&pDev[1]);
03563
03564         // Temporary save the server consistent data.
03565         memcpy((void*)&tmp, (void*)pGA, sizeof(sGA));
03566
03567         if (_bGetGAInput(pDev) == TRUE)
03568         {
03569             _bSendSRCPMessage(SRCP_CMD_SET, pDev);
03570
03571             // Restore the old data to stay consistent with the server.
03572             // The recently sent data will processed by the server and comes
03573             // back via an INFO message.
03574             memcpy((void*)pGA, (void*)&tmp, sizeof(sGA));
03575         }
03576     }
03577 }
03578
03579 // ////////////////////////////////////////////////////////////////////////////
03580 // ////////////////////////////////////////////////////////////////////////////
03581
03582 static void _updateView(SRCP_DEVICE * pDev)
03583 {
03584     // Is there a configured device for view?
03585     if (pDev == NULL)
03586     {
03587         return;     // No!
03588     }
03589
03590     if (pDev->eDevState == SRCP_DS_DISABLED)
03591     {
03592         // The device is not idle anymore. That means, that the server or
03593         // another client has terminated the device.
03594         StrTbl_GetString(lcdram_row1, STRTBLID_SERVER_HAS);
03595         StrTbl_GetString(lcdram_row2, STRTBLID_DEVICE_TERMINATED);
03596         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03597                      LCD_ROW2_MASK | LCD_CENTER2_MASK;
03598
03599         // Set the device state to disabled.
03600         pDev->eDevState = SRCP_DS_DISABLED;
03601     }
03602
03603     if (pDev->u16LastErrorCode)
03604     {
03605         _showServerError(pDev->u16LastErrorCode);
03606         pDev->u16LastErrorCode = 0;     // Acknowledge the error.
03607         _eSRCPsm = SRCP_ERROR;
03608         pDev->eDevState = SRCP_DS_DISABLED;
03609     }
03610
03611
03612     // New data for the view!
03613     if (pDev->sFlags.bNewData == TRUE)
03614     {
03615         switch(pDev->eDevType)
03616         {
03617             case SRCP_DT_GL:
03618                 _displayGLData(pDev);
03619                 break;
03620
03621             case SRCP_DT_GA:
03622                 _displayGAData(pDev);
03623                 break;
03624
03625             case SRCP_DT_POWER:
03626                 _displayPower(pDev);
03627                 break;
03628         }
03629
03630         pDev->sFlags.bNewData = FALSE;
03631     }
03632 }
03633
03634 // ////////////////////////////////////////////////////////////////////////////
03635 // ////////////////////////////////////////////////////////////////////////////
03636
03637 static BYTE _u8AddEntryToEEPROM(BYTE u8RawQuickIdx, SRCP_DEVICE * pDevice)
03638 {
03639     SPSET eepromSet;
03640     BYTE idx = u8RawQuickIdx & SRCP_EEPROMSET_IDX_MASK;
03641     DWORD newAdd = 0;
03642
03643     if (pDevice == NULL)
03644     {
03645         return 0xFF;
03646     }
03647
03648     // Step 1: Load the quick setting from eeprom:
03649     if (pDevice->eDevType == SRCP_DT_GA)
03650     {
03651         idx |= SRCP_EEPROMSET_GA_MASK;
03652     }
03653
03654     XEEReadArray(SRCP_SETS_EEPROM_ADD+(sizeof(SPSET) * idx), (BYTE *)&eepromSet, sizeof(SPSET));
03655
03656
03657     // Step 2: Check the device type and write new settings to quick structure.
03658     if (pDevice->eDevType == SRCP_DT_GA)
03659     {
03660         sGA * pGA = (sGA *)(&pDevice[1]);
03661         eepromSet.uSpec.sGA.u8MinP = pGA->u8MinPort;
03662         eepromSet.uSpec.sGA.u8MaxP = pGA->u8MaxPort;
03663     }
03664     else if (pDevice->eDevType == SRCP_DT_GL)
03665     {
03666         sGL * pGL = (sGL *)(&pDevice[1]);
03667         eepromSet.uSpec.sGL.u8MaxSteps = pGL->u8MaxSteps;
03668         eepromSet.uSpec.sGL.u8NrFunc = pGL->u8NrFunc;
03669     }
03670     else
03671     {
03672         // This device type is not supported for quick set.
03673         return 0xFF;
03674     }
03675
03676     newAdd = _u32GetAddress(pDevice);
03677     strncpy(eepromSet.au8Proto, DEVICE_PROTO_PTR(pDevice), SRCP_PROTO_MAXLEN);
03678     eepromSet.au8Proto[SRCP_PROTO_MAXLEN] = 0;
03679
03680     // Step 3: Compare current settings with new settings:
03681     if ((eepromSet.u32Address!=newAdd) || (eepromSet.u8BusNr!=pDevice->u8Bus))
03682     {
03683         // This is a completly new entry!
03684         // Default string "SX"
03685         eepromSet.au8Name[0] = 'S';
03686         eepromSet.au8Name[1] = '1' + u8RawQuickIdx;
03687         eepromSet.au8Name[2] = 0;
03688     }
03689
03690     // Step 4: Write new settings to EEPROM:
03691     eepromSet.u32Address = newAdd;
03692     eepromSet.u8BusNr = pDevice->u8Bus;
03693     eepromSet.sFlags.bActive = TRUE;
03694
03695     XEEWriteArray(SRCP_SETS_EEPROM_ADD+(sizeof(SPSET) * idx), (BYTE *)&eepromSet, sizeof(SPSET));
03696
03697
03698     // Step 5: Copy the EEPROM set name to the device
03699     {
03700         BYTE * pName = DEVICE_NAME_PTR(pDevice);
03701         strncpy(pName, eepromSet.au8Name, SRCP_NAME_MAXLEN);
03702         pName[SRCP_NAME_MAXLEN] = 0;
03703     }
03704
03705     // Return the stored EEPROM set index:
03706     return idx;
03707 }
03708
03709 // ////////////////////////////////////////////////////////////////////////////
03710 // ////////////////////////////////////////////////////////////////////////////
03711
03712 static BOOL _bCheckForSelectedSet(sStaticDeviceData* psDeviceData, BOOL bEncoder)
03713 {
03714     SPSET set;
03715     BYTE tmpidx;
03716
03717     if (psDeviceData == NULL)
03718     {
03719         return FALSE;
03720     }
03721
03722     if (_pActiveEEPROMSetList && (bEncoder == TRUE) && (bInputButtonPushed(ENC_BTN) == TRUE))
03723     {
03724         tmpidx = _pActiveEEPROMSetList[s16InputEncoderGetValue()];
03725     }
03726     else if (u8InputButtonQuickPushed() != 0xFF)
03727     {
03728         tmpidx =  u8InputButtonQuickPushed();
03729     }
03730     else
03731     {
03732         return FALSE;
03733     }
03734
03735     tmpidx &= SRCP_EEPROMSET_IDX_MASK;
03736     if (OutGetLEDMode(LED_ACC) == LED_ON)
03737     {
03738         // GA is selected.
03739         tmpidx |= SRCP_EEPROMSET_GA_MASK;
03740     }
03741
03742     // Read the quick data from EEPROM.
03743     XEEReadArray(SRCP_SETS_EEPROM_ADD+(sizeof(SPSET) * tmpidx), (BYTE *)&set, sizeof(SPSET));
03744
03745     if (set.sFlags.bActive == TRUE)
03746     {
03747         // This quick position is occupied.
03748         memset((void*)psDeviceData, 0, sizeof(sStaticDeviceData));
03749
03750         psDeviceData->u8BusNr = set.u8BusNr;
03751         psDeviceData->u32Address = set.u32Address;
03752         strncpy(psDeviceData->au8Proto, set.au8Proto, SRCP_PROTO_MAXLEN);
03753         strncpy(psDeviceData->au8Name, set.au8Name, SRCP_NAME_MAXLEN);
03754
03755         if (tmpidx & SRCP_EEPROMSET_GA_MASK)
03756         {
03757             psDeviceData->uSpec.sGASpec.u8MinP = set.uSpec.sGA.u8MinP;
03758             psDeviceData->uSpec.sGASpec.u8MaxP = set.uSpec.sGA.u8MaxP;
03759             psDeviceData->uSpec.sGASpec.s32Delay = set.uSpec.sGA.s32Delay;
03760         }
03761         else
03762         {
03763             psDeviceData->uSpec.sGLSpec.u8MaxSteps = set.uSpec.sGL.u8MaxSteps;
03764             psDeviceData->uSpec.sGLSpec.u8NrFunc = set.uSpec.sGL.u8NrFunc;
03765             psDeviceData->uSpec.sGLSpec.u16MaxV = set.uSpec.sGL.u16MaxV;
03766             psDeviceData->uSpec.sGLSpec.u32FunctionToggleMask = set.uSpec.sGL.u32FuncToggleMask;
03767         }
03768
03769         return TRUE;
03770     }
03771
03772     return FALSE;
03773 }
03774
03775 // ////////////////////////////////////////////////////////////////////////////
03776 // ////////////////////////////////////////////////////////////////////////////
03777
03778 static void _storeNameToEEPROM(BYTE u8EEPROMSetIdx, BYTE *pName)
03779 {
03780     SPSET eepromdata;
03781
03782     if ((pName == NULL)||(u8EEPROMSetIdx == 0xFF))
03783     {
03784         return;
03785     }
03786
03787     XEEReadArray(SRCP_SETS_EEPROM_ADD+(sizeof(SPSET) * u8EEPROMSetIdx), (BYTE *)&eepromdata, sizeof(SPSET));
03788     strncpy(eepromdata.au8Name, pName, SRCP_NAME_MAXLEN);
03789     eepromdata.au8Name[SRCP_NAME_MAXLEN] = 0;
03790     XEEWriteArray(SRCP_SETS_EEPROM_ADD+(sizeof(SPSET) * u8EEPROMSetIdx), (BYTE *)&eepromdata, sizeof(SPSET));
03791 }
03792
03793 // ////////////////////////////////////////////////////////////////////////////
03794 // ////////////////////////////////////////////////////////////////////////////
03795
03796 static void _UpdateServerCache(SRCP_PRM * pPrm, BOOL bAdd)
03797 {
03798     short i = 0;
03799
03800     // Step 1: Look for an appropriate entry in the cache list.
03801     // Only GLs are currently supported.
03802     if (pPrm->eDevType != SRCP_DT_GL)
03803     {
03804         return;
03805     }
03806
03807     for (i = 0; i < SERVER_CACHE_ENTRIES; i++)
03808     {
03809         if ((pPrm->u8Bus == _asServerCache[i].u8BusNr) &&
03810             (pPrm->uStat.sGL.u32Addr == _asServerCache[i].u32Address))
03811         {
03812             // Entry is already in the list.
03813             if (bAdd == TRUE)
03814             {
03815                 return;
03816             }
03817
03818             break;
03819         }
03820     }
03821
03822
03823     // Step 2: Reorder Cache.
03824     if (bAdd == TRUE)
03825     {
03826         // Add the device!
03827         for (i = (SERVER_CACHE_ENTRIES-2); i >= 0; i--)
03828         {
03829             if (_asServerCache[i].u8BusNr == 0)
03830             {
03831                 // Entry is empty, skip this step.
03832                 continue;
03833             }
03834
03835             // Move down in cache
03836             memcpy((void *)&_asServerCache[i+1], (void*)&_asServerCache[i], sizeof(sServerCacheEntry));
03837         }
03838
03839
03840         // Step 3: Store new entry in the list.
03841         _asServerCache[0].u8BusNr = pPrm->u8Bus;
03842         _asServerCache[0].u32Address = pPrm->uStat.sGL.u32Addr;
03843         strcpy(_asServerCache[0].au8Proto, pPrm->uStat.sGL.au8Proto);
03844         _asServerCache[0].u8MaxSteps = pPrm->uStat.sGL.u8MaxSteps;
03845         _asServerCache[0].u8NrFunc = pPrm->uStat.sGL.u8NrFunc;
03846     }
03847     else
03848     {
03849         if (SERVER_CACHE_ENTRIES == i)
03850         {
03851             // Not found in cache!
03852             return;
03853         }
03854
03855         // Remove the device!
03856         _asServerCache[i++].u8BusNr = 0;
03857
03858         for (; i < SERVER_CACHE_ENTRIES; i++)
03859         {
03860             // The end of cache?
03861             if (_asServerCache[i].u8BusNr == 0)
03862             {
03863                 break;
03864             }
03865
03866             // Move up in cache
03867             memcpy((void *)&_asServerCache[i-1], (void*)&_asServerCache[i], sizeof(sServerCacheEntry));
03868
03869             // Free the last index
03870             _asServerCache[i].u8BusNr = 0;
03871         }
03872     }
03873 }
03874
03875 // ////////////////////////////////////////////////////////////////////////////
03876 // ////////////////////////////////////////////////////////////////////////////
03877
03878 static BOOL _bPrepareServerCacheInput(void)
03879 {
03880     BYTE entries;
03881
03882     // Step 1: Check wether the cache is empty:
03883     if (_asServerCache[0].u8BusNr == 0)
03884     {
03885         // Server cache is empty. Give an error message to the user and abort
03886         // the preparation.
03887         lcd_addr1 = 0;
03888         lcd_addr2 = 0;
03889         StrTbl_GetString(lcdram_row1, STRTBLID_SERVER_CACHE);
03890         StrTbl_GetString(lcdram_row2, STRTBLID_IS_EMPTY);
03891         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
03892                         LCD_ROW2_MASK | LCD_CENTER2_MASK;
03893         return FALSE;
03894     }
03895
03896
03897     // Step 2: Get the server cache count:
03898     for (entries = 1; entries < SERVER_CACHE_ENTRIES; entries++)
03899     {
03900         if (_asServerCache[entries].u8BusNr == 0)
03901         {
03902             break;
03903         }
03904     }
03905
03906
03907     // Step 3: Get a local copy of the server cache which is stable for the
03908     // time of input.
03909     _apsSelectCache = (sServerCacheEntry *)(SRAMalloc((sizeof(sServerCacheEntry))*entries));
03910
03911     if (_apsSelectCache == NULL)
03912     {
03913         PrintCommonError(COMMON_ERROR_OUT_OF_MEMORY);
03914         return FALSE;
03915     }
03916
03917     memcpy((void*)_apsSelectCache,(void*)_asServerCache,(sizeof(sServerCacheEntry))*entries);
03918
03919
03920     // Step 4: Initialize the encoder.
03921     InputButtonReset(ENC_BTN);
03922     InputEncoderInit(0, 0, entries-1, 0);
03923
03924
03925     // Done.
03926     return TRUE;
03927 }
03928
03929 // ////////////////////////////////////////////////////////////////////////////
03930 // ////////////////////////////////////////////////////////////////////////////
03931
03932 void SRCPPrepareConnection(void)
03933 {
03934     // Prepare SRCP-Sockets:
03935     _sSRCPState.sCommand.u8Socket = INVALID_SOCKET;
03936     _sSRCPState.sCommand.bCommand = TRUE;
03937     _sSRCPState.sInfo.u8Socket = INVALID_SOCKET;
03938     _sSRCPState.sInfo.bCommand = FALSE;
03939
03940     // Prepare state machine stuff:
03941     _eSRCPCsm = SRCPC_SM_CONNECT_COMMAND;
03942     _eSRCPsm = SRCP_STARTUP;
03943
03944     _bSrvReqIsInProgress = FALSE;
03945     _psActualDevice = NULL;
03946
03947     memset(_au8ActiveProtos, 0, sizeof(_au8ActiveProtos));
03948
03949     memset(_asServerCache, 0 , sizeof(_asServerCache));
03950     _apsSelectCache = NULL;
03951
03952     memset(_apsDevices, 0, sizeof(_apsDevices));
03953     SRAMInitHeap();
03954 }
03955
03956 // ////////////////////////////////////////////////////////////////////////////
03957 // ////////////////////////////////////////////////////////////////////////////
03958
03959 APPL_CONNECTING_RETCODE SRCPHandleServerConnection(void)
03960 {
03961     switch(_eSRCPCsm)
03962     {
03963     case SRCPC_SM_CONNECT_COMMAND:
03964     {
03965         _sSRCPState.sCommand.u8Socket = TCPConnect(ApplGetServerNodeInfo(), ApplGetServerPort().Val);
03966
03967         if (_sSRCPState.sCommand.u8Socket == INVALID_SOCKET)
03968         {
03969              _eSRCPCsm = SRCPC_SM_ERROR_CONNECT;
03970         }
03971         else
03972         {
03973              _eSRCPCsm = SRCPC_SM_CONNECT_WAIT_COMMAND;
03974         }
03975         break;
03976     }
03977
03978     case SRCPC_SM_CONNECT_WAIT_COMMAND:
03979         if (TCPWasReset(_sSRCPState.sCommand.u8Socket) || (bInputButtonPushed(ENC_BTN) == TRUE))
03980         {
03981             _sSRCPState.sCommand.u8Socket = INVALID_SOCKET;
03982             _eSRCPCsm = SRCPC_SM_CLOSING;
03983         }
03984         else if (TCPIsConnected(_sSRCPState.sCommand.u8Socket))
03985         {
03986             OutSwitchOffAllLEDs();
03987             _startHandShake();
03988             _eSRCPCsm = SRCPC_SM_CONNECTED_COMMAND;
03989         }
03990         break;
03991
03992     case SRCPC_SM_CONNECTED_COMMAND:
03993         if (TCPWasReset(_sSRCPState.sCommand.u8Socket) || (bInputButtonPushed(ENC_BTN) == TRUE))
03994         {
03995             _sSRCPState.sCommand.u8Socket = INVALID_SOCKET;
03996             _eSRCPCsm = SRCPC_SM_CLOSING;
03997         }
03998         else
03999         {
04000             SRCP_HANDSHAKE_RETCODE ret = _eHandShake(&_sSRCPState.sCommand);
04001
04002             if (ret == SRCP_HR_ERROR)
04003             {
04004                 // Errors occurred during the handshake. Display the error
04005                 // message to the user (initiated in the Hand Shake Function)
04006                 // and close all open connections.
04007                 u8ApplTimer = 200;
04008                 _eSRCPCsm = SRCPC_SM_DELAY_CLOSING;
04009             }
04010             else if (ret == SRCP_HR_FINISHED)
04011             {
04012                 // Connect to the INFO socket.
04013                 _sSRCPState.sInfo.u8Socket = TCPConnect(ApplGetServerNodeInfo(), ApplGetServerPort().Val);
04014
04015                 if (_sSRCPState.sInfo.u8Socket == INVALID_SOCKET)
04016                 {
04017                     _eSRCPCsm = SRCPC_SM_CLOSING;
04018                 }
04019                 else
04020                 {
04021                     _eSRCPCsm = SRCPC_SM_CONNECT_WAIT_INFO;
04022                 }
04023             }
04024         }
04025         break;
04026
04027     case SRCPC_SM_CONNECT_WAIT_INFO:
04028         if(bInputButtonPushed(ENC_BTN) == TRUE)
04029         {
04030             _eSRCPCsm = SRCPC_SM_CLOSING;
04031         }
04032         else if (TCPIsConnected(_sSRCPState.sInfo.u8Socket))
04033         {
04034             _startHandShake();
04035             _eSRCPCsm = SRCPC_SM_CONNECTED_INFO;
04036         }
04037         break;
04038
04039     case SRCPC_SM_CONNECTED_INFO:
04040         if (bInputButtonPushed(ENC_BTN) == TRUE)
04041         {
04042             _eSRCPCsm = SRCPC_SM_CLOSING;
04043         }
04044         else if (TCPWasReset(_sSRCPState.sCommand.u8Socket))
04045         {
04046             _sSRCPState.sCommand.u8Socket = INVALID_SOCKET;
04047             _eSRCPCsm = SRCPC_SM_CLOSING;
04048         }
04049         else if (TCPWasReset(_sSRCPState.sInfo.u8Socket))
04050         {
04051             _sSRCPState.sInfo.u8Socket = INVALID_SOCKET;
04052             _eSRCPCsm = SRCPC_SM_CLOSING;
04053         }
04054         else
04055         {
04056             SRCP_HANDSHAKE_RETCODE ret = _eHandShake(&_sSRCPState.sInfo);
04057
04058             if (ret == SRCP_HR_ERROR)
04059             {
04060                 // Errors occurred during the handshake. Display the error
04061                 // message to the user (initiated in the Hand Shake Function)
04062                 // and close all open connections.
04063                 u8ApplTimer = 200;
04064                 _eSRCPCsm = SRCPC_SM_DELAY_CLOSING;
04065             }
04066             else if (ret == SRCP_HR_FINISHED)
04067             {
04068                 _eSRCPCsm = SRCPC_SM_CONNECTED;
04069             }
04070         }
04071         break;
04072
04073     case SRCPC_SM_DELAY_CLOSING:
04074         if (u8ApplTimer == 0)
04075         {
04076             _eSRCPCsm = SRCPC_SM_CLOSING;
04077         }
04078         break;
04079
04080     case SRCPC_SM_CLOSING:
04081         if (_sSRCPState.sCommand.u8Socket != INVALID_SOCKET)
04082         {
04083             TCPDisconnect(_sSRCPState.sCommand.u8Socket);
04084         }
04085         if (_sSRCPState.sInfo.u8Socket != INVALID_SOCKET)
04086         {
04087             TCPDisconnect(_sSRCPState.sInfo.u8Socket);
04088         }
04089
04090         _eSRCPCsm = SRCPC_SM_WAIT_FOR_CLOSING;
04091
04092         // Intented fall through.
04093
04094     case SRCPC_SM_WAIT_FOR_CLOSING:
04095         if ((_sSRCPState.sCommand.u8Socket != INVALID_SOCKET) && TCPWasReset(_sSRCPState.sCommand.u8Socket))
04096         {
04097             _sSRCPState.sCommand.u8Socket = INVALID_SOCKET;
04098         }
04099         if ((_sSRCPState.sInfo.u8Socket != INVALID_SOCKET) && TCPWasReset(_sSRCPState.sInfo.u8Socket))
04100         {
04101             _sSRCPState.sInfo.u8Socket = INVALID_SOCKET;
04102         }
04103
04104         if ((_sSRCPState.sCommand.u8Socket == INVALID_SOCKET) && (_sSRCPState.sInfo.u8Socket == INVALID_SOCKET))
04105         {
04106             _eSRCPCsm = SRCPC_SM_CLOSED;
04107         }
04108         break;
04109
04110     case SRCPC_SM_CLOSED:
04111         return APPL_CR_CLOSED;
04112
04113     case SRCPC_SM_CONNECTED:
04114         return APPL_CR_CONNECTED;
04115
04116     case SRCPC_SM_ERROR_CONNECT:
04117         return APPL_CR_ERROR;
04118     }
04119
04120     return APPL_CR_IN_PROGRESS;
04121 }
04122
04123 // ////////////////////////////////////////////////////////////////////////////
04124 // ////////////////////////////////////////////////////////////////////////////
04125
04126 BOOL SRCPIsConnected(void)
04127 {
04128     if ((_sSRCPState.sCommand.u8Socket != INVALID_SOCKET) &&
04129         (_sSRCPState.sInfo.u8Socket != INVALID_SOCKET))
04130     {
04131         return TRUE;
04132     }
04133     else
04134     {
04135         return FALSE;
04136     }
04137 }
04138
04139 // ////////////////////////////////////////////////////////////////////////////
04140 // ////////////////////////////////////////////////////////////////////////////
04141
04142 void SRCPStartDisconnect(void)
04143 {
04144     // Clean up the srcp module before completly disconnecting (destructor).
04145     FiniDialog(NULL);
04146
04147     _eSRCPCsm = SRCPC_SM_CLOSING;
04148 }
04149
04150 // ////////////////////////////////////////////////////////////////////////////
04151 // ////////////////////////////////////////////////////////////////////////////
04152
04153 static SRCP_DEVICE * _psInitializeNewDevice(SRCP_DEVTYPE eDevType, BYTE u8Bus,
04154                                             void * pPrm)
04155 {
04156     BYTE size;
04157     SRCP_DEVICE * pDev = NULL;
04158
04160     // Step 1: Determine the size of the requested device structure.
04161     switch(eDevType)
04162     {
04163         case SRCP_DT_POWER:
04164             size = sizeof(sPower);
04165             break;
04166
04167         case SRCP_DT_LOCK:
04168             size = sizeof(sLock);
04169             break;
04170
04171         case SRCP_DT_GL:
04172             size = sizeof(sGL);
04173             break;
04174
04175         case SRCP_DT_GA:
04176             size = sizeof(sGA);
04177             break;
04178     }
04179
04180     size += sizeof(SRCP_DEVICE);
04181
04182
04184     // Step 2: Allocate and initialize the device structure.
04185
04186     pDev = (SRCP_DEVICE*)SRAMalloc(size);
04187     if (pDev == NULL)
04188     {
04189         return NULL;
04190     }
04191
04192     memset(pDev, 0, size);
04193     pDev->eDevType = eDevType;
04194     pDev->eDevState = SRCP_DS_UNKNOWN;
04195     pDev->u8Bus = u8Bus;
04196
04197     if (pPrm)
04198     {
04199         size -= sizeof(SRCP_DEVICE);
04200         memcpy((void *)&pDev[1], pPrm, size);
04201     }
04202
04203     return pDev;
04204 }
04205
04206 // ////////////////////////////////////////////////////////////////////////////
04207 // ////////////////////////////////////////////////////////////////////////////
04208
04209 static DWORD _u32GetAddress(SRCP_DEVICE * psDevice)
04210 {
04211     // The address is always located at the same field position regardless
04212     // of the device type.
04213
04214     if (psDevice == NULL)
04215     {
04216         return 0;
04217     }
04218
04219     if ((psDevice->eDevType == SRCP_DT_GL)||
04220         (psDevice->eDevType == SRCP_DT_GA)||
04221         (psDevice->eDevType == SRCP_DT_LOCK))
04222     {
04223         return (*((DWORD *)(&psDevice[1])));
04224     }
04225     else
04226     {
04227         return 0;
04228     }
04229 }
04230
04231 // ////////////////////////////////////////////////////////////////////////////
04232 // ////////////////////////////////////////////////////////////////////////////
04233
04234 static void _refreshDeviceList(void)
04235 {
04236     BYTE i, j;
04237     BOOL bListIsEmpty = TRUE;
04238
04239     // Step 1: Check for double pointers in the list and remove them.
04240     for (i = 0; i < MAX_SRCP_DEVICES; i++)
04241     {
04242         if (_apsDevices[i] == NULL)
04243         {
04244             continue;
04245         }
04246
04247         bListIsEmpty = FALSE;
04248         for (j = 0; j < MAX_SRCP_DEVICES; j++)
04249         {
04250             if ((i!=j) && (_apsDevices[i] == _apsDevices[j]))
04251             {
04252                 _apsDevices[j] = NULL;
04253             }
04254         }
04255     }
04256
04257     if (bListIsEmpty == TRUE)
04258     {
04259         return;
04260     }
04261
04262     // Step 2: Remove disabled devices from the device list.
04263     for (i = 0; i < MAX_SRCP_DEVICES; i++)
04264     {
04265         if (_apsDevices[i] == NULL)
04266         {
04267             continue;
04268         }
04269
04270         if (_apsDevices[i]->eDevState == SRCP_DS_DISABLED)
04271         {
04272             if (_psActualDevice == _apsDevices[i])
04273             {
04274                 _psActualDevice = NULL;
04275             }
04276             SRAMfree((BYTE *)(_apsDevices[i]));
04277             _apsDevices[i] = NULL;
04278         }
04279     }
04280
04281
04282     // Step 3: Move all NULL pointers to the end of the list.
04283     for (i = FREQUENT_SRCP_DEVICE_OFFSET; i < MAX_SRCP_DEVICES; i++)
04284     {
04285         if (_apsDevices[i] != NULL)
04286         {
04287             continue;
04288         }
04289
04290         // Find a valid pointer after this NULL position.
04291         for (j = i+1; j < MAX_SRCP_DEVICES; j++)
04292         {
04293             if (_apsDevices[j] != NULL)
04294             {
04295                 // Move the valid pointer to the NULL position:
04296                 _apsDevices[i] = _apsDevices[j];
04297                 _apsDevices[j] = NULL;
04298                 break;
04299             }
04300         }
04301     }
04302 }
04303
04304 // ////////////////////////////////////////////////////////////////////////////
04305 // ////////////////////////////////////////////////////////////////////////////
04306
04307 static SRCP_DEVICE * _pTakeOverDevice(SRCP_DEVICE * pDevice)
04308 {
04309     SRCP_DEVICE * pLastDevice = NULL;
04310     BYTE mainDeviceIdx = 0;
04311
04312     if (pDevice == NULL)
04313     {
04314         return NULL;
04315     }
04316
04317     // Check the device type (only GA and GL can be main devices).
04318     if (pDevice->eDevType == SRCP_DT_GA)
04319     {
04320         mainDeviceIdx = 1;
04321     }
04322     else if (pDevice->eDevType != SRCP_DT_GL)
04323     {
04324         return NULL;
04325     }
04326
04327     // Is the device already stored as frequently used device?
04328     if (pDevice == _apsDevices[mainDeviceIdx])
04329     {
04330         return pDevice;
04331     }
04332
04333
04334     // Delete the last main device of the appropriate category.
04335     if (_apsDevices[mainDeviceIdx])
04336     {
04337         // Delete the last device!
04338         SRAMfree((BYTE *)_apsDevices[mainDeviceIdx]);
04339     }
04340
04341     // Move the new device to the main position.
04342     _apsDevices[mainDeviceIdx] = pDevice;
04343
04344     _refreshDeviceList();
04345
04346     return pDevice;
04347 }
04348
04349 // ////////////////////////////////////////////////////////////////////////////
04350 // ////////////////////////////////////////////////////////////////////////////
04351
04352 static SRCP_DEVICE * _pGetLatestGL(void)
04353 {
04354     return _apsDevices[0];
04355 }
04356
04357 // ////////////////////////////////////////////////////////////////////////////
04358 // ////////////////////////////////////////////////////////////////////////////
04359
04360 static SRCP_DEVICE * _pGetLatestGA(void)
04361 {
04362     return _apsDevices[1];
04363 }
04364
04365 // ////////////////////////////////////////////////////////////////////////////
04366 // ////////////////////////////////////////////////////////////////////////////
04367
04368 static BYTE _prepareEEPROMSetInput(BOOL bGL)
04369 {
04370     BYTE listsize, listoffset;
04371     BYTE i, entries;
04372     WORD address;
04373
04374     // Step 1: Initialize the device dependent margins for eeprom access.
04375     if (bGL == TRUE)
04376     {
04377         listoffset = 0;
04378         listsize = SRCP_GLEEPROMSET_COUNT;
04379     }
04380     else
04381     {
04382         listoffset = SRCP_GLEEPROMSET_COUNT;
04383         listsize = SRCP_GAEEPROMSET_COUNT;
04384     }
04385
04386
04387     // Step 2: Allocate the EEPROM set list.
04388     _pActiveEEPROMSetList = SRAMalloc(listsize);
04389
04390     if (_pActiveEEPROMSetList == NULL)
04391     {
04392         PrintCommonError(COMMON_ERROR_OUT_OF_MEMORY);
04393         return 0;
04394     }
04395
04396
04397     // Step 3: Iterate through the eeprom set and find active sets.
04398     address = SRCP_SETS_EEPROM_ADD + (listoffset * sizeof(SPSET));
04399     for (i = listoffset, entries = 0; i < (listsize + listoffset); i++)
04400     {
04401         SPSET set;
04402         XEEReadArray(address, (BYTE *)&set, sizeof(SPSET));
04403         if (set.sFlags.bActive == TRUE)
04404         {
04405             _pActiveEEPROMSetList[entries++] = i;
04406         }
04407         address += sizeof(SPSET);
04408     }
04409
04410
04411     // Step 4: Evaluate the amount of sets.
04412     if (entries == 0)
04413     {
04414         lcd_addr1 = 0;
04415         lcd_addr2 = 0;
04416         StrTbl_GetString(lcdram_row1, STRTBLID_DATABASE);
04417         StrTbl_GetString(lcdram_row2, STRTBLID_IS_EMPTY);
04418         lcd_status = LCD_CLR_MASK | LCD_ROW1_MASK | LCD_CENTER1_MASK |
04419                         LCD_ROW2_MASK | LCD_CENTER2_MASK;
04420         return 0;
04421     }
04422
04423     return entries;
04424 }
04425
04426 // ////////////////////////////////////////////////////////////////////////////
04427 // ////////////////////////////////////////////////////////////////////////////
04428
04429 static void _destructEEPROMSet(void)
04430 {
04431     if (_pActiveEEPROMSetList)
04432     {
04433         SRAMfree(_pActiveEEPROMSetList);
04434         _pActiveEEPROMSetList = NULL;
04435     }
04436 }
04437
04438 // ////////////////////////////////////////////////////////////////////////////
04439 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: srcp.h Source File

srcp.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00015
00016 #ifndef SRCP_H
00017
00018 #define     SRCP_H
00019
00020
00021 // ////////////////////////////////////////////////////////////////////////////
00022 // Includes
00023 // ////////////////////////////////////////////////////////////////////////////
00024
00025 #include    <stdio.h>
00026 #include    "main.h"
00027 #include    "appl.h"
00028 #include    "projectdefs.h"
00029
00030
00031 // ////////////////////////////////////////////////////////////////////////////
00032 // Defines
00033 // ////////////////////////////////////////////////////////////////////////////
00034
00035 #ifdef SRCP_C
00036     #define PROTO
00037 #else
00038     #define PROTO extern
00039 #endif
00040
00041 #define EEPROM_GLS  SRCP_PROTOS_EEPROM_ADD
00042 #define EEPROM_GAS  (SRCP_PROTOS_EEPROM_ADD + (sizeof(SPPROTOCOL)*MAX_PROTO_SLOTS))
00043
00044
00045 // ////////////////////////////////////////////////////////////////////////////
00046 // Typedefs
00047 // ////////////////////////////////////////////////////////////////////////////
00048
00049
00050
00051 // ////////////////////////////////////////////////////////////////////////////
00052 // Global variables
00053 // ////////////////////////////////////////////////////////////////////////////
00054
00062 PROTO SPSRCPCONFIG sPSRCPConfig;
00063
00064
00065 // ////////////////////////////////////////////////////////////////////////////
00066 // Function prototypes
00067 // ////////////////////////////////////////////////////////////////////////////
00068
00069 void SRCP_GetProtoFromEEPROM(BYTE u8ProtoId, SPPROTOCOL * psProto);
00070 void SRCP_WriteProtoToEEPROM(BYTE u8ProtoId, SPPROTOCOL * psProto);
00071 void SRCP_GetSetFromEEPROM(BYTE u8SetIdx, SPSET * psSet);
00072 void SRCP_WriteSetToEEPROM(BYTE u8SetIdx, SPSET * psSet);
00073
00074 void SRCP_CancelInputProtoDialog(void);
00075 void SRCP_CancelInputSetDialog(void);
00076
00077
00081 // ////////////////////////////////////////////////////////////////////////////
00082 // Epilogue
00083 // ////////////////////////////////////////////////////////////////////////////
00084
00085     #undef      PROTO
00086 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: stringtable.c Source File

stringtable.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00015     #define     STRINGTABLE_C
00016
00017
00019 // Includes
00021
00022 #include "TCPIP.h"
00023 #include "stringtable.h"
00024
00025
00026 // ////////////////////////////////////////////////////////////////////////////
00027 // Local Defines
00028 // ////////////////////////////////////////////////////////////////////////////
00029
00030 typedef struct
00031 {
00032     ROM char *  pString;
00033 } STRING_POINTER;
00034
00035
00036 // ////////////////////////////////////////////////////////////////////////////
00037 // Local variables
00038 // ////////////////////////////////////////////////////////////////////////////
00039
00040 ROM STRING_POINTER _asROMStringListDe[] =
00041 {
00042 // STRTBLID_LANGUAGE_NAME
00043     {"Deutsch"},
00044 // STRTBLID_SUCCESSFULLY_CONNECTED
00045     {"Verbunden mit"},
00046 // STRTBLID_ALLOCATE
00047     {"Allokiere"},
00048 // STRTBLID_IP_ADDRESS
00049     {"IP-Adresse"},
00050 // STRTBLID_ADDRESS_CONFLICT1
00051     {"Adresskonflikt"},
00052 // STRTBLID_ADDRESS_CONFLICT2
00053     {"festgestellt!"},
00054 // STRTBLID_CABEL_UNPLUGGED1
00055     {"Netzwerkkabel"},
00056 // STRTBLID_CABEL_UNPLUGGED2
00057     {"wurde entfernt!"},
00058 // STRTBLID_OBTAINED_IP
00059     {"Zugewiesene IP:"},
00060 // STRTBLID_NAMESERVICE
00061     {"Namensdienst"},
00062 // STRTBLID_STOPPED
00063     {"gestoppt!"},
00064 // STRTBLID_SEARCHING
00065     {"Suche"},
00066 // STRTBLID_CONNECT_TO
00067     {"Verbinde zu"},
00068 // STRTBLID_CONNECTION_CLOSED1
00069     {"Verbindung wurde"},
00070 // STRTBLID_CONNECTION_CLOSED2
00071     {"geschlossen!"},
00072 // STRTBLID_DATA_NOT
00073     {"Daten nicht"},
00074 // STRTBLID_SAVED
00075     {"gespeichert."},
00076 // STRTBLID_IP_MENU
00077     {"- IP Men\x81 -"},
00078 // STRTBLID_IP_ALLOCATION
00079     {"IP-Zuweisung"},
00080 // STRTBLID_MANUAL
00081     {"Manuell"},
00082 // STRTBLID_AUTO
00083     {"Automatisch"},
00084 // STRTBLID_SUBNETMASK
00085     {"Subnetzmaske"},
00086 // STRTBLID_GATEWAY_ADDRESS
00087     {"Gateway"},
00088 // STRTBLID_SERVER_MENU
00089     {"- Server Men\x81 -"},
00090 // STRTBLID_FIND_SERVER
00091     {"Finde Server per"},
00092 // STRTBLID_NETWORK_NAME
00093     {"Netzwerkname"},
00094 // STRTBLID_NETWORK_SERVICE
00095     {"Netzwerkdienst"},
00096 // STRTBLID_SERVER_ADDRESS
00097     {"Serveradresse"},
00098 // STRTBLID_SERVER_NAME
00099     {"Servername"},
00100 // STRTBLID_SERVICE_NAME
00101     {"Dienstname"},
00102 // STRTBLID_PORT
00103     {"Port"},
00104 // STRTBLID_SET_PORT_TO1
00105     {"Port auf"},
00106 // STRTBLID_SET_PORT_TO2
00107     {"%hu gesetzt!"},
00108 // STRTBLID_DATA_WAS
00109     {"Daten wurden"},
00110 // STRTBLID_PROTOCOL
00111     {"Protokoll"},
00112 // STRTBLID_ADDRESS
00113     {"Adresse"},
00114 // STRTBLID_ACCESS
00115     {"Zugriff"},
00116 // STRTBLID_NORMAL
00117     {"Normal"},
00118 // STRTBLID_EXCLUSIVE
00119     {"Exklusiv"},
00120 // STRTBLID_NO_DEVICE
00121     {"Kein Ger\x84t."},
00122 // STRTBLID_SERVER_REPORTS
00123     {"Server meldet"},
00124 // STRTBLID_ERRORCODE
00125     {"Fehlercode %hu."},
00126 // STRTBLID_SERVERVERSION
00127     {"Serverversion"},
00128 // STRTBLID_UNKNOWN
00129     {"unbekannt!"},
00130 // STRTBLID_SRVVERSION
00131     {"Srv: Version"},
00132 // STRTBLID_SRVMODE
00133     {"Srv: Modus"},
00134 // STRTBLID_SRVUNSUFFICIENT_DATA1
00135     {"Srv: Ungen\x81-"},
00136 // STRTBLID_SRVUNSUFFICIENT_DATA2
00137     {"gende Angaben!"},
00138 // STRTBLID_SRVUNKNOWN_COMMAND1
00139     {"Srv: Unbekanntes"},
00140 // STRTBLID_SRVUNKNOWN_COMMAND2
00141     {"Kommando!"},
00142 // STRTBLID_SRVNO_RESSOURCES1
00143     {"Srv: Keine Res-"},
00144 // STRTBLID_SRVNO_RESSOURCES2
00145     {"sourcen frei!"},
00146 // STRTBLID_SERVER_HAS
00147     {"Server hat"},
00148 // STRTBLID_DEVICE_TERMINATED
00149     {"Ger\x84t beendet!"},
00150 // STRTBLID_INACTIVE
00151     {"Inaktiv"},
00152 // STRTBLID_ACTIVE
00153     {"Aktiv"},
00154 // STRTBLID_CLICK
00155     {"Per Klick"},
00156 // STRTBLID_ZEROPOINT
00157     {"Nullpunkt"},
00158 // STRTBLID_ON
00159     {"An"},
00160 // STRTBLID_OFF
00161     {"Aus"},
00162 // STRTBLID_FIRMWARE_VERSION
00163     {"Firmware-Version"},
00164 // STRTBLID_MAC_ADDRESS
00165     {"MAC-Adresse"},
00166 // STRTBLID_CONNECTION
00167     {"Verbindung"},
00168 // STRTBLID_LCD_BACKLIGHT
00169     {"LCD-Beleuchtung aus nach"},
00170 // STRTBLID_CHANGE_VALUES
00171     {"Werte &auml;ndern"},
00172 // STRTBLID_RESTART
00173     {"Neustart"},
00174 // STRTBLID_RESET_TO_FACTORY
00175     {"Zur&uuml;cksetzen auf Werkseinstellungen"},
00176 // STRTBLID_DIRECTION_MODE
00177     {"Umschalten der Fahrtrichtung"},
00178 // STRTBLID_PROTOCOL_LOCO_REQUEST
00179     {"Lokprotokollabfrage"},
00180 // STRTBLID_STANDARD_LOCO_PROTOCOL
00181     {"Standardlokprotokoll"},
00182 // STRTBLID_PROTOCOLS
00183     {"Protokolle"},
00184 // STRTBLID_NAME
00185     {"Name"},
00186 // STRTBLID_BUS
00187     {"Bus"},
00188 // STRTBLID_MIN_ADDRESS
00189     {"Min. Adresse"},
00190 // STRTBLID_MAX_ADDRESS
00191     {"Max. Adresse"},
00192 // STRTBLID_NO_OF_SPEED_STEPS
00193     {"Anzahl Geschw.-Stufen"},
00194 // STRTBLID_NO_OF_FUNCTIONS
00195     {"Anzahl Funktionen"},
00196 // STRTBLID_NUMBER
00197     {"Nr."},
00198 // STRTBLID_OK
00199     {"Ok"},
00200 // STRTBLID_RESET
00201     {"Zur&uuml;cksetzen"},
00202 // STRTBLID_PORT_DELAY
00203     {"Zubeh&ouml;reinschaltdauer<br>(-1 = Dauerhaft)"},
00204 // STRTBLID_MIN_PORT
00205     {"Min. Port"},
00206 // STRTBLID_MAX_PORT
00207     {"Max. Port"},
00208 // STRTBLID_LANGUAGE
00209     {"Sprache"},
00210 // STRTBLID_SERVER_CACHE
00211     {"Serverspeicher"},
00212 // STRTBLID_IS_EMPTY
00213     {"ist leer!"},
00214 // STRTBLID_BUS_ADDRESS
00215     {"Bus      Adresse"},
00216 // STRTBLID_LOCO_PROTOCOLS
00217     {"Lokprotokolle"},
00218 // STRTBLID_LOCO_DATABASE
00219     {"Lokdatenbank"},
00220 // STRTBLID_ACC_PROTOCOLS
00221     {"Zubeh&ouml;rprotokolle"},
00222 // STRTBLID_ACC_DATABASE
00223     {"Zubeh&ouml;rdatenbank"},
00224 // STRTBLID_CONFIGURATION
00225     {"Konfiguration"},
00226 // STRTBLID_SYSTEMSTATE
00227     {"STATUS"},
00228 // STRTBLID_COMMON
00229     {"ALLGEMEIN"},
00230 // STRTBLID_SRCP
00231     {"SRCP"},
00232 // STRTBLID_FILE
00233     {"DATEI"},
00234 // STRTBLID_PROTOCOL_ACC_REQUEST
00235     {"Zubeh&ouml;rprotokollabfrage"},
00236 // STRTBLID_STANDARD_ACC_PROTOCOL
00237     {"Standardzubeh&ouml;rprotokoll"},
00238 // STRTBLID_DOWNLOAD_CONFIG
00239     {"Die Konfiguration als XML Datei."},
00240 // STRTBLID_COMMON_ERROR1
00241     {"Allgemeiner"},
00242 // STRBLDID_COMMON_ERROR2
00243     {"Fehler: %hhu"},
00244 // STRTBLID_DATABASE
00245     {"Datenbank"},
00246 // STRTBLID_POSITION_X
00247     {"Position %u"},
00248 // STRTBLID_CONFIGURE
00249     {"Konfigurieren"},
00250 // STRTBLID_MAXSPEED
00251     {"H&ouml;chstgeschwindigkeit"},
00252 // STRTBLID_FUNCTIONS
00253     {"Funktionen"},
00254 // STRTBLID_PUSHBUTTON
00255     {"Taster"},
00256 // STRTBLID_SWITCH
00257     {"Schalter"},
00258 // STRTBLID_PROTOCOLDATA
00259     {"Protokolldaten"},
00260 // STRTBLID_SET_PORT_DELAY
00261     {"Einschaltdauer (0 = Standardwert, -1 = Dauerhaft)"},
00262 // STRTBLID_MIN_CHARACTER
00263     {"Min. 1 Zeichen"},
00264 // STRTBLID_SAVE
00265     {"Speichern"},
00266 // STRTBLID_UPLOAD_CONFIG
00267     {"Hochladen einer XML Konfigurationsdatei."},
00268 // STRTBLID_OPEN
00269     {"&Ouml;ffnen"},
00270 // STRTBLID_UPLOAD
00271     {"Hochladen"},
00272 // STRTBLID_SERVER_URL
00273     {"Server URL"},
00274 // STRTBLID_RESTART_NEEDED
00275     {"&Auml;nderungen werden erst nach Neustart wirksam!"},
00276 // STRTBLID_MANUAL_IP
00277     {"Manuelle IP:"},
00278 // STRTBLID_NO_LOCO
00279     {"Keine Lok!"},
00280 // STRTBLID_PLEASE_WAIT
00281     {"Bitte warten..."},
00282 // STRTBLID_BOOTLOADER_VERSION
00283     {"Bootloader Version"},
00284 // STRTBLID_CONNECTION_ERROR1
00285     {"Verbindungs-"},
00286 // STRTBLID_CONNECTION_ERROR2
00287     {"fehler!"},
00288 };
00289
00290 ROM STRING_POINTER _asROMStringListEn[] =
00291 {
00292 // STRTBLID_LANGUAGE_NAME
00293     {"English"},
00294 // STRTBLID_SUCCESSFULLY_CONNECTED
00295     {"Connected with"},
00296 // STRTBLID_ALLOCATE
00297     {"Allocating"},
00298 // STRTBLID_IP_ADDRESS
00299     {"IP Address"},
00300 // STRTBLID_ADDRESS_CONFLICT1
00301     {"Address conflict"},
00302 // STRTBLID_ADDRESS_CONFLICT2
00303     {"detected!"},
00304 // STRTBLID_CABEL_UNPLUGGED1
00305     {"Network cabel"},
00306 // STRTBLID_CABEL_UNPLUGGED2
00307     {"is unplugged!"},
00308 // STRTBLID_OBTAINED_IP
00309     {"Assigned IP:"},
00310 // STRTBLID_NAMESERVICE
00311     {"Name service"},
00312 // STRTBLID_STOPPED
00313     {"stopped!"},
00314 // STRTBLID_SEARCHING
00315     {"Searching"},
00316 // STRTBLID_CONNECT_TO
00317     {"Connecting to"},
00318 // STRTBLID_CONNECTION_CLOSED1
00319     {"Connection was"},
00320 // STRTBLID_CONNECTION_CLOSED2
00321     {"closed!"},
00322 // STRTBLID_DATA_NOT_SAVED1
00323     {"Data not"},
00324 // STRTBLID_DATA_NOT_SAVED2
00325     {"saved."},
00326 // STRTBLID_IP_MENU
00327     {"- IP Menu -"},
00328 // STRTBLID_IP_ALLOCATION
00329     {"IP Allocation"},
00330 // STRTBLID_MANUAL
00331     {"Manual"},
00332 // STRTBLID_AUTO
00333     {"Automatic"},
00334 // STRTBLID_SUBNETMASK
00335     {"Subnet mask"},
00336 // STRTBLID_GATEWAY_ADDRESS
00337     {"Gateway"},
00338 // STRTBLID_SERVER_MENU
00339     {"- Server Menu -"},
00340 // STRTBLID_FIND_SERVER
00341     {"Find Server via"},
00342 // STRTBLID_NETWORK_NAME
00343     {"Network name"},
00344 // STRTBLID_NETWORK_SERVICE
00345     {"Network service"},
00346 // STRTBLID_SERVER_ADDRESS
00347     {"Server address"},
00348 // STRTBLID_SERVER_NAME
00349     {"Server name"},
00350 // STRTBLID_SERVICE_NAME
00351     {"Service name"},
00352 // STRTBLID_PORT
00353     {"Port"},
00354 // STRTBLID_SET_PORT_TO1
00355     {"Set port"},
00356 // STRTBLID_SET_PORT_TO2
00357     {"to %hu!"},
00358 // STRTBLID_DATA_WAS
00359     {"Data was"},
00360 // STRTBLID_PROTOCOL
00361     {"Protocol"},
00362 // STRTBLID_ADDRESS
00363     {"Address"},
00364 // STRTBLID_ACCESS
00365     {"Access"},
00366 // STRTBLID_NORMAL
00367     {"Normal"},
00368 // STRTBLID_EXCLUSIVE
00369     {"Exclusive"},
00370 // STRTBLID_NO_DEVICE
00371     {"No device."},
00372 // STRTBLID_SERVER_REPORTS
00373     {"Server reports"},
00374 // STRTBLID_ERRORCODE
00375     {"error code %hu."},
00376 // STRTBLID_SERVERVERSION
00377     {"Server version"},
00378 // STRTBLID_UNKNOWN
00379     {"unknown!"},
00380 // STRTBLID_SRVVERSION
00381     {"Srv: Version"},
00382 // STRTBLID_SRVMODE
00383     {"Srv: Mode"},
00384 // STRTBLID_SRVUNSUFFICIENT_DATA1
00385     {"Srv: Unsuffi-"},
00386 // STRTBLID_SRVUNSUFFICIENT_DATA2
00387     {"cient data!"},
00388 // STRTBLID_SRVUNKNOWN_COMMAND1
00389     {"Srv: Unknown"},
00390 // STRTBLID_SRVUNKNOWN_COMMAND2
00391     {"command!"},
00392 // STRTBLID_SRVNO_RESSOURCES1
00393     {"Srv: Out of"},
00394 // STRTBLID_SRVNO_RESSOURCES2
00395     {"ressources!"},
00396 // STRTBLID_SERVER_HAS
00397     {"Server has ter-"},
00398 // STRTBLID_DEVICE_FINISHED
00399     {"minated device!"},
00400 // STRTBLID_INACTIVE
00401     {"Inactive"},
00402 // STRTBLID_ACTIVE
00403     {"Active"},
00404 // STRTBLID_CLICK
00405     {"Per click"},
00406 // STRTBLID_ZEROPOINT
00407     {"Zero point"},
00408 // STRTBLID_ON
00409     {"On"},
00410 // STRTBLID_OFF
00411     {"Off"},
00412 // STRTBLID_FIRMWARE_VERSION
00413     {"Firmware version"},
00414 // STRTBLID_MAC_ADDRESS
00415     {"MAC Address"},
00416 // STRTBLID_CONNECTION
00417     {"Connection"},
00418 // STRTBLID_LCD_BACKLIGHT
00419     {"LCD backlight off after"},
00420 // STRTBLID_CHANGE_VALUES
00421     {"Change values"},
00422 // STRTBLID_RESTART
00423     {"Restart"},
00424 // STRTBLID_RESET_TO_FACTORY
00425     {"Reset to factory settings"},
00426 // STRTBLID_DIRECTION_MODE
00427     {"Toggle loco direction"},
00428 // STRTBLID_PROTOCOL_LOCO_REQUEST
00429     {"Loco protocol request"},
00430 // STRTBLID_STANDARD_LOCO_PROTOCOL
00431     {"Standard loco protocol"},
00432 // STRTBLID_PROTOCOLS
00433     {"Protocols"},
00434 // STRTBLID_NAME
00435     {"Name"},
00436 // STRTBLID_BUS
00437     {"Bus"},
00438 // STRTBLID_MIN_ADDRESS
00439     {"Min. Address"},
00440 // STRTBLID_MAX_ADDRESS
00441     {"Max. Address"},
00442 // STRTBLID_NO_OF_SPEED_STEPS
00443     {"No. of speed steps"},
00444 // STRTBLID_NO_OF_FUNCTIONS
00445     {"No. of functions"},
00446 // STRTBLID_NUMBER
00447     {"No."},
00448 // STRTBLID_OK
00449     {"Ok"},
00450 // STRTBLID_RESET
00451     {"Reset"},
00452 // STRTBLID_PORT_DELAY
00453     {"Accessory delay<br>(-1 = infinite)"},
00454 // STRTBLID_MIN_PORT
00455     {"Min. Port"},
00456 // STRTBLID_MAX_PORT
00457     {"Max. Port"},
00458 // STRTBLID_LANGUAGE
00459     {"Language"},
00460 // STRTBLID_SERVER_CACHE
00461     {"Server cache"},
00462 // STRTBLID_IS_EMPTY
00463     {"is empty!"},
00464 // STRTBLID_BUS_ADDRESS
00465     {"Bus      Address"},
00466 // STRTBLID_LOCO_PROTOCOLS
00467     {"Loco protocols"},
00468 // STRTBLID_LOCO_DATABASE
00469     {"Loco database"},
00470 // STRTBLID_ACC_PROTOCOLS
00471     {"Accessory protocols"},
00472 // STRTBLID_ACC_DATABASE
00473     {"Accessory database"},
00474 // STRTBLID_CONFIGURATION
00475     {"Configuration"},
00476 // STRTBLID_SYSTEMSTATE
00477     {"SYSTEM STATE"},
00478 // STRTBLID_COMMON
00479     {"COMMON"},
00480 // STRTBLID_SRCP
00481     {"SRCP"},
00482 // STRTBLID_FILE
00483     {"FILE"},
00484 // STRTBLID_PROTOCOL_ACC_REQUEST
00485     {"Accessory protocol request"},
00486 // STRTBLID_STANDARD_ACC_PROTOCOL
00487     {"Standard accessory protocol"},
00488 // STRTBLID_DOWNLOAD_CONFIG
00489     {"The configuration as XML file."},
00490 // STRTBLID_COMMON_ERROR1
00491     {"Common"},
00492 // STRBLDID_COMMON_ERROR2
00493     {"error: %hhu"},
00494 // STRTBLID_DATABASE
00495     {"Database"},
00496 // STRTBLID_POSITION_X
00497     {"position %u"},
00498 // STRTBLID_CONFIGURE
00499     {"Configure"},
00500 // STRTBLID_MAXSPEED
00501     {"Top speed"},
00502 // STRTBLID_FUNCTIONS
00503     {"Functions"},
00504 // STRTBLID_PUSHBUTTON
00505     {"Push button"},
00506 // STRTBLID_SWITCH
00507     {"Switch"},
00508 // STRTBLID_PROTOCOLDATA
00509     {"Protocol data"},
00510 // STRTBLID_SET_PORT_DELAY
00511     {"Delay (0 = default, -1 = infinite)"},
00512 // STRTBLID_MIN_CHARACTER
00513     {"Min. 1 character"},
00514 // STRTBLID_SAVE
00515     {"Save"},
00516 // STRTBLID_UPLOAD_CONFIG
00517     {"Upload a configuration XML file."},
00518 // STRTBLID_OPEN
00519     {"Open"},
00520 // STRTBLID_UPLOAD
00521     {"Upload"},
00522 // STRTBLID_SERVER_URL
00523     {"Server URL"},
00524 // STRTBLID_RESTART_NEEDED
00525     {"Changes take effect after restart!"},
00526 // STRTBLID_MANUAL_IP
00527     {"Manual IP:"},
00528 // STRTBLID_RR_NO_LOCO
00529     {"No loco!"},
00530 // STRTBLID_RR_PLEASE_WAIT
00531     {"Please wait..."},
00532 // STRTBLID_BOOTLOADER_VERSION
00533     {"Bootloader version"},
00534 // STRTBLID_CONNECTION_ERROR1
00535     {"Error while"},
00536 // STRTBLID_CONNECTION_ERROR2
00537     {"connecting!"},
00538 };
00539
00540 ROM STRING_POINTER _asROMStringListIndex[] =
00541 {
00542 // 0 (German string table)
00543     {(ROM char *)_asROMStringListDe},
00544 // 1 (English string table)
00545     {(ROM char *)_asROMStringListEn},
00546 // Add more string tables here
00547 };
00548
00549 ROM void * s_pau8LangTable = _asROMStringListDe;
00550
00551
00552 // ////////////////////////////////////////////////////////////////////////////
00553 // Local function prototypes
00554 // ////////////////////////////////////////////////////////////////////////////
00555
00556
00557
00558 // ////////////////////////////////////////////////////////////////////////////
00559 // ////////////////////////////////////////////////////////////////////////////
00560
00561 void StrTbl_SetLanguage(BYTE u8LangId)
00562 {
00563     if ((u8LangId == LANGID_NOTSPECIFIED) || (u8LangId > LANGID_MAX))
00564     {
00565         u8LangId = LANGID_ENGLISH;
00566     }
00567
00568     s_pau8LangTable = (ROM void *)_asROMStringListIndex[u8LangId].pString;
00569 }
00570
00571 // ////////////////////////////////////////////////////////////////////////////
00572 // ////////////////////////////////////////////////////////////////////////////
00573
00574 void StrTbl_GetString(BYTE * pString, WORD u16StrId)
00575 {
00576     ROM char * pROMString;
00577     pROMString = (((ROM STRING_POINTER*)(s_pau8LangTable))+u16StrId)->pString;
00578     strcpypgm2ram(pString, pROMString);
00579 }
00580
00581 // ////////////////////////////////////////////////////////////////////////////
00582 // ////////////////////////////////////////////////////////////////////////////
00583
00584 ROM char * StrTbl_cau8GetStringPointer(WORD u16StrId)
00585 {
00586     ROM char * pROMString;
00587     pROMString = (((ROM STRING_POINTER*)(s_pau8LangTable))+u16StrId)->pString;
00588     return pROMString;
00589 }
00590
00591 // ////////////////////////////////////////////////////////////////////////////
00592 // ////////////////////////////////////////////////////////////////////////////
00593
00594 ROM char * StrTbl_cau8GetLanguageStringPointer(BYTE u8LangId, WORD u16StrId)
00595 {
00596     ROM char * pROMString;
00597     ROM void * pau8LangTable;
00598
00599     pau8LangTable = (ROM void *)_asROMStringListIndex[u8LangId].pString;
00600     pROMString = (((ROM STRING_POINTER*)(pau8LangTable))+u16StrId)->pString;
00601     return pROMString;
00602 }
00603
00604 // ////////////////////////////////////////////////////////////////////////////
00605 // ////////////////////////////////////////////////////////////////////////////
00606
00607 void StrTbl_GetStringN(BYTE * pString, BYTE u8BufferSize, WORD u16StrId)
00608 {
00609     ROM char * pROMString;
00610     pROMString = (((ROM STRING_POINTER*)(s_pau8LangTable))+u16StrId)->pString;
00611     strncpypgm2ram(pString, pROMString, u8BufferSize);
00612 }
00613
00614 // ////////////////////////////////////////////////////////////////////////////
00615 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: stringtable.h Source File

stringtable.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00022 // ////////////////////////////////////////////////////////////////////////////
00023 // ////////////////////////////////////////////////////////////////////////////
00024
00025 #ifndef STRINGTABLE_H
00026
00027     #define     STRINGTABLE_H
00028
00029
00030 // ////////////////////////////////////////////////////////////////////////////
00031 // Includes
00032 // ////////////////////////////////////////////////////////////////////////////
00033
00034 #include "GenericTypedefs.h"
00035 #include "Compiler.h"
00036
00037 // ////////////////////////////////////////////////////////////////////////////
00038 // Defines
00039 // ////////////////////////////////////////////////////////////////////////////
00040
00041     // Laguage Ids
00043     #define LANGID_NOTSPECIFIED (0xFFu)
00045     #define LANGID_GERMAN       (0x00u)
00047     #define LANGID_ENGLISH      (0x01u)
00049     #define LANGID_MAX          (0x01u)
00050
00051
00052 // ////////////////////////////////////////////////////////////////////////////
00053 // Typedefs
00054 // ////////////////////////////////////////////////////////////////////////////
00055
00057     typedef enum
00058     {
00059         STRTBLID_LANGUAGE_NAME = 0u,
00060         STRTBLID_SUCCESSFULLY_CONNECTED,
00061         STRTBLID_ALLOCATE,
00062         STRTBLID_IP_ADDRESS,
00063         STRTBLID_ADDRESS_CONFLICT1,
00064         STRTBLID_ADDRESS_CONFLICT2,
00065         STRTBLID_CABEL_UNPLUGGED1,
00066         STRTBLID_CABEL_UNPLUGGED2,
00067         STRTBLID_OBTAINED_IP,
00068         STRTBLID_NAMESERVICE,
00069         STRTBLID_STOPPED,
00070         STRTBLID_SEARCHING,
00071         STRTBLID_CONNECT_TO,
00072         STRTBLID_CONNECTION_CLOSED1,
00073         STRTBLID_CONNECTION_CLOSED2,
00074         STRTBLID_DATA_NOT,
00075         STRTBLID_SAVED,
00076         STRTBLID_IP_MENU,
00077         STRTBLID_IP_ALLOCATION,
00078         STRTBLID_MANUAL,
00079         STRTBLID_AUTO,
00080         STRTBLID_SUBNETMASK,
00081         STRTBLID_GATEWAY_ADDRESS,
00082         STRTBLID_SERVER_MENU,
00083         STRTBLID_FIND_SERVER,
00084         STRTBLID_NETWORK_NAME,
00085         STRTBLID_NETWORK_SERVICE,
00086         STRTBLID_SERVER_ADDRESS,
00087         STRTBLID_SERVER_NAME,
00088         STRTBLID_SERVICE_NAME,
00089         STRTBLID_PORT,
00090         STRTBLID_SET_PORT_TO1,
00091         STRTBLID_SET_PORT_TO2,
00092         STRTBLID_DATA_WAS,
00093         STRTBLID_PROTOCOL,
00094         STRTBLID_ADDRESS,
00095         STRTBLID_ACCESS,
00096         STRTBLID_NORMAL,
00097         STRTBLID_EXCLUSIVE,
00098         STRTBLID_NO_DEVICE,
00099         STRTBLID_SERVER_REPORTS,
00100         STRTBLID_ERRORCODE,
00101         STRTBLID_SERVERVERSION,
00102         STRTBLID_UNKNOWN,
00103         STRTBLID_SRVVERSION,
00104         STRTBLID_SRVMODE,
00105         STRTBLID_SRVUNSUFFICIENT_DATA1,
00106         STRTBLID_SRVUNSUFFICIENT_DATA2,
00107         STRTBLID_SRVUNKNOWN_COMMAND1,
00108         STRTBLID_SRVUNKNOWN_COMMAND2,
00109         STRTBLID_SRVNO_RESSOURCES1,
00110         STRTBLID_SRVNO_RESSOURCES2,
00111         STRTBLID_SERVER_HAS,
00112         STRTBLID_DEVICE_TERMINATED,
00113         STRTBLID_INACTIVE,
00114         STRTBLID_ACTIVE,
00115         STRTBLID_CLICK,
00116         STRTBLID_ZEROPOINT,
00117         STRTBLID_ON,
00118         STRTBLID_OFF,
00119         STRTBLID_FIRMWARE_VERSION,
00120         STRTBLID_MAC_ADDRESS,
00121         STRTBLID_CONNECTION,
00122         STRTBLID_LCD_BACKLIGHT,
00123         STRTBLID_CHANGE_VALUES,
00124         STRTBLID_RESTART,
00125         STRTBLID_RESET_TO_FACTORY,
00126         STRTBLID_DIRECTION_MODE,
00127         STRTBLID_PROTOCOL_LOCO_REQUEST,
00128         STRTBLID_STANDARD_LOCO_PROTOCOL,
00129         STRTBLID_PROTOCOLS,
00130         STRTBLID_NAME,
00131         STRTBLID_BUS,
00132         STRTBLID_MIN_ADDRESS,
00133         STRTBLID_MAX_ADDRESS,
00134         STRTBLID_NO_OF_SPEED_STEPS,
00135         STRTBLID_NO_OF_FUNCTIONS,
00136         STRTBLID_NUMBER,
00137         STRTBLID_OK,
00138         STRTBLID_RESET,
00139         STRTBLID_PORT_DELAY,
00140         STRTBLID_MIN_PORT,
00141         STRTBLID_MAX_PORT,
00142         STRTBLID_LANGUAGE,
00143         STRTBLID_SERVER_CACHE,
00144         STRTBLID_IS_EMPTY,
00145         STRTBLID_BUS_ADDRESS,
00146         STRTBLID_LOCO_PROTOCOLS,
00147         STRTBLID_LOCO_DATABASE,
00148         STRTBLID_ACC_PROTOCOLS,
00149         STRTBLID_ACC_DATABASE,
00150         STRTBLID_CONFIGURATION,
00151         STRTBLID_SYSTEMSTATE,
00152         STRTBLID_COMMON,
00153         STRTBLID_SRCP,
00154         STRTBLID_FILE,
00155         STRTBLID_PROTOCOL_ACC_REQUEST,
00156         STRTBLID_STANDARD_ACC_PROTOCOL,
00157         STRTBLID_DOWNLOAD_CONFIG,
00158         STRTBLID_COMMON_ERROR1,
00159         STRTBLID_COMMON_ERROR2,
00160         STRTBLID_DATABASE,
00161         STRTBLID_POSITION_X,
00162         STRTBLID_CONFIGURE,
00163         STRTBLID_MAXSPEED,
00164         STRTBLID_FUNCTIONS,
00165         STRTBLID_PUSHBUTTON,
00166         STRTBLID_SWITCH,
00167         STRTBLID_PROTOCOLDATA,
00168         STRTBLID_SET_PORT_DELAY,
00169         STRTBLID_MIN_CHARACTER,
00170         STRTBLID_SAVE,
00171         STRTBLID_UPLOAD_CONFIG,
00172         STRTBLID_OPEN,
00173         STRTBLID_UPLOAD,
00174         STRTBLID_SERVER_URL,
00175         STRTBLID_RESTART_NEEDED,
00176         STRTBLID_MANUAL_IP,
00177         STRTBLID_NO_LOCO,
00178         STRTBLID_PLEASE_WAIT,
00179         STRTBLID_BOOTLOADER_VERSION,
00180         STRTBLID_CONNECTION_ERROR1,
00181         STRTBLID_CONNECTION_ERROR2
00182     } STRTBLIDS;
00183
00184
00185 // ////////////////////////////////////////////////////////////////////////////
00186 // Function prototypes
00187 // ////////////////////////////////////////////////////////////////////////////
00188
00189 // ////////////////////////////////////////////////////////////////////////////
00200 void StrTbl_SetLanguage(BYTE u8LangId);
00201
00202
00203 // ////////////////////////////////////////////////////////////////////////////
00216 void StrTbl_GetString(BYTE * pString, WORD u16StrId);
00217
00218
00219 // ////////////////////////////////////////////////////////////////////////////
00232 void StrTbl_GetStringN(BYTE * pString, BYTE u8BufferSize, WORD u16StrId);
00233
00234
00235 // ////////////////////////////////////////////////////////////////////////////
00248 ROM char * StrTbl_cau8GetStringPointer(WORD u16StrId);
00249
00250
00251 // ////////////////////////////////////////////////////////////////////////////
00269 ROM char * StrTbl_cau8GetLanguageStringPointer(BYTE u8LangId, WORD u16StrId);
00270
00271
00272 // ////////////////////////////////////////////////////////////////////////////
00273 // Epilogue
00274 // ////////////////////////////////////////////////////////////////////////////
00275
00278 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: version.h Source File

version.h

00001 /* This is an automatically generated file by the shell script version.sh. */
00002
00003 #define FIRMWARE_VERSION_MAJOR  (1u)
00004 #define FIRMWARE_VERSION_MINOR  (1u)
00005 #define FIRMWARE_VERSION_BUILD  (204u)
00006 #define FIRMWARE_VERSION_STRING "V1.1.204"
00007 #define FIRMWARE_VERSION        (0x010100CCul)
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: web.c Source File

web.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00013 // ////////////////////////////////////////////////////////////////////////////
00014 // ////////////////////////////////////////////////////////////////////////////
00015
00016     #define     WEB_C
00017     #include    "web.h"
00018     #include    "webprocess.h"
00019     #include    "config.h"
00020     #include    "xml.h"
00021
00022     #include    "projectdefs.h"
00023
00024
00025 // ////////////////////////////////////////////////////////////////////////////
00026 // Local Defines
00027 // ////////////////////////////////////////////////////////////////////////////
00028
00029 #define WEB_STACKSIZE   200
00030
00031 // ////////////////////////////////////////////////////////////////////////////
00032 // Local Typedefs
00033 // ////////////////////////////////////////////////////////////////////////////
00034
00035 typedef enum
00036 {
00037     VAR_PROTO_ACTIVATE_REQ = 0,
00038     VAR_PROTO_NAME_REQ,
00039     VAR_PROTO_BUS_REQ,
00040     VAR_PROTO_REQ,
00041     VAR_PROTO_MINADD_REQ,
00042     VAR_PROTO_MAXADD_REQ,
00043     VAR_PROTO_SPEC1_REQ,
00044     VAR_PROTO_SPEC2_REQ,
00045     VAR_PROTO_REQ_COUNT
00046 } PROTO_REQ_VARS;
00047
00048 typedef enum
00049 {
00050     VAR_SET_NR_REQ = 0,
00051     VAR_SET_ACTIVATE_REQ,
00052     VAR_SET_NAME_REQ,
00053     VAR_SET_ADDRESS_REQ,
00054     VAR_SET_SETTINGS,
00055     VAR_SET_REQ_COUNT
00056 } SET_REQ_VARS;
00057
00058 typedef enum
00059 {
00060     NAV_CLOSE = 0,
00061     NAV_SUBNAV,
00062     NAV_END,
00063     NAV_SUBNAVEND
00064 } NAV_CONTROL;
00065
00066 typedef struct
00067 {
00068     WORD u16StringId;
00069     ROM BYTE * pFilename;
00070     NAV_CONTROL eNavControl;
00071 } sNavigation;
00072
00073
00074 // ////////////////////////////////////////////////////////////////////////////
00075 // Local Variables
00076 // ////////////////////////////////////////////////////////////////////////////
00077
00078 static BYTE str[WEB_STACKSIZE];
00079 static BYTE * pStr;
00080 static BYTE _currentProcessingIdx = 0;
00081
00082 ROM sNavigation _asROMNavigation[] =
00083 {
00084     PROJECT_WEBSITES
00085 };
00086
00087
00089 // Local Function Prototypes
00091
00092 static BYTE _u8OptionROM(auto BOOL bSel, auto BYTE u8Val, auto char * pu8Dest, auto ROM BYTE * pu8String);
00093 static BYTE _u8RadioROM(auto ROM BYTE * pu8Name, auto DWORD u32Val, auto BOOL bSel, auto BYTE * pu8Dest);
00094 static void _loadNavigation(WORD u16NavId, ROM sNavigation * pNavEntry);
00095
00096 #ifdef _SRCP
00097 static BYTE _u8Option(auto BOOL bSel, auto BYTE u8Val, auto char * pu8Dest, auto BYTE * pu8String);
00098 static BYTE _u8CheckboxROM(auto ROM BYTE * pu8Name, auto BYTE u8Val, auto BOOL bSel, auto BYTE * pu8Dest);
00099 static BYTE _u8TextROM(auto ROM BYTE * pu8Name, auto BYTE * pu8Val, auto BYTE u8Size, auto BYTE * pu8Dest);
00100 static BYTE _u8Radio(auto BYTE * pu8Name, auto DWORD u32Val, auto BOOL bSel, auto BYTE * pu8Dest);
00101 static BYTE _u8HiddenROM(auto ROM BYTE * pu8Name, auto BYTE u8Val, auto BYTE * pu8Dest);
00102 #endif
00103
00104 // ////////////////////////////////////////////////////////////////////////////
00105 // ////////////////////////////////////////////////////////////////////////////
00106
00107 void HTTPPrint_string(WORD u16StringId)
00108 {
00109     TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(u16StringId));
00110 }
00111
00112 // ////////////////////////////////////////////////////////////////////////////
00113 // ////////////////////////////////////////////////////////////////////////////
00114
00115 void HTTPPrint_header(WORD u16NavId)
00116 {
00117     if(curHTTP.callbackPos == 0)
00118     {
00119         // Include the head line.
00120         TCPPutROMString(sktHTTP, (ROM BYTE *)"<h1>eWicht ");
00121         TCPPutROMString(sktHTTP, StrTbl_cau8GetStringPointer(STRTBLID_CONFIGURATION));
00122         TCPPutROMString(sktHTTP, (ROM BYTE *)"</h1>");
00123
00124         // Include the navigation.
00125         TCPPutROMString(sktHTTP, (ROM BYTE *)"<ul id=\"nav\">");
00126     }
00127
00128     if (curHTTP.callbackPos < sizeof(_asROMNavigation)/sizeof(sNavigation))
00129     {
00130         _loadNavigation(u16NavId, &_asROMNavigation[curHTTP.callbackPos++]);
00131     }
00132     else
00133         curHTTP.callbackPos = 0;
00134 }
00135
00136 // ////////////////////////////////////////////////////////////////////////////
00137 // ////////////////////////////////////////////////////////////////////////////
00138
00139 static void _loadNavigation(WORD u16NavId, ROM sNavigation * pNavEntry)
00140 {
00141     TCPPutROMString(sktHTTP, (ROM BYTE *)"<li><a ");
00142     if(u16NavId == pNavEntry->u16StringId)
00143     {
00144         TCPPutROMString(sktHTTP, (ROM BYTE *)"class=\"active\" ");
00145     }
00146     TCPPutROMString(sktHTTP, (ROM BYTE *)"href=\"");
00147     TCPPutROMString(sktHTTP, pNavEntry->pFilename);
00148     TCPPutROMString(sktHTTP, (ROM BYTE *)"\">");
00149     TCPPutROMString(sktHTTP, StrTbl_cau8GetStringPointer(pNavEntry->u16StringId));
00150     TCPPutROMString(sktHTTP, (ROM BYTE *)"</a>");
00151
00152     switch(pNavEntry->eNavControl)
00153     {
00154     case NAV_CLOSE:
00155         TCPPutROMString(sktHTTP, (ROM BYTE *)"</li>");
00156         break;
00157     case NAV_SUBNAV:
00158         TCPPutROMString(sktHTTP, (ROM BYTE *)"<ul>");
00159         break;
00160     case NAV_SUBNAVEND:
00161         TCPPutROMString(sktHTTP, (ROM BYTE *)"</li></ul></li>");
00162         break;
00163     case NAV_END:
00164         TCPPutROMString(sktHTTP, (ROM BYTE *)"</li></ul>");
00165         break;
00166     }
00167 }
00168
00169 // ////////////////////////////////////////////////////////////////////////////
00170 // ////////////////////////////////////////////////////////////////////////////
00171
00172 void HTTPPrint_version(WORD u16Pos)
00173 {
00174     // Determine the version digit.
00175     switch(u16Pos)
00176     {
00177     case VAR_FIRMWARE_VERSION_MAJOR:
00178         TCPPut(sktHTTP, FIRMWARE_VERSION_MAJOR+0x30);
00179         break;
00180
00181     case VAR_FIRMWARE_VERSION_MINOR:
00182         TCPPut(sktHTTP, FIRMWARE_VERSION_MINOR+0x30);
00183         break;
00184
00185     case VAR_FIRMWARE_VERSION_STRING:
00186         TCPPutROMString(sktHTTP, (ROM char *) PROJECT_NAME " ");
00187         TCPPutROMString(sktHTTP, (ROM char *) FIRMWARE_VERSION_STRING " ");
00188         TCPPutROMString(sktHTTP, (ROM char*)__DATE__);
00189         break;
00190
00191     case VAR_BOOTLOADER_VERSION:
00192         {
00193             LONG version;
00194
00195             memcpypgm2ram((void *)&version, BOOTVERSION, sizeof(version));
00196
00197             // First bootloader had no version id (only unwritten flash with value -1).
00198             // Handle this version like version 1:
00199             if (version == -1)
00200             {
00201                 version = 1;
00202             }
00203
00204             sprintf(str, (ROM char *)"%lu", version);
00205             TCPPutString(sktHTTP, str);
00206         }
00207         break;
00208     }
00209 }
00210
00211 // ////////////////////////////////////////////////////////////////////////////
00212 // ////////////////////////////////////////////////////////////////////////////
00213
00214 void HTTPPrint_macaddress(void)
00215 {
00216     // Format the entire string
00217     BYTE i = 0;
00218     while(1)
00219     {
00220         TCPPut(sktHTTP, btohexa_high(pu8MAC[i]));
00221         TCPPut(sktHTTP, btohexa_low(pu8MAC[i]));
00222
00223         if(++i == 6)
00224         {
00225             break;
00226         }
00227         TCPPut(sktHTTP, '-');
00228     }
00229 }
00230
00231 // ////////////////////////////////////////////////////////////////////////////
00232 // ////////////////////////////////////////////////////////////////////////////
00233
00234 void HTTPPrint_ip(WORD u16Pos)
00235 {
00236     // Format the entire string
00237     BYTE i;
00238     DWORD helper = 0;
00239     BYTE * pDataSource = (BYTE*) &helper;
00240
00241     switch(u16Pos)
00242     {
00243         case VAR_IP_ADDRESS:
00244             pDataSource = (BYTE*)&sIPConfig.MyIPAddr;
00245             break;
00246
00247         case VAR_SUBNET_MASK:
00248             pDataSource = (BYTE*)&sIPConfig.MyMask;
00249             break;
00250
00251         case VAR_GATEWAY_ADDRESS:
00252             pDataSource = (BYTE*)&sIPConfig.MyGateway;
00253             break;
00254
00255         case VAR_CONNECTED_SERVER_IP:
00256             if (ApplIsConnected())
00257             {
00258                 pDataSource = (BYTE*)ApplGetServerIP();
00259             }
00260             break;
00261
00262         case VAR_MAN_IP_ADDRESS:
00263             pDataSource = (BYTE*)&sPCommonConfig.ManIPAddr;
00264             break;
00265
00266         case VAR_MAN_SUBNET_MASK:
00267             helper = IPConvertSubnetToMask(sPCommonConfig.ManMask);
00268             break;
00269
00270         case VAR_MAN_GATEWAY_ADDRESS:
00271             pDataSource = (BYTE*)&sPCommonConfig.ManGateway;
00272             break;
00273
00274         case VAR_SERVER_IP:
00275             pDataSource = (BYTE*)&sPApplConfig.sSrvIPAdd;
00276             break;
00277
00278         case VAR_IP_ADDRESS_EEPROM:
00279             XEEReadArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, ManIPAddr), (BYTE *)&helper, sizeof(IP_ADDR));
00280             break;
00281
00282         case VAR_SUBNET_MASK_EEPROM:
00283             XEEReadArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, ManMask), &i, 1);
00284             helper = IPConvertSubnetToMask(i);
00285             break;
00286
00287         case VAR_GATEWAY_ADDRESS_EEPROM:
00288             XEEReadArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, ManGateway), (BYTE *)&helper, sizeof(IP_ADDR));
00289             break;
00290
00291         case VAR_SERVER_IP_EEPROM:
00292             XEEReadArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, sSrvIPAdd), (BYTE *)&helper, sizeof(IP_ADDR));
00293             break;
00294     }
00295
00296     if (pDataSource==0)
00297     {
00298         TCPPutROMString(sktHTTP,(ROM char*)"0.0.0.0");
00299     }
00300     else
00301     {
00302         i = 0;
00303
00304         while(1)
00305         {
00306             itoa((WORD)*pDataSource++, str);
00307             TCPPutString(sktHTTP,str);
00308             if(++i == 4)
00309             {
00310                 break;
00311             }
00312             TCPPut(sktHTTP, '.');
00313         }
00314     }
00315 }
00316
00317 // ////////////////////////////////////////////////////////////////////////////
00318 // ////////////////////////////////////////////////////////////////////////////
00319
00320 void HTTPPrint_addressmode(void)
00321 {
00322     if(sPCommonConfig.Flags.bIsDHCPEnabled)
00323     {
00324         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_AUTO));
00325     }
00326     else
00327     {
00328         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_MANUAL));
00329     }
00330 }
00331
00332 // ////////////////////////////////////////////////////////////////////////////
00333 // ////////////////////////////////////////////////////////////////////////////
00334
00335 void HTTPPrint_askforaddressmode(void)
00336 {
00337     sIPFlags flags;
00338     XEEReadArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, Flags), (BYTE *)&flags, sizeof(sIPFlags));
00339
00340
00341     _u8RadioROM((ROM char *)"ubm", TRUE, flags.bIsDHCPEnabled==TRUE, str);
00342     TCPPutString(sktHTTP, str);
00343     TCPPut(sktHTTP, ' ');
00344     TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_AUTO));
00345
00346     TCPPutROMString(sktHTTP,(ROM char *)"<br>");
00347
00348     _u8RadioROM((ROM char *)"ubm", FALSE, flags.bIsDHCPEnabled==FALSE, str);
00349     TCPPutString(sktHTTP, str);
00350     TCPPut(sktHTTP, ' ');
00351     TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_MANUAL));
00352 }
00353
00354 // ////////////////////////////////////////////////////////////////////////////
00355 // ////////////////////////////////////////////////////////////////////////////
00356
00357 void HTTPPrint_hostname(void)
00358 {
00359     TCPPutROMString(sktHTTP, HOSTNAME);
00360 }
00361
00362 // ////////////////////////////////////////////////////////////////////////////
00363 // ////////////////////////////////////////////////////////////////////////////
00364
00365 void HTTPPrint_mdns(void)
00366 {
00367     if(eGetMDNSState() == MDNS_HAS_STOPPED)
00368     {
00369         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_INACTIVE));
00370     }
00371     else
00372     {
00373         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_ACTIVE));
00374     }
00375 }
00376
00377 // ////////////////////////////////////////////////////////////////////////////
00378 // ////////////////////////////////////////////////////////////////////////////
00379
00380 void HTTPPrint_connection(void)
00381 {
00382     if (ApplIsConnected()==TRUE)
00383     {
00384         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_ACTIVE));
00385     }
00386     else
00387     {
00388         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_INACTIVE));
00389     }
00390 }
00391
00392 // ////////////////////////////////////////////////////////////////////////////
00393 // ////////////////////////////////////////////////////////////////////////////
00394
00395 void HTTPPrint_serverport(void)
00396 {
00397     WORD port = ApplGetServerPort().Val;
00398     if (ApplIsConnected()==FALSE)
00399     {
00400         port = 0;
00401     }
00402     sprintf(str, (ROM char *) "%5hu", port);
00403     TCPPutString(sktHTTP, str);
00404 }
00405
00406 // ////////////////////////////////////////////////////////////////////////////
00407 // ////////////////////////////////////////////////////////////////////////////
00408
00409 void HTTPPrint_locodir(void)
00410 {
00411     if (sPApplConfig.sFlags.bToggleLocoDirMode==TOGGLEDIRMODE_CLICK)
00412     {
00413         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_CLICK));
00414     }
00415     else
00416     {
00417         TCPPutROMString(sktHTTP,StrTbl_cau8GetStringPointer(STRTBLID_ZEROPOINT));
00418     }
00419 }
00420
00421 // ////////////////////////////////////////////////////////////////////////////
00422 // ////////////////////////////////////////////////////////////////////////////
00423
00424 void HTTPPrint_toggledir(void)
00425 {
00426     WORD len = TCPIsPutReady(sktHTTP);
00427     BOOL bFlag = FALSE;
00428
00429     if(curHTTP.callbackPos == 0)
00430     {
00431         pStr = str;
00432         curHTTP.callbackPos =
00433             _u8OptionROM(!sPApplConfig.sFlags.bToggleLocoDirMode,
00434                          TOGGLEDIRMODE_CLICK,
00435                          pStr,
00436                          StrTbl_cau8GetStringPointer(STRTBLID_CLICK));
00437
00438         curHTTP.callbackPos +=
00439             _u8OptionROM(sPApplConfig.sFlags.bToggleLocoDirMode,
00440                          TOGGLEDIRMODE_ZERO,
00441                          &pStr[curHTTP.callbackPos],
00442                          StrTbl_cau8GetStringPointer(STRTBLID_ZEROPOINT));
00443     }
00444
00445     if (len > curHTTP.callbackPos)
00446     {
00447         len = curHTTP.callbackPos;
00448     }
00449
00450     TCPPutArray(sktHTTP, pStr, len);
00451     pStr+=len;
00452     curHTTP.callbackPos-= len;
00453 }
00454
00455 // ////////////////////////////////////////////////////////////////////////////
00456 // ////////////////////////////////////////////////////////////////////////////
00457
00458 void HTTPPrint_xmllanguage(void)
00459 {
00460     sprintf(str,
00461             (ROM char *)"%hhu",
00462             sPCommonConfig.u8LanguageID);
00463     TCPPutString(sktHTTP, str);
00464 }
00465
00466 // ////////////////////////////////////////////////////////////////////////////
00467 // ////////////////////////////////////////////////////////////////////////////
00468
00469 void HTTPPrint_ledlight(void)
00470 {
00471     sprintf(str, (ROM char *)"%hhu", sPCommonConfig.u8LCDLight);
00472     TCPPutString(sktHTTP, str);
00473 }
00474
00475 // ////////////////////////////////////////////////////////////////////////////
00476 // ////////////////////////////////////////////////////////////////////////////
00477
00478 void HTTPPrint_xmlip(void)
00479 {
00480     TCPPutROMString(sktHTTP, (ROM char *)"autoip=\"");
00481
00482     if (sPCommonConfig.Flags.bIsDHCPEnabled == TRUE)
00483     {
00484         // No IP settings if DHCP (resp. AutoIP) is enabled.
00485         TCPPut(sktHTTP, '1');
00486     }
00487     else
00488     {
00489         TCPPut(sktHTTP, '0');
00490         TCPPutROMString(sktHTTP, (ROM char *)"ip=\"");
00491         HTTPPrint_ip(VAR_MAN_IP_ADDRESS);
00492         TCPPutROMString(sktHTTP, (ROM char *)"\" sub=\"");
00493         HTTPPrint_ip(VAR_MAN_SUBNET_MASK);
00494         TCPPutROMString(sktHTTP, (ROM char *)"\" gate=\"");
00495         HTTPPrint_ip(VAR_MAN_GATEWAY_ADDRESS);
00496     }
00497     TCPPut(sktHTTP, '\"');
00498 }
00499
00500 // ////////////////////////////////////////////////////////////////////////////
00501 // ////////////////////////////////////////////////////////////////////////////
00502
00503 void HTTPPrint_xmltoggle(void)
00504 {
00505     str[0] = '0';
00506     str[1] = 0;
00507     if (sPApplConfig.sFlags.bToggleLocoDirMode)
00508     {
00509         str[0] = '1';
00510     }
00511     TCPPutString(sktHTTP, str);
00512 }
00513
00514 // ////////////////////////////////////////////////////////////////////////////
00515 // ////////////////////////////////////////////////////////////////////////////
00516
00517 void HTTPPrint_serverurl(void)
00518 {
00519     SEARCH_MODE mode;
00520     XEEReadArray(APPL_EEPROM_ADD + offsetof(SPAPPLDATA, eFindMode), (BYTE *)&mode, sizeof(SEARCH_MODE));
00521
00522     switch(mode)
00523     {
00524         case SEARCH_UNKNOWN:
00525             return;
00526
00527         case SEARCH_IP:
00528             {
00529                 WORD port;
00530                 HTTPPrint_ip(VAR_SERVER_IP_EEPROM);
00531                 XEEReadArray(APPL_EEPROM_ADD + offsetof(SPAPPLDATA, sIPPort), (BYTE *)&port, 2);
00532                 sprintf(str, (ROM char *)":%hu", port);
00533             }
00534             break;
00535
00536         case SEARCH_NAME:
00537             {
00538                 WORD port;
00539                 XEEReadArray(APPL_EEPROM_ADD + offsetof(SPAPPLDATA, au8Name), str, LCD_CHARS_IN_A_ROW+1);
00540                 XEEReadArray(APPL_EEPROM_ADD + offsetof(SPAPPLDATA, sNamePort), (BYTE *)&port, 2);
00541                 sprintf(&str[strlen(str)], (ROM char *)":%hu", port);
00542             }
00543             break;
00544
00545         case SEARCH_SERVICE:
00546             XEEReadArray(APPL_EEPROM_ADD + offsetof(SPAPPLDATA, au8Service), str, LCD_CHARS_IN_A_ROW+1);
00547             break;
00548     }
00549
00550
00551     TCPPutString(sktHTTP, str);
00552 }
00553
00554 // ////////////////////////////////////////////////////////////////////////////
00555 // ////////////////////////////////////////////////////////////////////////////
00556
00557 void HTTPPrint_language(void)
00558 {
00559     WORD len = TCPIsPutReady(sktHTTP);
00560     BOOL bFlag = FALSE;
00561
00562     if(curHTTP.callbackPos == 0)
00563     {
00564         pStr = str;
00565
00566         curHTTP.callbackPos =
00567             _u8OptionROM(sPCommonConfig.u8LanguageID==LANGID_GERMAN,
00568                          LANGID_GERMAN,
00569                          pStr,
00570                          StrTbl_cau8GetLanguageStringPointer(LANGID_GERMAN, STRTBLID_LANGUAGE_NAME));
00571
00572         curHTTP.callbackPos +=
00573             _u8OptionROM(sPCommonConfig.u8LanguageID==LANGID_ENGLISH,
00574                          LANGID_ENGLISH,
00575                          &pStr[curHTTP.callbackPos],
00576                          StrTbl_cau8GetLanguageStringPointer(LANGID_ENGLISH, STRTBLID_LANGUAGE_NAME));
00577     }
00578
00579     if (len > curHTTP.callbackPos)
00580         len = curHTTP.callbackPos;
00581
00582     TCPPutArray(sktHTTP, pStr, len);
00583     pStr+=len;
00584     curHTTP.callbackPos -= len;
00585 }
00586
00587
00588 // ////////////////////////////////////////////////////////////////////////////
00589 #ifdef _SRCP
00590 // ////////////////////////////////////////////////////////////////////////////
00591
00592 #include "srcp.h"
00593
00594 void HTTPPrint_locoproto(void)
00595 {
00596     if (sPSRCPConfig.sFlags.bGLAskForProto == TRUE)
00597     {
00598         TCPPutROMString(sktHTTP, StrTbl_cau8GetStringPointer(STRTBLID_ON));
00599     }
00600     else
00601     {
00602         TCPPutROMString(sktHTTP, StrTbl_cau8GetStringPointer(STRTBLID_OFF));
00603     }
00604 }
00605
00606 // ////////////////////////////////////////////////////////////////////////////
00607 // ////////////////////////////////////////////////////////////////////////////
00608
00609 void HTTPPrint_accproto(void)
00610 {
00611     if (sPSRCPConfig.sFlags.bGAAskForProto == TRUE)
00612     {
00613         TCPPutROMString(sktHTTP, StrTbl_cau8GetStringPointer(STRTBLID_ON));
00614     }
00615     else
00616     {
00617         TCPPutROMString(sktHTTP, StrTbl_cau8GetStringPointer(STRTBLID_OFF));
00618     }
00619 }
00620
00621 // ////////////////////////////////////////////////////////////////////////////
00622 // ////////////////////////////////////////////////////////////////////////////
00623
00624 void HTTPPrint_xmldelay(void)
00625 {
00626     sprintf(str, (ROM char *) "%ld", sPSRCPConfig.s32GADelay);
00627     TCPPutString(sktHTTP, str);
00628 }
00629
00630 // ////////////////////////////////////////////////////////////////////////////
00631 // ////////////////////////////////////////////////////////////////////////////
00632
00633 void HTTPPrint_askfordelay(void)
00634 {
00635     BYTE num[20];
00636     sprintf(num, (ROM char *) "%ld", sPSRCPConfig.s32GADelay);
00637     _u8TextROM((ROM char *)"dV", num, 9, str);
00638
00639     TCPPutString(sktHTTP, str);
00640 }
00641
00642 // ////////////////////////////////////////////////////////////////////////////
00643 // ////////////////////////////////////////////////////////////////////////////
00644
00645 void HTTPPrint_askforproto(WORD u16IsGL)
00646 {
00647     WORD len = TCPIsPutReady(sktHTTP);
00648     BOOL bFlag = FALSE;
00649
00650     if (u16IsGL)
00651     {
00652         bFlag = sPSRCPConfig.sFlags.bGLAskForProto;
00653     }
00654     else
00655     {
00656         bFlag = sPSRCPConfig.sFlags.bGAAskForProto;
00657     }
00658
00659     if(curHTTP.callbackPos == 0)
00660     {
00661         pStr = str;
00662         curHTTP.callbackPos =
00663             _u8OptionROM(!bFlag,
00664                          0,
00665                          pStr,
00666                          StrTbl_cau8GetStringPointer(STRTBLID_OFF));
00667
00668         curHTTP.callbackPos += _u8OptionROM(bFlag,
00669                          1,
00670                          &pStr[curHTTP.callbackPos],
00671                          StrTbl_cau8GetStringPointer(STRTBLID_ON));
00672     }
00673
00674     if (len > curHTTP.callbackPos)
00675     {
00676         len = curHTTP.callbackPos;
00677     }
00678
00679     TCPPutArray(sktHTTP, pStr, len);
00680     pStr+=len;
00681     curHTTP.callbackPos -= len;
00682 }
00683
00684 // ////////////////////////////////////////////////////////////////////////////
00685 // ////////////////////////////////////////////////////////////////////////////
00686
00687 void HTTPPrint_xmlproto(WORD u16Pos)
00688 {
00689     SPPROTOCOL protocoldata;
00690     WORD len;
00691
00692     SRCP_GetProtoFromEEPROM((BYTE)u16Pos, &protocoldata);
00693
00694     if (protocoldata.sFlags.bActive == FALSE)
00695     {
00696         return;
00697     }
00698
00699     len = TCPIsPutReady(sktHTTP);
00700
00701     TCPPutROMString(sktHTTP, (ROM char *) "\n<srcpproto ");
00702     sprintf(str, (ROM char *)" id=\"%hu\">\n\t<data", u16Pos);
00703     TCPPutString(sktHTTP, str);
00704
00705     TCPPutROMString(sktHTTP, (ROM char *)" name=\"");
00706     XMLPutString(sktHTTP, protocoldata.au8Desc);
00707     TCPPut(sktHTTP, '\"');
00708
00709     TCPPutROMString(sktHTTP, (ROM char *)" proto=\"");
00710     XMLPutString(sktHTTP, protocoldata.au8Proto);
00711     TCPPut(sktHTTP, '\"');
00712
00713     sprintf(str, (ROM char *)" bus=\"%hhu\" minadd=\"%hu\" maxadd=\"%hu\"",
00714             protocoldata.u8Bus, protocoldata.u16MinAdd, protocoldata.u16MaxAdd);
00715     TCPPutString(sktHTTP, str);
00716
00717     // Check for accessory:
00718     if (u16Pos >= MAX_PROTO_SLOTS)
00719     {
00720         sprintf(str, (ROM char *) " minport=\"%hhu\" maxport=\"%hhu\"",
00721             protocoldata.uSpec.sGA.u8MinP, protocoldata.uSpec.sGA.u8MaxP);
00722     }
00723     else
00724     {
00725         sprintf(str, (ROM char *) " steps=\"%hhu\" funcs=\"%hhu\"",
00726             protocoldata.uSpec.sGL.u8MaxSteps, protocoldata.uSpec.sGL.u8NrFunc);
00727     }
00728
00729     TCPPutString(sktHTTP, str);
00730     TCPPutROMString(sktHTTP, (ROM char *) "/></srcpproto>\n");
00731 }
00732
00733 // ////////////////////////////////////////////////////////////////////////////
00734 // ////////////////////////////////////////////////////////////////////////////
00735
00736 void HTTPPrint_xmlset(WORD u16SetIdx)
00737 {
00738     SPSET setdata;
00739     SRCP_GetSetFromEEPROM((BYTE)u16SetIdx, &setdata);
00740
00741     if (setdata.sFlags.bActive == FALSE)
00742     {
00743         return;
00744     }
00745
00746     TCPPutROMString(sktHTTP, (ROM char *) "\n<srcpdb ");
00747
00748     sprintf(str, (ROM char *)"id=\"%hu\">\n\t<data", u16SetIdx);
00749     TCPPutString(sktHTTP, str);
00750     TCPPutROMString(sktHTTP, (ROM char *)" name=\"");
00751     XMLPutString(sktHTTP, setdata.au8Name);
00752     sprintf(str, (ROM char *)"\" bus=\"%hhu\"", setdata.u8BusNr);
00753     TCPPutString(sktHTTP, str);
00754     TCPPutROMString(sktHTTP, (ROM char *)" proto=\"");
00755     XMLPutString(sktHTTP, setdata.au8Proto);
00756     sprintf(str, (ROM char *)"\" add=\"%lu\"", setdata.u32Address);
00757     TCPPutString(sktHTTP, str);
00758
00759     if (u16SetIdx & SRCP_EEPROMSET_GA_MASK)
00760     {
00761         sprintf(str, (ROM char *)" minport=\"%hu\" maxport=\"%hu\" delay=\"%ld\"",
00762             setdata.uSpec.sGA.u8MinP, setdata.uSpec.sGA.u8MaxP, setdata.uSpec.sGA.s32Delay);
00763     }
00764     else
00765     {
00766         sprintf(str, (ROM char *)" steps=\"%hu\" funcs=\"%hu\" maxspeed=\"%hu\" togglemask=\"%lu\"",
00767             setdata.uSpec.sGL.u8MaxSteps, setdata.uSpec.sGL.u8NrFunc, setdata.uSpec.sGL.u16MaxV, setdata.uSpec.sGL.u32FuncToggleMask);
00768     }
00769
00770     TCPPutString(sktHTTP, str);
00771     TCPPutROMString(sktHTTP, (ROM char *) "/></srcpdb>\n");
00772 }
00773
00774 // ////////////////////////////////////////////////////////////////////////////
00775 // ////////////////////////////////////////////////////////////////////////////
00776
00777 static BYTE u8Colcount;
00778 static BOOL bStartNewCol;
00779
00780 void HTTPPrint_eepromset(WORD u16SetIdx)
00781 {
00782     WORD len = TCPIsPutReady(sktHTTP);
00783
00784     if(curHTTP.callbackPos == 0)
00785     {
00786         // First time here!
00787         u8Colcount = 0;
00788         bStartNewCol = TRUE;
00789
00790         // Starting the row...
00791         strcpypgm2ram(str, (ROM char *) "<tr>");
00792         pStr = &str[4];
00793     }
00794
00795     if (bStartNewCol == TRUE)
00796     {
00797         SPSET setdata;
00798         BYTE num[6];
00799         SRCP_GetSetFromEEPROM(u16SetIdx, &setdata);
00800
00801         strcpypgm2ram(pStr, (ROM char *) "<td>");
00802         pStr += 4;
00803
00804         switch(u8Colcount++)
00805         {
00806             case VAR_SET_NR_REQ:
00807             {
00808                 BYTE nr = u16SetIdx & SRCP_EEPROMSET_IDX_MASK;
00809                 pStr += _u8HiddenROM((ROM BYTE *)"A", u16SetIdx, pStr);
00810                 pStr += sprintf(pStr, (ROM char *) "S%hu", nr+1);
00811                 break;
00812             }
00813
00814             case VAR_SET_ACTIVATE_REQ:
00815                 pStr += _u8CheckboxROM((ROM char *)"c",
00816                                     u16SetIdx,
00817                                     (setdata.sFlags.bActive),
00818                                     pStr);
00819                 break;
00820
00821             case VAR_SET_NAME_REQ:
00822                 pStr += _u8TextROM((ROM char *)"n", setdata.au8Name, SRCP_NAME_MAXLEN, pStr);
00823                 break;
00824
00825             case VAR_SET_ADDRESS_REQ:
00826                 sprintf(num, (ROM char *) "%lu", setdata.u32Address);
00827                 pStr += _u8TextROM((ROM char *)"usm", num, 5, pStr);
00828                 break;
00829
00830             case VAR_SET_SETTINGS:
00831                 if (setdata.sFlags.bGL == FALSE)
00832                 {
00833                     strcpypgm2ram(pStr, (ROM char *)"<a href=\"accset.htm?");
00834                 }
00835                 else
00836                 {
00837                     strcpypgm2ram(pStr, (ROM char *)"<a href=\"locoset.htm?");
00838                 }
00839
00840                 pStr = &str[strlen(str)];
00841                 sprintf(pStr, (ROM char *)"%hhu\">%HS...</a>", u16SetIdx, StrTbl_cau8GetStringPointer(STRTBLID_CONFIGURE));
00842                 pStr = &str[strlen(str)];
00843                 pStr += _u8HiddenROM((ROM BYTE *)"E", u16SetIdx, pStr);
00844                 break;
00845         }
00846
00847         strcpypgm2ram(pStr, (ROM char *) "</td>");
00848         pStr += 5;
00849
00850         // Have we reached the last column?
00851         if (u8Colcount == VAR_PROTO_REQ_COUNT)
00852         {
00853             // Lets close the row!
00854             strcpypgm2ram(pStr, (ROM char *) "</tr>");
00855         }
00856
00857         bStartNewCol = FALSE;
00858         curHTTP.callbackPos = strlen(str);
00859         pStr = str;
00860     }
00861
00862 #ifdef __DEBUG
00863     if(curHTTP.callbackPos>WEB_STACKSIZE)
00864     {
00865         while(1);
00866     }
00867 #endif
00868
00869     if (len > curHTTP.callbackPos)
00870     {
00871         len = curHTTP.callbackPos;
00872     }
00873
00874     TCPPutArray(sktHTTP, pStr, len);
00875     curHTTP.callbackPos-= len;
00876
00877     if (curHTTP.callbackPos == 0)
00878     {
00879         bStartNewCol = TRUE;
00880
00881         if (u8Colcount == VAR_SET_REQ_COUNT)
00882         {
00883             // Finished writing the entire row.
00884             return;
00885         }
00886
00887         // Ensure that the function is called again.
00888         curHTTP.callbackPos = 1;
00889     }
00890     else
00891     {
00892         pStr+=len;
00893     }
00894 }
00895
00896 // ////////////////////////////////////////////////////////////////////////////
00897 // ////////////////////////////////////////////////////////////////////////////
00898
00899 void HTTPPrint_protoreq(WORD u16Pos)
00900 {
00901     WORD len = TCPIsPutReady(sktHTTP);
00902
00903     if(curHTTP.callbackPos == 0)
00904     {
00905         // First time here!
00906         u8Colcount = 0;
00907         bStartNewCol = TRUE;
00908     }
00909
00910     if (bStartNewCol == TRUE)
00911     {
00912         SPPROTOCOL protocoldata;
00913         BYTE num[6];
00914         SRCP_GetProtoFromEEPROM(u16Pos, &protocoldata);
00915
00916         pStr = str;
00917         if (u8Colcount == 0)
00918         {
00919             strcpypgm2ram(pStr, (ROM char *) "<tr>");
00920             pStr = &str[4];
00921         }
00922
00923         strcpypgm2ram(pStr, (ROM char *) "<td>");
00924         pStr += 4;
00925
00926         switch(u8Colcount++)
00927         {
00928             case VAR_PROTO_ACTIVATE_REQ:
00929                 pStr += _u8HiddenROM((ROM BYTE *)"A", u16Pos, pStr);
00930                 pStr += _u8CheckboxROM((ROM char *)"c",
00931                                        u16Pos,
00932                                        protocoldata.sFlags.bActive,
00933                                        pStr);
00934                 break;
00935
00936             case VAR_PROTO_NAME_REQ:
00937                 pStr += _u8TextROM((ROM char *)"n", protocoldata.au8Desc, 16, pStr);
00938                 break;
00939
00940             case VAR_PROTO_BUS_REQ:
00941                 sprintf(num, (ROM char *) "%hhu", protocoldata.u8Bus);
00942                 pStr += _u8TextROM((ROM char *)"ubb", num, 3, pStr);
00943                 break;
00944
00945             case VAR_PROTO_REQ:
00946                 pStr += _u8TextROM((ROM char *)"p", protocoldata.au8Proto, 3, pStr);
00947                 break;
00948
00949             case VAR_PROTO_MINADD_REQ:
00950                 sprintf(num, (ROM char *) "%hu", protocoldata.u16MinAdd);
00951                 pStr += _u8TextROM((ROM char *)"usm", num, 5, pStr);
00952                 break;
00953
00954             case VAR_PROTO_MAXADD_REQ:
00955                 sprintf(num, (ROM char *) "%hu", protocoldata.u16MaxAdd);
00956                 pStr += _u8TextROM((ROM char *)"usx", num, 5, pStr);
00957                 break;
00958
00959             case VAR_PROTO_SPEC1_REQ:
00960                 sprintf(num, (ROM char *) "%hhu", protocoldata.uSpec.sGL.u8MaxSteps);
00961                 if (protocoldata.sFlags.bGL == TRUE)
00962                 {
00963                     pStr += _u8TextROM((ROM char *)"ubs", num, 3, pStr);
00964                 }
00965                 else
00966                 {
00967                     pStr += _u8TextROM((ROM char *)"ubq", num, 3, pStr);
00968                 }
00969                 break;
00970
00971             case VAR_PROTO_SPEC2_REQ:
00972                 sprintf(num, (ROM char *) "%hhu", protocoldata.uSpec.sGL.u8NrFunc);
00973                 if (protocoldata.sFlags.bGL == TRUE)
00974                 {
00975                     pStr += _u8TextROM((ROM char *)"ubf", num, 3, pStr);
00976                 }
00977                 else
00978                 {
00979                     pStr += _u8TextROM((ROM char *)"ubr", num, 3, pStr);
00980                 }
00981                 pStr += _u8HiddenROM((ROM BYTE *)"E", u16Pos, pStr);
00982                 break;
00983         }
00984
00985         strcpypgm2ram(pStr, (ROM char *) "</td>");
00986         pStr += 5;
00987
00988         // Have we reached the last column?
00989         if (u8Colcount == VAR_PROTO_REQ_COUNT)
00990         {
00991             // Lets close the row!
00992             strcpypgm2ram(pStr, (ROM char *) "</tr>");
00993         }
00994
00995         bStartNewCol = FALSE;
00996         curHTTP.callbackPos = strlen(str);
00997         pStr = str;
00998     }
00999
01000 #ifdef __DEBUG
01001     if(curHTTP.callbackPos>WEB_STACKSIZE)
01002     {
01003         while(1);
01004     }
01005 #endif
01006
01007     if (len > curHTTP.callbackPos)
01008     {
01009         len = curHTTP.callbackPos;
01010     }
01011
01012     TCPPutArray(sktHTTP, pStr, len);
01013     curHTTP.callbackPos-= len;
01014
01015     if (curHTTP.callbackPos == 0)
01016     {
01017         bStartNewCol = TRUE;
01018
01019         if (u8Colcount == VAR_PROTO_REQ_COUNT)
01020         {
01021             // Finished writing the entire row.
01022             return;
01023         }
01024
01025         // Ensure that the function is called again.
01026         curHTTP.callbackPos = 1;
01027     }
01028     else
01029     {
01030         pStr+=len;
01031     }
01032 }
01033
01034 // ////////////////////////////////////////////////////////////////////////////
01035 // ////////////////////////////////////////////////////////////////////////////
01036
01037 void HTTPPrint_xmllocoprotoreq(void)
01038 {
01039     if (sPSRCPConfig.sFlags.bGLAskForProto)
01040     {
01041         TCPPut(sktHTTP, '1');
01042     }
01043     else
01044     {
01045         TCPPut(sktHTTP, '0');
01046     }
01047 }
01048
01049 // ////////////////////////////////////////////////////////////////////////////
01050 // ////////////////////////////////////////////////////////////////////////////
01051
01052 void HTTPPrint_xmlaccprotoreq(void)
01053 {
01054     if (sPSRCPConfig.sFlags.bGAAskForProto)
01055     {
01056         TCPPut(sktHTTP, '1');
01057     }
01058     else
01059     {
01060         TCPPut(sktHTTP, '0');
01061     }
01062 }
01063
01064 // ////////////////////////////////////////////////////////////////////////////
01065 // ////////////////////////////////////////////////////////////////////////////
01066
01067 void HTTPPrint_xmllocostandard(void)
01068 {
01069     sprintf(str, (ROM char *)"%hhu", sPSRCPConfig.u8DefaultGLProtoId);
01070     TCPPutString(sktHTTP, str);
01071 }
01072
01073 // ////////////////////////////////////////////////////////////////////////////
01074 // ////////////////////////////////////////////////////////////////////////////
01075
01076 void HTTPPrint_xmlaccstandard(void)
01077 {
01078     sprintf(str, (ROM char *)"%hhu", sPSRCPConfig.u8DefaultGAProtoId);
01079     TCPPutString(sktHTTP, str);
01080 }
01081
01082 // ////////////////////////////////////////////////////////////////////////////
01083 // ////////////////////////////////////////////////////////////////////////////
01084
01085 void HTTPPrint_locostandard(void)
01086 {
01087     auto WORD len = TCPIsPutReady(sktHTTP);
01088
01089     if(curHTTP.callbackPos == 0)
01090     {
01091         // First time here!
01092         _u8OptionROM(sPSRCPConfig.u8DefaultGLProtoId == SRCP_SERVERCACHE_ID,
01093                              SRCP_SERVERCACHE_ID,
01094                              str,
01095                              StrTbl_cau8GetStringPointer(STRTBLID_SERVER_CACHE));
01096
01097         pStr = &str[strlen(str)];
01098         _u8OptionROM(sPSRCPConfig.u8DefaultGLProtoId == SRCP_EEPROMSET_ID,
01099                              SRCP_EEPROMSET_ID,
01100                              pStr,
01101                              StrTbl_cau8GetStringPointer(STRTBLID_DATABASE));
01102
01103         pStr = str;
01104         // As long as callbackPos is not zero the function is called again and
01105         // again.
01106         curHTTP.callbackPos = 1;
01107     }
01108     else if ((strlen(pStr) == 0) && (curHTTP.callbackPos < 9))
01109     {
01110         SPPROTOCOL protocoldata;
01111         SRCP_GetProtoFromEEPROM(curHTTP.callbackPos-1, &protocoldata);
01112
01113         if (protocoldata.sFlags.bActive)
01114         {
01115             _u8Option(sPSRCPConfig.u8DefaultGLProtoId == (curHTTP.callbackPos-1),
01116                                         curHTTP.callbackPos-1,
01117                                         str,
01118                                         protocoldata.au8Desc);
01119             pStr = str;
01120         }
01121         curHTTP.callbackPos++;
01122     }
01123
01124     if (len > strlen(pStr))
01125     {
01126         len = strlen(pStr);
01127     }
01128
01129     TCPPutArray(sktHTTP, pStr, len);
01130     pStr+=len;
01131
01132     if ((strlen(pStr) == 0) && (curHTTP.callbackPos == 9))
01133     {
01134         curHTTP.callbackPos = 0;
01135         return;
01136     }
01137 }
01138
01139 // ////////////////////////////////////////////////////////////////////////////
01140 // ////////////////////////////////////////////////////////////////////////////
01141
01142 void HTTPPrint_accstandard(void)
01143 {
01144     auto WORD len = TCPIsPutReady(sktHTTP);
01145
01146     if(curHTTP.callbackPos == 0)
01147     {
01148         // First time here!
01149         _u8OptionROM(sPSRCPConfig.u8DefaultGAProtoId == SRCP_EEPROMSET_ID,
01150                              SRCP_EEPROMSET_ID,
01151                              str,
01152                              StrTbl_cau8GetStringPointer(STRTBLID_DATABASE));
01153
01154         pStr = str;
01155         // As long as callbackPos is not zero the function is called again and
01156         // again.
01157         curHTTP.callbackPos = 8;
01158     }
01159
01160     if ((strlen(pStr) == 0)&&(curHTTP.callbackPos<16))
01161     {
01162         SPPROTOCOL protocoldata;
01163         SRCP_GetProtoFromEEPROM(curHTTP.callbackPos, &protocoldata);
01164
01165         if (protocoldata.sFlags.bActive)
01166         {
01167             _u8Option(sPSRCPConfig.u8DefaultGAProtoId == (curHTTP.callbackPos),
01168                                         curHTTP.callbackPos,
01169                                         str,
01170                                         protocoldata.au8Desc);
01171             pStr = str;
01172         }
01173         curHTTP.callbackPos++;
01174     }
01175
01176     if (len > strlen(pStr))
01177     {
01178         len = strlen(pStr);
01179     }
01180
01181     TCPPutArray(sktHTTP, pStr, len);
01182     pStr+=len;
01183
01184     if ((strlen(pStr) == 0) && (curHTTP.callbackPos == 16))
01185     {
01186         curHTTP.callbackPos = 0;
01187         return;
01188     }
01189 }
01190
01191 // ////////////////////////////////////////////////////////////////////////////
01192 // ////////////////////////////////////////////////////////////////////////////
01193
01194 void HTTPPrint_setid(void)
01195 {
01196     auto BYTE tmp[6];
01197     btoa((_currentProcessingIdx & SRCP_EEPROMSET_IDX_MASK)+1, tmp);
01198     TCPPutString(sktHTTP, tmp);
01199 }
01200
01201 // ////////////////////////////////////////////////////////////////////////////
01202 // ////////////////////////////////////////////////////////////////////////////
01203
01204 void HTTPPrint_setidx(void)
01205 {
01206     auto BYTE tmp[6];
01207     btoa(_currentProcessingIdx, tmp);
01208     TCPPutString(sktHTTP, tmp);
01209 }
01210
01211 // ////////////////////////////////////////////////////////////////////////////
01212 // ////////////////////////////////////////////////////////////////////////////
01213
01214 void HTTPPrint_setname(void)
01215 {
01216     auto SPSET * pSetdata = (SPSET *)str;
01217     BYTE * pStr = &str[sizeof(SPSET)];
01218
01219     _u8TextROM((ROM char *)"n",pSetdata->au8Name,SRCP_NAME_MAXLEN,pStr);
01220     TCPPutString(sktHTTP, pStr);
01221 }
01222
01223 // ////////////////////////////////////////////////////////////////////////////
01224 // ////////////////////////////////////////////////////////////////////////////
01225
01226 void HTTPPrint_setaddress(void)
01227 {
01228     auto SPSET * pSetdata = (SPSET *)str;
01229     auto BYTE num[10];
01230     auto BYTE * pStr = &str[sizeof(SPSET)];
01231
01232     sprintf(num, (ROM char *) "%lu", pSetdata->u32Address);
01233     _u8TextROM((ROM char *)"usm", num, 5, pStr);
01234     TCPPutString(sktHTTP, pStr);
01235 }
01236
01237 // ////////////////////////////////////////////////////////////////////////////
01238 // ////////////////////////////////////////////////////////////////////////////
01239
01240 void HTTPPrint_setmaxspeed(void)
01241 {
01242     auto SPSET * pSetdata = (SPSET *)str;
01243     auto BYTE num[6];
01244     auto BYTE * pStr = &str[sizeof(SPSET)];
01245
01246     sprintf(num, (ROM char *) "%hu", pSetdata->uSpec.sGL.u16MaxV);
01247     _u8TextROM((ROM char *)"ush", num, 5, pStr);
01248     TCPPutString(sktHTTP, pStr);
01249 }
01250
01251 // ////////////////////////////////////////////////////////////////////////////
01252 // ////////////////////////////////////////////////////////////////////////////
01253
01254 void HTTPPrint_setbus(void)
01255 {
01256     auto SPSET * pSetdata = (SPSET *)str;
01257     auto BYTE num[4];
01258     auto BYTE * pStr = &str[sizeof(SPSET)];
01259
01260     sprintf(num, (ROM char *) "%hhu", pSetdata->u8BusNr);
01261     _u8TextROM((ROM char *)"ubb", num, 3, pStr);
01262     TCPPutString(sktHTTP, pStr);
01263 }
01264
01265 // ////////////////////////////////////////////////////////////////////////////
01266 // ////////////////////////////////////////////////////////////////////////////
01267
01268 void HTTPPrint_setprotocol(void)
01269 {
01270     auto SPSET * pSetdata = (SPSET *)str;
01271     auto BYTE num[4];
01272     auto BYTE * pStr = &str[sizeof(SPSET)];
01273
01274     _u8TextROM((ROM char *)"p", pSetdata->au8Proto, 3, pStr);
01275     TCPPutString(sktHTTP, pStr);
01276 }
01277
01278 // ////////////////////////////////////////////////////////////////////////////
01279 // ////////////////////////////////////////////////////////////////////////////
01280
01281 void HTTPPrint_setsteps(void)
01282 {
01283     auto SPSET * pSetdata = (SPSET *)str;
01284     auto BYTE num[4];
01285     auto BYTE * pStr = &str[sizeof(SPSET)];
01286
01287     sprintf(num, (ROM char *) "%hhu", pSetdata->uSpec.sGL.u8MaxSteps);
01288     _u8TextROM((ROM char *)"ubs", num, 3, pStr);
01289     TCPPutString(sktHTTP, pStr);
01290 }
01291
01292 // ////////////////////////////////////////////////////////////////////////////
01293 // ////////////////////////////////////////////////////////////////////////////
01294
01295 void HTTPPrint_setfunctions(void)
01296 {
01297     auto SPSET * pSetdata = (SPSET *)str;
01298     auto BYTE num[4];
01299     auto BYTE * pStr = &str[sizeof(SPSET)];
01300
01301     sprintf(num, (ROM char *) "%hhu", pSetdata->uSpec.sGL.u8NrFunc);
01302     _u8TextROM((ROM char *)"ubf", num, 3, pStr);
01303     TCPPutString(sktHTTP, pStr);
01304 }
01305
01306 // ////////////////////////////////////////////////////////////////////////////
01307 // ////////////////////////////////////////////////////////////////////////////
01308
01309 void HTTPPrint_setprotos(WORD u16ProtoId)
01310 {
01311     auto SPSET * pSetdata = (SPSET *)str;
01312     auto SPPROTOCOL protocoldata;
01313     auto BYTE num[4];
01314     auto BYTE * pStr = &str[sizeof(SPSET)];
01315
01316     SRCP_GetProtoFromEEPROM((BYTE)u16ProtoId, &protocoldata);
01317
01318     if (protocoldata.sFlags.bActive == FALSE)
01319     {
01320         return;
01321     }
01322
01323     TCPPutROMString(sktHTTP, (ROM char *)"<tr><td>");
01324     _u8RadioROM((ROM char *)"P", u16ProtoId, FALSE, pStr);
01325     TCPPutString(sktHTTP, pStr);
01326     TCPPutROMString(sktHTTP, (ROM char *)"</td><td>");
01327     TCPPutString(sktHTTP, protocoldata.au8Desc);
01328     TCPPutROMString(sktHTTP, (ROM char *)"</td><td>");
01329     sprintf(num, (ROM char *) "%hhu", protocoldata.u8Bus);
01330     TCPPutString(sktHTTP, num);
01331     TCPPutROMString(sktHTTP, (ROM char *)"</td><td>");
01332     TCPPutString(sktHTTP, protocoldata.au8Proto);
01333
01334     if (pSetdata->sFlags.bGL == TRUE)
01335     {
01336         TCPPutROMString(sktHTTP, (ROM char *)"</td><td>");
01337         sprintf(num, (ROM char *) "%hhu", protocoldata.uSpec.sGL.u8MaxSteps);
01338         TCPPutString(sktHTTP, num);
01339         TCPPutROMString(sktHTTP, (ROM char *)"</td><td>");
01340         sprintf(num, (ROM char *) "%hhu", protocoldata.uSpec.sGL.u8NrFunc);
01341         TCPPutString(sktHTTP, num);
01342     }
01343     else
01344     {
01345         TCPPutROMString(sktHTTP, (ROM char *)"</td><td>");
01346         sprintf(num, (ROM char *) "%hhu", protocoldata.uSpec.sGA.u8MinP);
01347         TCPPutString(sktHTTP, num);
01348         TCPPutROMString(sktHTTP, (ROM char *)"</td><td>");
01349         sprintf(num, (ROM char *) "%hhu", protocoldata.uSpec.sGA.u8MaxP);
01350         TCPPutString(sktHTTP, num);
01351     }
01352
01353     TCPPutROMString(sktHTTP, (ROM char *)"</td></tr>");
01354 }
01355
01356 // ////////////////////////////////////////////////////////////////////////////
01357 // ////////////////////////////////////////////////////////////////////////////
01358
01359 void HTTPPrint_setfunction(WORD u16FunctionNr, WORD u16Mode)
01360 {
01361     auto SPSET * pSetdata = (SPSET *)str;
01362     auto BYTE format[4];
01363     auto DWORD mask;
01364     auto DWORD valuemask = 0;
01365     auto WORD i;
01366     auto BOOL bDefault = FALSE;
01367     auto BYTE * pStr = &str[sizeof(SPSET)];
01368
01369     // Build the mask for the current function.
01370     mask = 0x01;
01371     for (i = 0; i < u16FunctionNr; i++)
01372     {
01373         mask = mask << 1;
01374     }
01375
01376     // Set the default value (depends on what is currently configured in the set)
01377     if ((u16Mode && (pSetdata->uSpec.sGL.u32FuncToggleMask & mask)) ||
01378         ((u16Mode == 0) && ((pSetdata->uSpec.sGL.u32FuncToggleMask & mask) == 0)))
01379     {
01380         bDefault = TRUE;
01381     }
01382
01383     if (u16Mode)
01384     {
01385         valuemask = mask;
01386     }
01387
01388     TCPPutROMString(sktHTTP, (ROM char *)"<td>");
01389     sprintf(format, (ROM char *) "F%hu", u16FunctionNr);
01390     _u8Radio(format, valuemask, bDefault, pStr);
01391     TCPPutString(sktHTTP, pStr);
01392     TCPPutROMString(sktHTTP, (ROM char *)"</td>");
01393 }
01394
01395 // ////////////////////////////////////////////////////////////////////////////
01396 // ////////////////////////////////////////////////////////////////////////////
01397
01398 void HTTPPrint_setminport(void)
01399 {
01400     auto SPSET * pSetdata = (SPSET *)str;
01401     auto BYTE num[4];
01402     auto BYTE * pStr = &str[sizeof(SPSET)];
01403
01404     sprintf(num, (ROM char *) "%hhu", pSetdata->uSpec.sGA.u8MinP);
01405     _u8TextROM((ROM char *)"ubq", num, 3, pStr);
01406     TCPPutString(sktHTTP, pStr);
01407 }
01408
01409 // ////////////////////////////////////////////////////////////////////////////
01410 // ////////////////////////////////////////////////////////////////////////////
01411
01412 void HTTPPrint_setmaxport(void)
01413 {
01414     auto SPSET * pSetdata = (SPSET *)str;
01415     auto BYTE num[4];
01416     auto BYTE * pStr = &str[sizeof(SPSET)];
01417
01418     sprintf(num, (ROM char *) "%hhu", pSetdata->uSpec.sGA.u8MaxP);
01419     _u8TextROM((ROM char *)"ubr", num, 3, pStr);
01420     TCPPutString(sktHTTP, pStr);
01421 }
01422
01423 // ////////////////////////////////////////////////////////////////////////////
01424 // ////////////////////////////////////////////////////////////////////////////
01425
01426 void HTTPPrint_setdelay(void)
01427 {
01428     auto SPSET * pSetdata = (SPSET *)str;
01429     auto BYTE num[10];
01430     auto BYTE * pStr = &str[sizeof(SPSET)];
01431
01432     sprintf(num, (ROM char *) "%ld", pSetdata->uSpec.sGA.s32Delay);
01433     _u8TextROM((ROM char *)"dd", num, 9, pStr);
01434     TCPPutString(sktHTTP, pStr);
01435 }
01436
01437
01438 // ////////////////////////////////////////////////////////////////////////////
01439 #endif  // #ifdef _SRCP
01440 // ////////////////////////////////////////////////////////////////////////////
01441
01442
01443
01444 HTTP_IO_RESULT HTTPExecuteGet(void)
01445 {
01446     BYTE *ptr;
01447     BYTE filename[20];
01448
01449     // Load the file name
01450     // Make sure BYTE filename[] above is large enough for your longest name
01451     MPFSGetFilename(curHTTP.file, filename, 20);
01452
01453
01454     // Verify the file name
01455     if(!strcmppgm2ram(filename, (ROM char*)"index.htm"))
01456     {
01457         ApplRestart(curHTTP.data[0]=='2');
01458     }
01459
01460 #ifdef _SRCP
01461     else if(!strcmppgm2ram(filename, (ROM char*)"locoset.htm")||
01462             !strcmppgm2ram(filename, (ROM char*)"accset.htm"))
01463     {
01464         _currentProcessingIdx = atob(curHTTP.data);
01465         if (_currentProcessingIdx >= SRCP_EEPROMSET_COUNT)
01466         {
01467             _currentProcessingIdx = 0;
01468         }
01469
01470         SRCP_GetSetFromEEPROM(_currentProcessingIdx, (SPSET *)str);
01471     }
01472 #endif
01473
01474     curHTTP.httpStatus = HTTP_REDIRECT;
01475     strcpy(curHTTP.data, filename);
01476
01477     // Indicate completion
01478     return HTTP_IO_DONE;
01479 }
01480
01481
01482 // ////////////////////////////////////////////////////////////////////////////
01483 // ////////////////////////////////////////////////////////////////////////////
01484
01485 // Define post state machine values
01486 #define SM_READ_NAME       (0u)
01487 #define SM_READ_VALUE      (1u)
01488
01489 #define EXEC_POST_NAME_LENGTH       (5+1)
01490 #define EXEC_POST_FILENAME_LENGTH   (20+1)
01491 #define EXEC_POST_VALUE_LENGTH      (32+1)
01492
01493 #define EXEC_POST_NEEDED_SPACE      (EXEC_POST_NAME_LENGTH+EXEC_POST_FILENAME_LENGTH+EXEC_POST_VALUE_LENGTH)
01494
01495
01496 HTTP_IO_RESULT HTTPExecutePost(void)
01497 {
01498     auto BYTE * name = str;
01499     auto BYTE * filename = &str[EXEC_POST_NAME_LENGTH];
01500     auto BYTE * value = &filename[EXEC_POST_FILENAME_LENGTH];
01501
01502     // Load the file name
01503     // Make sure BYTE filename[] above is large enough for your longest name
01504     MPFSGetFilename(curHTTP.file, filename, (EXEC_POST_FILENAME_LENGTH-1));
01505
01506     // Verify the file name
01507     if(!strcmppgm2ram(filename, (ROM char*)"file.htm"))
01508     {
01509         return ConfigPostFile(str);
01510     }
01511
01512
01513     while(1)
01514     {
01515         // Fetch the name value pair from the post stream.
01516         switch(curHTTP.smPost)
01517         {
01518         case SM_READ_NAME:
01519             if(HTTPReadPostName(name, (EXEC_POST_NAME_LENGTH-1)) == HTTP_READ_INCOMPLETE)
01520             {
01521                 return HTTP_IO_NEED_DATA;
01522             }
01523
01524             // Move to the next state, but do not break yet
01525             curHTTP.smPost = SM_READ_VALUE;
01526             // Intented fall through...
01527
01528         case SM_READ_VALUE:
01529             if(HTTPReadPostValue(value, (EXEC_POST_VALUE_LENGTH-1)) == HTTP_READ_INCOMPLETE)
01530             {
01531                 return HTTP_IO_NEED_DATA;
01532             }
01533
01534             // Return to read a new name
01535             curHTTP.smPost = SM_READ_NAME;
01536             break;
01537         }
01538
01539         if (strcmppgm2ram(filename, (ROM char*)"common.htm")==0)
01540         {
01541             ProcessCommonData(name, value);
01542         }
01543
01544 #ifdef _SRCP
01545         else if (strcmppgm2ram(filename, (ROM char*)"srcp.htm")==0)
01546         {
01547             ProcessSRCPData(name, value);
01548         }
01549         else if (strcmppgm2ram(filename, (ROM char*)"locoproto.htm")==0)
01550         {
01551             ProcessProtoData(&str[EXEC_POST_NEEDED_SPACE], name, value);
01552         }
01553         else if (strcmppgm2ram(filename, (ROM char*)"accproto.htm")==0)
01554         {
01555             ProcessProtoData(&str[EXEC_POST_NEEDED_SPACE], name, value);
01556         }
01557         else if (!strcmppgm2ram(filename, (ROM char*)"locos.htm")==0)
01558         {
01559             ProcessSetData(&str[EXEC_POST_NEEDED_SPACE], name, value);
01560         }
01561         else if (!strcmppgm2ram(filename, (ROM char*)"accs.htm")==0)
01562         {
01563             ProcessSetData(&str[EXEC_POST_NEEDED_SPACE], name, value);
01564         }
01565         else if (!strcmppgm2ram(filename, (ROM char*)"locoset.htm")==0)
01566         {
01567             ProcessSetData(&str[EXEC_POST_NEEDED_SPACE], name, value);
01568         }
01569         else if (!strcmppgm2ram(filename, (ROM char*)"accset.htm")==0)
01570         {
01571             ProcessSetData(&str[EXEC_POST_NEEDED_SPACE], name, value);
01572         }
01573 #endif
01574
01575         if (name[0] == 'R')
01576         {
01577             ApplRestart(FALSE); // Restart without factory reset.
01578             strcpypgm2ram(curHTTP.data, (ROM char*)"index.htm");
01579             curHTTP.httpStatus = HTTP_REDIRECT;
01580             return HTTP_IO_DONE;
01581         }
01582         else if (name[0] == 'O')
01583         {
01584             curHTTP.httpStatus = HTTP_REDIRECT;
01585             strcpy(curHTTP.data, filename);
01586             return HTTP_IO_DONE;
01587         }
01588     }
01589 }
01590
01591 // ////////////////////////////////////////////////////////////////////////////
01592 // ////////////////////////////////////////////////////////////////////////////
01593
01594 static BYTE _u8RadioROM(auto ROM BYTE * pu8Name, auto DWORD u32Val, auto BOOL bSel, auto BYTE * pu8Dest)
01595 {
01596     auto BYTE len=sprintf(pu8Dest,
01597             (ROM char *)"<input type=\"radio\" name=\"%HS\" value=\"%lu\"",
01598             pu8Name, u32Val);
01599
01600     if (bSel==TRUE)
01601     {
01602         strcpypgm2ram(&pu8Dest[len], (ROM char *)" checked=\"checked\"");
01603         len+=18;
01604     }
01605
01606     strcpypgm2ram(&pu8Dest[len], (ROM char *)" />");
01607     return (len+3);
01608 }
01609
01610 // ////////////////////////////////////////////////////////////////////////////
01611 // ////////////////////////////////////////////////////////////////////////////
01612
01613 static BYTE _u8OptionROM(auto BOOL bSel, auto BYTE u8Val, auto char * pu8Dest,
01614                                                           auto ROM BYTE * pu8String)
01615 {
01616     BYTE len=sprintf(pu8Dest, (ROM char *)"<option value=\"%hhu\"", u8Val);
01617
01618     if (bSel == TRUE)
01619     {
01620         strcpypgm2ram(&pu8Dest[len], (ROM char *)" selected=\"selected\"");
01621         len += 20;
01622     }
01623     pu8Dest[len++] = '>';
01624     strcpypgm2ram(&pu8Dest[len], (ROM char *)pu8String);
01625     len += strlenpgm((ROM char *)pu8String);
01626     strcpypgm2ram(&pu8Dest[len], (ROM char *)"</option>");
01627     len += 9;
01628
01629     return len;
01630 }
01631
01632 // ////////////////////////////////////////////////////////////////////////////
01633 #ifdef _SRCP
01634 // ////////////////////////////////////////////////////////////////////////////
01635
01636 static BYTE _u8HiddenROM(auto ROM BYTE * pu8Name, auto BYTE u8Val, auto BYTE * pu8Dest)
01637 {
01638     BYTE len=sprintf(pu8Dest,
01639         (ROM char *)"<input type=\"hidden\" name=\"%HS\" value=\"%hhu\" />",
01640         pu8Name, u8Val);
01641
01642     return len;
01643 }
01644
01645 // ////////////////////////////////////////////////////////////////////////////
01646 // ////////////////////////////////////////////////////////////////////////////
01647
01648 static BYTE _u8Option(auto BOOL bSel, auto BYTE u8Val, auto char * pu8Dest, auto BYTE * pu8String)
01649 {
01650     BYTE len=sprintf(pu8Dest, (ROM char *)"<option value=\"%hhu\"", u8Val);
01651
01652     if (bSel == TRUE)
01653     {
01654         strcpypgm2ram(&pu8Dest[len], (ROM char *)" selected=\"selected\"");
01655         len += 20;
01656     }
01657     pu8Dest[len++] = '>';
01658     strcpy(&pu8Dest[len], pu8String);
01659     len += strlen(pu8String);
01660     strcpypgm2ram(&pu8Dest[len], (ROM char *)"</option>");
01661     len += 9;
01662
01663     return len;
01664 }
01665
01666 // ////////////////////////////////////////////////////////////////////////////
01667 // ////////////////////////////////////////////////////////////////////////////
01668
01669 static BYTE _u8CheckboxROM(auto ROM BYTE * pu8Name, auto BYTE u8Val, auto BOOL bSel,
01670                                                                 auto BYTE * pu8Dest)
01671 {
01672     BYTE len=sprintf(pu8Dest,
01673             (ROM char *)"<input type=\"checkbox\" name=\"%HS\" value=\"%hhu\"",
01674             pu8Name, u8Val);
01675
01676     if (bSel==TRUE)
01677     {
01678         strcpypgm2ram(&pu8Dest[len], (ROM char *)" checked=\"checked\"");
01679         len+=18;
01680     }
01681
01682     strcpypgm2ram(&pu8Dest[len], (ROM char *)" />");
01683     return (len+3);
01684 }
01685
01686 // ////////////////////////////////////////////////////////////////////////////
01687 // ////////////////////////////////////////////////////////////////////////////
01688
01689 static BYTE _u8TextROM(auto ROM BYTE * pu8Name, auto BYTE * pu8Val, auto BYTE u8Size,
01690                     auto BYTE * pu8Dest)
01691 {
01692     BYTE len=sprintf(pu8Dest,
01693             (ROM char *)"<input type=\"text\" name=\"%HS\" value=\"%s\" ",
01694             pu8Name, pu8Val);
01695
01696     len+=sprintf(&pu8Dest[len],
01697             (ROM char *)"size=\"%hhu\" maxlength=\"%hhu\" />",
01698             u8Size, u8Size);
01699
01700     return len;
01701 }
01702
01703 // ////////////////////////////////////////////////////////////////////////////
01704 // ////////////////////////////////////////////////////////////////////////////
01705
01706 static BYTE _u8Radio(auto BYTE * pu8Name, auto DWORD u32Val, auto BOOL bSel, auto BYTE * pu8Dest)
01707 {
01708     auto BYTE len=sprintf(pu8Dest,
01709             (ROM char *)"<input type=\"radio\" name=\"%s\" value=\"%lu\"",
01710             pu8Name, u32Val);
01711
01712     if (bSel==TRUE)
01713     {
01714         strcpypgm2ram(&pu8Dest[len], (ROM char *)" checked=\"checked\"");
01715         len+=18;
01716     }
01717
01718     strcpypgm2ram(&pu8Dest[len], (ROM char *)" />");
01719     return (len+3);
01720 }
01721
01722 // ////////////////////////////////////////////////////////////////////////////
01723 #endif      // #ifdef _SRCP
01724 // ////////////////////////////////////////////////////////////////////////////
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: web.h Source File

web.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00024 // ////////////////////////////////////////////////////////////////////////////
00025 // ////////////////////////////////////////////////////////////////////////////
00026
00027 #ifndef WEB_H
00028
00029 #define WEB_H
00030
00031 #include    "GenericTypeDefs.h"
00032 #include    <string.h>
00033 #include    "TCPIP.h"
00034
00035 #ifdef WEB_C
00036     #define PROTO
00037 #else
00038     #define PROTO extern
00039 #endif
00040
00041
00042 // ////////////////////////////////////////////////////////////////////////////
00043 // Defines
00044 // ////////////////////////////////////////////////////////////////////////////
00045
00046 #define VAR_FIRMWARE_VERSION_MAJOR  (0x00)
00047 #define VAR_FIRMWARE_VERSION_MINOR  (0x01)
00048 #define VAR_FIRMWARE_VERSION_STRING (0x02)
00049 #define VAR_BOOTLOADER_VERSION      (0x03)
00050
00051 #define BOOTVERSION ((ROM DWORD *) 0x01fbec)
00052
00053 #define VAR_IP_ADDRESS              (0x0000u)
00054 #define VAR_GATEWAY_ADDRESS         (0x0001u)
00055 #define VAR_SUBNET_MASK             (0x0002u)
00056 #define VAR_CONNECTED_SERVER_IP     (0x0003u)
00057 #define VAR_MAN_IP_ADDRESS          (0x0004u)
00058 #define VAR_MAN_SUBNET_MASK         (0x0005u)
00059 #define VAR_MAN_GATEWAY_ADDRESS     (0x0006u)
00060 #define VAR_SERVER_IP               (0x0007u)
00061 #define VAR_GATEWAY_ADDRESS_EEPROM  (0x0008u)
00062 #define VAR_IP_ADDRESS_EEPROM       (0x0009u)
00063 #define VAR_SUBNET_MASK_EEPROM      (0x000Au)
00064 #define VAR_SERVER_IP_EEPROM        (0x000Bu)
00065
00066
00067 // ////////////////////////////////////////////////////////////////////////////
00068 // Prototypes
00069 // ////////////////////////////////////////////////////////////////////////////
00070
00073 // ////////////////////////////////////////////////////////////////////////////
00074 // Epilogue
00075 // ////////////////////////////////////////////////////////////////////////////
00076
00077 #undef  PROTO
00078
00079 #include    "main.h"
00080
00081 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: webprocess.c Source File

webprocess.c

00001
00002
00003 #define WEBPROCESS_C
00004
00005
00006
00008 // Includes
00010
00011 #include "webprocess.h"
00012 #include "projectdefs.h"
00013
00014
00016 // Local function prototypes
00018
00019 static BYTE * _pCheckLimits(auto BYTE * pu8Control, auto BYTE * pu8Value,
00020                                                auto long * pu32ProcessedValue);
00021 static void _ParseURL(auto BYTE * au8URL, auto WORD * pu16Port,
00022                     auto BYTE * au8HostBuffer, auto BYTE u8SizeOfHostBuffer);
00023
00024 #ifdef _SRCP
00025 static void _GetProtoSettings(auto BYTE u8ProtoId, auto SPSET * pSet);
00026 #endif
00027
00030
00031 void ProcessCommonData(auto BYTE * pu8Control, auto BYTE * pu8Value)
00032 {
00033     auto long val = 0;
00034
00035     if (pu8Value)
00036     {
00037         pu8Control = _pCheckLimits(pu8Control, pu8Value, &val);
00038     }
00039
00040     if (pu8Control == NULL)
00041     {
00042         return;
00043     }
00044
00045     switch(pu8Control[0])
00046     {
00047     case 'g':
00048         if (val <= LANGID_MAX)
00049         {
00050             sPCommonConfig.u8LanguageID = (BYTE)(val);
00051             StrTbl_SetLanguage(sPCommonConfig.u8LanguageID);
00052             XEEWriteArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, u8LanguageID), &sPCommonConfig.u8LanguageID, 1);
00053         }
00054         break;
00055
00056     case 'i':
00057         sPCommonConfig.u8LCDLight = (BYTE)(val);
00058         OutTriggerDisplay();
00059         XEEWriteArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, u8LCDLight), &sPCommonConfig.u8LCDLight, 1);
00060         break;
00061
00062     case 't':
00063         ApplChangeLocoDirMode((BOOL)(val));
00064         XEEWriteArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, sFlags), (BYTE *)&sPApplConfig.sFlags, 1);
00065         break;
00066
00067     case 'm':
00068         // IP access mode (Auto or manual):
00069         {
00070             sIPFlags flags;
00071             flags.bIsDHCPEnabled = (BOOL)(val);
00072             XEEWriteArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, Flags), (BYTE *)&flags, sizeof(sIPFlags));
00073         }
00074         break;
00075
00076     case 'p':
00077         // Manual IP address:
00078         {
00079             auto IP_ADDR ip;
00080             StringToIPAddress(pu8Value, &ip);
00081             XEEWriteArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, ManIPAddr), (BYTE *)&ip, sizeof(IP_ADDR));
00082         }
00083         break;
00084
00085     case 's':
00086         // Manual subnet:
00087         {
00088             auto BYTE mask[4];
00089             StringToIPAddress(pu8Value, (IP_ADDR *)mask);
00090             mask[0] = IPConvertMaskToSubnet(mask);
00091             XEEWriteArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, ManMask), mask, 1);
00092         }
00093         break;
00094
00095     case 'a':
00096         // Manual gateway:
00097         {
00098             auto IP_ADDR ip;
00099             StringToIPAddress(pu8Value, &ip);
00100             XEEWriteArray(BOOTUP_EEPROM_ADD+offsetof(PCOMMON_CONFIG, ManGateway), (BYTE *)&ip, sizeof(IP_ADDR));
00101         }
00102         break;
00103
00104     case 'x':
00105         {
00106             // Server URL:
00107             auto IP_ADDR ip;
00108             auto SEARCH_MODE mode;
00109             auto WORD port;
00110             auto BYTE hostname[LCD_CHARS_IN_A_ROW+1];
00111
00112             _ParseURL(pu8Value, &port, hostname, LCD_CHARS_IN_A_ROW+1);
00113
00114             if (hostname[0] == 0)
00115             {
00116                 mode = SEARCH_UNKNOWN;
00117             }
00118             else if (StringToIPAddress(hostname, &ip) == FALSE)
00119             {
00120                 if (port)
00121                 {
00122                     mode = SEARCH_NAME;
00123                     XEEWriteArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, au8Name), hostname, LCD_CHARS_IN_A_ROW+1);
00124                     XEEWriteArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, sNamePort), (BYTE *)&port, 2);
00125                 }
00126                 else
00127                 {
00128                     mode = SEARCH_SERVICE;
00129                     XEEWriteArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, au8Service), hostname, LCD_CHARS_IN_A_ROW+1);
00130                 }
00131             }
00132             else
00133             {
00134                 mode = SEARCH_IP;
00135                 XEEWriteArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, sSrvIPAdd), (BYTE *)&ip, sizeof(IP_ADDR));
00136                 XEEWriteArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, sIPPort), (BYTE *)&port, 2);
00137             }
00138
00139             XEEWriteArray(APPL_EEPROM_ADD+offsetof(SPAPPLDATA, eFindMode), (BYTE *)&mode, sizeof(SEARCH_MODE));
00140         }
00141         break;
00142     }
00143 }
00144
00145
00146
00148 #ifdef _SRCP
00150
00151 #include "srcp.h"
00152
00153 void ProcessSRCPData(auto BYTE * pu8Control, auto BYTE * pu8Value)
00154 {
00155     auto long val = 0;
00156
00157     if (pu8Value)
00158     {
00159         pu8Control = _pCheckLimits(pu8Control, pu8Value, &val);
00160     }
00161
00162     if (pu8Control == NULL)
00163     {
00164         return;
00165     }
00166
00167     switch(pu8Control[0])
00168     {
00169         case 'L':
00170             sPSRCPConfig.sFlags.bGLAskForProto = (BOOL)(val);
00171             break;
00172
00173         case 'B':
00174             if ((val == SRCP_EEPROMSET_ID) || (val == SRCP_SERVERCACHE_ID) || (val < MAX_PROTO_SLOTS))
00175             {
00176                 sPSRCPConfig.u8DefaultGLProtoId = (BYTE)(val);
00177             }
00178             break;
00179
00180         case 'A':
00181             sPSRCPConfig.sFlags.bGAAskForProto = (BOOL)(val);
00182             break;
00183
00184         case 'D':
00185             if ((val == SRCP_EEPROMSET_ID) || ((val >= MAX_PROTO_SLOTS) && (val < MAX_PROTO_SLOTS*2)))
00186             {
00187                 sPSRCPConfig.u8DefaultGAProtoId = (BYTE)(val);
00188             }
00189             break;
00190
00191         case 'V':
00192             if ((val == -1) || (val > 0))
00193             {
00194                 sPSRCPConfig.s32GADelay = val;
00195             }
00196             break;
00197
00198         case 'O':
00199             // Write the changed parameters to EEPROM.
00200             XEEWriteArray(SRCP_CONFIG_EEPROM_ADD, (BYTE*)&sPSRCPConfig, sizeof(SPSRCPCONFIG));
00201             break;
00202     }
00203 }
00204
00205
00208
00209 void ProcessProtoData(auto BYTE * pu8Space, auto BYTE * pu8Control,
00210                           auto BYTE * pu8Value)
00211 {
00212     auto SPPROTOCOL * pProto = (SPPROTOCOL *) &pu8Space[1];
00213     auto long val;
00214
00215     if (pu8Value)
00216     {
00217         pu8Control = _pCheckLimits(pu8Control, pu8Value, &val);
00218     }
00219
00220     if (pu8Control == NULL)
00221     {
00222         return;
00223     }
00224
00225     switch(*pu8Control)
00226     {
00227         case 'A':
00228             pu8Space[0] = (BYTE)val;
00229             SRCP_GetProtoFromEEPROM((BYTE)val, pProto);
00230             pProto->sFlags.bActive = FALSE;
00231             break;
00232
00233         case 'c':
00234             // Activation
00235             pProto->sFlags.bActive = TRUE;
00236             break;
00237
00238         case 'n':
00239             // Description resp. name of the protocol
00240             strncpy(pProto->au8Desc, pu8Value, SRCP_NAME_MAXLEN);
00241             pProto->au8Desc[SRCP_NAME_MAXLEN] = 0;
00242             break;
00243
00244         case 'p':
00245             // Protocol string.
00246             strncpy(pProto->au8Proto, pu8Value, SRCP_PROTO_MAXLEN);
00247             pProto->au8Proto[SRCP_PROTO_MAXLEN] = 0;
00248             break;
00249
00250         case 'b':
00251             if (val > 0)
00252             {
00253                 pProto->u8Bus = (BYTE) val;
00254             }
00255             break;
00256
00257         case 'm':
00258             pProto->u16MinAdd = (WORD) val;
00259             break;
00260
00261         case 'x':
00262             pProto->u16MaxAdd = (WORD) val;
00263             break;
00264
00265         case 's':
00266             if (val <= MAX_SRCP_SPEEDSTEPS)
00267             {
00268                 pProto->uSpec.sGL.u8MaxSteps = (BYTE) val;
00269             }
00270             break;
00271
00272         case 'q':
00273             pProto->uSpec.sGA.u8MinP = (BYTE) val;
00274             break;
00275
00276         case 'f':
00277             if (val <= MAX_SRCP_FUNCTIONS)
00278             {
00279                 pProto->uSpec.sGL.u8NrFunc = (BYTE) val;
00280             }
00281             break;
00282
00283         case 'r':
00284             pProto->uSpec.sGA.u8MaxP = (BYTE) val;
00285             break;
00286
00287         case 'E':
00288             if (pu8Space[0] >= (MAX_PROTO_SLOTS*2))
00289             {
00290                 // Invalid proto id!!! Do not store!
00291                 break;
00292             }
00293
00294             if (pProto->sFlags.bActive == TRUE)
00295             {
00296                 if (strlen(pProto->au8Desc) == 0)
00297                 {
00298                     sprintf(pProto->au8Desc, (ROM char *)"Proto%hhu", (BYTE)(pu8Space[0]+1));
00299                 }
00300
00301                 if ((strlen(pProto->au8Proto) == 0) || (pProto->u8Bus == 0))
00302                 {
00303                     pProto->sFlags.bActive = FALSE;
00304                 }
00305
00306                 if (pProto->sFlags.bGL == FALSE)
00307                 {
00308                     if (pProto->uSpec.sGA.u8MinP > pProto->uSpec.sGA.u8MaxP)
00309                     {
00310                         auto BYTE tmp = pProto->uSpec.sGA.u8MaxP;
00311                         pProto->uSpec.sGA.u8MaxP = pProto->uSpec.sGA.u8MinP;
00312                         pProto->uSpec.sGA.u8MinP = tmp;
00313                     }
00314                 }
00315
00316                 if (pProto->u16MinAdd > pProto->u16MaxAdd)
00317                 {
00318                     auto WORD tmp = pProto->u16MaxAdd;
00319                     pProto->u16MaxAdd = pProto->u16MinAdd;
00320                     pProto->u16MinAdd = tmp;
00321                 }
00322             }
00323
00324
00325             // Reset a open dialog if active.
00326             SRCP_CancelInputProtoDialog();
00327
00328             // Switch to a new protocol structure, save the last.
00329             SRCP_WriteProtoToEEPROM(pu8Space[0], pProto);
00330             break;
00331     }
00332 }
00333
00336
00337 void ProcessSetData(auto BYTE * pu8Space, auto BYTE * pu8Control,
00338                           auto BYTE * pu8Value)
00339 {
00340     auto SPSET * pSet = (SPSET *) &pu8Space[1];
00341     auto long val;
00342
00343     pu8Control = _pCheckLimits(pu8Control, pu8Value, &val);
00344
00345     if (pu8Control == NULL)
00346     {
00347         return;
00348     }
00349
00350     switch(*pu8Control)
00351     {
00352         case 'A':
00353             pu8Space[0] = (BYTE)val;
00354             SRCP_GetSetFromEEPROM((BYTE)val, pSet);
00355
00356             if (pu8Control[1] == 's')
00357             {
00358                 // Obviously someone has used the set dialog, because on
00359                 // the locos dialog is no address field.
00360
00361                 // Activate the set automatically.
00362                 pSet->sFlags.bActive = TRUE;
00363
00364                 if (pSet->sFlags.bGL == TRUE)
00365                 {
00366                     // Reset the function toggle mask.
00367                     pSet->uSpec.sGL.u32FuncToggleMask = 0;
00368                 }
00369             }
00370             else
00371             {
00372                 pSet->sFlags.bActive = FALSE;
00373             }
00374             break;
00375
00376         case 'c':
00377             pSet->sFlags.bActive = TRUE;
00378             break;
00379
00380         case 'n':
00381             strncpy(pSet->au8Name, pu8Value, SRCP_NAME_MAXLEN);
00382             pSet->au8Name[SRCP_NAME_MAXLEN] = 0;
00383             break;
00384
00385         case 'm':
00386             pSet->u32Address = val;
00387             break;
00388
00389         case 'h':
00390             pSet->uSpec.sGL.u16MaxV = (WORD) val;
00391             break;
00392
00393         case 'F':
00394             pSet->uSpec.sGL.u32FuncToggleMask |= (val & 0xFFFFFFFE);
00395             break;
00396
00397         case 'P':
00398             if (val != -1)
00399             {
00400                 _GetProtoSettings((BYTE)val, pSet);
00401             }
00402             break;
00403
00404         case 'p':
00405             strncpy(pSet->au8Proto, pu8Value, SRCP_PROTO_MAXLEN);
00406             break;
00407
00408         case 'b':
00409             if (val > 0)
00410             {
00411                 pSet->u8BusNr = (BYTE)val;
00412             }
00413             break;
00414
00415         case 's':
00416             if (val > 0)
00417             {
00418                 pSet->uSpec.sGL.u8MaxSteps = (BYTE)val;
00419             }
00420             break;
00421
00422         case 'f':
00423             if (val <= MAX_SRCP_FUNCTIONS)
00424             {
00425                 pSet->uSpec.sGL.u8NrFunc = (BYTE)val;
00426             }
00427             break;
00428
00429         case 'q':
00430             pSet->uSpec.sGA.u8MinP = (BYTE)val;
00431             break;
00432
00433         case 'r':
00434             pSet->uSpec.sGA.u8MaxP = (BYTE)val;
00435             break;
00436
00437         case 'd':
00438             if (val >= -1)
00439             {
00440                 pSet->uSpec.sGA.s32Delay = val;
00441             }
00442             break;
00443
00444         case 'E':
00445             if (pu8Space[0] >= (SRCP_GLEEPROMSET_COUNT + SRCP_GAEEPROMSET_COUNT))
00446             {
00447                 // Invalid db id!!! Do not store!
00448                 break;
00449             }
00450
00451             if (pSet->sFlags.bActive == TRUE)
00452             {
00453                 BYTE defaultProto;
00454
00455                 if (strlen(pSet->au8Name) == 0)
00456                 {
00457                     sprintf(pSet->au8Name, (ROM char *)"S%hhu", (BYTE)(val+1));
00458                 }
00459
00460                 if (pSet->sFlags.bGL == FALSE)
00461                 {
00462                     defaultProto = sPSRCPConfig.u8DefaultGAProtoId;
00463
00464                     if (pSet->uSpec.sGA.u8MinP > pSet->uSpec.sGA.u8MaxP)
00465                     {
00466                         auto BYTE tmp = pSet->uSpec.sGA.u8MaxP;
00467                         pSet->uSpec.sGA.u8MaxP = pSet->uSpec.sGA.u8MinP;
00468                         pSet->uSpec.sGA.u8MinP = tmp;
00469                     }
00470                 }
00471                 else
00472                 {
00473                     defaultProto = sPSRCPConfig.u8DefaultGLProtoId;
00474                 }
00475
00476                 if ((strlen(pSet->au8Proto) == 0) || (pSet->u8BusNr == 0))
00477                 {
00478                     // No valid protocol settings? Trying to load from the default
00479                     // settings.
00480                     if ((defaultProto & 0x80) == 0)
00481                     {
00482                         _GetProtoSettings(defaultProto, pSet);
00483                     }
00484                     else
00485                     {
00486                         pSet->sFlags.bActive = FALSE;
00487                     }
00488                 }
00489             }
00490
00491             // Reset an open dialog if active.
00492             SRCP_CancelInputSetDialog();
00493
00494             pSet->au8Proto[SRCP_PROTO_MAXLEN] = 0;
00495
00496             // Switch to a new quick structure, save the last.
00497             SRCP_WriteSetToEEPROM(pu8Space[0], pSet);
00498             break;
00499     }
00500 }
00501
00502
00505
00506 static void _GetProtoSettings(auto BYTE u8ProtoId, auto SPSET * pSet)
00507 {
00508     auto SPPROTOCOL proto;
00509
00510     // Load the protocol configuration (bus, protocol string, steps, functions)
00511     SRCP_GetProtoFromEEPROM(u8ProtoId, &proto);
00512     strncpy(pSet->au8Proto, proto.au8Proto, SRCP_PROTO_MAXLEN);
00513     pSet->u8BusNr = proto.u8Bus;
00514     pSet->uSpec.sGL.u8MaxSteps = proto.uSpec.sGL.u8MaxSteps;
00515     pSet->uSpec.sGL.u8NrFunc = proto.uSpec.sGL.u8NrFunc;
00516 }
00517
00518
00520 #endif  // #ifdef _SRCP
00522
00523
00524 static BYTE * _pCheckLimits(auto BYTE * pu8Control, auto BYTE * pu8Value,
00525                             auto long * pu32ProcessedValue)
00526 {
00527     auto BOOL bSign = FALSE;
00528     auto BYTE numbercount = 0;
00529     auto long min;
00530     auto long max;
00531
00532     if (pu32ProcessedValue)
00533     {
00534         *pu32ProcessedValue = atol(pu8Value);
00535     }
00536
00537     if ((pu8Control[0] != 'u') && (pu8Control[0] != 'd'))
00538     {
00539         return pu8Control;
00540     }
00541
00542     if (pu8Control[0] == 'd')
00543     {
00544         bSign = TRUE;
00545     }
00546
00547     if ((bSign == FALSE) && (pu8Value[0] == '-'))
00548     {
00549         // Negative numbers are not allowed (Unsigned!)
00550         return NULL;
00551     }
00552
00553     while (((*pu8Value) < '0') || ((*pu8Value) > '9'))
00554     {
00555         pu8Value++;
00556         if ((*pu8Value) == 0)
00557         {
00558             // No numbers found!
00559             return NULL;
00560         }
00561     }
00562
00563     // Numeric value, check for numbers greater then 32 Bit (9 characters)
00564     while ((pu8Value[0] >= '0') && (pu8Value[0] <= '9'))
00565     {
00566         numbercount++;
00567
00568         if (numbercount > 9)
00569         {
00570             return NULL;
00571         }
00572
00573         pu8Value++;
00574     }
00575
00576     if (pu8Control[1] == 'b')
00577     {
00578         // Character!
00579         if (bSign == TRUE)
00580         {
00581             min = -127;
00582             max = 128;
00583         }
00584         else
00585         {
00586             min = 0;
00587             max = 255;
00588         }
00589     }
00590     else if (pu8Control[1] == 's')
00591     {
00592         // Short integer!
00593         if (bSign == TRUE)
00594         {
00595             min = -32767;
00596             max = 32768;
00597         }
00598         else
00599         {
00600             min = 0;
00601             max = 65535;
00602         }
00603     }
00604     else
00605     {
00606         // Long integer!
00607         return &pu8Control[1];
00608     }
00609
00610
00611     if ((*pu32ProcessedValue < min) || (*pu32ProcessedValue > max))
00612     {
00613         return NULL;
00614     }
00615
00616     return &pu8Control[2];
00617 }
00618
00621
00622 static void _ParseURL(auto BYTE * au8URL, auto WORD * pu16Port,
00623                      auto BYTE * au8HostBuffer, auto BYTE u8SizeOfHostBuffer)
00624 {
00625     auto BYTE * pTemp;
00626
00627
00629     // Step 1: Preparation and initialization
00630     if ((au8URL == NULL) || (pu16Port == NULL) || (au8HostBuffer == NULL))
00631     {
00632         return;
00633     }
00634
00635     *pu16Port = 0;
00636
00637     strlwr(au8URL); // Accept lowercase letters only.
00638
00639
00641     // Step 2: Extract the protocol specifier.
00642     pTemp = strstrrampgm(au8URL, (ROM char *)"://");
00643
00644     if (pTemp)
00645     {
00646         pTemp[0] = 0;
00647         pTemp += 3;
00648     }
00649
00650
00651     if (pTemp == NULL)
00652     {
00653         pTemp = au8URL;
00654     }
00655
00656     au8URL = pTemp;
00657
00658
00660     // Step 3: Parse for user/pw and throw it away!
00661     pTemp = strchr(au8URL, '@');
00662     if (pTemp)
00663     {
00664         au8URL = pTemp;
00665     }
00666
00667
00669     // Step 4: Extract the host name.
00670     pTemp = strchr(au8URL, ':');
00671
00672     if (pTemp)
00673     {
00674         // A port is given!
00675         *pu16Port = (WORD)(atoi(pTemp + 1));
00676     }
00677     else
00678     {
00679         // No port is given!
00680         pTemp = strchr(au8URL, '/');
00681     }
00682
00683     if (pTemp)
00684     {
00685         pTemp[0] = 0;
00686     }
00687
00688
00689
00691     // Step 5: Get the host name:
00692
00693     // Left space for 0 termination:
00694     u8SizeOfHostBuffer--;
00695
00696     while(u8SizeOfHostBuffer--)
00697     {
00698         if (*au8URL == 0)
00699         {
00700             break;
00701         }
00702
00703         if (((*au8URL >= 'a') && (*au8URL <= 'z')) ||
00704             ((*au8URL >= '0') && (*au8URL <= '9')) ||
00705             (*au8URL == '-') ||
00706             (*au8URL == '.'))
00707         {
00708             *au8HostBuffer = *au8URL;
00709             au8HostBuffer++;
00710         }
00711
00712         au8URL++;
00713     }
00714
00715     *au8HostBuffer = 0;
00716
00717     return;
00718 }
00719
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: webprocess.h Source File

webprocess.h

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00019 // ////////////////////////////////////////////////////////////////////////////
00020 // ////////////////////////////////////////////////////////////////////////////
00021
00022 #ifndef WEBPROCESS_H
00023
00024     #define WEBPROCESS_H
00025
00026     #include    "GenericTypeDefs.h"
00027     #include    "string.h"
00028     #include    "TCPIP.h"
00029     #include    "mdns.h"
00030     #include    "eeprom_adds.h"
00031     #include    "stringtable.h"
00032
00033     #ifdef WEBPROCESS_C
00034         #define PROTO
00035     #else
00036         #define PROTO extern
00037     #endif
00038
00039
00040 // ////////////////////////////////////////////////////////////////////////////
00041 // Defines
00042 // ////////////////////////////////////////////////////////////////////////////
00043
00044
00045
00046 // ////////////////////////////////////////////////////////////////////////////
00047 // Function prototypes
00048 // ////////////////////////////////////////////////////////////////////////////
00049
00050 PROTO void ProcessCommonData(auto BYTE * pu8Control, auto BYTE * pu8Value);
00051 PROTO void ProcessSRCPData(auto BYTE * pu8Control, auto BYTE * pu8Value);
00052 PROTO void ProcessProtoData(auto BYTE * pu8Space, auto BYTE * pu8Control,
00053                                           auto BYTE * pu8Value);
00054 PROTO void ProcessSetData(auto BYTE * pu8Space, auto BYTE * pu8Control,
00055                                                         auto BYTE * pu8Value);
00056
00057 // ////////////////////////////////////////////////////////////////////////////
00058 // Epilogue
00059 // ////////////////////////////////////////////////////////////////////////////
00060
00063     #undef  PROTO
00064
00065     #include    "main.h"
00066
00067 #endif
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: xml.c Source File

xml.c

Go to the documentation of this file.
00001
00002
00003
00013
00014
00015
00016 /*
00017
00018 Wie Parser bedienen?
00019 - Durchzuführendes Kommando aufrufen.
00020 - Danach SM aufrufen. Antwortcodes
00021     - Ready: Kommando ausgeführt, Parameter können ausgewertet werden. Danach
00022       kann nächstes Kommando abgesetzt werden.
00023     - Failed: Kommando konnte nicht ausgeführt werden. Nächstes Kommando bitte.
00024     - Need more data: Es werden mehr Daten für die Verarbeitung benötigt!
00025     - EOF: Alle Daten verarbeitet.
00026
00027
00028 1) XML-Parser Cursor steht auf '|':
00029 |<...>
00030     <...>
00031     <...>
00032     <...>
00033 </...>
00034
00035 1.1) Tag ist ein Kommentar oder Control.
00036 |<!...> oder
00037 |<?...>
00038
00039 -> Parse automatisch auf nächstes '<'. Gehe zu 1)
00040
00041 1.2) Tag ist Starttag und enthält kein oder ein Attribut.
00042 -> Parse bis '>', Nodename wird geparst und abgespeichert.
00043 -> Rufe Steuerfunktion auf und sage ihr, dass ein Starttag komplett geparst wurde.
00044
00045 1.3) Tag ist Endtag, beginnt also mit "</"
00046 -> Parse bis '>'
00047 -> Rufe Steuerfunktion auf und sage ihr, dass ein Endtag komplett geparst wurde.
00048
00049 1.4) Leertag mit keinem oder einem Attribut endet also mit "/>"
00050 -> Parse bis '>', Nodename wird geparst und abgespeichert.
00051 -> Rufe Steuerfunktion auf und sage ihr, dass ein Leertag komplett geparst wurde.
00052
00053 1.5) Start- oder Endtag mit mehr als einem Attribut.
00054 -> Parse bis Whitespace, Nodename wird geparst und abgespeichert.
00055 -> Parse erstes Attribut und Wert.
00056 -> Rufe Steuerfunktion auf und sage ihr, dass ein weiteres Attribut komplett
00057 geparst wurde.
00058
00059
00060 2) XML-Steuermodul und XML-Auftraege
00061 Dieses Steuermodul hat folgenden Status:
00062 -> Aktuelle XML-Baumtiefe
00063 -> Flag, ob XML-Parser in Attribut-Liste ist
00064
00065 2.1) _GetNextSibling_
00066 Falls Parser sich in Attributliste befindet, muss zunaechst das Tag durch den
00067 Parser abgeschlossen werden (Zustand=?).
00068 Nachdem das Tag abgeschlossen wurde, muss falls es kein Leertag war, noch
00069 solange gesucht werden, bis ein Endtag gefunden wird, welches zur gleichen
00070 Baumtiefe führt (Zustand=?).
00071
00072 Command API liefert SUCCESS wenn
00073 a) Endtag mit Namen und Attribut (optional) - Leertag
00074 b) Starttag (Inkrementiere Baumtiefe)
00075 c) Attribut
00076 gefunden wurde.
00077
00078 Command API liefert FAILED wenn ein Endtag ohne Name gefunden wurde. Die
00079 aktuelle Baumebene wird in dem Fall verlassen und dekrementiert.
00080
00081
00082 2.2) _GetFirstChildNode_
00083 Falls Parser sich in Attributliste befindet, muss zunaechst das Tag durch den
00084 Parser abgeschlossen werden.
00085
00086 a)
00087
00088
00089 Command API liefert SUCCESS wenn ein Starttag gefunden wurde.
00090
00091 Command API liefert FAILED wenn ein Endtag ohne Name gefunden wurde. Die
00092 aktuelle Baumebene wird in dem Fall verlassen und dekrementiert.
00093
00094
00095 2.3) _GetNextParent_
00096
00097
00098 2.4) _GetNextAttribute_
00099
00100
00101
00102 */
00103
00104
00105 #define XML_C
00106
00107
00109 // Includes
00111
00112 #include "TCPIP.h"
00113 #include "xml.h"
00114
00115
00117 // Local defines
00119
00120 #define MAX_ELEMENT_NAME_LENGTH     20
00121
00122 #ifdef _ROCRAIL
00123     #define XML_PROCESSORS              2
00124 #else
00125     #define XML_PROCESSORS              1
00126 #endif
00127
00128
00130 // Local typedefs
00132
00133 // Internal states of the XML state machine.
00134 typedef enum
00135 {
00136     XML_SM_IDLE = 0,
00137     XML_SM_SEARCHING_START_OF_TAG,
00138     XML_SM_START_HEAD_TAG,
00139     XML_SM_END_HEAD_TAG,
00140     XML_SM_START_ROOT,
00141     XML_SM_ROOT_FOUND,
00142     XML_SM_START_TAG,
00143     XML_SM_PARSE_FOR_TAG_CLOSE,
00144     XML_SM_PARSE_ELEMENT_NAME,
00145     XML_SM_ERROR
00146 } SM_XML;
00147
00148 typedef enum
00149 {
00150     XML_SM_START = 0,
00151     XML_SM_NAME,
00152     XML_SM_ATTRIBUTE,
00153     XML_SM_ATTCONTENT,
00154     XML_SM_END
00155 } SM_XMLTAG;
00156
00157 typedef enum
00158 {
00159     XML_CMD_NOCOMMAND = 0,
00160     XML_CMD_GETNEXTSIBLING
00161 } CMD_XML;
00162
00163 typedef struct
00164 {
00165     XML_STATES eState;
00166     WORD u16PosOfTagEnd;
00167     WORD u16TextcontentLength;
00168     WORD u16ProcessedBytes;
00169     BYTE u8CurrentXMLTreeDepth;
00170     BYTE u8Socket;
00171     struct
00172     {
00173         BYTE bEmptyTag : 1;
00174         BYTE bTokenCompletlyParsed : 1;
00175     } sFlags;
00176     BYTE au8CurrentNodeName[MAX_ELEMENT_NAME_LENGTH+1];
00177 } sXMLState;
00178
00180 // Local Variables
00182
00183 // static
00184 sXMLState _asXMLState[XML_PROCESSORS];
00185
00186
00188 // Local function prototypes
00190
00191
00193 // Implementation
00195
00196 void InitXMLParser(void)
00197 {
00198     BYTE i = 0;
00199     while (i < XML_PROCESSORS)
00200     {
00201         _asXMLState[i].u8Socket = INVALID_SOCKET;
00202         i++;
00203     }
00204 }
00205
00208
00209 void InitXMLProcessor(BYTE u8Handle, BYTE u8Socket)
00210 {
00211     if (u8Handle > XML_PROCESSORS)
00212     {
00213         return;
00214     }
00215
00216     // Allocate the XML processor:
00217     _asXMLState[u8Handle].u8Socket = u8Socket;
00218
00219     // Initialize the structure members:
00220     _asXMLState[u8Handle].eState = XML_READY;
00221     _asXMLState[u8Handle].sFlags.bEmptyTag = FALSE;
00222     _asXMLState[u8Handle].sFlags.bTokenCompletlyParsed = FALSE;
00223
00224     _asXMLState[u8Handle].u8CurrentXMLTreeDepth = 0;
00225     _asXMLState[u8Handle].u16TextcontentLength = 0;
00226
00227     _asXMLState[u8Handle].u16ProcessedBytes = 0;
00228     _asXMLState[u8Handle].u16PosOfTagEnd = 0xFFFF;
00229
00230 }
00231
00234 /*
00235 SM_EXTXML eXMLGetState()
00236 {
00237     if (_eXMLSM == XML_SM_ROOT_FOUND)
00238         return XMLEXT_SM_ROOT_FOUND;
00239     else if (_eXMLSM == XML_SM_ERROR)
00240         return XMLEXT_SM_ERROR;
00241     else
00242         return XMLEXT_NEED_MORE_DATA;
00243 }
00244 */
00247
00248 BOOL _bIsWhiteSpace(BYTE u8Character)
00249 {
00250     if ((u8Character == ' ') || (u8Character == 0x09))
00251         return TRUE;
00252
00253     if ((u8Character == 0x0d) || (u8Character == 0x0a))
00254         return TRUE;
00255
00256     return FALSE;
00257 }
00258
00261
00262 XML_STATES eXMLGetState(BYTE u8Handle)
00263 {
00264     return _asXMLState[u8Handle].eState;
00265 }
00266
00269
00270 /*
00271 \retval FALSE Need more data for a complete token.
00272 \retval TRUE Token parsed, see the flags for token state.
00273 */
00274
00275
00276 /* Call this function to walk through a given xml tree. If the read pointer
00277 stays within a token found before this token is completly read from buffer.
00278
00279 \retval XML_NEED_MORE_DATA There is not enough data in the receive buffer for
00280 a parsing a complete token. Call again if there is more data in the buffer.
00281 \retval XML_READY A start token was found. Call pu8GetCurrentNodeName to obtain
00282 the name of the token.
00283 \retval XML_ROOT_LEAVED The
00284 */
00285 BOOL bXMLWalkTheTree(BYTE u8XMLProcessorHandle)
00286 {
00287     sXMLState * pState = &_asXMLState[u8XMLProcessorHandle];
00288     BYTE socket = pState->u8Socket;
00289     BYTE idx;
00290
00291     if (TCPIsGetReady(socket)==0)
00292     {
00293         // Need more data!
00294         return FALSE;
00295     }
00296
00297     switch(pState->eState)
00298     {
00299         case XML_ROOT_LEAVED:
00300             pState->u16PosOfTagEnd = 0xFFFF;
00301             pState->u16ProcessedBytes = 0;
00302             pState->u8CurrentXMLTreeDepth = 0;
00303
00304         case XML_READY:
00305         case XML_LEVEL_LEAVED:
00306             pState->eState = XML_SEARCHING_START_OF_TAG;
00307             // Intended fall through...
00308
00309         case XML_SEARCHING_START_OF_TAG:
00310         {
00311             WORD pos;
00312
00313             if (pState->u16PosOfTagEnd != 0xFFFF)
00314             {
00315                 // Parse the rest of the current token and throw it away.
00316                 if (pState->u16PosOfTagEnd)
00317                 {
00318                     pState->u16ProcessedBytes += TCPGetArray(socket, NULL, pState->u16PosOfTagEnd);
00319                 }
00320
00321                 if (pState->sFlags.bEmptyTag == FALSE)
00322                 {
00323                     // Increment the level of the XML tree.
00324                     pState->u8CurrentXMLTreeDepth++;
00325                 }
00326                 pState->u16PosOfTagEnd = 0xFFFF;
00327
00328                 // Checking for the root level (if one single empty tag is the
00329                 // only element in the document).
00330                 if ((pState->sFlags.bEmptyTag == TRUE) &&
00331                     (pState->u8CurrentXMLTreeDepth == 0))
00332                 {
00333                     pState->eState = XML_ROOT_LEAVED;
00334                     return TRUE;
00335                 }
00336             }
00337
00338 findXMLToken:
00339             pos = TCPFind(socket, '<', 0, FALSE);
00340             if (pos == 0xFFFF)
00341             {
00342                 pState->u16ProcessedBytes += TCPIsGetReady(socket);
00343                 TCPDiscard(socket);
00344                 return FALSE;
00345             }
00346
00347             // Remove all data until '<' (including).
00348             pState->u16ProcessedBytes += TCPGetArray(socket, NULL, pos+1);
00349
00350             pState->eState = XML_SEARCHING_END_OF_TAG;
00351             // Intended fall through...
00352         }
00353
00354         case XML_SEARCHING_END_OF_TAG:
00355         {
00356             BYTE chr;
00357             WORD pos = TCPFind(socket, '>', 0, FALSE);
00358             if (pos == 0xFFFF)
00359             {
00360                 // Need more data!
00361                 return FALSE;
00362             }
00363
00364             // Fetch the first character of the tag:
00365             TCPGet(socket, &chr);
00366             pState->u16ProcessedBytes++;
00367
00368             if ((chr == '?') || (chr == '!'))
00369             {
00370                 // Comments and controls are skipped automatically.
00371                 pState->eState = XML_SEARCHING_START_OF_TAG;
00372                 goto findXMLToken;
00373             }
00374             else if (chr == '/')
00375             {
00376                 // End tags are skipped automatically.
00377                 pState->u16ProcessedBytes += TCPGetArray(socket, NULL, pos);
00378                 pState->u8CurrentXMLTreeDepth--;
00379                 if (pState->u8CurrentXMLTreeDepth == 0)
00380                 {
00381                     pState->eState = XML_ROOT_LEAVED;
00382                 }
00383                 else
00384                 {
00385                     pState->eState = XML_LEVEL_LEAVED;
00386                 }
00387
00388                 return TRUE;
00389             }
00390
00391             // Just a start or empty token!
00392             pState->u16PosOfTagEnd = pos;
00393             pState->au8CurrentNodeName[0] = chr;
00394
00395             // Check whether it is an empty tag:
00396             pos = TCPFindROMArrayEx(socket, (ROM BYTE*)"/>", 2, 0, pos+1, FALSE);
00397
00398             if (pos != 0xFFFF)
00399             {
00400                 pState->sFlags.bEmptyTag = TRUE;
00401                 pState->u16TextcontentLength = 0;
00402                 break;
00403             }
00404
00405             pState->sFlags.bEmptyTag = FALSE;
00406             pState->eState = XML_SEARCHING_NEXT_TAG;
00407
00408             // Intended fall through...
00409         }
00410
00411         case XML_SEARCHING_NEXT_TAG:
00412         {
00413             // Searching for content.
00414             WORD pos = TCPFind(socket, '<', 0, FALSE);
00415             if (pos == 0xFFFF)
00416                 // Need more data!
00417                 return FALSE;
00418
00419             pState->u16TextcontentLength = pos - pState->u16PosOfTagEnd - 1;
00420         }
00421     }
00422
00423
00425     // Ok, we have a new token! Lets look at the content!
00426
00427     pState->eState = XML_READY;
00428     idx = 1;
00429
00430     // Fetch the node name
00431     while(1)
00432     {
00433         BYTE chr;
00434         TCPGet(socket, &chr);
00435         pState->u16PosOfTagEnd--;
00436         pState->u16ProcessedBytes++;
00437
00438         // White space is the end of the name.
00439         if (_bIsWhiteSpace(chr)==TRUE)
00440             break;
00441
00442         if ((chr=='/')||(pState->u16PosOfTagEnd == 0))
00443         {
00444             break;
00445         }
00446
00447         if (idx < MAX_ELEMENT_NAME_LENGTH)
00448         {   // Store elements name.
00449             pState->au8CurrentNodeName[idx++] = chr;
00450         }
00451     }
00452
00453     // Close the string:
00454     pState->au8CurrentNodeName[idx] = 0;
00455
00456     return TRUE;
00457 }
00458
00461
00462 BOOL bXMLCheckForNodeWithoutDepth(BYTE u8Handle, ROM char * pNodeName)
00463 {
00464     sXMLState * pState = &_asXMLState[u8Handle];
00465
00466     if ((pState->eState == XML_READY) &&
00467         (strcmppgm2ram(pState->au8CurrentNodeName,pNodeName) == 0))
00468     {
00469         return TRUE;
00470     }
00471
00472     return FALSE;
00473 }
00474
00477
00478 BOOL bXMLCheckForNode(BYTE u8Handle, BYTE u8TreeDepth, ROM char * pNodeName)
00479 {
00480     sXMLState * pState = &_asXMLState[u8Handle];
00481
00482     if ((pState->eState == XML_READY) &&
00483         (u8TreeDepth == pState->u8CurrentXMLTreeDepth) &&
00484         (strcmppgm2ram(pState->au8CurrentNodeName,pNodeName) == 0))
00485     {
00486         return TRUE;
00487     }
00488
00489     return FALSE;
00490 }
00491
00494
00495 BOOL bXMLSearchAttributeU16(BYTE u8Handle, ROM char * pu8Name, WORD * pu16Val)
00496 {
00497     BYTE val[MAX_ELEMENT_NAME_LENGTH+1];
00498
00499     if (pu16Val == NULL)
00500     {
00501         return FALSE;
00502     }
00503
00504     *pu16Val = 0;
00505     val[MAX_ELEMENT_NAME_LENGTH] = 0;
00506     if (bXMLSearchAttribute(u8Handle, pu8Name, val, MAX_ELEMENT_NAME_LENGTH+1) == FALSE)
00507     {
00508         return FALSE;
00509     }
00510
00511     if (val[MAX_ELEMENT_NAME_LENGTH] != 0)
00512     {
00513         // buffer was too small...
00514         return FALSE;
00515     }
00516
00517     *pu16Val = (WORD) atoi((const char *)val);
00518     return TRUE;
00519 }
00520
00523
00524 BOOL bXMLSearchAttribute(BYTE u8Handle, ROM char * pu8Name, BYTE * pu8Value,
00525                                                         BYTE u8ValueBufferSize)
00526 {
00527     BYTE buf[MAX_ELEMENT_NAME_LENGTH+1];
00528
00529     while (bXMLGetNextAttribute(u8Handle, buf, sizeof(buf), pu8Value, u8ValueBufferSize) == TRUE)
00530     {
00531         if (strcmppgm2ram(buf, pu8Name) == 0)
00532         {
00533             return TRUE;
00534         }
00535     }
00536
00537     return FALSE;
00538 }
00539
00542
00543 BOOL bXMLGetNextAttribute(BYTE u8Handle,
00544                             char * pu8Name, BYTE u8NameBufferSize,
00545                             char * pu8Value, BYTE u8ValueBufferSize)
00546 {
00547     BYTE chr;
00548     BYTE idx;
00549     sXMLState * pState = &_asXMLState[u8Handle];
00550     BYTE socket = pState->u8Socket;
00551     BYTE escapeSequence[10];
00552     BYTE escapeIndex = 0xFF;
00553
00554
00556     // Step 1:
00557     // Check whether there is a valid node with attributes.
00558     if (pState->eState != XML_READY)
00559     {
00560         return FALSE;
00561     }
00562
00563     if (pState->u16PosOfTagEnd == 0)
00564     {
00565         return FALSE;
00566     }
00567
00568
00570     // Step 2:
00571     // Remove trailing whitespaces.
00572     do
00573     {
00574         TCPGet(socket, &chr);
00575         pState->u16PosOfTagEnd--;
00576         pState->u16ProcessedBytes++;
00577     }
00578     while((_bIsWhiteSpace(chr) == TRUE)||(chr == '\"'));
00579
00580
00581
00583     // Step 3:
00584     // Check for tag end.
00585     if ((chr == '/') || (pState->u16PosOfTagEnd == 0))
00586     {
00587         return FALSE;
00588     }
00589
00590
00592     // Step 4:
00593     // Get attribute name.
00594     idx = 0;
00595     do
00596     {
00597         if (idx < u8NameBufferSize)
00598         {   // Store elements name.
00599             pu8Name[idx++] = chr;
00600         }
00601
00602         TCPGet(socket, &chr);
00603         pState->u16PosOfTagEnd--;
00604         pState->u16ProcessedBytes++;
00605
00606         if (chr == '=')
00607         {
00608             break;
00609         }
00610
00611         // White space is the end of the name.
00612     } while(_bIsWhiteSpace(chr) == FALSE);
00613
00614     // Close the string:
00615     if (idx < u8NameBufferSize)
00616     {
00617         pu8Name[idx] = 0;
00618     }
00619
00620
00622     // Step 5:
00623     // Remove trailing whitespaces.
00624     do
00625     {
00626         TCPGet(socket, &chr);
00627         pState->u16PosOfTagEnd--;
00628         pState->u16ProcessedBytes++;
00629     } while(_bIsWhiteSpace(chr) == TRUE);
00630
00631
00632
00634     // Step 6:
00635     // Get and store the value of the attribute element.
00636     idx = 0;
00637     escapeIndex = 0xFF;
00638
00639     while(1)
00640     {
00641         TCPGet(socket, &chr);
00642         pState->u16PosOfTagEnd--;
00643         pState->u16ProcessedBytes++;
00644
00645         if (chr == '"')
00646         {
00647             // The attribute value ends with a trailing quote.
00648             break;
00649         }
00650
00651
00652         if (escapeIndex != 0xFF)
00653         {
00654             if (chr == ';')
00655             {
00656                 // Close string:
00657                 escapeSequence[escapeIndex] = 0;
00658                 escapeIndex = 0xFF;
00659
00660                 if (strcmppgm2ram(escapeSequence, (ROM char *)"quot") == 0)
00661                 {
00662                     chr = '"';
00663                 }
00664                 else if (strcmppgm2ram(escapeSequence, (ROM char *)"lt") == 0)
00665                 {
00666                     chr = '<';
00667                 }
00668                 else if (strcmppgm2ram(escapeSequence, (ROM char *)"gt") == 0)
00669                 {
00670                     chr = '>';
00671                 }
00672                 else if (strcmppgm2ram(escapeSequence, (ROM char *)"amp") == 0)
00673                 {
00674                     chr = '&';
00675                 }
00676                 else if (strcmppgm2ram(escapeSequence, (ROM char *)"apos") == 0)
00677                 {
00678                     chr = '\'';
00679                 }
00680
00681                 if ((chr != ';') && (idx < (u8ValueBufferSize-1)))
00682                 {   // Store elements name.
00683                     pu8Value[idx++] = chr;
00684                 }
00685             }
00686             else if (escapeIndex < (sizeof(escapeSequence)-1))
00687             {
00688                 escapeSequence[escapeIndex++] = chr;
00689             }
00690         }
00691         else if (chr=='&')
00692         {
00693             escapeIndex = 0;
00694         }
00695         else if (idx < u8ValueBufferSize)
00696         {   // Store elements name.
00697             pu8Value[idx++] = chr;
00698         }
00699     }
00700
00701
00703     // Step 7:
00704     // Finish.
00705
00706     // Close the string (if space left):
00707     if (idx < u8ValueBufferSize)
00708     {
00709         pu8Value[idx] = 0;
00710     }
00711
00712     return TRUE;
00713 }
00714
00717
00718
00719 /*
00720 BOOL _GetAttribute(BYTE * pu8AttributeName, BYTE * pu8AttributeValue)
00721 {
00722     BYTE chr;
00723     BYTE idx = 0;
00724
00726     // Step 1:
00727     // Remove trailing whitespaces.
00728     do
00729     {
00730         TCPGet(hSocket, &chr);
00731         u16PosOfTagEnd--;
00732     } while((_bIsWhiteSpace(chr) == TRUE)||(chr == '\"'));
00733
00734
00736     // Step 2:
00737     // Check for tag end.
00738     if (chr == '/')
00739     {
00740         TCPGet(hSocket, &chr);
00741         u16PosOfTagEnd--;
00742     }
00743     if (chr == '>')
00744     {
00745         _bCompletlyParsed = TRUE;
00746         return FALSE;
00747     }
00748
00749
00751     // Step 3:
00752     // Store attribute name.
00753     do
00754     {
00755         if (idx < MAX_ELEMENT_NAME_LENGTH)
00756         {   // Store elements name.
00757             pu8AttributeName[idx++] = chr;
00758         }
00759
00760         TCPGet(hSocket, &chr);
00761         u16PosOfTagEnd--;
00762
00763         if (chr == '=')
00764             break;
00765
00766         // White space is the end of the name.
00767     } while(_bIsWhiteSpace(chr)==FALSE);
00768
00769     // Close string:
00770     pu8AttributeName[idx] = 0;
00771
00772
00774     // Step 4:
00775     // Remove trailing whitespaces.
00776     do
00777     {
00778         TCPGet(hSocket, &chr);
00779         u16PosOfTagEnd--;
00780     } while((_bIsWhiteSpace(chr)==TRUE)||(chr=='=')||(chr=='\"'));
00781
00782
00784     // Step 5:
00785     // Store attribute element.
00786     do
00787     {
00788         if (idx < MAX_ELEMENT_NAME_LENGTH)
00789         {   // Store elements name.
00790             pu8AttributeValue[idx++] = chr;
00791         }
00792
00793         TCPGet(hSocket, &chr);
00794         u16PosOfTagEnd--;
00795
00796         if (chr == '/')
00797         {
00798             TCPGet(hSocket, &chr);
00799             u16PosOfTagEnd--;
00800         }
00801         if (chr == '>')
00802         {
00803             _bCompletlyParsed = TRUE;
00804             break;
00805         }
00806
00807         // White space is the end of the name.
00808     } while(_bIsWhiteSpace(chr)==FALSE);
00809
00810     // Close string (remove closing "):
00811     pu8AttributeValue[idx-1] = 0;
00812     return TRUE;
00813 }
00814 */
00815
00818
00819 WORD u16XMLGetProcessedBytes(BYTE u8Handle)
00820 {
00821     sXMLState * pState = &_asXMLState[u8Handle];
00822     return _asXMLState[u8Handle].u16ProcessedBytes;
00823 }
00824
00827
00828 BOOL bXMLIsLevelLeaved(BYTE u8ProcessorHandle, BYTE u8TreeDepth)
00829 {
00830     sXMLState * pState = &_asXMLState[u8ProcessorHandle];
00831
00832     if ((pState->eState == XML_LEVEL_LEAVED) &&
00833         (u8TreeDepth == pState->u8CurrentXMLTreeDepth))
00834     {
00835         return TRUE;
00836     }
00837
00838     return FALSE;
00839 }
00840
00843
00844 void XMLPutString(BYTE u8Socket, BYTE * au8String)
00845 {
00846     BYTE index = 0;
00847
00848     while(1)
00849     {
00850         switch(au8String[index])
00851         {
00852             case '&':
00853                 TCPPutROMString(u8Socket, (ROM char *)"&amp;");
00854                 break;
00855
00856             case '"':
00857                 TCPPutROMString(u8Socket, (ROM char *)"&quot;");
00858                 break;
00859
00860             case '<':
00861                 TCPPutROMString(u8Socket, (ROM char *)"&lt;");
00862                 break;
00863
00864             case '>':
00865                 TCPPutROMString(u8Socket, (ROM char *)"&gt;");
00866                 break;
00867
00868             case '\'':
00869                 TCPPutROMString(u8Socket, (ROM char *)"&apos;");
00870                 break;
00871
00872             case 0:
00873                 return;
00874
00875             default:
00876                 TCPPut(u8Socket, au8String[index]);
00877         }
00878
00879         index++;
00880     }
00881 }
00882
00885
00886 void XMLCopyString(BYTE * au8DestString, BYTE * au8SrcString)
00887 {
00888     BYTE index = 0;
00889
00890     while(1)
00891     {
00892         switch(au8SrcString[index])
00893         {
00894             case '&':
00895                 strcpypgm2ram(au8DestString, (ROM char *)"&amp;");
00896                 break;
00897
00898             case '"':
00899                 strcpypgm2ram(au8DestString, (ROM char *)"&quot;");
00900                 break;
00901
00902             case '<':
00903                 strcpypgm2ram(au8DestString, (ROM char *)"&lt;");
00904                 break;
00905
00906             case '>':
00907                 strcpypgm2ram(au8DestString, (ROM char *)"&gt;");
00908                 break;
00909
00910             case '\'':
00911                 strcpypgm2ram(au8DestString, (ROM char *)"&apos;");
00912                 break;
00913
00914             case 0:
00915                 return;
00916
00917             default:
00918                 *au8DestString = au8SrcString[index];
00919         }
00920
00921         index++;
00922         au8DestString += strlen(au8DestString);
00923     }
00924 }
00925
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5


eWicht: xml.h Source File

xml.h

Go to the documentation of this file.
00001
00002
00003
00020
00021
00022
00023
00024 #ifndef XML_H
00025 #define XML_H
00026
00028 // Defines
00030
00031 #ifdef XML_C
00032     #define PROTO
00033 #else
00034     #define PROTO extern
00035 #endif
00036
00037 #define XML_CONFIG_HANDLE   0
00038 #define XML_RR_HANDLE       1
00039
00040
00042 // Typedefs
00044
00045 // External states of the XML state machine.
00046 typedef enum
00047 {
00048     XMLEXT_NEED_MORE_DATA = 0,
00049     XMLEXT_SM_ROOT_FOUND,
00050     XMLEXT_SM_ERROR
00051 } SM_EXTXML;
00052
00053 typedef enum
00054 {
00055     XML_SEARCHING_START_OF_TAG = 0,
00056     XML_SEARCHING_END_OF_TAG,
00057     XML_SEARCHING_NEXT_TAG,
00058     XML_ROOT_LEAVED,
00059     XML_LEVEL_LEAVED,
00060     XML_READY
00061 } XML_STATES;
00062
00065
00066
00068 // Function prototypes
00070
00071 PROTO void InitXMLParser(void);
00072 PROTO void InitXMLProcessor(BYTE u8Handle, BYTE u8Socket);
00073 PROTO BOOL bXMLWalkTheTree(BYTE u8Socket);
00074 PROTO XML_STATES eXMLGetState(BYTE u8Handle);
00075 PROTO WORD u16XMLGetProcessedBytes(BYTE u8Handle);
00076 PROTO BOOL bXMLIsLevelLeaved(BYTE u8ProcessorHandle, BYTE u8TreeDepth);
00077 PROTO BOOL bXMLCheckForNode(BYTE u8Handle, BYTE u8TreeDepth,
00078                                                          ROM char * pNodeName);
00079 BOOL bXMLCheckForNodeWithoutDepth(BYTE u8Handle, ROM char * pNodeName);
00080
00081 PROTO BOOL bXMLSearchAttribute(BYTE u8Handle, ROM char * pu8Name,
00082                                       BYTE * pu8Value, BYTE u8ValueBufferSize);
00083 PROTO BOOL bXMLSearchAttributeU16(BYTE u8Handle, ROM char * pu8Name,
00084                                                                WORD * pu16Val);
00085
00086 PROTO BOOL bXMLGetNextAttribute(BYTE u8Handle,
00087                             char * pu8Name, BYTE u8NameBufferSize,
00088                             char * pu8Value, BYTE u8ValueBufferSize);
00089
00090 PROTO void XMLPutString(BYTE u8Socket, BYTE * au8String);
00091 PROTO void XMLCopyString(BYTE * au8DestString, BYTE * au8SrcString);
00092
00096
00097 // Epilogue
00099
00100 #undef PROTO
00101
00102 #endif  // #ifndef XML_H
Generated on Sun Nov 27 20:02:39 2011 for eWicht by doxygen 1.5.5