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