/** Process characters typed in by the user. Normally this will fire off a menu command, unless
we are awaiting the user to enter a two-byte (four ascii character) short address or eight byte
(16 ascii character) long address.
@note: processCommand modifies variables shortAddressEntered and longAddressEntered
 @return the state to transition to next
 */
enum STATE processCommand(char cmd)
{
#define ESCAPE_KEY 0x1B
    if (cmd == ESCAPE_KEY)
    {
        printf("Resetting Command Line Interpreter\r\n");
        commandLineInterfaceMode = CLI_MODE_NORMAL;
        cliInputBufferIndex = 0;
        pendingState = STATE_IDLE;
        displayCommandLineInterfaceHelp();
        return STATE_IDLE;
    }

    if (cmd == '\r')
    {
        printf("\r\n");
        return STATE_IDLE;
    }

    if (commandLineInterfaceMode == CLI_MODE_NORMAL)
    {
        switch (cmd)
        {
        case '?':
            displayCommandLineInterfaceHelp();
            return STATE_IDLE;
        case 'n':
        case 'N':
            return STATE_DISPLAY_NETWORK_INFORMATION;
        case 'r':
        case 'R':
            return STATE_INIT;
        case 'S':
        case 's':
        {
            printf("Enter short address of destination, for example '2F6B' or Escape key to exit\r\n");
            commandLineInterfaceMode = CLI_MODE_ENTER_SHORT_ADDRESS;    // Next, get a short address typed by the user
            pendingState = STATE_SEND_MESSAGE_VIA_SHORT_ADDRESS;  // After a full short address has been entered
            return STATE_IDLE;
        }
        case 'L':
        case 'l':
        {
            printf("Enter long (MAC) address of destination, for example '00124B0012345678' or Escape key to exit\r\n");
            commandLineInterfaceMode = CLI_MODE_ENTER_LONG_ADDRESS;
            pendingState = STATE_SEND_MESSAGE_VIA_LONG_ADDRESS;  //when a full long address has been entered
            return STATE_IDLE;
        }
        case 'h':
        case 'H':
        {
            printf("Enter two byte short address to find, for example '2F6B' or press Escape key to exit\r\n");
            commandLineInterfaceMode = CLI_MODE_ENTER_SHORT_ADDRESS;
            pendingState = STATE_FIND_VIA_SHORT_ADDRESS;  //when a full short address has been entered
            return STATE_IDLE;
        }
        case 'j':
        case 'J':
        {
            printf("Enter eight byte long (MAC) address to find, for example '00124B0012345678' or press Escape key to exit\r\n");
            commandLineInterfaceMode = CLI_MODE_ENTER_LONG_ADDRESS;
            pendingState = STATE_FIND_VIA_LONG_ADDRESS;  //when a full long address has been entered
            return STATE_IDLE;
        }
        case 'v':
        case 'V':
        {
            printf("Module Version Information:\r\n");
            if (sysVersion() == MODULE_SUCCESS)                  //gets the version string
            {
                displaySysVersion();  // Display the contents of the received SYS_VERSION
            } else {
                printf("ERROR\r\n");
            }
            return STATE_IDLE;
        }

        /* Note: more commands can be added here */

        default:
            printf("Unknown command %c\r\n", cmd);
        }
        return STATE_IDLE;

    } else if (commandLineInterfaceMode == CLI_MODE_ENTER_SHORT_ADDRESS)    //accepts two hex numbers (4 ASCII characters)
    {
        if (IS_VALID_HEXADECIMAL_CHARACTER(cmd))
        {
            TO_UPPER_CASE(cmd);
            printf("%c", cmd);  //echo output
            cliInputBuffer[cliInputBufferIndex++] = (char) cmd;
            if (cliInputBufferIndex == 4)  
            {
                cliInputBuffer[4] = 0; //null terminate it so we can treat it as a string
                //now attempt to convert it:
                long val = 0;
                errno = 0;      // used in stdlib.h
                val = strtol(cliInputBuffer, NULL, 16);    // Interpret the string as a hex number
                if (errno != 0) // Should have already been error checked, but validate anyway
                {
                    printf("strtol parse error\r\n");
                } else { //no errors
                    shortAddressEntered = (uint16_t) val;
                    printf("Short Address = 0x%04X\r\n", shortAddressEntered);
                    //we're all done, so clear out buffers:
                    commandLineInterfaceMode = CLI_MODE_NORMAL;
                    cliInputBufferIndex = 0;
                    return STATE_VALID_SHORT_ADDRESS_ENTERED;
                }
                commandLineInterfaceMode = CLI_MODE_NORMAL;
                cliInputBufferIndex = 0;
                return STATE_IDLE;
            }
            /* Continue, since our buffer isn't full yet - leave settings alone */

        } else {
            /* not a hex number! */
            printf("\r\nNumber must be in hex: 0..9 or a..f inclusive\r\nAborting\r\n");
            displayCommandLineInterfaceHelp();
            commandLineInterfaceMode = CLI_MODE_NORMAL;
            cliInputBufferIndex = 0;
        }
        return STATE_IDLE;

    } else if (commandLineInterfaceMode == CLI_MODE_ENTER_LONG_ADDRESS)  //accepts eight hex numbers (16 ASCII characters)
    {

        if (IS_VALID_HEXADECIMAL_CHARACTER(cmd))
        {
            TO_UPPER_CASE(cmd);
            printf("%c", cmd);  //echo output

            cliInputBuffer[cliInputBufferIndex++] = (char) cmd;

            /* To used a tokenized substring splitter method, add a '-' at the end of each 2 characters. */
            if ((cliInputBufferIndex != 0) && ((cliInputBufferIndex+1) % 3 == 0) && (cliInputBufferIndex != 23))
            {
                cliInputBuffer[cliInputBufferIndex++] = '-';
                printf("-");
            }

            if (cliInputBufferIndex == 23)
            {
                printf("\r\nParsed '%s' into:", cliInputBuffer);

                /* now attempt to convert it: */
                char *substr = NULL;
                substr = strtok(cliInputBuffer,"-");    // Initialize string splitter

                /* Loops until there are no more substrings*/
                uint8_t parsedMacIndex = 0;
                while(substr!=NULL)
                {
                    /* Process the substring */
                    long val = 0;
                    /* errno is used in stdlib.h to indicate a parse error */
                    errno = 0;     
                    val = strtol(substr, NULL, 16);    // Interpret the string as a hex number
                    if (errno != 0) // Should have already been error checked, but validate anyway
                    {
                        printf("strtol parse error\r\n");
                        commandLineInterfaceMode = CLI_MODE_NORMAL;
                        cliInputBufferIndex = 0;
                        return STATE_IDLE;

                    } else { //no errors
                        longAddressEntered[parsedMacIndex] = (uint16_t) val;
                        printf("%02X ", longAddressEntered[parsedMacIndex]);
                    }
                    parsedMacIndex++;

                    substr = strtok(NULL,"-");  //Get the next substring
                }
                printf("\r\n");

                /* Now we have the mac address */
                if (!((longAddressEntered[0] == 0x00) &&
                        (longAddressEntered[1] == 0x12) &&
                        (longAddressEntered[2] == 0x4b)))
                    printf("Warning - MAC does not have 00-12-4B as first three bytes!\r\n");
                commandLineInterfaceMode = CLI_MODE_NORMAL;
                cliInputBufferIndex = 0;
                return STATE_VALID_LONG_ADDRESS_ENTERED;
            }

            /* continue, since our buffer isn't full yet - leave settings alone */
        } else {  //not a hex number!
            printf("Number must be in hex: 0..9 or a..f inclusive\r\nAborting\r\n");
            displayCommandLineInterfaceHelp();
            commandLineInterfaceMode = CLI_MODE_NORMAL;
            cliInputBufferIndex = 0;
        }  

        return STATE_IDLE;
    }

