blob: 4fbb1c276de5130e5c963c4e8e47f89ec7333b48 [file] [log] [blame]
/*
* Copyright (C) 2014 Google, Inc.
*
* 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.projectara.araepm;
import android.hardware.I2cManager;
import android.hardware.I2cTransaction;
import android.util.Log;
import java.io.IOException;
public class DME {
private static final int slaveAddress = 0x44;
private static final String TAG = "DME";
private static final String preferredI2cBus = "/dev/i2c-2";
private static String i2cBus;
private I2cManager i2c;
public static enum AttributeId {
T_PEERDEVICEID (0x4021),
T_PEERCPORTID (0x4022),
T_CONNECTIONSTATE (0x4020),
T_TRAFFICCLASS (0x4023),
T_PROTOCOLID (0x4024),
T_CPORTFLAGS (0x4025),
T_TXTOKENVALUE (0x4026),
T_RXTOKENVALUE (0x4027),
T_LOCALBUFFERSPACE(0x4028),
T_PEERBUFFERSPACE (0x4029),
T_CREDITSTOSEND (0x402A),
T_CPORTMODE (0x402B),
DME_LINKSTARTUP (0xD020),
DME_FC0PROTECTIONTIMEOUTVAL (0xD041),
DME_MAILBOX (0x6100);
private int id;
private AttributeId(int id) {
this.id = id;
}
}
public static enum FunctionId {
C0_SETREQ (0x00),
C0_SETCNF (0x01),
C0_PEERSETREQ (0x02),
C0_PEERSETCNF (0x03),
C0_GETREQ (0x04),
C0_GETCNF (0x05),
C0_PEERGETREQ (0x06),
C0_PEERGETCNF (0x07),
C0_LUTSETREQ (0x08),
C0_LUTSETCNF (0x09),
C0_LUTGETREQ (0x0a),
C0_LUTGETCNF (0x0b),
C0_SWITCHATTRSETREQ (0x0c),
C0_SWITCHATTRSETCNF (0x0d),
C0_SWITCHATTRGETREQ (0x0e),
C0_SWITCHATTERGETCNF(0x0f);
private int id;
private FunctionId(int id) {
this.id = id;
}
}
private class SetRequest {
int portId;
FunctionId functionId;
AttributeId attrId;
int selectorIndex;
int attrVal;
public byte[] getBytes() {
byte[] rawBytes = new byte[10];
rawBytes[0] = (byte)(portId & 0xFF);
rawBytes[1] = (byte)(functionId.id & 0xFF);
rawBytes[2] = (byte)((attrId.id >> 8) & 0xFF); // msb
rawBytes[3] = (byte)(attrId.id & 0xFF); // lsb
rawBytes[4] = (byte)((selectorIndex >> 8) & 0xFF);
rawBytes[5] = (byte)((selectorIndex) & 0xFF);
rawBytes[6] = (byte)((attrVal >> 24) & 0xFF);
rawBytes[7] = (byte)((attrVal >> 16) & 0xFF);
rawBytes[8] = (byte)((attrVal >> 8) & 0xFF);
rawBytes[9] = (byte)((attrVal) & 0xFF);
return rawBytes;
}
}
private class SetCnf {
public static final int MSG_SIZE = 4;
int portId;
FunctionId functionId;
int resultCode;
public SetCnf(byte[] setCnfBytes) {
portId = setCnfBytes[0] & 0xFF;
functionId = FunctionId.values()[setCnfBytes[1] & 0xFF];
resultCode = (((int)setCnfBytes[2] & 0xFF) << 8) |
(((int)setCnfBytes[3] & 0xFF));
}
}
private class GetRequest {
int portId;
FunctionId functionId;
AttributeId attrId;
int selectorIndex;
public byte[] getBytes() {
byte[] rawBytes = new byte[6];
rawBytes[0] = (byte)(portId & 0xFF);
rawBytes[1] = (byte)(functionId.id & 0xFF);
rawBytes[2] = (byte)((attrId.id >> 8) & 0xFF);
rawBytes[3] = (byte)(attrId.id & 0xFF);
rawBytes[4] = (byte)((selectorIndex >> 8) & 0xFF);
rawBytes[5] = (byte)((selectorIndex) & 0xFF);
return rawBytes;
}
}
private class GetCnf {
public static final int MSG_SIZE = 8;
int portId;
FunctionId functionId;
int resultCode;
int attrVal;
public GetCnf(byte[] getCnfBytes) {
portId = getCnfBytes[0] & 0xFF;
functionId = FunctionId.values()[getCnfBytes[1] & 0xFF];
resultCode = (((int)getCnfBytes[2] & 0xFF) << 8) |
(((int)getCnfBytes[3] & 0xFF));
attrVal = (((int)getCnfBytes[4] & 0xFF) << 24) |
(((int)getCnfBytes[5] & 0xFF) << 16) |
(((int)getCnfBytes[6] & 0xFF) << 8) |
(((int)getCnfBytes[7] & 0xFF));
}
}
public DME(I2cManager i2c) {
this.i2c = i2c;
String[] buses = i2c.getI2cBuses();
this.i2cBus = buses[0];
for (String bus: buses) {
if (bus.equals("/dev/i2c-2")) {
this.i2cBus = bus;
}
}
Log.i(TAG, "[EPM app] Using I2C bus: " + this.i2cBus);
}
private void logByteArray(String prefix, byte[] arr) {
StringBuilder builder = new StringBuilder(prefix);
for (byte b: arr) {
builder.append(String.format(" %02x", b));
}
Log.d(TAG, builder.toString());
}
// api_write_switch_config
public void writeDMEConfig(int port, boolean peer, AttributeId attrId,
int selectorIndex, int attrVal,
int expectedResultCode) throws IOException {
I2cTransaction txn = null;
SetRequest setReq = new SetRequest();
setReq.portId = port;
setReq.functionId = peer ? FunctionId.C0_PEERSETREQ : FunctionId.C0_SETREQ;
setReq.attrId = attrId;
setReq.selectorIndex = selectorIndex;
setReq.attrVal = attrVal;
byte[] raw = setReq.getBytes();
logByteArray("writeDMEConfig: setReq, raw:", raw);
Log.d(TAG, "writeDMEConfig: setReq: portID: " + setReq.portId);
Log.d(TAG, "writeDMEConfig: setReq: functionId: " + setReq.functionId);
Log.d(TAG, "writeDMEConfig: setReq: attrId: " + setReq.attrId);
Log.d(TAG, "writeDMEConfig: setReq: selectorIndex: " + setReq.selectorIndex);
Log.d(TAG, "writeDMEConfig: setReq: attrVal: " + setReq.attrVal +
String.format(" (0x%08x)", setReq.attrVal));
txn = I2cTransaction.newWrite(raw);
I2cTransaction[] results;
results = i2c.performTransactions(i2cBus, slaveAddress, txn);
txn = I2cTransaction.newRead(SetCnf.MSG_SIZE);
results = i2c.performTransactions(i2cBus, slaveAddress, txn);
SetCnf setCnf = new SetCnf(results[0].data);
logByteArray("writeDMEConfig: setCnf, raw:", results[0].data);
Log.d(TAG, "writeDMEConfig: setCnf portId: " + setCnf.portId);
Log.d(TAG, "writeDMEConfig: setCnf functionId: " + setCnf.functionId);
Log.d(TAG, "writeDMEConfig: setCnf resultCode: " + setCnf.resultCode);
FunctionId expectedFunctionId =
(peer ? FunctionId.C0_PEERSETCNF : FunctionId.C0_SETCNF);
if (setCnf.resultCode != expectedResultCode) {
String err = "Unexpected resultCode: " + setCnf.resultCode +
" (expected " + expectedResultCode + ")";
Log.e(TAG, err);
throw new IOException(err);
} else if (setCnf.functionId != expectedFunctionId) {
throw new IOException("Unexpected setCnf functionId: " +
setCnf.functionId);
}
return;
}
public int readDMEConfig(int port,
boolean peer,
AttributeId attrId,
int selectorIndex,
int expectedResultCode) throws IOException {
I2cTransaction txn = null;
GetRequest getReq = new GetRequest();
getReq.portId = port;
getReq.functionId = peer ? FunctionId.C0_PEERGETREQ : FunctionId.C0_GETREQ;
getReq.attrId = attrId;
getReq.selectorIndex = selectorIndex;
byte[] raw = getReq.getBytes();
logByteArray("readDMEConfig: getReq, raw:", raw);
Log.d(TAG, "readDMEConfig: getReq: portID: " + getReq.portId);
Log.d(TAG, "readDMEConfig: getReq: functionId: " + getReq.functionId);
Log.d(TAG, "readDMEConfig: getReq: attrId: " + getReq.attrId);
Log.d(TAG, "readDMEConfig: getReq: selectorIndex: " + getReq.selectorIndex);
txn = I2cTransaction.newWrite(raw);
I2cTransaction[] results;
results = i2c.performTransactions(i2cBus, slaveAddress, txn);
txn = I2cTransaction.newRead(GetCnf.MSG_SIZE);
results = i2c.performTransactions(i2cBus, slaveAddress, txn);
GetCnf getCnf = new GetCnf(results[0].data);
logByteArray("readDMEConfig: getCnf, raw:", results[0].data);
Log.d(TAG, "readDMEConfig: getCnf portId: " + getCnf.portId);
Log.d(TAG, "readDMEConfig: getCnf functionId: " + getCnf.functionId);
Log.d(TAG, "readDMEConfig: getCnf resultCode: " + getCnf.resultCode);
Log.d(TAG, "readDMEConfig: getCnf attrVal: " + getCnf.attrVal +
String.format(" (0x%08x)", getCnf.attrVal));
FunctionId expectedFunctionId =
(peer ? FunctionId.C0_PEERGETCNF : FunctionId.C0_GETCNF);
if (getCnf.resultCode != expectedResultCode) {
String err = "Unexpected resultCode: " + getCnf.resultCode +
" (expected " + expectedResultCode + ")";
Log.e(TAG, err);
throw new IOException(err);
} else if (getCnf.functionId != expectedFunctionId) {
throw new IOException("Unexpected getCnf functionId: " +
getCnf.functionId);
}
return getCnf.attrVal;
}
}