cgi.c
来自「针对AVR单片机开发的嵌入式操作系统」· C语言 代码 · 共 721 行 · 第 1/2 页
C
721 行
/*
* Copyright (C) 2002-2005 by egnite Software GmbH. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
* SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* For additional information see http://www.ethernut.de/
*
*/
#include <string.h>
#include <stdio.h>
#include <io.h>
#include <dev/spidigio.h>
#include <pro/httpd.h>
#include "db_shift.h"
#include "webport.h"
/*!
* \file cgi.c
* \brief CGI Callbacks.
*/
/*!
* \addtogroup xgCGI
*/
/*@{*/
static u_char spi_ni = 255; /*!< \brief Number of detected opto inputs. */
static u_char spi_no = 255; /*!< \brief Number of detected relays. */
static u_long relay_status; /*!< \brief Relays status. */
static u_char relay_known; /*!< \brief Equals zero as long as the relay status is unknown. */
/*!
* \brief Print HTML code for a row of LEDs.
*
* The resulting HTML code will present a row of LEDs. The color and
* the lit state of each LED is determined by three bit values. The
* required images are expected in the URL root of the urom flash
* filesystem:
*
* - r0.gif Red LED not lit. Will be displayed if the corresponding
* bit in the direction mask is set and the input and output
* bits are both not set.
* - r1.gif Red LED lit. Will be displayed if the corresponding
* bit in the direction mask is set and the input and output
* bits are both set.
* - g0.gif Green LED not lit. Will be displayed if the corresponding
* bit in the direction mask and the input value are both not set.
* - g1.gif Green LED lit. Will be displayed if the corresponding
* bit in the direction mask is not set and the input bit is set.
* - y0.gif Yellow LED not lit. Will be displayed if the corresponding
* bit in the direction mask is set, the output bit is set
* but the input bit is not set.
* - y1.gif Yellow LED lit. Will be displayed if the corresponding
* bit in the direction mask is set, the output bit is not set
* but the input bit is set.
*
* All LED images must be of the same size, 28 x 28 pixels.
*
* \param stream HTML code is printed to this stream device.
* \param num The number of LEDs to print.
* \param desc If not equal zero, bits are processed in descending order.
* \param ival Input bit values.
* \param oval Output bit values.
* \param dir Data direction mask. Any bit set to one represents an output.
*/
static void HtmlLedRow(FILE * stream, u_char num, u_char desc, u_long ival, u_long oval, u_long dir)
{
u_char i;
u_long mask;
for (i = 0; i < num; i++) {
if (desc)
mask = 1UL << (num - i - 1);
else
mask = 1UL << i;
fputs("<td><img src=\"/", stream);
if (dir & mask) {
if (oval & mask) {
if (ival & mask)
fputs("r1", stream);
else
fputs("y0", stream);
} else {
if (ival & mask)
fputs("y1", stream);
else
fputs("r0", stream);
}
} else {
if (ival & mask) {
fputs("g1", stream);
} else {
fputs("g0", stream);
}
}
fputs(".gif\" width=\"28\" heigth=\"28\"></td>\r\n", stream);
}
}
/*!
* \brief Print HTML code for a row of checkboxes.
*
* The resulting HTML code will present a row of checkboxes.
*
* \param stream HTML code is printed to this stream device.
* \param num The number of checkboxes to print.
* \param desc If not equal zero, bits are processed in descending order.
* \param name Identifier of the checkboxes.
* \param check The checkbox will be checked if the corresponding bit is set.
* \param enable The checkbox will be created only, ff the corresponding bit
* in this bitmask is set.
*/
static void HtmlCheckboxRow(FILE * stream, u_char num, u_char desc, u_char * name, u_long check, u_long enable)
{
u_char i;
u_long mask;
for (i = 0; i < num; i++) {
if (desc)
mask = 1UL << (num - i - 1);
else
mask = 1UL << i;
if (enable & mask) {
fputs("<td><input type=\"checkbox\" name=\"", stream);
fprintf(stream, "%s\" value=\"%u\" ", name, num - i - 1);
if (check & mask)
fputs(" checked=\"checked\"", stream);
fputs("></td>\r\n", stream);
} else
fputs("<td></td>\r\n", stream);
}
}
/*!
* \brief Print HTML code for a separator row.
*
* The resulting HTML code will present a black row.
*
* \param stream HTML code is printed to this stream device.
* \param width Separator width in columns.
* \param height Separator width in pixels.
*/
static void HtmlSeparatorRow(FILE * stream, u_char width, u_char height)
{
fprintf(stream, "<tr bgcolor=\"#000000\"><td colspan=\"%u\" " /* */
"height=\"%u\"></td></tr>", width, height);
}
/*!
* \brief Print HTML code to display a single I/O port.
*
* The resulting HTML code will present a row of LEDs and two rows of
* checkboxes. While the LEDs show the current port status, the checkboxes
* may be used to modify the port output and the data direction register.
*
* See HtmlLedRow() for further details about how LEDs are displayed.
* The checkboxes are created by calling HtmlCheckboxRow().
*
* \param stream HTML code is printed to this stream device.
* \param name Port identifier, typically 'A' for Port A, 'B' for port B etc.
* \param pin Contents of the PIN register.
* \param port Contents of the PORT register.
* \param ddr Contents of the data direction register.
* \param enable If a bit is not set in this bit mask, then the corresponding
* checkboxes are not created and the port bits and data direction
* can't be modified.
*/
static void HtmlInOutPortRow(FILE * stream, char name, u_char pin, u_char port, u_char ddr, u_char enable)
{
char ditem[3] = { 'D', 'X', 0 };
char pitem[3] = { 'P', 'X', 0 };
ditem[1] = name;
pitem[1] = name;
fputs("<tr><th rowspan=\"4\">", stream);
fprintf(stream, "%c", name);
fputs("</th><td>Status</td>", stream);
HtmlLedRow(stream, 8, 1, pin, port, ddr);
fputs("</tr>\r\n<tr><td>Output</td>", stream);
HtmlCheckboxRow(stream, 8, 1, ditem, ddr, enable);
fputs("</tr>\r\n<tr><td>Pull up</td>", stream);
HtmlCheckboxRow(stream, 8, 1, pitem, port, enable);
fputs("</tr>\r\n", stream);
}
/*!
* \brief Process request parameters for CPU port control.
*
* Parse the CGI query and perform the corresponding action:
*
* - Dx=y will set bit y in the data direction register of port x.
* - Px=y will set bit y in the port output register of port x.
*
* All other bits are switched off.
*
* \param query CGI query string.
*/
static void ProcessCgiPortRequest(REQUEST * req)
{
u_char ddrb = 0;
u_char portb = 0;
u_char ddrd = 0;
u_char portd = 0;
u_char ddre = 0;
u_char porte = 0;
int mods = 0;
int i;
int pcount = NutHttpGetParameterCount(req);
char *name;
char *value;
for (i = 0; i < pcount; i++) {
name = NutHttpGetParameterName(req, i);
value = NutHttpGetParameterValue(req, i);
if (strcmp(name, "DB") == 0) {
ddrb |= BV(*value - '0');
mods++;
} else if (strcmp(name, "PB") == 0) {
portb |= BV(*value - '0');
mods++;
} else if (strcmp(name, "DD") == 0) {
ddrd |= BV(*value - '0');
mods++;
} else if (strcmp(name, "PD") == 0) {
portd |= BV(*value - '0');
mods++;
} else if (strcmp(name, "DE") == 0) {
ddre |= BV(*value - '0');
ddre &= ~_BV(5);
mods++;
} else if (strcmp(name, "PE") == 0) {
porte |= BV(*value - '0');
porte &= ~_BV(5);
mods++;
}
}
if (mods) {
outb(DDRB, ddrb);
outb(PORTB, portb);
outb(DDRD, ddrd);
outb(PORTD, portd);
outb(DDRE, ddre);
outb(PORTE, porte);
}
}
/*!
* \brief Process request parameters for relay output control.
*
* Parse the CGI query and switch the corresponding relays.
* 'S=y' will switch on relay y. All other relays are switched off.
*
* Note, that before calling this function is called for the first time,
* the status of the relays is unknown.
*
* \param query CGI query string.
*/
static void ProcessCgiRelayRequest(char *query)
{
u_char *item = query;
u_char *val;
relay_status = 0;
for (;;) {
if ((val = strchr(item, '=')) == 0)
break;
*val++ = 0;
if (item[0] == 'S')
relay_status |= 1UL << (7 - (*val - '0'));
if ((item = strchr(val, '&')) == 0)
break;
item++;
}
SpiDigitalSet(spi_no, relay_status);
relay_known = 1;
}
/*!
* \brief CGI callback function to control the CPU ports.
*
* Creates HTML code to show the status of CPU ports B, D, E and F
* plus a HTML form to modify the port and data direction registers
* of ports B, D and E by checkboxes.
*
* The resulting HTML code is send back to the browser. If the submit
* button is clicked on this page, this function will be called again
* to process the checkboxes.
*
* \image html cport.gif
*
*
*
* This function is called by the HTTP module when a browser requests
* a CGI function, for which this routine has been registered via
* NutRegisterCgi().
*
* \param stream Stream of the HTTP connection.
* \param req Pointer to the CGI REQUEST structure. Detailed information
* is available in the Nut/OS API documentation.
*
* \return 0 on success or -1 in case of any failure.
*/
int CpuPortControl(FILE * stream, REQUEST * req)
{
static prog_char head[] = "<html>" /* */
"<head>" /* */
"<meta http-equiv=\"expires\" content=\"0\">" /* */
"<title>Ethernut CPU Port Control</title>" /* */
"</head>" /* */
"<body bgcolor=\"#C7D0D9\"><a href=\"/\">" /* */
"<img src=\"/enmini.gif\" border=\"0\" width=\"70\" height=\"17\">" /* */
"</a><div align=\"center\">";
static prog_char thdr[] = "<form action=\"" PORT_CONTROL_CGI /* */
"\" enctype=\"text/plain\">" /* */
"<table border=\"1\" cellspacing=\"0\">\r\n" /* */
"<thead><tr><th rowspan=\"2\"> PORT </th>" /* */
"<th rowspan=\"2\"> Type </th>" /* */
"<th colspan=\"8\">Bit</th></tr>" /* */
"<tr><th>7</th><th>6</th><th>5</th><th>4</th><th>3</th>" /* */
"<th>2</th><th>1</th><th>0</th></tr>" /* */
"</thead><tfoot>\r\n";
static prog_char foot[] = "</tfoot></table><br>" /* */
" <input type=\"submit\" value=\" Set \"> " /* */
" <input type=\"reset\" value=\" Cancel \"> " /* */
"</form>\r\n</div></body>\r\n</html>";
NutHttpSendHeaderTop(stream, req, 200, "Ok");
NutHttpSendHeaderBot(stream, "text/html", -1);
fputs_P(head, stream);
if (req->req_url)
ProcessCgiPortRequest(req);
fputs_P(thdr, stream);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?