/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.bluetooth; import java.util.*; /** * An AT (Hayes command) Parser based on (a subset of) the ITU-T V.250 standard. *
* * Conformant with the subset of V.250 required for implementation of the * Bluetooth Headset and Handsfree Profiles, as per Bluetooth SIP * specifications. Also implements some V.250 features not required by * Bluetooth - such as chained commands.
* * Command handlers are registered with an AtParser object. These handlers are * invoked when command lines are processed by AtParser's process() method.
* * The AtParser object accepts a new command line to parse via its process() * method. It breaks each command line into one or more commands. Each command * is parsed for name, type, and (optional) arguments, and an appropriate * external handler method is called through the AtCommandHandler interface. * * The command types are
* * Basic commands cannot be chained in this implementation. For Bluetooth * headset/handsfree use this is acceptable, because they only use the basic * commands ATA and ATD, which are not allowed to be chained. For general V.250 * use we would need to improve this class to allow Basic command chaining - * however it's tricky to get right because there is no delimiter for Basic * command chaining.
* * Extended commands can be chained. For example:
* AT+VGM?;+VGM=14;+CIMI
* This is equivalent to:
* AT+VGM? * AT+VGM=14 * AT+CIMI * Except that only one final result code is return (although several * intermediate responses may be returned), and as soon as one command in the * chain fails the rest are abandoned.
* * Handlers are registered by there command name via register(Char c, ...) or * register(String s, ...). Handlers for Basic command should be registered by * the basic command character, and handlers for Extended commands should be * registered by String.
* * Refer to:
* No handlers are registered.
*/
public AtParser() {
mBasicHandlers = new HashMap
* Basic command handlers are later called via their
*
* Extended command handlers are later called via:handleBasicCommand(String args)
method.
* @param command Command name - a single character
* @param handler Handler to register
*/
public void register(Character command, AtCommandHandler handler) {
mBasicHandlers.put(command, handler);
}
/**
* Register an Extended command handler.
*
* Only one method will be called for each command processed.
* @param command Command name - can be multiple characters
* @param handler Handler to register
*/
public void register(String command, AtCommandHandler handler) {
mExtHandlers.put(command, handler);
}
/**
* Strip input of whitespace and force Uppercase - except sections inside
* quotes. Also fixes unmatched quotes (by appending a quote). Double
* quotes " are the only quotes allowed by V.250
*/
static private String clean(String input) {
StringBuilder out = new StringBuilder(input.length());
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '"') {
int j = input.indexOf('"', i + 1 ); // search for closing "
if (j == -1) { // unmatched ", insert one.
out.append(input.substring(i, input.length()));
out.append('"');
break;
}
out.append(input.substring(i, j + 1));
i = j;
} else if (c != ' ') {
out.append(Character.toUpperCase(c));
}
}
return out.toString();
}
static private boolean isAtoZ(char c) {
return (c >= 'A' && c <= 'Z');
}
/**
* Find a character ch, ignoring quoted sections.
* Return input.length() if not found.
*/
static private int findChar(char ch, String input, int fromIndex) {
for (int i = fromIndex; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '"') {
i = input.indexOf('"', i + 1);
if (i == -1) {
return input.length();
}
} else if (c == ch) {
return i;
}
}
return input.length();
}
/**
* Break an argument string into individual arguments (comma delimited).
* Integer arguments are turned into Integer objects. Otherwise a String
* object is used.
*/
static private Object[] generateArgs(String input) {
int i = 0;
int j;
ArrayListhandleActionCommand()
* handleGetCommand()
* handleSetCommand()
* handleTestCommand()
*