static inline bool mcc_msc(struct rfcomm_frame *rfcomm_frame, uint8_t indent) { struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame; struct rfcomm_lmsc msc; if (!l2cap_frame_get_u8(frame, &msc.dlci)) return false; print_field("%*cdlci %d ", indent, ' ', RFCOMM_GET_DLCI(msc.dlci)); if (!l2cap_frame_get_u8(frame, &msc.v24_sig)) return false; /* v24 control signals */ print_field("%*cfc %d rtc %d rtr %d ic %d dv %d", indent, ' ', GET_V24_FC(msc.v24_sig), GET_V24_RTC(msc.v24_sig), GET_V24_RTR(msc.v24_sig), GET_V24_IC(msc.v24_sig), GET_V24_DV(msc.v24_sig)); if (frame->size < 2) goto done; /* * TODO: Implement the break signals decoding. */ packet_hexdump(frame->data, frame->size); done: return true; }
static void rfcomm_disc_recv(struct bthost *bthost, struct btconn *conn, struct l2conn *l2conn, const void *data, uint16_t len) { const struct rfcomm_cmd *hdr = data; uint8_t dlci = RFCOMM_GET_DLCI(hdr->address); rfcomm_ua_send(bthost, conn, l2conn, 0, dlci); }
static inline bool mcc_rpn(struct rfcomm_frame *rfcomm_frame, uint8_t indent) { struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame; struct rfcomm_rpn rpn; if (!l2cap_frame_get_u8(frame, &rpn.dlci)) return false; print_field("%*cdlci %d", indent, ' ', RFCOMM_GET_DLCI(rpn.dlci)); if (frame->size < 7) goto done; /* port value octets (optional) */ if (!l2cap_frame_get_u8(frame, &rpn.bit_rate)) return false; if (!l2cap_frame_get_u8(frame, &rpn.parity)) return false; if (!l2cap_frame_get_u8(frame, &rpn.io)) return false; print_field("%*cbr %d db %d sb %d p %d pt %d xi %d xo %d", indent, ' ', rpn.bit_rate, GET_RPN_DB(rpn.parity), GET_RPN_SB(rpn.parity), GET_RPN_PARITY(rpn.parity), GET_RPN_PTYPE(rpn.parity), GET_RPN_XIN(rpn.io), GET_RPN_XOUT(rpn.io)); if (!l2cap_frame_get_u8(frame, &rpn.xon)) return false; if (!l2cap_frame_get_u8(frame, &rpn.xoff)) return false; print_field("%*crtri %d rtro %d rtci %d rtco %d xon %d xoff %d", indent, ' ', GET_RPN_RTRI(rpn.io), GET_RPN_RTRO(rpn.io), GET_RPN_RTCI(rpn.io), GET_RPN_RTCO(rpn.io), rpn.xon, rpn.xoff); if (!l2cap_frame_get_le16(frame, &rpn.pm)) return false; print_field("%*cpm 0x%04x", indent, ' ', rpn.pm); done: return true; }
static inline bool mcc_rls(struct rfcomm_frame *rfcomm_frame, uint8_t indent) { struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame; struct rfcomm_rls rls; if (!l2cap_frame_get_u8(frame, &rls.dlci)) return false; if (!l2cap_frame_get_u8(frame, &rls.error)) return false; print_field("%*cdlci %d error: %d", indent, ' ', RFCOMM_GET_DLCI(rls.dlci), GET_ERROR(rls.error)); return true; }
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 void print_rfcomm_hdr(struct rfcomm_frame *rfcomm_frame, uint8_t indent) { struct rfcomm_lhdr hdr = rfcomm_frame->hdr; /* Address field */ print_field("%*cAddress: 0x%2.2x cr %d dlci 0x%2.2x", indent, ' ', hdr.address, GET_CR(hdr.address), RFCOMM_GET_DLCI(hdr.address)); /* Control field */ print_field("%*cControl: 0x%2.2x poll/final %d", indent, ' ', hdr.control, GET_PF(hdr.control)); /* Length and FCS */ print_field("%*cLength: %d", indent, ' ', hdr.length); print_field("%*cFCS: 0x%2.2x", indent, ' ', hdr.fcs); }
static void rfcomm_sabm_recv(struct bthost *bthost, struct btconn *conn, struct l2conn *l2conn, const void *data, uint16_t len) { const struct rfcomm_cmd *hdr = data; uint8_t dlci = RFCOMM_GET_DLCI(hdr->address); struct rfcomm_conn_cb_data *cb; uint8_t chan = RFCOMM_GET_CHANNEL(hdr->address); cb = bthost_find_rfcomm_cb_by_channel(bthost, chan); if (!dlci || cb) { rfcomm_ua_send(bthost, conn, l2conn, 1, dlci); if (cb && cb->func) cb->func(conn->handle, l2conn->scid, cb->user_data, true); } else { rfcomm_dm_send(bthost, conn, l2conn, 1, dlci); } }