blob: 9a76734943d666621d1f2fcc0ecc9898574a83f2 [file] [log] [blame]
Jungshik Janga1fa91f2014-05-08 20:56:41 +09001/*
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;
Jungshik Jangc47e26c2014-05-27 19:52:39 +090023import java.util.Arrays;
Jungshik Janga1fa91f2014-05-08 20:56:41 +090024
25/**
26 * A helper class to build {@link HdmiCecMessage} from various cec commands.
27 */
28public class HdmiCecMessageBuilder {
29 // TODO: move these values to HdmiCec.java once make it internal constant class.
30 // CEC's ABORT reason values.
31 static final int ABORT_UNRECOGNIZED_MODE = 0;
32 static final int ABORT_NOT_IN_CORRECT_MODE = 1;
33 static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
34 static final int ABORT_INVALID_OPERAND = 3;
35 static final int ABORT_REFUSED = 4;
36 static final int ABORT_UNABLE_TO_DETERMINE = 5;
37
38 private static final int OSD_NAME_MAX_LENGTH = 13;
39
40 private HdmiCecMessageBuilder() {}
41
42 /**
Jungshik Jangc47e26c2014-05-27 19:52:39 +090043 * Build {@link HdmiCecMessage} from raw data.
44 *
45 * @param src source address of command
46 * @param dest destination address of command
47 * @param body body of message. It includes opcode.
48 * @return newly created {@link HdmiCecMessage}
49 */
50 static HdmiCecMessage of(int src, int dest, byte[] body) {
51 byte opcode = body[0];
52 byte params[] = Arrays.copyOfRange(body, 1, body.length);
53 return new HdmiCecMessage(src, dest, opcode, params);
54 }
55
56 /**
Jungshik Janga1fa91f2014-05-08 20:56:41 +090057 * Build <Feature Abort> command. <Feature Abort> consists of
58 * 1 byte original opcode and 1 byte reason fields with basic fields.
59 *
60 * @param src source address of command
61 * @param dest destination address of command
62 * @param originalOpcode original opcode causing feature abort
63 * @param reason reason of feature abort
64 * @return newly created {@link HdmiCecMessage}
65 */
66 static HdmiCecMessage buildFeatureAbortCommand(int src, int dest, int originalOpcode,
67 int reason) {
68 byte[] params = new byte[] {
69 (byte) originalOpcode,
70 (byte) reason,
71 };
72 return buildCommand(src, dest, HdmiCec.MESSAGE_FEATURE_ABORT, params);
73 }
74
75 /**
Jungshik Jangd42a7a32014-05-27 13:27:36 +090076 * Build <Give Physical Address> command.
77 *
78 * @param src source address of command
79 * @param dest destination address of command
80 * @return newly created {@link HdmiCecMessage}
81 */
82 static HdmiCecMessage buildGivePhysicalAddress(int src, int dest) {
83 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_PHYSICAL_ADDRESS);
84 }
85
86 /**
Jungshik Jangbe9cd8e2014-05-15 14:29:01 +090087 * Build <Give Osd Name> command.
Jungshik Janga1fa91f2014-05-08 20:56:41 +090088 *
89 * @param src source address of command
90 * @param dest destination address of command
91 * @return newly created {@link HdmiCecMessage}
92 */
Jungshik Jangbe9cd8e2014-05-15 14:29:01 +090093 static HdmiCecMessage buildGiveOsdNameCommand(int src, int dest) {
94 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_OSD_NAME);
Jungshik Janga1fa91f2014-05-08 20:56:41 +090095 }
96
97 /**
98 * Build <Give Vendor Id Command> command.
99 *
100 * @param src source address of command
101 * @param dest destination address of command
102 * @return newly created {@link HdmiCecMessage}
103 */
104 static HdmiCecMessage buildGiveDeviceVendorIdCommand(int src, int dest) {
105 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID);
106 }
107
108 /**
109 * Build <Set Menu Language > command.
110 *
111 * <p>This is a broadcast message sent to all devices on the bus.
112 *
113 * @param src source address of command
114 * @param language 3-letter ISO639-2 based language code
115 * @return newly created {@link HdmiCecMessage} if language is valid.
116 * Otherwise, return null
117 */
118 static HdmiCecMessage buildSetMenuLanguageCommand(int src, String language) {
119 if (language.length() != 3) {
120 return null;
121 }
122 // Hdmi CEC uses lower-cased ISO 639-2 (3 letters code).
123 String normalized = language.toLowerCase();
124 byte[] params = new byte[] {
125 (byte) normalized.charAt(0),
126 (byte) normalized.charAt(1),
127 (byte) normalized.charAt(2),
128 };
129 // <Set Menu Language> is broadcast message.
130 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_SET_MENU_LANGUAGE,
131 params);
132 }
133
134 /**
135 * Build &lt;Set Osd Name &gt; command.
136 *
137 * @param src source address of command
138 * @param name display (OSD) name of device
139 * @return newly created {@link HdmiCecMessage} if valid name. Otherwise,
140 * return null
141 */
142 static HdmiCecMessage buildSetOsdNameCommand(int src, int dest, String name) {
143 int length = Math.min(name.length(), OSD_NAME_MAX_LENGTH);
144 byte[] params;
145 try {
146 params = name.substring(0, length).getBytes("US-ASCII");
147 } catch (UnsupportedEncodingException e) {
148 return null;
149 }
150 return buildCommand(src, dest, HdmiCec.MESSAGE_SET_OSD_NAME, params);
151 }
152
153 /**
154 * Build &lt;Report Physical Address&gt; command. It has two bytes physical
155 * address and one byte device type as parameter.
156 *
157 * <p>This is a broadcast message sent to all devices on the bus.
158 *
159 * @param src source address of command
160 * @param address physical address of device
161 * @param deviceType type of device
162 * @return newly created {@link HdmiCecMessage}
163 */
164 static HdmiCecMessage buildReportPhysicalAddressCommand(int src, int address, int deviceType) {
165 byte[] params = new byte[] {
166 // Two bytes for physical address
167 (byte) ((address >> 8) & 0xFF),
168 (byte) (address & 0xFF),
169 // One byte device type
170 (byte) deviceType
171 };
172 // <Report Physical Address> is broadcast message.
173 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS,
174 params);
175 }
176
177 /**
178 * Build &lt;Device Vendor Id&gt; command. It has three bytes vendor id as
179 * parameter.
180 *
181 * <p>This is a broadcast message sent to all devices on the bus.
182 *
183 * @param src source address of command
184 * @param vendorId device's vendor id
185 * @return newly created {@link HdmiCecMessage}
186 */
187 static HdmiCecMessage buildDeviceVendorIdCommand(int src, int vendorId) {
188 byte[] params = new byte[] {
189 (byte) ((vendorId >> 16) & 0xFF),
190 (byte) ((vendorId >> 8) & 0xFF),
191 (byte) (vendorId & 0xFF)
192 };
193 // <Device Vendor Id> is broadcast message.
194 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_DEVICE_VENDOR_ID,
195 params);
196 }
197
198 /**
199 * Build &lt;Device Vendor Id&gt; command. It has one byte cec version as parameter.
200 *
201 * @param src source address of command
202 * @param dest destination address of command
203 * @param version version of cec. Use 0x04 for "Version 1.3a" and 0x05 for
204 * "Version 1.4 or 1.4a or 1.4b
205 * @return newly created {@link HdmiCecMessage}
206 */
207 static HdmiCecMessage buildCecVersion(int src, int dest, int version) {
208 byte[] params = new byte[] {
209 (byte) version
210 };
211 return buildCommand(src, dest, HdmiCec.MESSAGE_CEC_VERSION, params);
212 }
213
214 /**
Jungshik Jang67ea5212014-05-15 14:05:24 +0900215 * Build &lt;Request Arc Initiation&gt;
216 *
217 * @param src source address of command
218 * @param dest destination address of command
219 * @return newly created {@link HdmiCecMessage}
220 */
221 static HdmiCecMessage buildRequestArcInitiation(int src, int dest) {
222 return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_INITIATION);
223 }
224
225 /**
226 * Build &lt;Request Arc Termination&gt;
227 *
228 * @param src source address of command
229 * @param dest destination address of command
230 * @return newly created {@link HdmiCecMessage}
231 */
232 static HdmiCecMessage buildRequestArcTermination(int src, int dest) {
233 return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_TERMINATION);
234 }
235
236 /**
237 * Build &lt;Report Arc Initiated&gt;
238 *
239 * @param src source address of command
240 * @param dest destination address of command
241 * @return newly created {@link HdmiCecMessage}
242 */
243 static HdmiCecMessage buildReportArcInitiated(int src, int dest) {
244 return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_INITIATED);
245 }
246
247 /**
248 * Build &lt;Report Arc Terminated&gt;
249 *
250 * @param src source address of command
251 * @param dest destination address of command
252 * @return newly created {@link HdmiCecMessage}
253 */
254 static HdmiCecMessage buildReportArcTerminated(int src, int dest) {
255 return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_TERMINATED);
256 }
257
258 /**
Jinsuk Kim78d695d2014-05-13 16:36:15 +0900259 * Build &lt;Text View On&gt; command.
260 *
261 * @param src source address of command
262 * @param dest destination address of command
263 * @return newly created {@link HdmiCecMessage}
264 */
265 static HdmiCecMessage buildTextViewOn(int src, int dest) {
266 return buildCommand(src, dest, HdmiCec.MESSAGE_TEXT_VIEW_ON);
267 }
268
269 /**
270 * Build &lt;Active Source&gt; command.
271 *
272 * @param src source address of command
273 * @param physicalAddress physical address of the device to become active
274 * @return newly created {@link HdmiCecMessage}
275 */
276 static HdmiCecMessage buildActiveSource(int src, int physicalAddress) {
277 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ACTIVE_SOURCE,
278 physicalAddressToParam(physicalAddress));
279 }
280
281 /**
282 * Build &lt;Give Device Power Status&gt; command.
283 *
284 * @param src source address of command
285 * @param dest destination address of command
286 * @return newly created {@link HdmiCecMessage}
287 */
288 static HdmiCecMessage buildGiveDevicePowerStatus(int src, int dest) {
289 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS);
290 }
291
292 /**
Jungshik Janga1fa91f2014-05-08 20:56:41 +0900293 * Build a {@link HdmiCecMessage} without extra parameter.
294 *
295 * @param src source address of command
296 * @param dest destination address of command
297 * @param opcode opcode for a message
298 * @return newly created {@link HdmiCecMessage}
299 */
300 private static HdmiCecMessage buildCommand(int src, int dest, int opcode) {
301 return new HdmiCecMessage(src, dest, opcode, HdmiCecMessage.EMPTY_PARAM);
302 }
303
304 /**
305 * Build a {@link HdmiCecMessage} with given values.
306 *
307 * @param src source address of command
308 * @param dest destination address of command
309 * @param opcode opcode for a message
310 * @param params extra parameters for command
311 * @return newly created {@link HdmiCecMessage}
312 */
313 private static HdmiCecMessage buildCommand(int src, int dest, int opcode, byte[] params) {
314 return new HdmiCecMessage(src, dest, opcode, params);
315 }
Jinsuk Kim78d695d2014-05-13 16:36:15 +0900316
317 private static byte[] physicalAddressToParam(int physicalAddress) {
318 return new byte[] {
319 (byte) (physicalAddress >> 8),
320 (byte) (physicalAddress & 0xFF)
321 };
322 }
Jungshik Janga1fa91f2014-05-08 20:56:41 +0900323}