1 /* 2 * Copyright (C) 2013 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 package android.bluetooth; 17 18 import android.annotation.IntDef; 19 import android.annotation.NonNull; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.os.Parcel; 22 import android.os.ParcelUuid; 23 import android.os.Parcelable; 24 25 import java.lang.annotation.Retention; 26 import java.lang.annotation.RetentionPolicy; 27 import java.util.ArrayList; 28 import java.util.List; 29 import java.util.UUID; 30 31 /** 32 * Represents a Bluetooth GATT Characteristic 33 * 34 * <p>A GATT characteristic is a basic data element used to construct a GATT service, {@link 35 * BluetoothGattService}. The characteristic contains a value as well as additional information and 36 * optional GATT descriptors, {@link BluetoothGattDescriptor}. 37 */ 38 public class BluetoothGattCharacteristic implements Parcelable { 39 40 /** Characteristic property: Characteristic is broadcastable. */ 41 public static final int PROPERTY_BROADCAST = 0x01; 42 43 /** Characteristic property: Characteristic is readable. */ 44 public static final int PROPERTY_READ = 0x02; 45 46 /** Characteristic property: Characteristic can be written without response. */ 47 public static final int PROPERTY_WRITE_NO_RESPONSE = 0x04; 48 49 /** Characteristic property: Characteristic can be written. */ 50 public static final int PROPERTY_WRITE = 0x08; 51 52 /** Characteristic property: Characteristic supports notification */ 53 public static final int PROPERTY_NOTIFY = 0x10; 54 55 /** Characteristic property: Characteristic supports indication */ 56 public static final int PROPERTY_INDICATE = 0x20; 57 58 /** Characteristic property: Characteristic supports write with signature */ 59 public static final int PROPERTY_SIGNED_WRITE = 0x40; 60 61 /** Characteristic property: Characteristic has extended properties */ 62 public static final int PROPERTY_EXTENDED_PROPS = 0x80; 63 64 /** Characteristic read permission */ 65 public static final int PERMISSION_READ = 0x01; 66 67 /** Characteristic permission: Allow encrypted read operations */ 68 public static final int PERMISSION_READ_ENCRYPTED = 0x02; 69 70 /** Characteristic permission: Allow reading with person-in-the-middle protection */ 71 public static final int PERMISSION_READ_ENCRYPTED_MITM = 0x04; 72 73 /** Characteristic write permission */ 74 public static final int PERMISSION_WRITE = 0x10; 75 76 /** Characteristic permission: Allow encrypted writes */ 77 public static final int PERMISSION_WRITE_ENCRYPTED = 0x20; 78 79 /** Characteristic permission: Allow encrypted writes with person-in-the-middle protection */ 80 public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 0x40; 81 82 /** Characteristic permission: Allow signed write operations */ 83 public static final int PERMISSION_WRITE_SIGNED = 0x80; 84 85 /** 86 * Characteristic permission: Allow signed write operations with person-in-the-middle protection 87 */ 88 public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100; 89 90 /** @hide */ 91 @Retention(RetentionPolicy.SOURCE) 92 @IntDef( 93 prefix = "WRITE_TYPE_", 94 value = {WRITE_TYPE_DEFAULT, WRITE_TYPE_NO_RESPONSE, WRITE_TYPE_SIGNED}) 95 public @interface WriteType {} 96 97 /** Write characteristic, requesting acknowledgement by the remote device */ 98 public static final int WRITE_TYPE_DEFAULT = 0x02; 99 100 /** Write characteristic without requiring a response by the remote device */ 101 public static final int WRITE_TYPE_NO_RESPONSE = 0x01; 102 103 /** Write characteristic including authentication signature */ 104 public static final int WRITE_TYPE_SIGNED = 0x04; 105 106 /** Characteristic value format type uint8 */ 107 public static final int FORMAT_UINT8 = 0x11; 108 109 /** Characteristic value format type uint16 */ 110 public static final int FORMAT_UINT16 = 0x12; 111 112 /** Characteristic value format type uint32 */ 113 public static final int FORMAT_UINT32 = 0x14; 114 115 /** Characteristic value format type sint8 */ 116 public static final int FORMAT_SINT8 = 0x21; 117 118 /** Characteristic value format type sint16 */ 119 public static final int FORMAT_SINT16 = 0x22; 120 121 /** Characteristic value format type sint32 */ 122 public static final int FORMAT_SINT32 = 0x24; 123 124 /** Characteristic value format type sfloat (16-bit float) */ 125 public static final int FORMAT_SFLOAT = 0x32; 126 127 /** Characteristic value format type float (32-bit float) */ 128 public static final int FORMAT_FLOAT = 0x34; 129 130 /** 131 * The UUID of this characteristic. 132 * 133 * @hide 134 */ 135 protected UUID mUuid; 136 137 /** 138 * Instance ID for this characteristic. 139 * 140 * @hide 141 */ 142 @UnsupportedAppUsage protected int mInstance; 143 144 /** 145 * Characteristic properties. 146 * 147 * @hide 148 */ 149 protected int mProperties; 150 151 /** 152 * Characteristic permissions. 153 * 154 * @hide 155 */ 156 protected int mPermissions; 157 158 /** 159 * Key size (default = 16). 160 * 161 * @hide 162 */ 163 protected int mKeySize = 16; 164 165 /** 166 * Write type for this characteristic. See WRITE_TYPE_* constants. 167 * 168 * @hide 169 */ 170 protected int mWriteType; 171 172 /** 173 * Back-reference to the service this characteristic belongs to. 174 * 175 * @hide 176 */ 177 @UnsupportedAppUsage protected BluetoothGattService mService; 178 179 /** 180 * The cached value of this characteristic. 181 * 182 * @hide 183 */ 184 protected byte[] mValue; 185 186 /** List of descriptors included in this characteristic. */ 187 protected List<BluetoothGattDescriptor> mDescriptors; 188 189 /** 190 * Create a new BluetoothGattCharacteristic. 191 * 192 * @param uuid The UUID for this characteristic 193 * @param properties Properties of this characteristic 194 * @param permissions Permissions for this characteristic 195 */ BluetoothGattCharacteristic(UUID uuid, int properties, int permissions)196 public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) { 197 initCharacteristic(null, uuid, 0, properties, permissions); 198 } 199 200 /** 201 * Create a new BluetoothGattCharacteristic 202 * 203 * @hide 204 */ BluetoothGattCharacteristic( BluetoothGattService service, UUID uuid, int instanceId, int properties, int permissions)205 /*package*/ BluetoothGattCharacteristic( 206 BluetoothGattService service, 207 UUID uuid, 208 int instanceId, 209 int properties, 210 int permissions) { 211 initCharacteristic(service, uuid, instanceId, properties, permissions); 212 } 213 214 /** 215 * Create a new BluetoothGattCharacteristic 216 * 217 * @hide 218 */ BluetoothGattCharacteristic(UUID uuid, int instanceId, int properties, int permissions)219 public BluetoothGattCharacteristic(UUID uuid, int instanceId, int properties, int permissions) { 220 initCharacteristic(null, uuid, instanceId, properties, permissions); 221 } 222 initCharacteristic( BluetoothGattService service, UUID uuid, int instanceId, int properties, int permissions)223 private void initCharacteristic( 224 BluetoothGattService service, 225 UUID uuid, 226 int instanceId, 227 int properties, 228 int permissions) { 229 mUuid = uuid; 230 mInstance = instanceId; 231 mProperties = properties; 232 mPermissions = permissions; 233 mService = service; 234 mValue = null; 235 mDescriptors = new ArrayList<BluetoothGattDescriptor>(); 236 237 if ((mProperties & PROPERTY_WRITE_NO_RESPONSE) != 0) { 238 mWriteType = WRITE_TYPE_NO_RESPONSE; 239 } else { 240 mWriteType = WRITE_TYPE_DEFAULT; 241 } 242 } 243 244 @Override describeContents()245 public int describeContents() { 246 return 0; 247 } 248 249 @Override writeToParcel(Parcel out, int flags)250 public void writeToParcel(Parcel out, int flags) { 251 out.writeParcelable(new ParcelUuid(mUuid), 0); 252 out.writeInt(mInstance); 253 out.writeInt(mProperties); 254 out.writeInt(mPermissions); 255 out.writeInt(mKeySize); 256 out.writeInt(mWriteType); 257 out.writeTypedList(mDescriptors); 258 } 259 260 public static final @NonNull Creator<BluetoothGattCharacteristic> CREATOR = 261 new Creator<>() { 262 public BluetoothGattCharacteristic createFromParcel(Parcel in) { 263 return new BluetoothGattCharacteristic(in); 264 } 265 266 public BluetoothGattCharacteristic[] newArray(int size) { 267 return new BluetoothGattCharacteristic[size]; 268 } 269 }; 270 BluetoothGattCharacteristic(Parcel in)271 private BluetoothGattCharacteristic(Parcel in) { 272 mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid(); 273 mInstance = in.readInt(); 274 mProperties = in.readInt(); 275 mPermissions = in.readInt(); 276 mKeySize = in.readInt(); 277 mWriteType = in.readInt(); 278 279 mDescriptors = new ArrayList<BluetoothGattDescriptor>(); 280 281 ArrayList<BluetoothGattDescriptor> descs = 282 in.createTypedArrayList(BluetoothGattDescriptor.CREATOR); 283 if (descs != null) { 284 for (BluetoothGattDescriptor desc : descs) { 285 desc.setCharacteristic(this); 286 mDescriptors.add(desc); 287 } 288 } 289 } 290 291 /** 292 * Returns the desired key size. 293 * 294 * @hide 295 */ getKeySize()296 public int getKeySize() { 297 return mKeySize; 298 } 299 300 /** 301 * Adds a descriptor to this characteristic. 302 * 303 * @param descriptor Descriptor to be added to this characteristic. 304 * @return true, if the descriptor was added to the characteristic 305 */ addDescriptor(BluetoothGattDescriptor descriptor)306 public boolean addDescriptor(BluetoothGattDescriptor descriptor) { 307 mDescriptors.add(descriptor); 308 descriptor.setCharacteristic(this); 309 return true; 310 } 311 312 /** 313 * Get a descriptor by UUID and instance id. 314 * 315 * @hide 316 */ getDescriptor(UUID uuid, int instanceId)317 /*package*/ BluetoothGattDescriptor getDescriptor(UUID uuid, int instanceId) { 318 for (BluetoothGattDescriptor descriptor : mDescriptors) { 319 if (descriptor.getUuid().equals(uuid) && descriptor.getInstanceId() == instanceId) { 320 return descriptor; 321 } 322 } 323 return null; 324 } 325 326 /** 327 * Returns the service this characteristic belongs to. 328 * 329 * @return The associated service 330 */ getService()331 public BluetoothGattService getService() { 332 return mService; 333 } 334 335 /** 336 * Sets the service associated with this device. 337 * 338 * @hide 339 */ 340 @UnsupportedAppUsage setService(BluetoothGattService service)341 /*package*/ void setService(BluetoothGattService service) { 342 mService = service; 343 } 344 345 /** 346 * Returns the UUID of this characteristic 347 * 348 * @return UUID of this characteristic 349 */ getUuid()350 public UUID getUuid() { 351 return mUuid; 352 } 353 354 /** 355 * Returns the instance ID for this characteristic. 356 * 357 * <p>If a remote device offers multiple characteristics with the same UUID, the instance ID is 358 * used to distuinguish between characteristics. 359 * 360 * @return Instance ID of this characteristic 361 */ getInstanceId()362 public int getInstanceId() { 363 return mInstance; 364 } 365 366 /** 367 * Force the instance ID. 368 * 369 * @hide 370 */ setInstanceId(int instanceId)371 public void setInstanceId(int instanceId) { 372 mInstance = instanceId; 373 } 374 375 /** 376 * Returns the properties of this characteristic. 377 * 378 * <p>The properties contain a bit mask of property flags indicating the features of this 379 * characteristic. 380 * 381 * @return Properties of this characteristic 382 */ getProperties()383 public int getProperties() { 384 return mProperties; 385 } 386 387 /** 388 * Returns the permissions for this characteristic. 389 * 390 * @return Permissions of this characteristic 391 */ getPermissions()392 public int getPermissions() { 393 return mPermissions; 394 } 395 396 /** 397 * Gets the write type for this characteristic. 398 * 399 * @return Write type for this characteristic 400 */ getWriteType()401 public int getWriteType() { 402 return mWriteType; 403 } 404 405 /** 406 * Set the write type for this characteristic 407 * 408 * <p>Setting the write type of a characteristic determines how the {@link 409 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} function write 410 * this characteristic. 411 * 412 * @param writeType The write type to for this characteristic. Can be one of: {@link 413 * #WRITE_TYPE_DEFAULT}, {@link #WRITE_TYPE_NO_RESPONSE} or {@link #WRITE_TYPE_SIGNED}. 414 */ setWriteType(int writeType)415 public void setWriteType(int writeType) { 416 mWriteType = writeType; 417 } 418 419 /** 420 * Set the desired key size. 421 * 422 * @hide 423 */ 424 @UnsupportedAppUsage setKeySize(int keySize)425 public void setKeySize(int keySize) { 426 mKeySize = keySize; 427 } 428 429 /** 430 * Returns a list of descriptors for this characteristic. 431 * 432 * @return Descriptors for this characteristic 433 */ getDescriptors()434 public List<BluetoothGattDescriptor> getDescriptors() { 435 return mDescriptors; 436 } 437 438 /** 439 * Returns a descriptor with a given UUID out of the list of descriptors for this 440 * characteristic. 441 * 442 * @return GATT descriptor object or null if no descriptor with the given UUID was found. 443 */ getDescriptor(UUID uuid)444 public BluetoothGattDescriptor getDescriptor(UUID uuid) { 445 for (BluetoothGattDescriptor descriptor : mDescriptors) { 446 if (descriptor.getUuid().equals(uuid)) { 447 return descriptor; 448 } 449 } 450 return null; 451 } 452 453 /** 454 * Get the stored value for this characteristic. 455 * 456 * <p>This function returns the stored value for this characteristic as retrieved by calling 457 * {@link BluetoothGatt#readCharacteristic}. The cached value of the characteristic is updated 458 * as a result of a read characteristic operation or if a characteristic update notification has 459 * been received. 460 * 461 * @return Cached value of the characteristic 462 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} instead 463 */ 464 @Deprecated getValue()465 public byte[] getValue() { 466 return mValue; 467 } 468 469 /** 470 * Return the stored value of this characteristic. 471 * 472 * <p>The formatType parameter determines how the characteristic value is to be interpreted. For 473 * example, setting formatType to {@link #FORMAT_UINT16} specifies that the first two bytes of 474 * the characteristic value at the given offset are interpreted to generate the return value. 475 * 476 * @param formatType The format type used to interpret the characteristic value. 477 * @param offset Offset at which the integer value can be found. 478 * @return Cached value of the characteristic or null of offset exceeds value size. 479 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get 480 * the characteristic value 481 */ 482 @Deprecated getIntValue(int formatType, int offset)483 public Integer getIntValue(int formatType, int offset) { 484 if ((offset + getTypeLen(formatType)) > mValue.length) return null; 485 486 switch (formatType) { 487 case FORMAT_UINT8: 488 return unsignedByteToInt(mValue[offset]); 489 490 case FORMAT_UINT16: 491 return unsignedBytesToInt(mValue[offset], mValue[offset + 1]); 492 493 case FORMAT_UINT32: 494 return unsignedBytesToInt( 495 mValue[offset], mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]); 496 case FORMAT_SINT8: 497 return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8); 498 499 case FORMAT_SINT16: 500 return unsignedToSigned(unsignedBytesToInt(mValue[offset], mValue[offset + 1]), 16); 501 502 case FORMAT_SINT32: 503 return unsignedToSigned( 504 unsignedBytesToInt( 505 mValue[offset], 506 mValue[offset + 1], 507 mValue[offset + 2], 508 mValue[offset + 3]), 509 32); 510 } 511 512 return null; 513 } 514 515 /** 516 * Return the stored value of this characteristic. 517 * 518 * <p>See {@link #getValue} for details. 519 * 520 * @param formatType The format type used to interpret the characteristic value. 521 * @param offset Offset at which the float value can be found. 522 * @return Cached value of the characteristic at a given offset or null if the requested offset 523 * exceeds the value size. 524 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get 525 * the characteristic value 526 */ 527 @Deprecated getFloatValue(int formatType, int offset)528 public Float getFloatValue(int formatType, int offset) { 529 if ((offset + getTypeLen(formatType)) > mValue.length) return null; 530 531 switch (formatType) { 532 case FORMAT_SFLOAT: 533 return bytesToFloat(mValue[offset], mValue[offset + 1]); 534 535 case FORMAT_FLOAT: 536 return bytesToFloat( 537 mValue[offset], mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]); 538 } 539 540 return null; 541 } 542 543 /** 544 * Return the stored value of this characteristic. 545 * 546 * <p>See {@link #getValue} for details. 547 * 548 * @param offset Offset at which the string value can be found. 549 * @return Cached value of the characteristic 550 * @deprecated Use {@link BluetoothGatt#readCharacteristic(BluetoothGattCharacteristic)} to get 551 * the characteristic value 552 */ 553 @Deprecated getStringValue(int offset)554 public String getStringValue(int offset) { 555 if (mValue == null || offset > mValue.length) return null; 556 byte[] strBytes = new byte[mValue.length - offset]; 557 for (int i = 0; i != (mValue.length - offset); ++i) strBytes[i] = mValue[offset + i]; 558 return new String(strBytes); 559 } 560 561 /** 562 * Updates the locally stored value of this characteristic. 563 * 564 * <p>This function modifies the locally stored cached value of this characteristic. To send the 565 * value to the remote device, call {@link BluetoothGatt#writeCharacteristic} to send the value 566 * to the remote device. 567 * 568 * @param value New value for this characteristic 569 * @return true if the locally stored value has been set, false if the requested value could not 570 * be stored locally. 571 * @deprecated Pass the characteristic value directly into {@link 572 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 573 */ 574 @Deprecated setValue(byte[] value)575 public boolean setValue(byte[] value) { 576 mValue = value; 577 return true; 578 } 579 580 /** 581 * Set the locally stored value of this characteristic. 582 * 583 * <p>See {@link #setValue(byte[])} for details. 584 * 585 * @param value New value for this characteristic 586 * @param formatType Integer format type used to transform the value parameter 587 * @param offset Offset at which the value should be placed 588 * @return true if the locally stored value has been set 589 * @deprecated Pass the characteristic value directly into {@link 590 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 591 */ 592 @Deprecated setValue(int value, int formatType, int offset)593 public boolean setValue(int value, int formatType, int offset) { 594 int len = offset + getTypeLen(formatType); 595 if (mValue == null) mValue = new byte[len]; 596 if (len > mValue.length) return false; 597 598 switch (formatType) { 599 case FORMAT_SINT8: 600 value = intToSignedBits(value, 8); 601 // Fall-through intended 602 case FORMAT_UINT8: 603 mValue[offset] = (byte) (value & 0xFF); 604 break; 605 606 case FORMAT_SINT16: 607 value = intToSignedBits(value, 16); 608 // Fall-through intended 609 case FORMAT_UINT16: 610 mValue[offset++] = (byte) (value & 0xFF); 611 mValue[offset] = (byte) ((value >> 8) & 0xFF); 612 break; 613 614 case FORMAT_SINT32: 615 value = intToSignedBits(value, 32); 616 // Fall-through intended 617 case FORMAT_UINT32: 618 mValue[offset++] = (byte) (value & 0xFF); 619 mValue[offset++] = (byte) ((value >> 8) & 0xFF); 620 mValue[offset++] = (byte) ((value >> 16) & 0xFF); 621 mValue[offset] = (byte) ((value >> 24) & 0xFF); 622 break; 623 624 default: 625 return false; 626 } 627 return true; 628 } 629 630 /** 631 * Set the locally stored value of this characteristic. 632 * 633 * <p>See {@link #setValue(byte[])} for details. 634 * 635 * @param mantissa Mantissa for this characteristic 636 * @param exponent exponent value for this characteristic 637 * @param formatType Float format type used to transform the value parameter 638 * @param offset Offset at which the value should be placed 639 * @return true if the locally stored value has been set 640 * @deprecated Pass the characteristic value directly into {@link 641 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 642 */ 643 @Deprecated setValue(int mantissa, int exponent, int formatType, int offset)644 public boolean setValue(int mantissa, int exponent, int formatType, int offset) { 645 int len = offset + getTypeLen(formatType); 646 if (mValue == null) mValue = new byte[len]; 647 if (len > mValue.length) return false; 648 649 switch (formatType) { 650 case FORMAT_SFLOAT: 651 mantissa = intToSignedBits(mantissa, 12); 652 exponent = intToSignedBits(exponent, 4); 653 mValue[offset++] = (byte) (mantissa & 0xFF); 654 mValue[offset] = (byte) ((mantissa >> 8) & 0x0F); 655 mValue[offset] += (byte) ((exponent & 0x0F) << 4); 656 break; 657 658 case FORMAT_FLOAT: 659 mantissa = intToSignedBits(mantissa, 24); 660 exponent = intToSignedBits(exponent, 8); 661 mValue[offset++] = (byte) (mantissa & 0xFF); 662 mValue[offset++] = (byte) ((mantissa >> 8) & 0xFF); 663 mValue[offset++] = (byte) ((mantissa >> 16) & 0xFF); 664 mValue[offset] += (byte) (exponent & 0xFF); 665 break; 666 667 default: 668 return false; 669 } 670 671 return true; 672 } 673 674 /** 675 * Set the locally stored value of this characteristic. 676 * 677 * <p>See {@link #setValue(byte[])} for details. 678 * 679 * @param value New value for this characteristic 680 * @return true if the locally stored value has been set 681 * @deprecated Pass the characteristic value directly into {@link 682 * BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} 683 */ 684 @Deprecated setValue(String value)685 public boolean setValue(String value) { 686 mValue = value.getBytes(); 687 return true; 688 } 689 690 /** Returns the size of a give value type. */ getTypeLen(int formatType)691 private int getTypeLen(int formatType) { 692 return formatType & 0xF; 693 } 694 695 /** Convert a signed byte to an unsigned int. */ unsignedByteToInt(byte b)696 private int unsignedByteToInt(byte b) { 697 return b & 0xFF; 698 } 699 700 /** Convert signed bytes to a 16-bit unsigned int. */ unsignedBytesToInt(byte b0, byte b1)701 private int unsignedBytesToInt(byte b0, byte b1) { 702 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)); 703 } 704 705 /** Convert signed bytes to a 32-bit unsigned int. */ unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3)706 private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) { 707 return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)) 708 + (unsignedByteToInt(b2) << 16) 709 + (unsignedByteToInt(b3) << 24); 710 } 711 712 /** Convert signed bytes to a 16-bit short float value. */ bytesToFloat(byte b0, byte b1)713 private float bytesToFloat(byte b0, byte b1) { 714 int mantissa = 715 unsignedToSigned(unsignedByteToInt(b0) + ((unsignedByteToInt(b1) & 0x0F) << 8), 12); 716 int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4); 717 return (float) (mantissa * Math.pow(10, exponent)); 718 } 719 720 /** Convert signed bytes to a 32-bit short float value. */ bytesToFloat(byte b0, byte b1, byte b2, byte b3)721 private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) { 722 int mantissa = 723 unsignedToSigned( 724 unsignedByteToInt(b0) 725 + (unsignedByteToInt(b1) << 8) 726 + (unsignedByteToInt(b2) << 16), 727 24); 728 return (float) (mantissa * Math.pow(10, b3)); 729 } 730 731 /** Convert an unsigned integer value to a two's-complement encoded signed value. */ unsignedToSigned(int unsigned, int size)732 private int unsignedToSigned(int unsigned, int size) { 733 if ((unsigned & (1 << (size - 1))) != 0) { 734 unsigned = -1 * ((1 << (size - 1)) - (unsigned & ((1 << (size - 1)) - 1))); 735 } 736 return unsigned; 737 } 738 739 /** Convert an integer into the signed bits of a given length. */ intToSignedBits(int i, int size)740 private int intToSignedBits(int i, int size) { 741 if (i < 0) { 742 i = (1 << (size - 1)) + (i & ((1 << (size - 1)) - 1)); 743 } 744 return i; 745 } 746 } 747