1e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood/*
2e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Copyright (C) 2010 The Android Open Source Project
3e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood *
4e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
5e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * you may not use this file except in compliance with the License.
6e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * You may obtain a copy of the License at
7e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood *
8e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
9e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood *
10e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * Unless required by applicable law or agreed to in writing, software
11e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
12e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * See the License for the specific language governing permissions and
14e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood * limitations under the License.
15e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */
16e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
17c4308f01c965571dc2354107c3574df113e397eeMike Lockwoodpackage android.hardware.usb;
18e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
19e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.Bundle;
20e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.Parcel;
21e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.os.Parcelable;
22e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport android.util.Log;
23e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
24e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwoodimport java.io.FileDescriptor;
25e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
26e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood/**
2711dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * This class represents a USB device attached to the android device with the android device
2811dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * acting as the USB host.
2911dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * Each device contains one or more {@link UsbInterface}s, each of which contains a number of
3011dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * {@link UsbEndpoint}s (the channels via which data is transmitted over USB).
3111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood *
3211dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * <p> This class contains information (along with {@link UsbInterface} and {@link UsbEndpoint})
3311dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * that describes the capabilities of the USB device.
3411dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * To communicate with the device, you open a {@link UsbDeviceConnection} for the device
3511dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * and use {@link UsbRequest} to send and receive data on an endpoint.
3611dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood * {@link UsbDeviceConnection#controlTransfer} is used for control requests on endpoint zero.
373aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez *
383aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference">
393aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3>
403aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about communicating with USB hardware, read the
413aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
423aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div>
43e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood */
44acc29cc91be634070c92a807df412ced97b9b375Mike Lockwoodpublic class UsbDevice implements Parcelable {
45e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
46e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    private static final String TAG = "UsbDevice";
47e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
48acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    private final String mName;
49acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    private final int mVendorId;
50acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    private final int mProductId;
51acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    private final int mClass;
52acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    private final int mSubclass;
53acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    private final int mProtocol;
54acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood    private final Parcelable[] mInterfaces;
55e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
56e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
57e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * UsbDevice should only be instantiated by UsbService implementation
58e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @hide
59e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
60e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public UsbDevice(String name, int vendorId, int productId,
61e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            int Class, int subClass, int protocol, Parcelable[] interfaces) {
62e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        mName = name;
63e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        mVendorId = vendorId;
64e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        mProductId = productId;
65e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        mClass = Class;
66e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        mSubclass = subClass;
67e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        mProtocol = protocol;
68e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        mInterfaces = interfaces;
69e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
70e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
71e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
72e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * Returns the name of the device.
73e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * In the standard implementation, this is the path of the device file
74e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * for the device in the usbfs file system.
75e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
76e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the device name
77e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
78e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public String getDeviceName() {
79e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return mName;
80e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
81e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
82e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
83e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * Returns a unique integer ID for the device.
84e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * This is a convenience for clients that want to use an integer to represent
85e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * the device, rather than the device name.
86e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * IDs are not persistent across USB disconnects.
87e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
88e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the device ID
89e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
90e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int getDeviceId() {
91e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return getDeviceId(mName);
92e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
93e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
94e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
95e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * Returns a vendor ID for the device.
96e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
97e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the device vendor ID
98e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
99e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int getVendorId() {
100e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return mVendorId;
101e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
102e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
103e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
104e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * Returns a product ID for the device.
105e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
106e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the device product ID
107e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
108e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int getProductId() {
109e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return mProductId;
110e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
111e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
112e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
113e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * Returns the devices's class field.
11411dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood     * Some useful constants for USB device classes can be found in {@link UsbConstants}.
115e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
116e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the devices's class
117e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
118e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int getDeviceClass() {
119e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return mClass;
120e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
121e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
122e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
123e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * Returns the device's subclass field.
124e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
125e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the device's subclass
126e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
127e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int getDeviceSubclass() {
128e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return mSubclass;
129e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
130e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
131e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
13211dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood     * Returns the device's protocol field.
133e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
134e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the device's protocol
135e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
136e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int getDeviceProtocol() {
137e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return mProtocol;
138e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
139e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
140e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
14111dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood     * Returns the number of {@link UsbInterface}s this device contains.
142e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
143e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the number of interfaces
144e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
145e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int getInterfaceCount() {
146e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return mInterfaces.length;
147e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
148e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
149e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    /**
15011dd5ae97b1cd5889bb66862fd12718da62a9c75Mike Lockwood     * Returns the {@link UsbInterface} at the given index.
151e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     *
152e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     * @return the interface
153e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood     */
154e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public UsbInterface getInterface(int index) {
155e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return (UsbInterface)mInterfaces[index];
156e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
157e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
158e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    @Override
159e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public boolean equals(Object o) {
160e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        if (o instanceof UsbDevice) {
161e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            return ((UsbDevice)o).mName.equals(mName);
162e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        } else if (o instanceof String) {
163e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            return ((String)o).equals(mName);
164e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        } else {
165e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            return false;
166e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        }
167e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
168e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
169e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    @Override
170c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood    public int hashCode() {
171c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood        return mName.hashCode();
172c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood    }
173c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood
174c6f23e8521dedac7a07119031913235be3ca37c3Mike Lockwood    @Override
175e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public String toString() {
176e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return "UsbDevice[mName=" + mName + ",mVendorId=" + mVendorId +
177e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood                ",mProductId=" + mProductId + ",mClass=" + mClass +
178e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood                ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
179e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood                ",mInterfaces=" + mInterfaces + "]";
180e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
181e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
182e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public static final Parcelable.Creator<UsbDevice> CREATOR =
183e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        new Parcelable.Creator<UsbDevice>() {
184e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        public UsbDevice createFromParcel(Parcel in) {
185e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            String name = in.readString();
186e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            int vendorId = in.readInt();
187e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            int productId = in.readInt();
188e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            int clasz = in.readInt();
189e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            int subClass = in.readInt();
190e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            int protocol = in.readInt();
191e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
192acc29cc91be634070c92a807df412ced97b9b375Mike Lockwood            return new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, interfaces);
193e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        }
194e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
195e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        public UsbDevice[] newArray(int size) {
196e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood            return new UsbDevice[size];
197e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        }
198e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    };
199e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
200e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public int describeContents() {
201e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return 0;
202e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
203e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
204e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public void writeToParcel(Parcel parcel, int flags) {
205e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        parcel.writeString(mName);
206e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        parcel.writeInt(mVendorId);
207e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        parcel.writeInt(mProductId);
208e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        parcel.writeInt(mClass);
209e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        parcel.writeInt(mSubclass);
210e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        parcel.writeInt(mProtocol);
211e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        parcel.writeParcelableArray(mInterfaces, 0);
212e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood   }
213e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
214e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public static int getDeviceId(String name) {
215e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return native_get_device_id(name);
216e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
217e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
218e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    public static String getDeviceName(int id) {
219e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood        return native_get_device_name(id);
220e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    }
221e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood
222e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    private static native int native_get_device_id(String name);
223e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood    private static native String native_get_device_name(int id);
224e7d511e148bc901ef41ac44d7b3593e5d803f72fMike Lockwood}
225