content: /*
   * Copyright (C) 2017 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 com.android.server.usb.descriptors.tree;
  
  import com.android.server.usb.descriptors.UsbACInterface;
  import com.android.server.usb.descriptors.UsbConfigDescriptor;
  import com.android.server.usb.descriptors.UsbDescriptor;
  import com.android.server.usb.descriptors.UsbDescriptorParser;
  import com.android.server.usb.descriptors.UsbDeviceDescriptor;
  import com.android.server.usb.descriptors.UsbEndpointDescriptor;
  import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
  import com.android.server.usb.descriptors.report.ReportCanvas;
  
  import java.util.ArrayList;
  
  /*
   * The general layout of the tree looks like this, though no guarentee about
   * ordering of descriptors beyond the Device -> Config -> Interface.
   *
   * Device Descriptor
   *   +- Config Descriptor
   *       +- Interface Descriptor
   *       |   +- Audio Class Interface
   *       |   +- Audio Class Interface
   *       |   +- Audio Class Interface
   *       |   +- Endpoint Descriptor
   *       |   +- Endpoint Descriptor
   *       +- Interface Descriptor
   *           +- Endpoint Descriptor
   */
  /**
   * @hide
   *
   * A class which builds a tree representation from the results of a (linear)
   * parse of USB descriptors.
   *
   * @see {@link com.android.server.usb.descriptors.UsbDescriptorsParser UsbDescriptorsParser}
   */
  public final class UsbDescriptorsTree {
      private static final String TAG = "UsbDescriptorsTree";
  
      private UsbDescriptorsDeviceNode mDeviceNode;
      private UsbDescriptorsConfigNode mConfigNode;   // being parsed
      private UsbDescriptorsInterfaceNode mInterfaceNode; // being parsed
  
      /**
       * Adds THE device descriptor as the root of the tree.
       */
      private void addDeviceDescriptor(UsbDeviceDescriptor deviceDescriptor) {
          mDeviceNode = new UsbDescriptorsDeviceNode(deviceDescriptor);
      }
  
      /**
       * Adds A config descriptor to the tree.
       */
      private void addConfigDescriptor(UsbConfigDescriptor configDescriptor) {
          mConfigNode = new UsbDescriptorsConfigNode(configDescriptor);
          mDeviceNode.addConfigDescriptorNode(mConfigNode);
      }
  
      /**
       * Adds AN interface descriptor to the current configuration in the tree.
       */
      private void addInterfaceDescriptor(UsbInterfaceDescriptor interfaceDescriptor) {
          mInterfaceNode = new UsbDescriptorsInterfaceNode(interfaceDescriptor);
          mConfigNode.addInterfaceNode(mInterfaceNode);
      }
  
      /**
       * Adds an endpoint descriptor to the current interface in the tree.
       */
      private void addEndpointDescriptor(UsbEndpointDescriptor endpointDescriptor) {
          mInterfaceNode.addEndpointNode(new UsbDescriptorsEndpointNode(endpointDescriptor));
      }
  
      /**
       * Adds an audio-class interface descriptor to the current interface in the tree.
       */
      private void addACInterface(UsbACInterface acInterface) {
          mInterfaceNode.addACInterfaceNode(new UsbDescriptorsACInterfaceNode(acInterface));
      }
  
      /**
       * Parses the linear descriptor list contained in the parser argument, into a tree
       * representation corresponding to the logical structure of the USB descriptors.
       */
      public void parse(UsbDescriptorParser parser) {
  
          ArrayList<UsbDescriptor> descriptors = parser.getDescriptors();
  
          for (int descrIndex = 0; descrIndex < descriptors.size(); descrIndex++) {
              UsbDescriptor descriptor = descriptors.get(descrIndex);
              switch (descriptor.getType()) {
                  //
                  // Basic Descriptors
                  //
                  case UsbDescriptor.DESCRIPTORTYPE_DEVICE:
                      addDeviceDescriptor((UsbDeviceDescriptor) descriptor);
                      break;
  
                  case UsbDescriptor.DESCRIPTORTYPE_CONFIG:
                      addConfigDescriptor((UsbConfigDescriptor) descriptor);
                      break;
  
                  case UsbDescriptor.DESCRIPTORTYPE_INTERFACE:
                      addInterfaceDescriptor((UsbInterfaceDescriptor) descriptor);
                      break;
  
                  case UsbDescriptor.DESCRIPTORTYPE_ENDPOINT:
                      addEndpointDescriptor((UsbEndpointDescriptor) descriptor);
                      break;
  
                  //
                  // Audio Class Descriptors
                  //
                  case UsbDescriptor.DESCRIPTORTYPE_AUDIO_INTERFACE:
                      addACInterface((UsbACInterface) descriptor);
                      break;
  
                  case UsbDescriptor.DESCRIPTORTYPE_AUDIO_ENDPOINT:
                      break;
              }
          }
      }
  
      /**
       * Generate a report of the descriptors tree.
       */
      public void report(ReportCanvas canvas) {
          mDeviceNode.report(canvas);
      }
  }
  