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