    return STATE_IDLE;
}
Ejemplo n.º 2
0
static int
utf16_to_shortname (int pass,
                    const UTF16 *utf16,
                    struct fs_fat_shortname *shortname)
{
  int len;
  int a, b;
  int dotsfromstart = 0;
  int extdot = -1;
  unsigned long crc_num;
  int needs_long_filename;

  /* A sanity check of all pointers */
  if ((shortname == 0) || (utf16 == 0) ||
      (shortname->name == 0) || (shortname->ext == 0))
    return 0;

  /*
   * Algorithm for a file name to end up in LFN entry:
   * a) If the file name length excluding ext is greater than 8 bytes.
   * b) If the file name has special chars that are not allowed in short file.
   * c) If a collision is detected (pass > 1).
   */

  needs_long_filename = 0;

  /* Pass code is more than 1 means there was an entry found with the same
   * name, so now force the name conversion to use crc */
  if (pass > 1)
    needs_long_filename = 1;

  /* calculate the length and other characteristics of the filename */
  for (len = 0; utf16[len] != 0; len++)
  {
    /* If the char is out side the ASCII range then we need conversion */
    if (utf16[len] > 0x7F)
      needs_long_filename = 1;
  }

  /* Prefill needed if our chars won't fill name, ext completely */
  (void) memset (shortname->name, ' ', 8);
  (void) memset (shortname->ext, ' ', 3);

