HdmiCecMessageBuilder.java revision a1fa91fe263c483cf13066e2847a440de2cd52a5
1/*
2 * Copyright (C) 2014 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
17package com.android.server.hdmi;
18
19import android.hardware.hdmi.HdmiCec;
20import android.hardware.hdmi.HdmiCecMessage;
21
22import java.io.UnsupportedEncodingException;
23
24/**
25 * A helper class to build {@link HdmiCecMessage} from various cec commands.
26 */
27public class HdmiCecMessageBuilder {
28    // TODO: move these values to HdmiCec.java once make it internal constant class.
29    // CEC's ABORT reason values.
30    static final int ABORT_UNRECOGNIZED_MODE = 0;
31    static final int ABORT_NOT_IN_CORRECT_MODE = 1;
32    static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
33    static final int ABORT_INVALID_OPERAND = 3;
34    static final int ABORT_REFUSED = 4;
35    static final int ABORT_UNABLE_TO_DETERMINE = 5;
36
37    private static final int OSD_NAME_MAX_LENGTH = 13;
38
39    private HdmiCecMessageBuilder() {}
40
41    /**
42     * Build <Feature Abort> command. <Feature Abort> consists of
43     * 1 byte original opcode and 1 byte reason fields with basic fields.
44     *
45     * @param src source address of command
46     * @param dest destination address of command
47     * @param originalOpcode original opcode causing feature abort
48     * @param reason reason of feature abort
49     * @return newly created {@link HdmiCecMessage}
50     */
51    static HdmiCecMessage buildFeatureAbortCommand(int src, int dest, int originalOpcode,
52            int reason) {
53        byte[] params = new byte[] {
54                (byte) originalOpcode,
55                (byte) reason,
56        };
57        return buildCommand(src, dest, HdmiCec.MESSAGE_FEATURE_ABORT, params);
58    }
59
60    /**
61     * Build <Get Osd Name> command.
62     *
63     * @param src source address of command
64     * @param dest destination address of command
65     * @return newly created {@link HdmiCecMessage}
66     */
67    static HdmiCecMessage buildGetOsdNameCommand(int src, int dest) {
68        return buildCommand(src, dest, HdmiCec.MESSAGE_GET_OSD_NAME);
69    }
70
71    /**
72     * Build <Give Vendor Id Command> command.
73     *
74     * @param src source address of command
75     * @param dest destination address of command
76     * @return newly created {@link HdmiCecMessage}
77     */
78    static HdmiCecMessage buildGiveDeviceVendorIdCommand(int src, int dest) {
79        return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID);
80    }
81
82    /**
83     * Build <Set Menu Language > command.
84     *
85     * <p>This is a broadcast message sent to all devices on the bus.
86     *
87     * @param src source address of command
88     * @param language 3-letter ISO639-2 based language code
89     * @return newly created {@link HdmiCecMessage} if language is valid.
90     *         Otherwise, return null
91     */
92    static HdmiCecMessage buildSetMenuLanguageCommand(int src, String language) {
93        if (language.length() != 3) {
94            return null;
95        }
96        // Hdmi CEC uses lower-cased ISO 639-2 (3 letters code).
97        String normalized = language.toLowerCase();
98        byte[] params = new byte[] {
99                (byte) normalized.charAt(0),
100                (byte) normalized.charAt(1),
101                (byte) normalized.charAt(2),
102        };
103        // <Set Menu Language> is broadcast message.
104        return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_SET_MENU_LANGUAGE,
105                params);
106    }
107
108    /**
109     * Build &lt;Set Osd Name &gt; command.
110     *
111     * @param src source address of command
112     * @param name display (OSD) name of device
113     * @return newly created {@link HdmiCecMessage} if valid name. Otherwise,
114     *         return null
115     */
116    static HdmiCecMessage buildSetOsdNameCommand(int src, int dest, String name) {
117        int length = Math.min(name.length(), OSD_NAME_MAX_LENGTH);
118        byte[] params;
119        try {
120            params = name.substring(0, length).getBytes("US-ASCII");
121        } catch (UnsupportedEncodingException e) {
122            return null;
123        }
124        return buildCommand(src, dest, HdmiCec.MESSAGE_SET_OSD_NAME, params);
125    }
126
127    /**
128     * Build &lt;Report Physical Address&gt; command. It has two bytes physical
129     * address and one byte device type as parameter.
130     *
131     * <p>This is a broadcast message sent to all devices on the bus.
132     *
133     * @param src source address of command
134     * @param address physical address of device
135     * @param deviceType type of device
136     * @return newly created {@link HdmiCecMessage}
137     */
138    static HdmiCecMessage buildReportPhysicalAddressCommand(int src, int address, int deviceType) {
139        byte[] params = new byte[] {
140                // Two bytes for physical address
141                (byte) ((address >> 8) & 0xFF),
142                (byte) (address & 0xFF),
143                // One byte device type
144                (byte) deviceType
145        };
146        // <Report Physical Address> is broadcast message.
147        return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS,
148                params);
149    }
150
151    /**
152     * Build &lt;Device Vendor Id&gt; command. It has three bytes vendor id as
153     * parameter.
154     *
155     * <p>This is a broadcast message sent to all devices on the bus.
156     *
157     * @param src source address of command
158     * @param vendorId device's vendor id
159     * @return newly created {@link HdmiCecMessage}
160     */
161    static HdmiCecMessage buildDeviceVendorIdCommand(int src, int vendorId) {
162        byte[] params = new byte[] {
163                (byte) ((vendorId >> 16) & 0xFF),
164                (byte) ((vendorId >> 8) & 0xFF),
165                (byte) (vendorId & 0xFF)
166        };
167        // <Device Vendor Id> is broadcast message.
168        return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_DEVICE_VENDOR_ID,
169                params);
170    }
171
172    /**
173     * Build &lt;Device Vendor Id&gt; command. It has one byte cec version as parameter.
174     *
175     * @param src source address of command
176     * @param dest destination address of command
177     * @param version version of cec. Use 0x04 for "Version 1.3a" and 0x05 for
178     *                "Version 1.4 or 1.4a or 1.4b
179     * @return newly created {@link HdmiCecMessage}
180     */
181    static HdmiCecMessage buildCecVersion(int src, int dest, int version) {
182        byte[] params = new byte[] {
183                (byte) version
184        };
185        return buildCommand(src, dest, HdmiCec.MESSAGE_CEC_VERSION, params);
186    }
187
188    /**
189     * Build a {@link HdmiCecMessage} without extra parameter.
190     *
191     * @param src source address of command
192     * @param dest destination address of command
193     * @param opcode opcode for a message
194     * @return newly created {@link HdmiCecMessage}
195     */
196    private static HdmiCecMessage buildCommand(int src, int dest, int opcode) {
197        return new HdmiCecMessage(src, dest, opcode, HdmiCecMessage.EMPTY_PARAM);
198    }
199
200    /**
201     * Build a {@link HdmiCecMessage} with given values.
202     *
203     * @param src source address of command
204     * @param dest destination address of command
205     * @param opcode opcode for a message
206     * @param params extra parameters for command
207     * @return newly created {@link HdmiCecMessage}
208     */
209    private static HdmiCecMessage buildCommand(int src, int dest, int opcode, byte[] params) {
210        return new HdmiCecMessage(src, dest, opcode, params);
211    }
212}
213