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 <Set Osd Name > 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 <Report Physical Address> 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 <Device Vendor Id> 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 <Device Vendor Id> 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