summaryrefslogtreecommitdiff
path: root/openpicc/application/cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/application/cmd.c')
-rw-r--r--openpicc/application/cmd.c303
1 files changed, 303 insertions, 0 deletions
diff --git a/openpicc/application/cmd.c b/openpicc/application/cmd.c
new file mode 100644
index 0000000..ec8236a
--- /dev/null
+++ b/openpicc/application/cmd.c
@@ -0,0 +1,303 @@
+#include <AT91SAM7.h>
+#include <FreeRTOS.h>
+#include <task.h>
+#include <queue.h>
+#include <USB-CDC.h>
+#include <board.h>
+
+#include "env.h"
+#include "cmd.h"
+#include "openpicc.h"
+#include "led.h"
+
+xQueueHandle xCmdQueue;
+xTaskHandle xCmdTask;
+xTaskHandle xCmdRecvUsbTask;
+
+/**********************************************************************/
+void DumpUIntToUSB(unsigned int data)
+{
+ int i=0;
+ unsigned char buffer[10],*p=&buffer[sizeof(buffer)];
+
+ do {
+ *--p='0'+(unsigned char)(data%10);
+ data/=10;
+ i++;
+ } while(data);
+
+ while(i--)
+ vUSBSendByte(*p++);
+}
+/**********************************************************************/
+
+void DumpStringToUSB(char* text)
+{
+ unsigned char data;
+
+ if(text)
+ while((data=*text++)!=0)
+ vUSBSendByte(data);
+}
+/**********************************************************************/
+
+static inline unsigned char HexChar(unsigned char nibble)
+{
+ return nibble + ((nibble<0x0A) ? '0':('A'-0xA));
+}
+
+void DumpBufferToUSB(char* buffer, int len)
+{
+ int i;
+
+ for(i=0; i<len; i++) {
+ vUSBSendByte(HexChar( *buffer >> 4));
+ vUSBSendByte(HexChar( *buffer++ & 0xf));
+ }
+}
+/**********************************************************************/
+
+/*
+ * Convert a string to an integer. Ignores leading spaces.
+ * Optionally returns a pointer to the end of the number in the string */
+int atoiEx(const char * nptr, char * * eptr)
+{
+ portBASE_TYPE sign = 1, i=0;
+ int curval = 0;
+ while(nptr[i] == ' ' && nptr[i] != 0) i++;
+ if(nptr[i] == 0) goto out;
+ if(nptr[i] == '-') {sign *= -1; i++; }
+ else if(nptr[i] == '+') { i++; }
+ while(nptr[i] != 0 && nptr[i] >= '0' && nptr[i] <= '9')
+ curval = curval * 10 + (nptr[i++] - '0');
+
+ out:
+ if(eptr != NULL) *eptr = (char*)nptr+i;
+ return sign * curval;
+}
+
+static const AT91PS_SPI spi = AT91C_BASE_SPI;
+#define SPI_MAX_XFER_LEN 33
+
+extern volatile unsigned portLONG ulCriticalNesting;
+void prvExecCommand(u_int32_t cmd, portCHAR *args) {
+ static int led = 0;
+ portCHAR cByte = cmd & 0xff;
+ portLONG j;
+ int i,h,m,s;
+ if(cByte>='A' && cByte<='Z')
+ cByte-=('A'-'a');
+
+ DumpStringToUSB("Got command ");
+ DumpUIntToUSB(cmd);
+ DumpStringToUSB(" with args ");
+ DumpStringToUSB(args);
+ DumpStringToUSB("\n\r");
+
+ i=0;
+ // Note: Commands have been uppercased when this code is called
+ switch(cmd)
+ {
+ case '4':
+ case '3':
+ case '2':
+ case '1':
+ env.e.mode=cmd-'0';
+ DumpStringToUSB(" * Switched to transmit mode at power level ");
+ DumpUIntToUSB(env.e.mode);
+ DumpStringToUSB("\n\r");
+ break;
+ case 'S':
+ env_store();
+ DumpStringToUSB(" * Stored environment variables\n\r");
+ break;
+ case '0':
+ DumpStringToUSB(" * switched to RX mode\n\r");
+ break;
+ case 'TEST':
+ DumpStringToUSB("Testing critical sections\r\n");
+ j=ulCriticalNesting;
+ DumpStringToUSB("Nesting is now ");
+ DumpUIntToUSB(j);
+ DumpStringToUSB("\n\r");
+ taskENTER_CRITICAL();
+ for(i=0; i<1000; i++) {;}
+ j=ulCriticalNesting;
+ taskEXIT_CRITICAL();
+ DumpStringToUSB("Nesting was ");
+ DumpUIntToUSB(j);
+ DumpStringToUSB("\n\r");
+ j=ulCriticalNesting;
+ DumpStringToUSB("Nesting is now ");
+ DumpUIntToUSB(j);
+ DumpStringToUSB("\n\r");
+ break;
+ case 'I':
+ i=atoiEx(args, &args);
+ if(i!=0) {
+ env.e.reader_id = i;
+ DumpStringToUSB("Reader ID set to ");
+ DumpUIntToUSB(env.e.reader_id);
+ DumpStringToUSB("\n\r");
+ }
+ break;
+ case 'C':
+ DumpStringToUSB(
+ " *****************************************************\n\r"
+ " * Current configuration: *\n\r"
+ " *****************************************************\n\r"
+ " *\n\r");
+ DumpStringToUSB(" * Uptime is ");
+ s=xTaskGetTickCount()/1000;
+ h=s/3600;
+ s%=3600;
+ m=s/60;
+ s%=60;
+ DumpUIntToUSB(h);
+ DumpStringToUSB("h:");
+ DumpUIntToUSB(m);
+ DumpStringToUSB("m:");
+ DumpUIntToUSB(s);
+ DumpStringToUSB("s");
+ DumpStringToUSB("\n\r");
+ DumpStringToUSB(" * The reader id is ");
+ DumpUIntToUSB(env.e.reader_id);
+ DumpStringToUSB("\n\r");
+ DumpStringToUSB(" * The mode is ");
+ DumpUIntToUSB(env.e.mode);
+ DumpStringToUSB("\n\r");
+ DumpStringToUSB(" * The transmit interval is ");
+ DumpUIntToUSB(env.e.speed);
+ DumpStringToUSB("00ms\n\r");
+ DumpStringToUSB(
+ " *\n\r"
+ " *****************************************************\n\r"
+ );
+ break;
+ case '+':
+ case '-':
+ if(cmd == '+')
+ {
+ if(env.e.speed<9)
+ env.e.speed++;
+ }
+ else
+ if(env.e.speed>1)
+ env.e.speed--;
+
+ DumpStringToUSB(" * Transmit interval set to ");
+ vUSBSendByte(((char)(env.e.speed))+'0');
+ DumpStringToUSB("00ms\n\r");
+ break;
+ case 'L':
+ led = (led+1)%4;
+ vLedSetRed( (led&1) );
+ vLedSetGreen( led&2 );
+ DumpStringToUSB(" * LEDs set to ");
+ vUSBSendByte( (char)led + '0' );
+ DumpStringToUSB("\n\r");
+ break;
+ case 'H':
+ case '?':
+ DumpStringToUSB(
+ " *****************************************************\n\r"
+ " * OpenPICC USB terminal *\n\r"
+ " * (C) 2007 Milosch Meriac <meriac@openbeacon.de> *\n\r"
+ " * (C) 2007 Henryk Plötz <henryk@ploetzli.ch> *\n\r"
+ " *****************************************************\n\r"
+ " *\n\r"
+ " * s - store transmitter settings\n\r"
+ " * test - test critical sections\n\r"
+ " * c - print configuration\n\r"
+ " * 0 - receive only mode\n\r"
+ " * 1..4 - automatic transmit at selected power levels\n\r"
+ " * +,- - faster/slower transmit speed\n\r"
+ " * l - cycle LEDs\n\r"
+ " * ?,h - display this help screen\n\r"
+ " *\n\r"
+ " *****************************************************\n\r"
+ );
+ break;
+ }
+
+}
+
+// A task to execute commands
+void vCmdCode(void *pvParameters) {
+ (void) pvParameters;
+ u_int32_t cmd;
+ portBASE_TYPE i, j=0;
+
+ for(;;) {
+ cmd_type next_command;
+ cmd = j = 0;
+ if( xQueueReceive(xCmdQueue, &next_command, ( portTickType ) 100 ) ) {
+ DumpStringToUSB("Command received:");
+ DumpStringToUSB(next_command.command);
+ DumpStringToUSB("\n\r");
+ while(next_command.command[j] == ' ' && next_command.command[j] != 0) {
+ j++;
+ }
+ for(i=0;i<4;i++) {
+ portCHAR cByte = next_command.command[i+j];
+ if(next_command.command[i+j] == 0 || next_command.command[i+j] == ' ')
+ break;
+ if(cByte>='a' && cByte<='z') {
+ cmd = (cmd<<8) | (cByte+('A'-'a'));
+ } else cmd = (cmd<<8) | cByte;
+ }
+ while(next_command.command[i+j] == ' ' && next_command.command[i+j] != 0) {
+ i++;
+ }
+ prvExecCommand(cmd, next_command.command+i+j);
+ } else {
+ }
+ }
+}
+
+// A task to read commands from USB
+void vCmdRecvUsbCode(void *pvParameters) {
+ portBASE_TYPE len=0;
+ cmd_type next_command = { source: SRC_USB, command: ""};
+ (void) pvParameters;
+
+ for( ;; ) {
+ if(vUSBRecvByte(&next_command.command[len], 1, 100)) {
+ next_command.command[len+1] = 0;
+ DumpStringToUSB(next_command.command + len);
+ if(next_command.command[len] == '\n' || next_command.command[len] == '\r') {
+ next_command.command[len] = 0;
+ if(len > 0) {
+ if( xQueueSend(xCmdQueue, &next_command, 0) != pdTRUE) {
+ DumpStringToUSB("Queue full, command can't be processed.\n");
+ }
+ len=0;
+ }
+ } else len++;
+ if(len >= MAX_CMD_LEN-1) {
+ DumpStringToUSB("ERROR: Command too long. Ignored.");
+ len=0;
+ }
+ }
+ }
+}
+
+portBASE_TYPE vCmdInit(void) {
+ /* FIXME Maybe modify to use pointers? */
+ xCmdQueue = xQueueCreate( 10, sizeof(cmd_type) );
+ if(xCmdQueue == 0) {
+ return 0;
+ }
+
+ if(xTaskCreate(vCmdCode, (signed portCHAR *)"CMD", TASK_CMD_STACK, NULL,
+ TASK_CMD_PRIORITY, &xCmdTask) != pdPASS) {
+ return 0;
+ }
+
+ if(xTaskCreate(vCmdRecvUsbCode, (signed portCHAR *)"CMDUSB", TASK_CMD_STACK, NULL,
+ TASK_CMD_PRIORITY, &xCmdRecvUsbTask) != pdPASS) {
+ return 0;
+ }
+
+ return 1;
+}
personal git repositories of Harald Welte. Your mileage may vary