Fields Summary |
---|
private static final byte | NULL_DATANULL data header. |
private static final byte | BOOLEAN_DATABoolean data header. |
private static final byte | INT1_SIGNED1-byte signed integer header. |
private static final byte | INT2_SIGNED2-byte signed integer header. |
private static final byte | INT4_SIGNED4-byte signed integer header. |
private static final byte | INT8_SIGNED8-byte signed integer header. |
private static final byte | INT16_SIGNED16-byte signed integer header. |
private static final byte | INT1_UNSIGNED1-byte unsigned integer header. |
private static final byte | INT2_UNSIGNED2-byte unsigned integer header. |
private static final byte | INT4_UNSIGNED4-byte unsigned integer header. |
private static final byte | INT8_UNSIGNED8-byte unsigned integer header. |
private static final byte | INT16_UNSIGNED16-byte unsigned integer header. |
private static final byte | UUID_216-bit UUID header. |
private static final byte | UUID_432-bit UUID header. |
private static final byte | UUID_16128-bit UUID header. |
private static final byte | TYPE_MASKMask to get type tag from header. |
private static final byte | SIZE_MASKMask to get size of data size field from header. |
private static final byte | STRING_TYPETag for string type. |
private static final byte | SEQUENCE_TYPETag for sequence type. |
private static final byte | ALTERNATIVE_TYPETag for an alternative type. |
private static final byte | SHORT_SIZETag that identifies that size of data size field is 2 bytes. |
private static final byte | NORMAL_SIZETag that identifies that size of data size field is 4 bytes. |
private static final byte | LONG_SIZETag that identifies that size of data size field is 8 bytes. |
protected byte[] | writeBufferDestination buffer which collects binary data of a data element. |
protected byte[] | readBufferSource buffer which contains binary data of a data element. |
protected long | writePosCurrent position at the destination buffer. |
protected long | readPosCurrent position at the source buffer. |
private Stack | readPosStackAllows to store and retrieve positions at the source buffer. |
Methods Summary |
---|
long | getDataSize(javax.bluetooth.DataElement data)Returns the size of DataElement with service information
to get the total size required to work with this DataElement.
int type = data.getDataType();
long size = getPureDataSize(data);
if ((type == DataElement.NULL) || (type == DataElement.BOOL)
|| (type == DataElement.INT_1) || (type == DataElement.U_INT_1)
|| (type == DataElement.INT_2) || (type == DataElement.U_INT_2)
|| (type == DataElement.INT_4) || (type == DataElement.U_INT_4)
|| (type == DataElement.INT_8) || (type == DataElement.U_INT_8)
|| (type == DataElement.INT_16)
|| (type == DataElement.U_INT_16)
|| (type == DataElement.UUID)) {
return size + 1;
} else if ((type == DataElement.DATSEQ)
|| (type == DataElement.DATALT) || (type == DataElement.STRING)
|| (type == DataElement.URL)) {
if (size <= 0xffL) {
return size + 2;
} else if (size <= 0xffffL) {
return size + 3;
} else if (size <= 0xffffffffL) {
return size + 5;
} else {
throw new RuntimeException("Data size is too large.");
}
} else {
throw new RuntimeException("Unexpected data type.");
}
|
long | getPureDataSize(javax.bluetooth.DataElement data)Returns the size of DataElement without service information.
switch (data.getDataType()) {
case DataElement.NULL:
return 0;
case DataElement.BOOL:
case DataElement.INT_1:
case DataElement.U_INT_1:
return 1;
case DataElement.INT_2:
case DataElement.U_INT_2:
return 2;
case DataElement.INT_4:
case DataElement.U_INT_4:
return 4;
case DataElement.INT_8:
case DataElement.U_INT_8:
return 8;
case DataElement.INT_16:
case DataElement.U_INT_16:
return 16;
case DataElement.DATSEQ:
case DataElement.DATALT:
long size = 0;
Enumeration elements = (Enumeration)data.getValue();
while (elements.hasMoreElements()) {
size += getDataSize((DataElement)elements.nextElement());
}
return size;
case DataElement.STRING:
case DataElement.URL:
return ((String)data.getValue()).length();
case DataElement.UUID:
return 16;
default:
throw new RuntimeException("Unknown data type.");
}
|
private long | popReadPos()Extracts saved read position.
return ((Long)readPosStack.pop()).longValue();
|
private void | pushReadPos()Saves the current read position.
readPosStack.push(new Long(readPos));
|
boolean | readBoolean()Reads boolean value from the connection.
return (readByte() != 0);
|
byte | readByte()Reads 1-byte value from the connection.
if (readPos < 0 || readPos >= readBuffer.length) {
throw new IndexOutOfBoundsException();
}
return readBuffer[(int)readPos++];
|
byte[] | readBytes(int size)Reads given number of bytes from the connection.
byte[] data = new byte[size];
int dataPos = 0;
if (readPos < 0 || readPos + data.length > readBuffer.length) {
throw new IndexOutOfBoundsException();
}
System.arraycopy(readBuffer, (int)readPos, data, 0, data.length);
readPos += data.length;
return data;
|
javax.bluetooth.DataElement | readDataElement()Creates a data element from the binary data in the read buffer.
byte header = readByte();
if ((header == NULL_DATA) || (header == BOOLEAN_DATA)
|| (header == INT1_SIGNED) || (header == INT1_UNSIGNED)
|| (header == INT2_SIGNED) || (header == INT2_UNSIGNED)
|| (header == INT4_SIGNED) || (header == INT4_UNSIGNED)
|| (header == INT8_SIGNED) || (header == INT8_UNSIGNED)
|| (header == INT16_SIGNED) || (header == INT16_UNSIGNED)) {
switch (header) {
case NULL_DATA:
return new DataElement(DataElement.NULL);
case BOOLEAN_DATA:
return new DataElement(readBoolean());
case INT1_SIGNED:
return new DataElement(DataElement.INT_1, readByte());
case INT1_UNSIGNED:
return new DataElement(DataElement.U_INT_1,
(readByte() & 0xffL));
case INT2_SIGNED:
return new DataElement(DataElement.INT_2, readShort());
case INT2_UNSIGNED:
return new DataElement(DataElement.U_INT_2,
(readShort() & 0xffffL));
case INT4_SIGNED:
return new DataElement(DataElement.INT_4, readInteger());
case INT4_UNSIGNED:
return new DataElement(DataElement.U_INT_4,
(readInteger() & 0xffffffffL));
case INT8_SIGNED:
return new DataElement(DataElement.INT_8, readLong());
case INT8_UNSIGNED:
return new DataElement(DataElement.U_INT_8, readBytes(8));
case INT16_SIGNED:
return new DataElement(DataElement.INT_16, readBytes(16));
case INT16_UNSIGNED:
return new DataElement(DataElement.U_INT_16, readBytes(16));
}
} else if (((header & TYPE_MASK) == STRING_TYPE)
|| ((header & TYPE_MASK) == SEQUENCE_TYPE)
|| ((header & TYPE_MASK) == ALTERNATIVE_TYPE)) {
long size = 0;
if ((header & SIZE_MASK) == SHORT_SIZE) {
size = readByte() & 0xffL;
} else if ((header & SIZE_MASK) == NORMAL_SIZE) {
size = readShort() & 0xffffL;
} else if ((header & SIZE_MASK) == LONG_SIZE) {
size = readInteger() & 0xffffffffL;
} else {
System.err.println("Unknown size mask.");
}
if ((header & TYPE_MASK) == STRING_TYPE) {
return new DataElement(DataElement.STRING,
new String(readBytes((int)size)));
} else {
DataElement data = null;
DataElement dataElement = null;
long dataPos = 0;
if ((header & TYPE_MASK) == SEQUENCE_TYPE) {
data = new DataElement(DataElement.DATSEQ);
} else {
data = new DataElement(DataElement.DATALT);
}
while (dataPos < size) {
pushReadPos();
dataElement = readDataElement();
dataPos += readPos - popReadPos();
data.addElement(dataElement);
}
return data;
}
} else if (header == UUID_2) {
return new DataElement(DataElement.UUID, readUUID(2));
} else if (header == UUID_4) {
return new DataElement(DataElement.UUID, readUUID(4));
} else if (header == UUID_16) {
return new DataElement(DataElement.UUID, readUUID(16));
} else {
throw new RuntimeException("Unknown data type.");
}
return null;
|
int | readInteger()Reads 4-byte value from the connection.
int data1 = ((int)readShort()) & 0xffff;
int data2 = ((int)readShort()) & 0xffff;
return ((data1 << 16) + (data2 << 0));
|
long | readLong()Reads 8-byte value from the connection.
long data1 = ((long)readInteger()) & 0xffffffffL;
long data2 = ((long)readInteger()) & 0xffffffffL;
return ((data1 << 32) + (data2 << 0));
|
short | readShort()Reads 2-byte value from the connection.
int data1 = ((int)readByte()) & 0xff;
int data2 = ((int)readByte()) & 0xff;
return (short)((data1 << 8) + (data2 << 0));
|
javax.bluetooth.UUID | readUUID(int len)Reads UUID of a given size.
String uuid = "";
for (int i = 0; i < len; i++) {
String digit = Integer.toHexString(readByte() & 0xff);
if (digit.length() == 1) digit = '0" + digit;
uuid += digit;
}
return new UUID(uuid, len < 16);
|
public synchronized javax.bluetooth.DataElement | restore(byte[] data)Constructs DataElement from byte array containing the element in
serialized form.
readBuffer = data;
readPos = 0;
DataElement result = readDataElement();
readBuffer = null;
return result;
|
public synchronized byte[] | serialize(javax.bluetooth.DataElement data)Serializes given DataElement object, i.e. creates an array of bytes
representing DataElement as described in Bluetooth Specification
Version 1.2, vol 3, page 127.
writeBuffer = new byte[(int)getDataSize(data)];
writePos = 0;
writeDataElement(data);
byte[] result = writeBuffer;
writeBuffer = null;
return result;
|
void | writeBoolean(boolean data)Writes boolean data to the buffer.
Writes only value given itself. Note that boolean data header
should be written before.
writeByte(data ? 1 : 0);
|
void | writeByte(long data)Writes 1-byte data to the buffer.
if (writePos < 0 || writePos >= writeBuffer.length) {
throw new IndexOutOfBoundsException();
}
writeBuffer[(int)writePos++] = (byte)data;
|
void | writeBytes(byte[] data)Writes given data to the connection.
if (writePos < 0 || writePos + data.length > writeBuffer.length) {
throw new IndexOutOfBoundsException();
}
System.arraycopy(data, 0, writeBuffer, (int)writePos, data.length);
writePos += data.length;
|
void | writeDataElement(javax.bluetooth.DataElement data)Writes given data element into the write buffer.
long size = getPureDataSize(data);
int type = data.getDataType();
byte typeBits = 0x00;
if ((type == DataElement.NULL) || (type == DataElement.BOOL)
|| (type == DataElement.INT_1) || (type == DataElement.U_INT_1)
|| (type == DataElement.INT_2) || (type == DataElement.U_INT_2)
|| (type == DataElement.INT_4) || (type == DataElement.U_INT_4)
|| (type == DataElement.INT_8) || (type == DataElement.U_INT_8)
|| (type == DataElement.INT_16)
|| (type == DataElement.U_INT_16)) {
switch (type) {
case DataElement.NULL:
writeByte(NULL_DATA);
break;
case DataElement.BOOL:
writeByte(BOOLEAN_DATA);
writeBoolean(data.getBoolean());
break;
case DataElement.INT_1:
writeByte(INT1_SIGNED);
writeByte((byte)data.getLong());
break;
case DataElement.U_INT_1:
writeByte(INT1_UNSIGNED);
writeByte((byte)data.getLong());
break;
case DataElement.INT_2:
writeByte(INT2_SIGNED);
writeShort((short)data.getLong());
break;
case DataElement.U_INT_2:
writeByte(INT2_UNSIGNED);
writeShort((short)data.getLong());
break;
case DataElement.INT_4:
writeByte(INT4_SIGNED);
writeInteger((int)data.getLong());
break;
case DataElement.U_INT_4:
writeByte(INT4_UNSIGNED);
writeInteger((int)data.getLong());
break;
case DataElement.INT_8:
writeByte(INT8_SIGNED);
writeLong(data.getLong());
break;
case DataElement.U_INT_8:
writeByte(INT8_UNSIGNED);
writeBytes((byte[])data.getValue());
break;
case DataElement.INT_16:
writeByte(INT16_SIGNED);
writeBytes((byte[])data.getValue());
break;
case DataElement.U_INT_16:
writeByte(INT16_UNSIGNED);
writeBytes((byte[])data.getValue());
break;
}
} else if ((type == DataElement.DATSEQ)
|| (type == DataElement.DATALT) || (type == DataElement.STRING)
|| (type == DataElement.URL)) {
switch (type) {
case DataElement.DATSEQ:
typeBits = (TYPE_MASK & SEQUENCE_TYPE);
break;
case DataElement.DATALT:
typeBits = (TYPE_MASK & ALTERNATIVE_TYPE);
break;
case DataElement.STRING:
case DataElement.URL:
typeBits = (TYPE_MASK & STRING_TYPE);
break;
}
if (size <= 0xff) {
writeByte(typeBits | (SIZE_MASK & SHORT_SIZE));
writeByte((byte)size);
} else if (size <= 0xffff) {
writeByte(typeBits | (SIZE_MASK & NORMAL_SIZE));
writeShort((short)size);
} else {
writeByte(typeBits | (SIZE_MASK & LONG_SIZE));
writeInteger((int)size);
}
if ((type == DataElement.DATSEQ) || (type == DataElement.DATALT)) {
Enumeration elements = (Enumeration) data.getValue();
while (elements.hasMoreElements()) {
writeDataElement((DataElement)elements.nextElement());
}
} else {
writeBytes(((String)data.getValue()).getBytes());
}
} else if (type == DataElement.UUID) {
writeByte(UUID_16);
String uuid = ((UUID)data.getValue()).toString();
while (uuid.length() < 32) {
uuid = '0" + uuid;
}
for (int i = 0; i < 16; i++) {
writeByte(Integer.parseInt(
uuid.substring(i * 2, i * 2 + 2), 16));
}
} else {
throw new RuntimeException("Unknown data type.");
}
|
void | writeInteger(int data)Writes 4-byte data to the connection.
writeShort((short)((data >>> 16) & 0xffff));
writeShort((short)((data >>> 0) & 0xffff));
|
void | writeLong(long data)Writes 8-byte data to the connection.
writeInteger((int)((data >>> 32) & 0xffffffff));
writeInteger((int)((data >>> 0) & 0xffffffff));
|
void | writeShort(short data)Writes 2-byte data to the buffer.
writeByte((byte)((data >>> 8) & 0xff));
writeByte((byte)((data >>> 0) & 0xff));
|