// Raspberry Pi LPC1114 I/O Processor Expansion Board // SPI agent firmware XML-RPC server // Copyright (C)2013-2018, Philip Munts, President, Munts AM Corp. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT HOLDER 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. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "spi-agent.h" extern void spiagent_open_ioctl(char *servername, int32_t *error); extern void spiagent_command_ioctl(SPIAGENT_COMMAND_MSG_t *cmd, SPIAGENT_RESPONSE_MSG_t *resp, int32_t *error); #define RESPONSEDELAY 0 #define PROGRAMNAME "spi_agent_xmlrpc_server" #define SERVICENAME "spiagent-xmlrpc" // This method function is just an XML-RPC wrapper around spiagent_command_ioctl() static xmlrpc_value *spi_transaction(xmlrpc_env * const env, xmlrpc_value * const parameters, void * const serverinfo) { SPIAGENT_COMMAND_MSG_t command; SPIAGENT_RESPONSE_MSG_t response; int32_t error; memset(&response, 0, sizeof(response)); // Extract parameters xmlrpc_decompose_value(env, parameters, "(iii)", &command.command, &command.pin, &command.data); if (env->fault_occurred) return NULL; // Perform the SPI transfers spiagent_command_ioctl(&command, &response, &error); if (error) { char errormessage[256]; memset(errormessage, 0, sizeof(errormessage)); snprintf(errormessage, sizeof(errormessage), "ERROR: spiagent_command_ioctl() failed, %s", strerror(error)); syslog(LOG_ERR, errormessage); XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, errormessage); } cleanup: return xmlrpc_build_value(env, "(iiii)", response.command, response.pin, response.data, response.error); } int main(void) { struct servent *service; int32_t error; xmlrpc_server_abyss_parms serverparms; xmlrpc_registry *registryP; xmlrpc_env env; openlog(PROGRAMNAME, LOG_NDELAY|LOG_PID|LOG_PERROR, LOG_DAEMON); syslog(LOG_INFO, "Starting LPC1114 SPI Agent Firmware XML-RPC server"); // Look up service definition service = getservbyname(SERVICENAME, "tcp"); if (service == NULL) { syslog(LOG_ERR, "ERROR: getservbyname() failed, unknown service"); exit(1); } // Open the Raspberry Pi LPC1114 I/O Processor Expansion Board SPI device spiagent_open_ioctl(NULL, &error); if (error) { syslog(LOG_ERR, "ERROR: spiagent_open_ioctl(() failed, %s", strerror(error)); exit(1); } // Become a nobody LINUX_drop_privileges("nobody", &error); if (error) { syslog(LOG_ERR, "ERROR: DropPrivileges() failed, %s", strerror(error)); exit(1); } // Initialize the XML-RPC library internal data structures xmlrpc_env_init(&env); // Register the XML-RPC method registryP = xmlrpc_registry_new(&env); if (env.fault_occurred) { syslog(LOG_ERR, "ERROR: xmlrpc_registry_new() failed, error=%d (%s)", env.fault_code, env.fault_string); exit(1); } xmlrpc_registry_add_method_w_doc(&env, registryP, NULL, "spi.agent.transaction", spi_transaction, NULL, "A:iii", "SPI Agent transaction wrapper"); if (env.fault_occurred) { syslog(LOG_ERR, "ERROR: xmlrpc_add_method_w_doc() failed, error=%d (%s)", env.fault_code, env.fault_string); exit(1); } // Configure the server serverparms.config_file_name = NULL; serverparms.registryP = registryP; serverparms.port_number = ntohs(service->s_port); // Switch to background if (daemon(0, 0)) { syslog(LOG_ERR, "ERROR: daemon() failed, %s", strerror(errno)); exit(1); } // Start the server xmlrpc_server_abyss(&env, &serverparms, XMLRPC_APSIZE(port_number)); if (env.fault_occurred) { syslog(LOG_ERR, "ERROR: xmlrpc_server_abyss() failed, error=%d (%s)", env.fault_code, env.fault_string); exit(1); } exit(0); }