summaryrefslogtreecommitdiff
path: root/src/interface/interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface/interface.c')
-rw-r--r--src/interface/interface.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/interface/interface.c b/src/interface/interface.c
new file mode 100644
index 00000000..e19bbc5b
--- /dev/null
+++ b/src/interface/interface.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011 Tomasz Boleslaw CEDRO <cederom@tlen.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/** @file: Generic OpenOCD interface. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <interface/interface.h>
+#include <jtag/interface.h>
+#include <helper/log.h>
+
+extern struct jtag_interface *jtag_interface;
+
+/******************************************************************************
+ * SIGNAL INFRASTRUCTURE AND OPERATIONS
+ ******************************************************************************/
+
+/** Check if specified signal is already defined (case insensitive) and return
+ * its pointer if defined.
+ * \param *name signal name to check
+ * \return pointer to signal structure in memory if found, NULL otherwise.
+ */
+oocd_interface_signal_t *oocd_interface_signal_find(char *name){
+ // Check if interface already exists
+ if (!jtag_interface){
+ LOG_ERROR("Interface does not yet exist!");
+ return NULL;
+ }
+ // Check if interface signal to work on already exists
+ if (!jtag_interface->signal){
+ LOG_WARNING("There are no signals defined yet.");
+ return NULL;
+ }
+ // Check if signal name is correct
+ if (!name || strncmp(name, " ", 1)==0){
+ LOG_ERROR("Signal name cannot be empty.");
+ return NULL;
+ }
+ // Check if signal name already exist
+ oocd_interface_signal_t *sig;
+ sig=jtag_interface->signal;
+ while (sig) {
+ if (!strncasecmp(sig->name, name, 32)){
+ LOG_DEBUG("Signal %s already exists.", sig->name);
+ return sig;
+ }
+ sig=sig->next;
+ }
+ // If signal is not found return null pointer.
+ LOG_DEBUG("Signal %s not (yet) on the list.", name);
+ return NULL;
+}
+/** Add new signal to the interface.
+ * Signal will be allocated in memory with provided name and mask.
+ * There is no sense for giving value field at this time because signal create
+ * can take place during initialization where interface is not yet ready, also
+ * they can be used for read and write, so this is higher level script task
+ * to initialize their default value with appropriate 'bitbang' call.
+ * The default value for new signal equals provided mask to maintain Hi-Z.
+ *
+ * \param *name is the signal name (max 32 char).
+ * \param mask is the signal mask (unsigned int).
+ * \param value is the initial value for signal to set.
+ * \return ERROR_OK on success or ERROR_FAIL on failure.
+ */
+int oocd_interface_signal_add(char *name, unsigned int mask){
+ // Check if interface already exists
+ if (!jtag_interface){
+ LOG_ERROR("Interface does not yet exist!");
+ return ERROR_FAIL;
+ }
+
+ // Check if name is correct string
+ if (!name || strncmp(name, " ", 1)==0){
+ LOG_ERROR("Signal name cannot be empty");
+ return ERROR_FAIL;
+ }
+
+ oocd_interface_signal_t *newsignal, *lastsignal;
+ int snlen;
+
+ // Check signal length (min=1, max=32 characters)
+ snlen=strnlen(name, 32);
+ if (snlen<1 || snlen>32) {
+ LOG_ERROR("Signal name too short or too long!");
+ return ERROR_FAIL;
+ }
+
+ // Check if signal name already exist and return error if so
+ if (oocd_interface_signal_find(name)){
+ LOG_ERROR("Specified signal already exist!");
+ return ERROR_FAIL;
+ }
+
+ // Allocate memory for new signal structure
+ newsignal=(oocd_interface_signal_t *)calloc(1, sizeof(oocd_interface_signal_t));
+ if (!newsignal) {
+ LOG_ERROR("cannot allocate memory for new signal: %s", name);
+ return ERROR_FAIL;
+ }
+ newsignal->name=(char *)calloc(1, snlen+1);
+ if (!newsignal->name) {
+ LOG_ERROR("cannot allocate memory for signal %s name", name);
+ return ERROR_FAIL;
+ }
+
+ // Initialize structure data and return or break on error
+ for(;;){
+ if (!strncpy(newsignal->name, name, snlen)) {
+ LOG_ERROR("cannot copy signal %s name!", name);
+ break;
+ }
+
+ newsignal->mask=mask;
+ newsignal->value=mask;
+
+ if (!jtag_interface->signal){
+ jtag_interface->signal=newsignal;
+ } else {
+ lastsignal=jtag_interface->signal;
+ while(lastsignal->next) {lastsignal=lastsignal->next;}
+ lastsignal->next=newsignal;
+ }
+ return ERROR_OK;
+ }
+
+ // If there was an error free up resources and return error
+ free(newsignal->name);
+ free(newsignal);
+ return ERROR_FAIL;
+}
+
+/** Delete interface signal.
+ * Removes signal from singly linked list of interface signals and free memory.
+ * \param name is the name of the signal to remove.
+ * \return ERROR_OK on success, ERROR_FAIL on failure.
+ */
+int oocd_interface_signal_del(char *name){
+ // Check if interface already exists
+ if (!jtag_interface){
+ LOG_ERROR("Interface does not yet exist!");
+ return ERROR_FAIL;
+ }
+ // Check if interface any signal exist
+ if (!jtag_interface->signal){
+ LOG_DEBUG("There are no signals defined yet.");
+ return ERROR_FAIL;
+ }
+
+ // Check if signal name is correct
+ if (!name || strncmp(name, " ", 1)==0){
+ LOG_ERROR("Signal name cannot be empty.");
+ return ERROR_FAIL;
+ }
+
+ oocd_interface_signal_t *delsig=NULL, *prevsig=NULL;
+
+ //look for the signal name on the list
+ delsig=oocd_interface_signal_find(name);
+
+ //return error if signal is not on the list
+ if (!delsig){
+ LOG_ERROR("Signal not found!");
+ return ERROR_FAIL;
+ }
+
+ //detach signal to be removed from the list
+ prevsig=jtag_interface->signal;
+ if (prevsig==delsig){
+ //we need to detach first signal on the list
+ jtag_interface->signal=jtag_interface->signal->next;
+ } else {
+ for (;prevsig->next;prevsig=prevsig->next){
+ if (prevsig->next==delsig) {
+ prevsig->next=prevsig->next->next;
+ break;
+ }
+ }
+ }
+
+ //now free memory of detached element
+ free(delsig->name);
+ free(delsig);
+ return ERROR_OK;
+}
+