  /* check if it starts with '.' e.g. ".foo" */
  if (utf16[0] == '.')
  {
    /* calculates the starting dots */
    for (a = 0; a < len; a++)
    {
      if (utf16[a] != '.')
        break;
      dotsfromstart++;
    }
  }

  /* generating extension */
  for (a = len; a > 0; a--)
  {
    if (utf16[a - 1] == '.')
    {
      /* check if we reach the starting dots, in this case this
       * is not an extension */
      if (a == dotsfromstart)
        break;
      extdot = a - 1;

      for (b = 0; b < 3; a++)
      {
        /* Short file name should only have UPPER case chars. NTRES flag can be
         * used for conversion, but here instead of NTRES, it results into long
         * file name component */
        UTF16 ch = (UTF16) TO_UPPER_CASE(utf16[a]);
        if (!ch)
          break;

        /* Space is an acceptable character in filename extension.
         * Spaces or invalid characters in filename are
         * handled by creating a long file name.
         * We are mapping any outside range char to _    */
        if ((ch == ' ') || !is_valid_char_in_short_name (ch))
        {
          needs_long_filename = 1;
          ch = '_';
        }

        shortname->ext[b++] = (char) ch;
      }
      break;
    }
  }

  /* if extdot == -1 then the file doesn't have extension,
   * or the file name start from . */
  if (extdot == -1)
  {
    if (len > 8)
      needs_long_filename = 1;
  }
  else
  {
    if (extdot > 8)
      needs_long_filename = 1;
  }

  /* Copy file name if conversion not needed. But if illegal chars
   * are there, then the conversion is needed. */
  if (needs_long_filename == 0)
  {
    for (a = b = 0; b < 8; a++)
    {
      /* Upper case needed */
      UTF16 ch = (UTF16) TO_UPPER_CASE (utf16[a]);
      if (!ch)
        break;

      if (ch == '.')
      {
        /* if we reach extension dot then stop */
        if (a == extdot)
          break;
      }

      /* Space is an acceptable character in the filename.
       * Spaces or invalid characters in filename are
       * handled by creating a long file name.              */
      if ( (ch == ' ') || (!is_valid_char_in_short_name (ch)))
      {
        needs_long_filename = 1;
        break;
      }

      shortname->name[b++] = (char) ch;
    }
  }

  if (needs_long_filename == 1)
  {
    unsigned char cch;

    /* Came here means we cannot have the short file name, so generate
     * a unique file name by calculating the CRC of the long file name
     * if a collision happens then we can generate a different file
     * name which would be a very rare occurrence. */

    /* Calculate CRC30 of the file name, so that it is unique */
    crc_num = crc_30_step (pass, (byte*)utf16, (len * sizeof (*utf16) * 8));

    /* Convert CRC to string for file name part */
    for (a = 7; a >= 0; --a)
    {
      cch = crc_num & 0xF;
      cch += ((cch < 10) ? '0' : ('A' - 10));
      shortname->name[a] = cch;
      crc_num >>= 4;
    }

  }