att.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2011 André Dieb Martins <andre.dieb@gmail.com>
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include "parser.h"
  20. #define GATT_PRIM_SVC_UUID 0x2800
  21. #define GATT_SND_SVC_UUID 0x2801
  22. #define GATT_INCLUDE_UUID 0x2802
  23. #define GATT_CHARAC_UUID 0x2803
  24. #define GATT_CHARAC_DEVICE_NAME 0x2A00
  25. #define GATT_CHARAC_APPEARANCE 0x2A01
  26. #define GATT_CHARAC_PERIPHERAL_PRIV_FLAG 0x2A02
  27. #define GATT_CHARAC_RECONNECTION_ADDRESS 0x2A03
  28. #define GATT_CHARAC_PERIPHERAL_PREF_CONN 0x2A04
  29. #define GATT_CHARAC_SERVICE_CHANGED 0x2A05
  30. #define GATT_CHARAC_EXT_PROPER_UUID 0x2900
  31. #define GATT_CHARAC_USER_DESC_UUID 0x2901
  32. #define GATT_CLIENT_CHARAC_CFG_UUID 0x2902
  33. #define GATT_SERVER_CHARAC_CFG_UUID 0x2903
  34. #define GATT_CHARAC_FMT_UUID 0x2904
  35. #define GATT_CHARAC_AGREG_FMT_UUID 0x2905
  36. /* Attribute Protocol Opcodes */
  37. #define ATT_OP_ERROR 0x01
  38. #define ATT_OP_MTU_REQ 0x02
  39. #define ATT_OP_MTU_RESP 0x03
  40. #define ATT_OP_FIND_INFO_REQ 0x04
  41. #define ATT_OP_FIND_INFO_RESP 0x05
  42. #define ATT_OP_FIND_BY_TYPE_REQ 0x06
  43. #define ATT_OP_FIND_BY_TYPE_RESP 0x07
  44. #define ATT_OP_READ_BY_TYPE_REQ 0x08
  45. #define ATT_OP_READ_BY_TYPE_RESP 0x09
  46. #define ATT_OP_READ_REQ 0x0A
  47. #define ATT_OP_READ_RESP 0x0B
  48. #define ATT_OP_READ_BLOB_REQ 0x0C
  49. #define ATT_OP_READ_BLOB_RESP 0x0D
  50. #define ATT_OP_READ_MULTI_REQ 0x0E
  51. #define ATT_OP_READ_MULTI_RESP 0x0F
  52. #define ATT_OP_READ_BY_GROUP_REQ 0x10
  53. #define ATT_OP_READ_BY_GROUP_RESP 0x11
  54. #define ATT_OP_WRITE_REQ 0x12
  55. #define ATT_OP_WRITE_RESP 0x13
  56. #define ATT_OP_WRITE_CMD 0x52
  57. #define ATT_OP_PREP_WRITE_REQ 0x16
  58. #define ATT_OP_PREP_WRITE_RESP 0x17
  59. #define ATT_OP_EXEC_WRITE_REQ 0x18
  60. #define ATT_OP_EXEC_WRITE_RESP 0x19
  61. #define ATT_OP_HANDLE_NOTIFY 0x1B
  62. #define ATT_OP_HANDLE_IND 0x1D
  63. #define ATT_OP_HANDLE_CNF 0x1E
  64. #define ATT_OP_SIGNED_WRITE_CMD 0xD2
  65. /* Error codes for Error response PDU */
  66. #define ATT_ECODE_INVALID_HANDLE 0x01
  67. #define ATT_ECODE_READ_NOT_PERM 0x02
  68. #define ATT_ECODE_WRITE_NOT_PERM 0x03
  69. #define ATT_ECODE_INVALID_PDU 0x04
  70. #define ATT_ECODE_INSUFF_AUTHEN 0x05
  71. #define ATT_ECODE_REQ_NOT_SUPP 0x06
  72. #define ATT_ECODE_INVALID_OFFSET 0x07
  73. #define ATT_ECODE_INSUFF_AUTHO 0x08
  74. #define ATT_ECODE_PREP_QUEUE_FULL 0x09
  75. #define ATT_ECODE_ATTR_NOT_FOUND 0x0A
  76. #define ATT_ECODE_ATTR_NOT_LONG 0x0B
  77. #define ATT_ECODE_INSUFF_ENCR_KEY_SIZE 0x0C
  78. #define ATT_ECODE_INVAL_ATTR_VALUE_LEN 0x0D
  79. #define ATT_ECODE_UNLIKELY 0x0E
  80. #define ATT_ECODE_INSUFF_ENC 0x0F
  81. #define ATT_ECODE_UNSUPP_GRP_TYPE 0x10
  82. #define ATT_ECODE_INSUFF_RESOURCES 0x11
  83. #define ATT_ECODE_IO 0xFF
  84. /* Attribute Protocol Opcodes */
  85. static const char *attop2str(uint8_t op)
  86. {
  87. switch (op) {
  88. case ATT_OP_ERROR:
  89. return "Error";
  90. case ATT_OP_MTU_REQ:
  91. return "MTU req";
  92. case ATT_OP_MTU_RESP:
  93. return "MTU resp";
  94. case ATT_OP_FIND_INFO_REQ:
  95. return "Find Information req";
  96. case ATT_OP_FIND_INFO_RESP:
  97. return "Find Information resp";
  98. case ATT_OP_FIND_BY_TYPE_REQ:
  99. return "Find By Type req";
  100. case ATT_OP_FIND_BY_TYPE_RESP:
  101. return "Find By Type resp";
  102. case ATT_OP_READ_BY_TYPE_REQ:
  103. return "Read By Type req";
  104. case ATT_OP_READ_BY_TYPE_RESP:
  105. return "Read By Type resp";
  106. case ATT_OP_READ_REQ:
  107. return "Read req";
  108. case ATT_OP_READ_RESP:
  109. return "Read resp";
  110. case ATT_OP_READ_BLOB_REQ:
  111. return "Read Blob req";
  112. case ATT_OP_READ_BLOB_RESP:
  113. return "Read Blob resp";
  114. case ATT_OP_READ_MULTI_REQ:
  115. return "Read Multi req";
  116. case ATT_OP_READ_MULTI_RESP:
  117. return "Read Multi resp";
  118. case ATT_OP_READ_BY_GROUP_REQ:
  119. return "Read By Group req";
  120. case ATT_OP_READ_BY_GROUP_RESP:
  121. return "Read By Group resp";
  122. case ATT_OP_WRITE_REQ:
  123. return "Write req";
  124. case ATT_OP_WRITE_RESP:
  125. return "Write resp";
  126. case ATT_OP_WRITE_CMD:
  127. return "Write cmd";
  128. case ATT_OP_PREP_WRITE_REQ:
  129. return "Prepare Write req";
  130. case ATT_OP_PREP_WRITE_RESP:
  131. return "Prepare Write resp";
  132. case ATT_OP_EXEC_WRITE_REQ:
  133. return "Exec Write req";
  134. case ATT_OP_EXEC_WRITE_RESP:
  135. return "Exec Write resp";
  136. case ATT_OP_HANDLE_NOTIFY:
  137. return "Handle notify";
  138. case ATT_OP_HANDLE_IND:
  139. return "Handle indicate";
  140. case ATT_OP_HANDLE_CNF:
  141. return "Handle CNF";
  142. case ATT_OP_SIGNED_WRITE_CMD:
  143. return "Signed Write Cmd";
  144. default:
  145. return "Unknown";
  146. }
  147. }
  148. static const char * atterror2str(uint8_t err)
  149. {
  150. switch (err) {
  151. case ATT_ECODE_INVALID_HANDLE:
  152. return "Invalid handle";
  153. case ATT_ECODE_READ_NOT_PERM:
  154. return "Read not permitted";
  155. case ATT_ECODE_WRITE_NOT_PERM:
  156. return "Write not permitted";
  157. case ATT_ECODE_INVALID_PDU:
  158. return "Invalid PDU";
  159. case ATT_ECODE_INSUFF_AUTHEN:
  160. return "Insufficient authentication";
  161. case ATT_ECODE_REQ_NOT_SUPP:
  162. return "Request not supported";
  163. case ATT_ECODE_INVALID_OFFSET:
  164. return "Invalid offset";
  165. case ATT_ECODE_INSUFF_AUTHO:
  166. return "Insufficient authorization";
  167. case ATT_ECODE_PREP_QUEUE_FULL:
  168. return "Prepare queue full";
  169. case ATT_ECODE_ATTR_NOT_FOUND:
  170. return "Attribute not found";
  171. case ATT_ECODE_ATTR_NOT_LONG:
  172. return "Attribute not long";
  173. case ATT_ECODE_INSUFF_ENCR_KEY_SIZE:
  174. return "Insufficient encryption key size";
  175. case ATT_ECODE_INVAL_ATTR_VALUE_LEN:
  176. return "Invalid attribute value length";
  177. case ATT_ECODE_UNLIKELY:
  178. return "Unlikely error";
  179. case ATT_ECODE_INSUFF_ENC:
  180. return "Insufficient encryption";
  181. case ATT_ECODE_UNSUPP_GRP_TYPE:
  182. return "Unsupported group type";
  183. case ATT_ECODE_INSUFF_RESOURCES:
  184. return "Insufficient resources";
  185. case ATT_ECODE_IO:
  186. return "Application Error";
  187. default:
  188. return "Reserved";
  189. }
  190. }
  191. static const char *uuid2str(uint16_t uuid)
  192. {
  193. switch (uuid) {
  194. case GATT_PRIM_SVC_UUID:
  195. return "GATT Primary Service";
  196. case GATT_SND_SVC_UUID:
  197. return "GATT Secondary Service";
  198. case GATT_INCLUDE_UUID:
  199. return "GATT Include";
  200. case GATT_CHARAC_UUID:
  201. return "GATT Characteristic";
  202. case GATT_CHARAC_DEVICE_NAME:
  203. return "GATT(type) Device Name";
  204. case GATT_CHARAC_APPEARANCE:
  205. return "GATT(type) Appearance";
  206. case GATT_CHARAC_PERIPHERAL_PRIV_FLAG:
  207. return "GATT(type) Peripheral Privacy Flag";
  208. case GATT_CHARAC_RECONNECTION_ADDRESS:
  209. return "GATT(type) Characteristic Reconnection Address";
  210. case GATT_CHARAC_PERIPHERAL_PREF_CONN:
  211. return "GATT(type) Characteristic Preferred Connection Parameters";
  212. case GATT_CHARAC_SERVICE_CHANGED:
  213. return "GATT(type) Characteristic Service Changed";
  214. case GATT_CHARAC_EXT_PROPER_UUID:
  215. return "GATT(desc) Characteristic Extended Properties";
  216. case GATT_CHARAC_USER_DESC_UUID:
  217. return "GATT(desc) User Description";
  218. case GATT_CLIENT_CHARAC_CFG_UUID:
  219. return "GATT(desc) Client Characteristic Configuration";
  220. case GATT_SERVER_CHARAC_CFG_UUID:
  221. return "GATT(desc) Server Characteristic Configuration";
  222. case GATT_CHARAC_FMT_UUID:
  223. return "GATT(desc) Format";
  224. case GATT_CHARAC_AGREG_FMT_UUID:
  225. return "GATT(desc) Aggregate Format";
  226. default:
  227. return "Unknown";
  228. }
  229. }
  230. static void att_error_dump(int level, struct frame *frm)
  231. {
  232. uint8_t op = p_get_u8(frm);
  233. uint16_t handle = btohs(htons(p_get_u16(frm)));
  234. uint8_t err = p_get_u8(frm);
  235. p_indent(level, frm);
  236. printf("Error: %s (%d)\n", atterror2str(err), err);
  237. p_indent(level, frm);
  238. printf("%s (0x%.2x) on handle 0x%4.4x\n", attop2str(op), op, handle);
  239. }
  240. static void att_mtu_req_dump(int level, struct frame *frm)
  241. {
  242. uint16_t client_rx_mtu = btohs(htons(p_get_u16(frm)));
  243. p_indent(level, frm);
  244. printf("client rx mtu %d\n", client_rx_mtu);
  245. }
  246. static void att_mtu_resp_dump(int level, struct frame *frm)
  247. {
  248. uint16_t server_rx_mtu = btohs(htons(p_get_u16(frm)));
  249. p_indent(level, frm);
  250. printf("server rx mtu %d\n", server_rx_mtu);
  251. }
  252. static void att_find_info_req_dump(int level, struct frame *frm)
  253. {
  254. uint16_t start = btohs(htons(p_get_u16(frm)));
  255. uint16_t end = btohs(htons(p_get_u16(frm)));
  256. p_indent(level, frm);
  257. printf("start 0x%4.4x, end 0x%4.4x\n", start, end);
  258. }
  259. static void print_uuid128(struct frame *frm)
  260. {
  261. uint8_t uuid[16];
  262. int i;
  263. for (i = 0; i < 16; i++)
  264. uuid[15 - i] = p_get_u8(frm);
  265. for (i = 0; i < 16; i++) {
  266. printf("%02x", uuid[i]);
  267. if (i == 3 || i == 5 || i == 7 || i == 9)
  268. printf("-");
  269. }
  270. }
  271. static void att_find_info_resp_dump(int level, struct frame *frm)
  272. {
  273. uint8_t fmt = p_get_u8(frm);
  274. p_indent(level, frm);
  275. if (fmt == 0x01) {
  276. printf("format: uuid-16\n");
  277. while (frm->len > 0) {
  278. uint16_t handle = btohs(htons(p_get_u16(frm)));
  279. uint16_t uuid = btohs(htons(p_get_u16(frm)));
  280. p_indent(level + 1, frm);
  281. printf("handle 0x%4.4x, uuid 0x%4.4x (%s)\n", handle, uuid,
  282. uuid2str(uuid));
  283. }
  284. } else {
  285. printf("format: uuid-128\n");
  286. while (frm->len > 0) {
  287. uint16_t handle = btohs(htons(p_get_u16(frm)));
  288. p_indent(level + 1, frm);
  289. printf("handle 0x%4.4x, uuid ", handle);
  290. print_uuid128(frm);
  291. printf("\n");
  292. }
  293. }
  294. }
  295. static void att_find_by_type_req_dump(int level, struct frame *frm)
  296. {
  297. uint16_t start = btohs(htons(p_get_u16(frm)));
  298. uint16_t end = btohs(htons(p_get_u16(frm)));
  299. uint16_t uuid = btohs(htons(p_get_u16(frm)));
  300. p_indent(level, frm);
  301. printf("start 0x%4.4x, end 0x%4.4x, uuid 0x%4.4x\n", start, end, uuid);
  302. p_indent(level, frm);
  303. printf("value");
  304. while (frm->len > 0)
  305. printf(" 0x%2.2x", p_get_u8(frm));
  306. printf("\n");
  307. }
  308. static void att_find_by_type_resp_dump(int level, struct frame *frm)
  309. {
  310. while (frm->len > 0) {
  311. uint16_t uuid = btohs(htons(p_get_u16(frm)));
  312. uint16_t end = btohs(htons(p_get_u16(frm)));
  313. p_indent(level, frm);
  314. printf("Found attr 0x%4.4x, group end handle 0x%4.4x\n",
  315. uuid, end);
  316. }
  317. }
  318. static void att_read_by_type_req_dump(int level, struct frame *frm)
  319. {
  320. uint16_t start = btohs(htons(p_get_u16(frm)));
  321. uint16_t end = btohs(htons(p_get_u16(frm)));
  322. p_indent(level, frm);
  323. printf("start 0x%4.4x, end 0x%4.4x\n", start, end);
  324. p_indent(level, frm);
  325. if (frm->len == 2) {
  326. printf("type-uuid 0x%4.4x\n", btohs(htons(p_get_u16(frm))));
  327. } else if (frm->len == 16) {
  328. printf("type-uuid ");
  329. print_uuid128(frm);
  330. printf("\n");
  331. } else {
  332. printf("malformed uuid (expected 2 or 16 octets)\n");
  333. p_indent(level, frm);
  334. raw_dump(level, frm);
  335. }
  336. }
  337. static void att_read_by_type_resp_dump(int level, struct frame *frm)
  338. {
  339. uint8_t length = p_get_u8(frm);
  340. p_indent(level, frm);
  341. printf("length: %d\n", length);
  342. while (frm->len > 0) {
  343. uint16_t handle = btohs(htons(p_get_u16(frm)));
  344. int val_len = length - 2;
  345. int i;
  346. p_indent(level + 1, frm);
  347. printf("handle 0x%4.4x, value ", handle);
  348. for (i = 0; i < val_len; i++) {
  349. printf("0x%.2x ", p_get_u8(frm));
  350. }
  351. printf("\n");
  352. }
  353. }
  354. static void att_read_req_dump(int level, struct frame *frm)
  355. {
  356. uint16_t handle = btohs(htons(p_get_u16(frm)));
  357. p_indent(level, frm);
  358. printf("handle 0x%4.4x\n", handle);
  359. }
  360. static void att_read_blob_req_dump(int level, struct frame *frm)
  361. {
  362. uint16_t handle = btohs(htons(p_get_u16(frm)));
  363. uint16_t offset = btohs(htons(p_get_u16(frm)));
  364. p_indent(level, frm);
  365. printf("handle 0x%4.4x offset 0x%4.4x\n", handle, offset);
  366. }
  367. static void att_read_blob_resp_dump(int level, struct frame *frm)
  368. {
  369. p_indent(level, frm);
  370. printf("value");
  371. while (frm->len > 0)
  372. printf(" 0x%2.2x", p_get_u8(frm));
  373. printf("\n");
  374. }
  375. static void att_read_multi_req_dump(int level, struct frame *frm)
  376. {
  377. p_indent(level, frm);
  378. printf("Handles\n");
  379. while (frm->len > 0) {
  380. p_indent(level, frm);
  381. printf("handle 0x%4.4x\n", btohs(htons(p_get_u16(frm))));
  382. }
  383. }
  384. static void att_read_multi_resp_dump(int level, struct frame *frm)
  385. {
  386. p_indent(level, frm);
  387. printf("values");
  388. while (frm->len > 0)
  389. printf(" 0x%2.2x", p_get_u8(frm));
  390. printf("\n");
  391. }
  392. static void att_read_by_group_resp_dump(int level, struct frame *frm)
  393. {
  394. uint8_t length = p_get_u8(frm);
  395. while (frm->len > 0) {
  396. uint16_t attr_handle = btohs(htons(p_get_u16(frm)));
  397. uint16_t end_grp_handle = btohs(htons(p_get_u16(frm)));
  398. uint8_t remaining = length - 4;
  399. p_indent(level, frm);
  400. printf("attr handle 0x%4.4x, end group handle 0x%4.4x\n",
  401. attr_handle, end_grp_handle);
  402. p_indent(level, frm);
  403. printf("value");
  404. while (remaining > 0) {
  405. printf(" 0x%2.2x", p_get_u8(frm));
  406. remaining--;
  407. }
  408. printf("\n");
  409. }
  410. }
  411. static void att_write_req_dump(int level, struct frame *frm)
  412. {
  413. uint16_t handle = btohs(htons(p_get_u16(frm)));
  414. p_indent(level, frm);
  415. printf("handle 0x%4.4x value ", handle);
  416. while (frm->len > 0)
  417. printf(" 0x%2.2x", p_get_u8(frm));
  418. printf("\n");
  419. }
  420. static void att_signed_write_dump(int level, struct frame *frm)
  421. {
  422. uint16_t handle = btohs(htons(p_get_u16(frm)));
  423. int value_len = frm->len - 12; /* handle:2 already accounted, sig: 12 */
  424. p_indent(level, frm);
  425. printf("handle 0x%4.4x value ", handle);
  426. while (value_len--)
  427. printf(" 0x%2.2x", p_get_u8(frm));
  428. printf("\n");
  429. p_indent(level, frm);
  430. printf("auth signature ");
  431. while (frm->len > 0)
  432. printf(" 0x%2.2x", p_get_u8(frm));
  433. printf("\n");
  434. }
  435. static void att_prep_write_dump(int level, struct frame *frm)
  436. {
  437. uint16_t handle = btohs(htons(p_get_u16(frm)));
  438. uint16_t val_offset = btohs(htons(p_get_u16(frm)));
  439. p_indent(level, frm);
  440. printf("attr handle 0x%4.4x, value offset 0x%4.4x\n", handle,
  441. val_offset);
  442. p_indent(level, frm);
  443. printf("part attr value ");
  444. while (frm->len > 0)
  445. printf(" 0x%2.2x", p_get_u8(frm));
  446. printf("\n");
  447. }
  448. static void att_exec_write_req_dump(int level, struct frame *frm)
  449. {
  450. uint8_t flags = p_get_u8(frm);
  451. p_indent(level, frm);
  452. if (flags == 0x00)
  453. printf("cancel all prepared writes ");
  454. else
  455. printf("immediatelly write all pending prepared values ");
  456. printf("(0x%2.2x)\n", flags);
  457. }
  458. static void att_handle_notify_dump(int level, struct frame *frm)
  459. {
  460. uint16_t handle = btohs(htons(p_get_u16(frm)));
  461. p_indent(level, frm);
  462. printf("handle 0x%4.4x\n", handle);
  463. p_indent(level, frm);
  464. printf("value ");
  465. while (frm->len > 0)
  466. printf("0x%.2x ", p_get_u8(frm));
  467. printf("\n");
  468. }
  469. void att_dump(int level, struct frame *frm)
  470. {
  471. uint8_t op;
  472. op = p_get_u8(frm);
  473. p_indent(level, frm);
  474. printf("ATT: %s (0x%.2x)\n", attop2str(op), op);
  475. switch (op) {
  476. case ATT_OP_ERROR:
  477. att_error_dump(level + 1, frm);
  478. break;
  479. case ATT_OP_MTU_REQ:
  480. att_mtu_req_dump(level + 1, frm);
  481. break;
  482. case ATT_OP_MTU_RESP:
  483. att_mtu_resp_dump(level + 1, frm);
  484. break;
  485. case ATT_OP_FIND_INFO_REQ:
  486. att_find_info_req_dump(level + 1, frm);
  487. break;
  488. case ATT_OP_FIND_INFO_RESP:
  489. att_find_info_resp_dump(level + 1, frm);
  490. break;
  491. case ATT_OP_FIND_BY_TYPE_REQ:
  492. att_find_by_type_req_dump(level + 1, frm);
  493. break;
  494. case ATT_OP_FIND_BY_TYPE_RESP:
  495. att_find_by_type_resp_dump(level + 1, frm);
  496. break;
  497. case ATT_OP_READ_BY_TYPE_REQ:
  498. case ATT_OP_READ_BY_GROUP_REQ: /* exact same parsing */
  499. att_read_by_type_req_dump(level + 1, frm);
  500. break;
  501. case ATT_OP_READ_BY_TYPE_RESP:
  502. att_read_by_type_resp_dump(level + 1, frm);
  503. break;
  504. case ATT_OP_READ_REQ:
  505. att_read_req_dump(level + 1, frm);
  506. break;
  507. case ATT_OP_READ_RESP:
  508. raw_dump(level + 1, frm);
  509. break;
  510. case ATT_OP_READ_BLOB_REQ:
  511. att_read_blob_req_dump(level + 1, frm);
  512. break;
  513. case ATT_OP_READ_BLOB_RESP:
  514. att_read_blob_resp_dump(level + 1, frm);
  515. break;
  516. case ATT_OP_READ_MULTI_REQ:
  517. att_read_multi_req_dump(level + 1, frm);
  518. break;
  519. case ATT_OP_READ_MULTI_RESP:
  520. att_read_multi_resp_dump(level + 1, frm);
  521. break;
  522. case ATT_OP_READ_BY_GROUP_RESP:
  523. att_read_by_group_resp_dump(level + 1, frm);
  524. break;
  525. case ATT_OP_WRITE_REQ:
  526. case ATT_OP_WRITE_CMD:
  527. att_write_req_dump(level + 1, frm);
  528. break;
  529. case ATT_OP_SIGNED_WRITE_CMD:
  530. att_signed_write_dump(level + 1, frm);
  531. break;
  532. case ATT_OP_PREP_WRITE_REQ:
  533. case ATT_OP_PREP_WRITE_RESP:
  534. att_prep_write_dump(level + 1, frm);
  535. break;
  536. case ATT_OP_EXEC_WRITE_REQ:
  537. att_exec_write_req_dump(level + 1, frm);
  538. break;
  539. case ATT_OP_HANDLE_NOTIFY:
  540. att_handle_notify_dump(level + 1, frm);
  541. break;
  542. default:
  543. raw_dump(level, frm);
  544. break;
  545. }
  546. }