static void rfcomm_uih_recv(struct bthost *bthost, struct btconn *conn, struct l2conn *l2conn, const void *data, uint16_t len) { const struct rfcomm_cmd *hdr = data; const void *p; if (RFCOMM_GET_DLCI(hdr->address)) return; if (RFCOMM_TEST_EA(hdr->length)) p = data + sizeof(struct rfcomm_hdr); else p = data + sizeof(struct rfcomm_hdr) + sizeof(uint8_t); rfcomm_mcc_recv(bthost, conn, l2conn, p, p - data); }
static inline bool mcc_frame(struct rfcomm_frame *rfcomm_frame, uint8_t indent) { uint8_t length, ex_length, type; const char *type_str; int i; struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame; struct rfcomm_lmcc mcc; const struct mcc_data *mcc_data = NULL; if (!l2cap_frame_get_u8(frame, &mcc.type) || !l2cap_frame_get_u8(frame, &length)) return false; if (RFCOMM_TEST_EA(length)) mcc.length = (uint16_t) GET_LEN8(length); else { if (!l2cap_frame_get_u8(frame, &ex_length)) return false; mcc.length = ((uint16_t) length << 8) | ex_length; mcc.length = GET_LEN16(mcc.length); } type = RFCOMM_GET_MCC_TYPE(mcc.type); for (i = 0; mcc_table[i].str; i++) { if (mcc_table[i].type == type) { mcc_data = &mcc_table[i]; break; } } if (mcc_data) type_str = mcc_data->str; else type_str = "Unknown"; print_field("%*cMCC Message type: %s %s(0x%2.2x)", indent, ' ', type_str, CR_STR(mcc.type), type); print_field("%*cLength: %d", indent+2, ' ', mcc.length); rfcomm_frame->mcc = mcc; packet_hexdump(frame->data, frame->size); return true; }
void rfcomm_packet(const struct l2cap_frame *frame) { uint8_t ctype, length, ex_length, indent = 1; const char *frame_str, *frame_color; struct l2cap_frame *l2cap_frame, tmp_frame; struct rfcomm_frame rfcomm_frame; struct rfcomm_lhdr hdr; const struct rfcomm_data *rfcomm_data = NULL; int i; l2cap_frame_pull(&rfcomm_frame.l2cap_frame, frame, 0); l2cap_frame = &rfcomm_frame.l2cap_frame; if (frame->size < 4) goto fail; if (!l2cap_frame_get_u8(l2cap_frame, &hdr.address) || !l2cap_frame_get_u8(l2cap_frame, &hdr.control) || !l2cap_frame_get_u8(l2cap_frame, &length)) goto fail; /* length maybe 1 or 2 octets */ if (RFCOMM_TEST_EA(length)) hdr.length = (uint16_t) GET_LEN8(length); else { if (!l2cap_frame_get_u8(l2cap_frame, &ex_length)) goto fail; hdr.length = ((uint16_t)length << 8) | ex_length; hdr.length = GET_LEN16(hdr.length); } l2cap_frame_pull(&tmp_frame, l2cap_frame, l2cap_frame->size-1); if(!l2cap_frame_get_u8(&tmp_frame, &hdr.fcs)) goto fail; /* Decoding frame type */ ctype = RFCOMM_GET_TYPE(hdr.control); for (i = 0; rfcomm_table[i].str; i++) { if (rfcomm_table[i].frame == ctype) { rfcomm_data = &rfcomm_table[i]; break; } } if (rfcomm_data) { if (frame->in) frame_color = COLOR_MAGENTA; else frame_color = COLOR_BLUE; frame_str = rfcomm_data->str; } else { frame_color = COLOR_WHITE_BG; frame_str = "Unknown"; } if (!rfcomm_data) { packet_hexdump(frame->data, frame->size); return; } print_indent(6, frame_color, "RFCOMM: ", frame_str, COLOR_OFF, "(0x%2.2x)", ctype); rfcomm_frame.hdr = hdr; print_rfcomm_hdr(&rfcomm_frame, indent); /* UIH frame */ if (ctype == 0xef) if (!uih_frame(&rfcomm_frame, indent)) goto fail; return; fail: print_text(COLOR_ERROR, "Frame too short"); packet_hexdump(frame->data, frame->size); return; }