Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / tools / parser / att.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2011  AndrĂ© Dieb Martins <andre.dieb@gmail.com>
6  *
7  *
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.
12  *
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.
17  *
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
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "parser.h"
35
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
40
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
47
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
54
55
56
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
86
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
106
107
108 /* Attribute Protocol Opcodes */
109 static const char *attop2str(uint8_t op)
110 {
111         switch (op) {
112         case ATT_OP_ERROR:
113                 return "Error";
114         case ATT_OP_MTU_REQ:
115                 return "MTU req";
116         case ATT_OP_MTU_RESP:
117                 return "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:
131                 return "Read req";
132         case ATT_OP_READ_RESP:
133                 return "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:
147                 return "Write req";
148         case ATT_OP_WRITE_RESP:
149                 return "Write resp";
150         case ATT_OP_WRITE_CMD:
151                 return "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:
165                 return "Handle CNF";
166         case ATT_OP_SIGNED_WRITE_CMD:
167                 return "Signed Write Cmd";
168         default:
169                 return "Unknown";
170         }
171 }
172
173 static const char * atterror2str(uint8_t err)
174 {
175         switch (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";
210         case ATT_ECODE_IO:
211                 return "Application Error";
212         default:
213                 return "Reserved";
214         }
215 }
216
217 static const char *uuid2str(uint16_t uuid)
218 {
219         switch (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";
252         default:
253                 return "Unknown";
254         }
255 }
256
257 static void att_error_dump(int level, struct frame *frm)
258 {
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);
262
263         p_indent(level, frm);
264         printf("Error: %s (%d)\n", atterror2str(err), err);
265
266         p_indent(level, frm);
267         printf("%s (0x%.2x) on handle 0x%4.4x\n", attop2str(op), op, handle);
268 }
269
270 static void att_mtu_req_dump(int level, struct frame *frm)
271 {
272         uint16_t client_rx_mtu = btohs(htons(p_get_u16(frm)));
273
274         p_indent(level, frm);
275         printf("client rx mtu %d\n", client_rx_mtu);
276 }
277
278 static void att_mtu_resp_dump(int level, struct frame *frm)
279 {
280         uint16_t server_rx_mtu = btohs(htons(p_get_u16(frm)));
281
282         p_indent(level, frm);
283         printf("server rx mtu %d\n", server_rx_mtu);
284 }
285
286 static void att_find_info_req_dump(int level, struct frame *frm)
287 {
288         uint16_t start = btohs(htons(p_get_u16(frm)));
289         uint16_t end = btohs(htons(p_get_u16(frm)));
290
291         p_indent(level, frm);
292         printf("start 0x%4.4x, end 0x%4.4x\n", start, end);
293 }
294
295 static void print_uuid128(struct frame *frm)
296 {
297         uint8_t uuid[16];
298         int i;
299
300         for (i = 0; i < 16; i++)
301                 uuid[15 - i] = p_get_u8(frm);
302
303         for (i = 0; i < 16; i++) {
304                 printf("%02x", uuid[i]);
305                 if (i == 3 || i == 5 || i == 7 || i == 9)
306                         printf("-");
307         }
308 }
309
310 static void att_find_info_resp_dump(int level, struct frame *frm)
311 {
312         uint8_t fmt = p_get_u8(frm);
313
314         p_indent(level, frm);
315
316         if (fmt == 0x01) {
317                 printf("format: uuid-16\n");
318
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,
324                                         uuid2str(uuid));
325                 }
326         } else {
327                 printf("format: uuid-128\n");
328
329                 while (frm->len > 0) {
330                         uint16_t handle = btohs(htons(p_get_u16(frm)));
331
332                         p_indent(level + 1, frm);
333                         printf("handle 0x%4.4x, uuid ", handle);
334                         print_uuid128(frm);
335                         printf("\n");
336                 }
337         }
338 }
339
340 static void att_find_by_type_req_dump(int level, struct frame *frm)
341 {
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)));
345
346         p_indent(level, frm);
347         printf("start 0x%4.4x, end 0x%4.4x, uuid 0x%4.4x\n", start, end, uuid);
348
349         p_indent(level, frm);
350         printf("value");
351         while (frm->len > 0)
352                 printf(" 0x%2.2x", p_get_u8(frm));
353         printf("\n");
354 }
355
356 static void att_find_by_type_resp_dump(int level, struct frame *frm)
357 {
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)));
361
362                 p_indent(level, frm);
363                 printf("Found attr 0x%4.4x, group end handle 0x%4.4x\n",
364                                                                 uuid, end);
365         }
366 }
367
368 static void att_read_by_type_req_dump(int level, struct frame *frm)
369 {
370         uint16_t start = btohs(htons(p_get_u16(frm)));
371         uint16_t end = btohs(htons(p_get_u16(frm)));
372
373         p_indent(level, frm);
374         printf("start 0x%4.4x, end 0x%4.4x\n", start, end);
375
376         p_indent(level, frm);
377         if (frm->len == 2) {
378                 printf("type-uuid 0x%4.4x\n", btohs(htons(p_get_u16(frm))));
379         } else if (frm->len == 16) {
380                 printf("type-uuid ");
381                 print_uuid128(frm);
382                 printf("\n");
383         } else {
384                 printf("malformed uuid (expected 2 or 16 octets)\n");
385                 p_indent(level, frm);
386                 raw_dump(level, frm);
387         }
388 }
389
390 static void att_read_by_type_resp_dump(int level, struct frame *frm)
391 {
392         uint8_t length = p_get_u8(frm);
393
394         p_indent(level, frm);
395         printf("length: %d\n", length);
396
397         while (frm->len > 0) {
398                 uint16_t handle = btohs(htons(p_get_u16(frm)));
399                 int val_len = length - 2;
400                 int i;
401
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));
406                 }
407                 printf("\n");
408         }
409 }
410
411 static void att_read_req_dump(int level, struct frame *frm)
412 {
413         uint16_t handle = btohs(htons(p_get_u16(frm)));
414
415         p_indent(level, frm);
416         printf("handle 0x%4.4x\n", handle);
417 }
418
419 static void att_read_blob_req_dump(int level, struct frame *frm)
420 {
421         uint16_t handle = btohs(htons(p_get_u16(frm)));
422         uint16_t offset = btohs(htons(p_get_u16(frm)));
423
424         p_indent(level, frm);
425         printf("handle 0x%4.4x offset 0x%4.4x\n", handle, offset);
426 }
427
428 static void att_read_blob_resp_dump(int level, struct frame *frm)
429 {
430         p_indent(level, frm);
431         printf("value");
432
433         while (frm->len > 0)
434                 printf(" 0x%2.2x", p_get_u8(frm));
435         printf("\n");
436 }
437
438 static void att_read_multi_req_dump(int level, struct frame *frm)
439 {
440         p_indent(level, frm);
441         printf("Handles\n");
442
443         while (frm->len > 0) {
444                 p_indent(level, frm);
445                 printf("handle 0x%4.4x\n", btohs(htons(p_get_u16(frm))));
446         }
447 }
448
449 static void att_read_multi_resp_dump(int level, struct frame *frm)
450 {
451         p_indent(level, frm);
452         printf("values");
453
454         while (frm->len > 0)
455                 printf(" 0x%2.2x", p_get_u8(frm));
456         printf("\n");
457 }
458
459 static void att_read_by_group_resp_dump(int level, struct frame *frm)
460 {
461         uint8_t length = p_get_u8(frm);
462
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;
467
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);
471
472                 p_indent(level, frm);
473                 printf("value");
474                 while (remaining > 0) {
475                         printf(" 0x%2.2x", p_get_u8(frm));
476                         remaining--;
477                 }
478                 printf("\n");
479         }
480 }
481
482 static void att_write_req_dump(int level, struct frame *frm)
483 {
484         uint16_t handle = btohs(htons(p_get_u16(frm)));
485
486         p_indent(level, frm);
487         printf("handle 0x%4.4x value ", handle);
488
489         while (frm->len > 0)
490                 printf(" 0x%2.2x", p_get_u8(frm));
491         printf("\n");
492 }
493
494 static void att_signed_write_dump(int level, struct frame *frm)
495 {
496         uint16_t handle = btohs(htons(p_get_u16(frm)));
497         int value_len = frm->len - 12; /* handle:2 already accounted, sig: 12 */
498
499         p_indent(level, frm);
500         printf("handle 0x%4.4x value ", handle);
501
502         while (value_len--)
503                 printf(" 0x%2.2x", p_get_u8(frm));
504         printf("\n");
505
506         p_indent(level, frm);
507         printf("auth signature ");
508         while (frm->len > 0)
509                 printf(" 0x%2.2x", p_get_u8(frm));
510         printf("\n");
511 }
512
513 static void att_prep_write_dump(int level, struct frame *frm)
514 {
515         uint16_t handle = btohs(htons(p_get_u16(frm)));
516         uint16_t val_offset = btohs(htons(p_get_u16(frm)));
517
518         p_indent(level, frm);
519         printf("attr handle 0x%4.4x, value offset 0x%4.4x\n", handle,
520                                                                 val_offset);
521
522         p_indent(level, frm);
523         printf("part attr value ");
524         while (frm->len > 0)
525                 printf(" 0x%2.2x", p_get_u8(frm));
526         printf("\n");
527 }
528
529 static void att_exec_write_req_dump(int level, struct frame *frm)
530 {
531         uint8_t flags = p_get_u8(frm);
532
533         p_indent(level, frm);
534         if (flags == 0x00)
535                 printf("cancel all prepared writes ");
536         else
537                 printf("immediatelly write all pending prepared values ");
538
539         printf("(0x%2.2x)\n", flags);
540 }
541
542 static void att_handle_notify_dump(int level, struct frame *frm)
543 {
544         uint16_t handle = btohs(htons(p_get_u16(frm)));
545
546         p_indent(level, frm);
547         printf("handle 0x%4.4x\n", handle);
548
549         p_indent(level, frm);
550         printf("value ");
551         while (frm->len > 0)
552                 printf("0x%.2x ", p_get_u8(frm));
553         printf("\n");
554 }
555
556 void att_dump(int level, struct frame *frm)
557 {
558         uint8_t op;
559
560         op = p_get_u8(frm);
561
562         p_indent(level, frm);
563         printf("ATT: %s (0x%.2x)\n", attop2str(op), op);
564
565         switch (op) {
566                 case ATT_OP_ERROR:
567                         att_error_dump(level + 1, frm);
568                         break;
569                 case ATT_OP_MTU_REQ:
570                         att_mtu_req_dump(level + 1, frm);
571                         break;
572                 case ATT_OP_MTU_RESP:
573                         att_mtu_resp_dump(level + 1, frm);
574                         break;
575                 case ATT_OP_FIND_INFO_REQ:
576                         att_find_info_req_dump(level + 1, frm);
577                         break;
578                 case ATT_OP_FIND_INFO_RESP:
579                         att_find_info_resp_dump(level + 1, frm);
580                         break;
581                 case ATT_OP_FIND_BY_TYPE_REQ:
582                         att_find_by_type_req_dump(level + 1, frm);
583                         break;
584                 case ATT_OP_FIND_BY_TYPE_RESP:
585                         att_find_by_type_resp_dump(level + 1, frm);
586                         break;
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);
590                         break;
591                 case ATT_OP_READ_BY_TYPE_RESP:
592                         att_read_by_type_resp_dump(level + 1, frm);
593                         break;
594                 case ATT_OP_READ_REQ:
595                         att_read_req_dump(level + 1, frm);
596                         break;
597                 case ATT_OP_READ_RESP:
598                         raw_dump(level + 1, frm);
599                         break;
600                 case ATT_OP_READ_BLOB_REQ:
601                         att_read_blob_req_dump(level + 1, frm);
602                         break;
603                 case ATT_OP_READ_BLOB_RESP:
604                         att_read_blob_resp_dump(level + 1, frm);
605                         break;
606                 case ATT_OP_READ_MULTI_REQ:
607                         att_read_multi_req_dump(level + 1, frm);
608                         break;
609                 case ATT_OP_READ_MULTI_RESP:
610                         att_read_multi_resp_dump(level + 1, frm);
611                         break;
612                 case ATT_OP_READ_BY_GROUP_RESP:
613                         att_read_by_group_resp_dump(level + 1, frm);
614                         break;
615                 case ATT_OP_WRITE_REQ:
616                 case ATT_OP_WRITE_CMD:
617                         att_write_req_dump(level + 1, frm);
618                         break;
619                 case ATT_OP_SIGNED_WRITE_CMD:
620                         att_signed_write_dump(level + 1, frm);
621                         break;
622                 case ATT_OP_PREP_WRITE_REQ:
623                 case ATT_OP_PREP_WRITE_RESP:
624                         att_prep_write_dump(level + 1, frm);
625                         break;
626                 case ATT_OP_EXEC_WRITE_REQ:
627                         att_exec_write_req_dump(level + 1, frm);
628                         break;
629                 case ATT_OP_HANDLE_NOTIFY:
630                         att_handle_notify_dump(level + 1, frm);
631                         break;
632                 default:
633                         raw_dump(level, frm);
634                         break;
635         }
636 }