Home | History | Annotate | Download | only in hid
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.commands.hid;
     18 
     19 import android.util.JsonReader;
     20 import android.util.JsonToken;
     21 import android.util.Log;
     22 import android.util.SparseArray;
     23 
     24 import libcore.io.IoUtils;
     25 
     26 import java.io.BufferedInputStream;
     27 import java.io.File;
     28 import java.io.FileInputStream;
     29 import java.io.FileNotFoundException;
     30 import java.io.InputStream;
     31 import java.io.InputStreamReader;
     32 import java.io.IOException;
     33 import java.io.UnsupportedEncodingException;
     34 import java.util.ArrayList;
     35 
     36 public class Hid {
     37     private static final String TAG = "HID";
     38 
     39     private final Event.Reader mReader;
     40     private final SparseArray<Device> mDevices;
     41 
     42     private static void usage() {
     43         error("Usage: hid [FILE]");
     44     }
     45 
     46     public static void main(String[] args) {
     47         if (args.length != 1) {
     48             usage();
     49             System.exit(1);
     50         }
     51 
     52         InputStream stream = null;
     53         try {
     54             if (args[0].equals("-")) {
     55                 stream = System.in;
     56             } else {
     57                 File f = new File(args[0]);
     58                 stream = new FileInputStream(f);
     59             }
     60             (new Hid(stream)).run();
     61         } catch (Exception e) {
     62             error("HID injection failed.", e);
     63             System.exit(1);
     64         } finally {
     65             IoUtils.closeQuietly(stream);
     66         }
     67     }
     68 
     69     private Hid(InputStream in) {
     70         mDevices = new SparseArray<Device>();
     71         try {
     72             mReader = new Event.Reader(new InputStreamReader(in, "UTF-8"));
     73         } catch (UnsupportedEncodingException e) {
     74             throw new RuntimeException(e);
     75         }
     76     }
     77 
     78     private void run() {
     79         try {
     80             Event e = null;
     81             while ((e = mReader.getNextEvent()) != null) {
     82                 process(e);
     83             }
     84         } catch (IOException ex) {
     85             error("Error reading in events.", ex);
     86         }
     87 
     88         for (int i = 0; i < mDevices.size(); i++) {
     89             mDevices.valueAt(i).close();
     90         }
     91     }
     92 
     93     private void process(Event e) {
     94         final int index = mDevices.indexOfKey(e.getId());
     95         if (index >= 0) {
     96             Device d = mDevices.valueAt(index);
     97             if (Event.COMMAND_DELAY.equals(e.getCommand())) {
     98                 d.addDelay(e.getDuration());
     99             } else if (Event.COMMAND_REPORT.equals(e.getCommand())) {
    100                 d.sendReport(e.getReport());
    101             } else {
    102                 if (Event.COMMAND_REGISTER.equals(e.getCommand())) {
    103                     error("Device id=" + e.getId() + " is already registered. Ignoring event.");
    104                 } else {
    105                     error("Unknown command \"" + e.getCommand() + "\". Ignoring event.");
    106                 }
    107             }
    108         } else if (Event.COMMAND_REGISTER.equals(e.getCommand())) {
    109             registerDevice(e);
    110         } else {
    111             Log.e(TAG, "Unknown device id specified. Ignoring event.");
    112         }
    113     }
    114 
    115     private void registerDevice(Event e) {
    116         if (!Event.COMMAND_REGISTER.equals(e.getCommand())) {
    117             throw new IllegalStateException(
    118                     "Tried to send command \"" + e.getCommand() + "\" to an unregistered device!");
    119         }
    120         int id = e.getId();
    121         Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(),
    122                 e.getDescriptor(), e.getReport());
    123         mDevices.append(id, d);
    124     }
    125 
    126     private static void error(String msg) {
    127         error(msg, null);
    128     }
    129 
    130     private static void error(String msg, Exception e) {
    131         Log.e(TAG, msg);
    132         if (e != null) {
    133             Log.e(TAG, Log.getStackTraceString(e));
    134         }
    135     }
    136 }
    137