• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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