3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2011 André Dieb Martins <andre.dieb@gmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 #define GATT_PRIM_SVC_UUID 0x2800
37 #define GATT_SND_SVC_UUID 0x2801
38 #define GATT_INCLUDE_UUID 0x2802
39 #define GATT_CHARAC_UUID 0x2803
41 #define GATT_CHARAC_DEVICE_NAME 0x2A00
42 #define GATT_CHARAC_APPEARANCE 0x2A01
43 #define GATT_CHARAC_PERIPHERAL_PRIV_FLAG 0x2A02
44 #define GATT_CHARAC_RECONNECTION_ADDRESS 0x2A03
45 #define GATT_CHARAC_PERIPHERAL_PREF_CONN 0x2A04
46 #define GATT_CHARAC_SERVICE_CHANGED 0x2A05
48 #define GATT_CHARAC_EXT_PROPER_UUID 0x2900
49 #define GATT_CHARAC_USER_DESC_UUID 0x2901
50 #define GATT_CLIENT_CHARAC_CFG_UUID 0x2902
51 #define GATT_SERVER_CHARAC_CFG_UUID 0x2903
52 #define GATT_CHARAC_FMT_UUID 0x2904
53 #define GATT_CHARAC_AGREG_FMT_UUID 0x2905
57 /* Attribute Protocol Opcodes */
58 #define ATT_OP_ERROR 0x01
59 #define ATT_OP_MTU_REQ 0x02
60 #define ATT_OP_MTU_RESP 0x03
61 #define ATT_OP_FIND_INFO_REQ 0x04
62 #define ATT_OP_FIND_INFO_RESP 0x05
63 #define ATT_OP_FIND_BY_TYPE_REQ 0x06
64 #define ATT_OP_FIND_BY_TYPE_RESP 0x07
65 #define ATT_OP_READ_BY_TYPE_REQ 0x08
66 #define ATT_OP_READ_BY_TYPE_RESP 0x09
67 #define ATT_OP_READ_REQ 0x0A
68 #define ATT_OP_READ_RESP 0x0B
69 #define ATT_OP_READ_BLOB_REQ 0x0C
70 #define ATT_OP_READ_BLOB_RESP 0x0D
71 #define ATT_OP_READ_MULTI_REQ 0x0E
72 #define ATT_OP_READ_MULTI_RESP 0x0F
73 #define ATT_OP_READ_BY_GROUP_REQ 0x10
74 #define ATT_OP_READ_BY_GROUP_RESP 0x11
75 #define ATT_OP_WRITE_REQ 0x12
76 #define ATT_OP_WRITE_RESP 0x13
77 #define ATT_OP_WRITE_CMD 0x52
78 #define ATT_OP_PREP_WRITE_REQ 0x16
79 #define ATT_OP_PREP_WRITE_RESP 0x17
80 #define ATT_OP_EXEC_WRITE_REQ 0x18
81 #define ATT_OP_EXEC_WRITE_RESP 0x19
82 #define ATT_OP_HANDLE_NOTIFY 0x1B
83 #define ATT_OP_HANDLE_IND 0x1D
84 #define ATT_OP_HANDLE_CNF 0x1E
85 #define ATT_OP_SIGNED_WRITE_CMD 0xD2
87 /* Error codes for Error response PDU */
88 #define ATT_ECODE_INVALID_HANDLE 0x01
89 #define ATT_ECODE_READ_NOT_PERM 0x02
90 #define ATT_ECODE_WRITE_NOT_PERM 0x03
91 #define ATT_ECODE_INVALID_PDU 0x04
92 #define ATT_ECODE_INSUFF_AUTHEN 0x05
93 #define ATT_ECODE_REQ_NOT_SUPP 0x06
94 #define ATT_ECODE_INVALID_OFFSET 0x07
95 #define ATT_ECODE_INSUFF_AUTHO 0x08
96 #define ATT_ECODE_PREP_QUEUE_FULL 0x09
97 #define ATT_ECODE_ATTR_NOT_FOUND 0x0A
98 #define ATT_ECODE_ATTR_NOT_LONG 0x0B
99 #define ATT_ECODE_INSUFF_ENCR_KEY_SIZE 0x0C
100 #define ATT_ECODE_INVAL_ATTR_VALUE_LEN 0x0D
101 #define ATT_ECODE_UNLIKELY 0x0E
102 #define ATT_ECODE_INSUFF_ENC 0x0F
103 #define ATT_ECODE_UNSUPP_GRP_TYPE 0x10
104 #define ATT_ECODE_INSUFF_RESOURCES 0x11
105 #define ATT_ECODE_IO 0xFF
108 /* Attribute Protocol Opcodes */
109 static const char *attop2str(uint8_t op)
116 case ATT_OP_MTU_RESP:
118 case ATT_OP_FIND_INFO_REQ:
119 return "Find Information req";
120 case ATT_OP_FIND_INFO_RESP:
121 return "Find Information resp";
122 case ATT_OP_FIND_BY_TYPE_REQ:
123 return "Find By Type req";
124 case ATT_OP_FIND_BY_TYPE_RESP:
125 return "Find By Type resp";
126 case ATT_OP_READ_BY_TYPE_REQ:
127 return "Read By Type req";
128 case ATT_OP_READ_BY_TYPE_RESP:
129 return "Read By Type resp";
130 case ATT_OP_READ_REQ:
132 case ATT_OP_READ_RESP:
134 case ATT_OP_READ_BLOB_REQ:
135 return "Read Blob req";
136 case ATT_OP_READ_BLOB_RESP:
137 return "Read Blob resp";
138 case ATT_OP_READ_MULTI_REQ:
139 return "Read Multi req";
140 case ATT_OP_READ_MULTI_RESP:
141 return "Read Multi resp";
142 case ATT_OP_READ_BY_GROUP_REQ:
143 return "Read By Group req";
144 case ATT_OP_READ_BY_GROUP_RESP:
145 return "Read By Group resp";
146 case ATT_OP_WRITE_REQ:
148 case ATT_OP_WRITE_RESP:
150 case ATT_OP_WRITE_CMD:
152 case ATT_OP_PREP_WRITE_REQ:
153 return "Prepare Write req";
154 case ATT_OP_PREP_WRITE_RESP:
155 return "Prepare Write resp";
156 case ATT_OP_EXEC_WRITE_REQ:
157 return "Exec Write req";
158 case ATT_OP_EXEC_WRITE_RESP:
159 return "Exec Write resp";
160 case ATT_OP_HANDLE_NOTIFY:
161 return "Handle notify";
162 case ATT_OP_HANDLE_IND:
163 return "Handle indicate";
164 case ATT_OP_HANDLE_CNF:
166 case ATT_OP_SIGNED_WRITE_CMD:
167 return "Signed Write Cmd";
173 static const char * atterror2str(uint8_t err)
176 case ATT_ECODE_INVALID_HANDLE:
177 return "Invalid handle";
178 case ATT_ECODE_READ_NOT_PERM:
179 return "Read not permitted";
180 case ATT_ECODE_WRITE_NOT_PERM:
181 return "Write not permitted";
182 case ATT_ECODE_INVALID_PDU:
183 return "Invalid PDU";
184 case ATT_ECODE_INSUFF_AUTHEN:
185 return "Insufficient authentication";
186 case ATT_ECODE_REQ_NOT_SUPP:
187 return "Request not supported";
188 case ATT_ECODE_INVALID_OFFSET:
189 return "Invalid offset";
190 case ATT_ECODE_INSUFF_AUTHO:
191 return "Insufficient authorization";
192 case ATT_ECODE_PREP_QUEUE_FULL:
193 return "Prepare queue full";
194 case ATT_ECODE_ATTR_NOT_FOUND:
195 return "Attribute not found";
196 case ATT_ECODE_ATTR_NOT_LONG:
197 return "Attribute not long";
198 case ATT_ECODE_INSUFF_ENCR_KEY_SIZE:
199 return "Insufficient encryption key size";
200 case ATT_ECODE_INVAL_ATTR_VALUE_LEN:
201 return "Invalid attribute value length";
202 case ATT_ECODE_UNLIKELY:
203 return "Unlikely error";
204 case ATT_ECODE_INSUFF_ENC:
205 return "Insufficient encryption";
206 case ATT_ECODE_UNSUPP_GRP_TYPE:
207 return "Unsupported group type";
208 case ATT_ECODE_INSUFF_RESOURCES:
209 return "Insufficient resources";
211 return "Application Error";
217 static const char *uuid2str(uint16_t uuid)
220 case GATT_PRIM_SVC_UUID:
221 return "GATT Primary Service";
222 case GATT_SND_SVC_UUID:
223 return "GATT Secondary Service";
224 case GATT_INCLUDE_UUID:
225 return "GATT Include";
226 case GATT_CHARAC_UUID:
227 return "GATT Characteristic";
228 case GATT_CHARAC_DEVICE_NAME:
229 return "GATT(type) Device Name";
230 case GATT_CHARAC_APPEARANCE:
231 return "GATT(type) Appearance";
232 case GATT_CHARAC_PERIPHERAL_PRIV_FLAG:
233 return "GATT(type) Peripheral Privacy Flag";
234 case GATT_CHARAC_RECONNECTION_ADDRESS:
235 return "GATT(type) Characteristic Reconnection Address";
236 case GATT_CHARAC_PERIPHERAL_PREF_CONN:
237 return "GATT(type) Characteristic Preferred Connection Parameters";
238 case GATT_CHARAC_SERVICE_CHANGED:
239 return "GATT(type) Characteristic Service Changed";
240 case GATT_CHARAC_EXT_PROPER_UUID:
241 return "GATT(desc) Characteristic Extended Properties";
242 case GATT_CHARAC_USER_DESC_UUID:
243 return "GATT(desc) User Description";
244 case GATT_CLIENT_CHARAC_CFG_UUID:
245 return "GATT(desc) Client Characteristic Configuration";
246 case GATT_SERVER_CHARAC_CFG_UUID:
247 return "GATT(desc) Server Characteristic Configuration";
248 case GATT_CHARAC_FMT_UUID:
249 return "GATT(desc) Format";
250 case GATT_CHARAC_AGREG_FMT_UUID:
251 return "GATT(desc) Aggregate Format";
257 static void att_error_dump(int level, struct frame *frm)
259 uint8_t op = p_get_u8(frm);
260 uint16_t handle = btohs(htons(p_get_u16(frm)));
261 uint8_t err = p_get_u8(frm);
263 p_indent(level, frm);
264 printf("Error: %s (%d)\n", atterror2str(err), err);
266 p_indent(level, frm);
267 printf("%s (0x%.2x) on handle 0x%4.4x\n", attop2str(op), op, handle);
270 static void att_mtu_req_dump(int level, struct frame *frm)
272 uint16_t client_rx_mtu = btohs(htons(p_get_u16(frm)));
274 p_indent(level, frm);
275 printf("client rx mtu %d\n", client_rx_mtu);
278 static void att_mtu_resp_dump(int level, struct frame *frm)
280 uint16_t server_rx_mtu = btohs(htons(p_get_u16(frm)));
282 p_indent(level, frm);
283 printf("server rx mtu %d\n", server_rx_mtu);
286 static void att_find_info_req_dump(int level, struct frame *frm)
288 uint16_t start = btohs(htons(p_get_u16(frm)));
289 uint16_t end = btohs(htons(p_get_u16(frm)));
291 p_indent(level, frm);
292 printf("start 0x%4.4x, end 0x%4.4x\n", start, end);
295 static void print_uuid128(struct frame *frm)
300 for (i = 0; i < 16; i++)
301 uuid[15 - i] = p_get_u8(frm);
303 for (i = 0; i < 16; i++) {
304 printf("%02x", uuid[i]);
305 if (i == 3 || i == 5 || i == 7 || i == 9)
310 static void att_find_info_resp_dump(int level, struct frame *frm)
312 uint8_t fmt = p_get_u8(frm);
314 p_indent(level, frm);
317 printf("format: uuid-16\n");
319 while (frm->len > 0) {
320 uint16_t handle = btohs(htons(p_get_u16(frm)));
321 uint16_t uuid = btohs(htons(p_get_u16(frm)));
322 p_indent(level + 1, frm);
323 printf("handle 0x%4.4x, uuid 0x%4.4x (%s)\n", handle, uuid,
327 printf("format: uuid-128\n");
329 while (frm->len > 0) {
330 uint16_t handle = btohs(htons(p_get_u16(frm)));
332 p_indent(level + 1, frm);
333 printf("handle 0x%4.4x, uuid ", handle);
340 static void att_find_by_type_req_dump(int level, struct frame *frm)
342 uint16_t start = btohs(htons(p_get_u16(frm)));
343 uint16_t end = btohs(htons(p_get_u16(frm)));
344 uint16_t uuid = btohs(htons(p_get_u16(frm)));
346 p_indent(level, frm);
347 printf("start 0x%4.4x, end 0x%4.4x, uuid 0x%4.4x\n", start, end, uuid);
349 p_indent(level, frm);
352 printf(" 0x%2.2x", p_get_u8(frm));
356 static void att_find_by_type_resp_dump(int level, struct frame *frm)
358 while (frm->len > 0) {
359 uint16_t uuid = btohs(htons(p_get_u16(frm)));
360 uint16_t end = btohs(htons(p_get_u16(frm)));
362 p_indent(level, frm);
363 printf("Found attr 0x%4.4x, group end handle 0x%4.4x\n",
368 static void att_read_by_type_req_dump(int level, struct frame *frm)
370 uint16_t start = btohs(htons(p_get_u16(frm)));
371 uint16_t end = btohs(htons(p_get_u16(frm)));
373 p_indent(level, frm);
374 printf("start 0x%4.4x, end 0x%4.4x\n", start, end);
376 p_indent(level, frm);
378 printf("type-uuid 0x%4.4x\n", btohs(htons(p_get_u16(frm))));
379 } else if (frm->len == 16) {
380 printf("type-uuid ");
384 printf("malformed uuid (expected 2 or 16 octets)\n");
385 p_indent(level, frm);
386 raw_dump(level, frm);
390 static void att_read_by_type_resp_dump(int level, struct frame *frm)
392 uint8_t length = p_get_u8(frm);
394 p_indent(level, frm);
395 printf("length: %d\n", length);
397 while (frm->len > 0) {
398 uint16_t handle = btohs(htons(p_get_u16(frm)));
399 int val_len = length - 2;
402 p_indent(level + 1, frm);
403 printf("handle 0x%4.4x, value ", handle);
404 for (i = 0; i < val_len; i++) {
405 printf("0x%.2x ", p_get_u8(frm));
411 static void att_read_req_dump(int level, struct frame *frm)
413 uint16_t handle = btohs(htons(p_get_u16(frm)));
415 p_indent(level, frm);
416 printf("handle 0x%4.4x\n", handle);
419 static void att_read_blob_req_dump(int level, struct frame *frm)
421 uint16_t handle = btohs(htons(p_get_u16(frm)));
422 uint16_t offset = btohs(htons(p_get_u16(frm)));
424 p_indent(level, frm);
425 printf("handle 0x%4.4x offset 0x%4.4x\n", handle, offset);
428 static void att_read_blob_resp_dump(int level, struct frame *frm)
430 p_indent(level, frm);
434 printf(" 0x%2.2x", p_get_u8(frm));
438 static void att_read_multi_req_dump(int level, struct frame *frm)
440 p_indent(level, frm);
443 while (frm->len > 0) {
444 p_indent(level, frm);
445 printf("handle 0x%4.4x\n", btohs(htons(p_get_u16(frm))));
449 static void att_read_multi_resp_dump(int level, struct frame *frm)
451 p_indent(level, frm);
455 printf(" 0x%2.2x", p_get_u8(frm));
459 static void att_read_by_group_resp_dump(int level, struct frame *frm)
461 uint8_t length = p_get_u8(frm);
463 while (frm->len > 0) {
464 uint16_t attr_handle = btohs(htons(p_get_u16(frm)));
465 uint16_t end_grp_handle = btohs(htons(p_get_u16(frm)));
466 uint8_t remaining = length - 4;
468 p_indent(level, frm);
469 printf("attr handle 0x%4.4x, end group handle 0x%4.4x\n",
470 attr_handle, end_grp_handle);
472 p_indent(level, frm);
474 while (remaining > 0) {
475 printf(" 0x%2.2x", p_get_u8(frm));
482 static void att_write_req_dump(int level, struct frame *frm)
484 uint16_t handle = btohs(htons(p_get_u16(frm)));
486 p_indent(level, frm);
487 printf("handle 0x%4.4x value ", handle);
490 printf(" 0x%2.2x", p_get_u8(frm));
494 static void att_signed_write_dump(int level, struct frame *frm)
496 uint16_t handle = btohs(htons(p_get_u16(frm)));
497 int value_len = frm->len - 12; /* handle:2 already accounted, sig: 12 */
499 p_indent(level, frm);
500 printf("handle 0x%4.4x value ", handle);
503 printf(" 0x%2.2x", p_get_u8(frm));
506 p_indent(level, frm);
507 printf("auth signature ");
509 printf(" 0x%2.2x", p_get_u8(frm));
513 static void att_prep_write_dump(int level, struct frame *frm)
515 uint16_t handle = btohs(htons(p_get_u16(frm)));
516 uint16_t val_offset = btohs(htons(p_get_u16(frm)));
518 p_indent(level, frm);
519 printf("attr handle 0x%4.4x, value offset 0x%4.4x\n", handle,
522 p_indent(level, frm);
523 printf("part attr value ");
525 printf(" 0x%2.2x", p_get_u8(frm));
529 static void att_exec_write_req_dump(int level, struct frame *frm)
531 uint8_t flags = p_get_u8(frm);
533 p_indent(level, frm);
535 printf("cancel all prepared writes ");
537 printf("immediatelly write all pending prepared values ");
539 printf("(0x%2.2x)\n", flags);
542 static void att_handle_notify_dump(int level, struct frame *frm)
544 uint16_t handle = btohs(htons(p_get_u16(frm)));
546 p_indent(level, frm);
547 printf("handle 0x%4.4x\n", handle);
549 p_indent(level, frm);
552 printf("0x%.2x ", p_get_u8(frm));
556 void att_dump(int level, struct frame *frm)
562 p_indent(level, frm);
563 printf("ATT: %s (0x%.2x)\n", attop2str(op), op);
567 att_error_dump(level + 1, frm);
570 att_mtu_req_dump(level + 1, frm);
572 case ATT_OP_MTU_RESP:
573 att_mtu_resp_dump(level + 1, frm);
575 case ATT_OP_FIND_INFO_REQ:
576 att_find_info_req_dump(level + 1, frm);
578 case ATT_OP_FIND_INFO_RESP:
579 att_find_info_resp_dump(level + 1, frm);
581 case ATT_OP_FIND_BY_TYPE_REQ:
582 att_find_by_type_req_dump(level + 1, frm);
584 case ATT_OP_FIND_BY_TYPE_RESP:
585 att_find_by_type_resp_dump(level + 1, frm);
587 case ATT_OP_READ_BY_TYPE_REQ:
588 case ATT_OP_READ_BY_GROUP_REQ: /* exact same parsing */
589 att_read_by_type_req_dump(level + 1, frm);
591 case ATT_OP_READ_BY_TYPE_RESP:
592 att_read_by_type_resp_dump(level + 1, frm);
594 case ATT_OP_READ_REQ:
595 att_read_req_dump(level + 1, frm);
597 case ATT_OP_READ_RESP:
598 raw_dump(level + 1, frm);
600 case ATT_OP_READ_BLOB_REQ:
601 att_read_blob_req_dump(level + 1, frm);
603 case ATT_OP_READ_BLOB_RESP:
604 att_read_blob_resp_dump(level + 1, frm);
606 case ATT_OP_READ_MULTI_REQ:
607 att_read_multi_req_dump(level + 1, frm);
609 case ATT_OP_READ_MULTI_RESP:
610 att_read_multi_resp_dump(level + 1, frm);
612 case ATT_OP_READ_BY_GROUP_RESP:
613 att_read_by_group_resp_dump(level + 1, frm);
615 case ATT_OP_WRITE_REQ:
616 case ATT_OP_WRITE_CMD:
617 att_write_req_dump(level + 1, frm);
619 case ATT_OP_SIGNED_WRITE_CMD:
620 att_signed_write_dump(level + 1, frm);
622 case ATT_OP_PREP_WRITE_REQ:
623 case ATT_OP_PREP_WRITE_RESP:
624 att_prep_write_dump(level + 1, frm);
626 case ATT_OP_EXEC_WRITE_REQ:
627 att_exec_write_req_dump(level + 1, frm);
629 case ATT_OP_HANDLE_NOTIFY:
630 att_handle_notify_dump(level + 1, frm);
633 raw_dump(level, frm);