Beispiel #1
0
static bool avrcp_set_player_value(struct avctp_frame *avctp_frame,
					uint8_t ctype, uint8_t len,
					uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint8_t num;

	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
		return true;

	if (!l2cap_frame_get_u8(frame, &num))
		return false;

	print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num);

	for (; num > 0; num--) {
		uint8_t attr, value;

		if (!l2cap_frame_get_u8(frame, &attr))
			return false;

		print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ',
							attr, attr2str(attr));

		if (!l2cap_frame_get_u8(frame, &value))
			return false;

		print_field("%*cValueID: 0x%02x (%s)", (indent - 8), ' ',
						value, value2str(attr, value));
	}

	return true;
}
Beispiel #2
0
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;
}
Beispiel #3
0
static bool avrcp_list_player_attributes(struct avctp_frame *avctp_frame,
						uint8_t ctype, uint8_t len,
						uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint8_t num;
	int i;

	if (len == 0)
		return true;

	if (!l2cap_frame_get_u8(frame, &num))
		return false;

	print_field("%*cAttributeCount: 0x%02x", (indent - 8), ' ', num);

	for (i = 0; num > 0; num--, i++) {
		uint8_t attr;

		if (!l2cap_frame_get_u8(frame, &attr))
			return false;

		print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ',
							attr, attr2str(attr));
	}

	return true;
}
Beispiel #4
0
static bool avrcp_displayable_charset(struct avctp_frame *avctp_frame,
					uint8_t ctype, uint8_t len,
					uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint8_t num;

	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
		return true;

	if (!l2cap_frame_get_u8(frame, &num))
		return false;

	print_field("%*cCharsetCount: 0x%02x", (indent - 8), ' ', num);

	for (; num > 0; num--) {
		uint16_t charset;

		if (!l2cap_frame_get_be16(frame, &charset))
			return false;

		print_field("%*cCharsetID: 0x%04x (%s)", (indent - 8),
					' ', charset, charset2str(charset));
	}

	return true;
}
Beispiel #5
0
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;
}
Beispiel #6
0
static bool avrcp_set_addressed_player(struct avctp_frame *avctp_frame,
						uint8_t ctype, uint8_t len,
						uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint16_t id;
	uint8_t status;

	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
		goto response;

	if (!l2cap_frame_get_be16(frame, &id))
		return false;

	print_field("%*cPlayerID: 0x%04x (%u)", (indent - 8), ' ', id, id);

	return true;

response:
	if (!l2cap_frame_get_u8(frame, &status))
		return false;

	print_field("%*cStatus: 0x%02x (%s)", (indent - 8), ' ',
						status, error2str(status));

	return true;
}
Beispiel #7
0
void avctp_packet(const struct l2cap_frame *frame)
{
	struct l2cap_frame *l2cap_frame;
	struct avctp_frame avctp_frame;
	const char *pdu_color;

	l2cap_frame_pull(&avctp_frame.l2cap_frame, frame, 0);

	l2cap_frame = &avctp_frame.l2cap_frame;

	if (!l2cap_frame_get_u8(l2cap_frame, &avctp_frame.hdr) ||
			!l2cap_frame_get_be16(l2cap_frame, &avctp_frame.pid)) {
		print_text(COLOR_ERROR, "frame too short");
		packet_hexdump(frame->data, frame->size);
		return;
	}

	if (frame->in)
		pdu_color = COLOR_MAGENTA;
	else
		pdu_color = COLOR_BLUE;

	print_indent(6, pdu_color, "AVCTP", "", COLOR_OFF,
				" %s: %s: type 0x%02x label %d PID 0x%04x",
				frame->psm == 23 ? "Control" : "Browsing",
				avctp_frame.hdr & 0x02 ? "Response" : "Command",
				avctp_frame.hdr & 0x0c, avctp_frame.hdr >> 4,
				avctp_frame.pid);

	if (avctp_frame.pid == 0x110e || avctp_frame.pid == 0x110c)
		avrcp_packet(&avctp_frame);
	else
		packet_hexdump(frame->data, frame->size);
}
Beispiel #8
0
static bool avrcp_get_play_status(struct avctp_frame *avctp_frame,
					uint8_t ctype, uint8_t len,
					uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint32_t interval;
	uint8_t status;

	if (ctype <= AVC_CTYPE_GENERAL_INQUIRY)
		return true;

	if (!l2cap_frame_get_be32(frame, &interval))
		return false;

	print_field("%*cSongLength: 0x%08x (%u miliseconds)",
					(indent - 8), ' ', interval, interval);

	if (!l2cap_frame_get_be32(frame, &interval))
		return false;

	print_field("%*cSongPosition: 0x%08x (%u miliseconds)",
					(indent - 8), ' ', interval, interval);

	if (!l2cap_frame_get_u8(frame, &status))
		return false;

	print_field("%*cPlayStatus: 0x%02x (%s)", (indent - 8),
					' ', status, playstatus2str(status));

	return true;
}
Beispiel #9
0
void sdp_packet(const struct l2cap_frame *frame)
{
	uint8_t pdu;
	uint16_t tid, plen;
	struct l2cap_frame sdp_frame;
	struct tid_data *tid_info;
	const struct sdp_data *sdp_data = NULL;
	const char *pdu_color, *pdu_str;
	int i;

	l2cap_frame_pull(&sdp_frame, frame, 0);

	if (!l2cap_frame_get_u8(&sdp_frame, &pdu) ||
				!l2cap_frame_get_be16(&sdp_frame, &tid) ||
				!l2cap_frame_get_be16(&sdp_frame, &plen)) {
		print_text(COLOR_ERROR, "frame too short");
		packet_hexdump(frame->data, frame->size);
		return;
	}

	if (sdp_frame.size != plen) {
		print_text(COLOR_ERROR, "invalid frame size");
		packet_hexdump(sdp_frame.data, sdp_frame.size);
		return;
	}

	for (i = 0; sdp_table[i].str; i++) {
		if (sdp_table[i].pdu == pdu) {
			sdp_data = &sdp_table[i];
			break;
		}
	}

	if (sdp_data) {
		if (sdp_data->func) {
			if (frame->in)
				pdu_color = COLOR_MAGENTA;
			else
				pdu_color = COLOR_BLUE;
		} else
			pdu_color = COLOR_WHITE_BG;
		pdu_str = sdp_data->str;
	} else {
		pdu_color = COLOR_WHITE_BG;
		pdu_str = "Unknown";
	}

	print_indent(6, pdu_color, "SDP: ", pdu_str, COLOR_OFF,
				" (0x%2.2x) tid %d len %d", pdu, tid, plen);

	tid_info = get_tid(tid, frame->chan);

	if (!sdp_data || !sdp_data->func || !tid_info) {
		packet_hexdump(sdp_frame.data, sdp_frame.size);
		return;
	}

	sdp_data->func(&sdp_frame, tid_info);
}
Beispiel #10
0
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;
}
Beispiel #11
0
static bool avrcp_pdu_packet(struct avctp_frame *avctp_frame, uint8_t ctype,
								uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint8_t pduid;
	uint16_t len;
	int i;
	const struct avrcp_ctrl_pdu_data *ctrl_pdu_data = NULL;

	if (!l2cap_frame_get_u8(frame, &pduid))
		return false;

	if (!l2cap_frame_get_u8(frame, &avctp_frame->pt))
		return false;

	if (!l2cap_frame_get_be16(frame, &len))
		return false;

	print_indent(indent, COLOR_OFF, "AVRCP: ", pdu2str(pduid), COLOR_OFF,
			" pt %s len 0x%04x", pt2str(avctp_frame->pt), len);

	if (frame->size != len)
		return false;

	if (ctype == 0xA)
		return avrcp_rejected_packet(frame, indent + 2);

	for (i = 0; avrcp_ctrl_pdu_table[i].func; i++) {
		if (avrcp_ctrl_pdu_table[i].pduid == pduid) {
			ctrl_pdu_data = &avrcp_ctrl_pdu_table[i];
			break;
		}
	}

	if (!ctrl_pdu_data || !ctrl_pdu_data->func) {
		packet_hexdump(frame->data, frame->size);
		return true;
	}

	return ctrl_pdu_data->func(avctp_frame, ctype, len, indent + 2);
}
Beispiel #12
0
static bool avrcp_add_to_now_playing(struct avctp_frame *avctp_frame,
						uint8_t ctype, uint8_t len,
						uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint64_t uid;
	uint16_t uidcounter;
	uint8_t scope, status;

	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
		goto response;

	if (!l2cap_frame_get_u8(frame, &scope))
		return false;

	print_field("%*cScope: 0x%02x (%s)", (indent - 8), ' ',
						scope, scope2str(scope));

	if (!l2cap_frame_get_be64(frame, &uid))
		return false;

	print_field("%*cUID: 0x%16" PRIx64 " (%" PRIu64 ")", (indent - 8),
								' ', uid, uid);

	if (!l2cap_frame_get_be16(frame, &uidcounter))
		return false;

	print_field("%*cUIDCounter: 0x%04x (%u)", (indent - 8), ' ',
							uidcounter, uidcounter);

	return true;

response:
	if (!l2cap_frame_get_u8(frame, &status))
		return false;

	print_field("%*cStatus: 0x%02x (%s)", (indent - 8), ' ', status,
							error2str(status));

	return true;
}
Beispiel #13
0
static bool cmd_nt_understood(struct bnep_frame *bnep_frame, uint8_t indent)
{
	struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
	uint8_t ptype;

	if (!l2cap_frame_get_u8(frame, &ptype))
		return false;

	print_field("%*cType: 0x%02x ", indent, ' ', ptype);

	return true;
}
Beispiel #14
0
static bool avrcp_rejected_packet(struct l2cap_frame *frame, uint8_t indent)
{
	uint8_t status;

	if (!l2cap_frame_get_u8(frame, &status))
		return false;

	print_field("%*cError: 0x%02x (%s)", (indent - 8), ' ', status,
							error2str(status));

	return true;
}
Beispiel #15
0
static inline bool mcc_nsc(struct rfcomm_frame *rfcomm_frame, uint8_t indent)
{
	struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame;
	struct rfcomm_nsc nsc;

	if (!l2cap_frame_get_u8(frame, &nsc.cmd_type))
		return false;

	print_field("%*ccr %d, mcc_cmd_type %x", indent, ' ',
		GET_CR(nsc.cmd_type), RFCOMM_GET_MCC_TYPE(nsc.cmd_type));

	return true;
}
Beispiel #16
0
static bool setup_conn_req(struct bnep_frame *bnep_frame, uint8_t indent)
{

	struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
	uint8_t uuid_size;
	uint32_t src_uuid = 0, dst_uuid = 0;

	if (!l2cap_frame_get_u8(frame, &uuid_size))
		return false;

	print_field("%*cSize: 0x%02x ", indent, ' ', uuid_size);

	switch (uuid_size) {
	case 2:
		if (!l2cap_frame_get_be16(frame, (uint16_t *) &dst_uuid))
			return false;

		if (!l2cap_frame_get_be16(frame, (uint16_t *) &src_uuid))
			return false;
		break;
	case 4:
		if (!l2cap_frame_get_be32(frame, &dst_uuid))
			return false;

		if (!l2cap_frame_get_be32(frame, &src_uuid))
			return false;
		break;
	case 16:
		if (!l2cap_frame_get_be32(frame, &dst_uuid))
			return false;

		l2cap_frame_pull(frame, frame, 12);

		if (!l2cap_frame_get_be32(frame, &src_uuid))
			return false;

		l2cap_frame_pull(frame, frame, 12);
		break;
	default:
		l2cap_frame_pull(frame, frame, (uuid_size * 2));
		return true;
	}

	print_field("%*cDst: 0x%x(%s)", indent, ' ', dst_uuid,
						bt_uuid32_to_str(dst_uuid));
	print_field("%*cSrc: 0x%x(%s)", indent, ' ', src_uuid,
						bt_uuid32_to_str(src_uuid));
	return true;
}
Beispiel #17
0
static bool get_macaddr(struct bnep_frame *bnep_frame, char *str)
{
	uint8_t addr[6];
	struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
	int i;

	for (i = 0; i < 6; i++)
		if (!l2cap_frame_get_u8(frame, &addr[i]))
			return false;

	sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
		addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);

	return true;
}
Beispiel #18
0
static bool bnep_eval_extension(struct bnep_frame *bnep_frame, uint8_t indent)
{
	struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
	uint8_t type, length;
	int extension;

	if (!l2cap_frame_get_u8(frame, &type))
		return false;

	if (!l2cap_frame_get_u8(frame, &length))
		return false;

	extension = GET_EXTENSION(type);
	type = GET_PKT_TYPE(type);

	switch (type) {
	case BNEP_EXTENSION_CONTROL:
		print_field("%*cExt Control(0x%02x|%s) len 0x%02x", indent,
				' ', type, extension ? "1" : "0", length);
		if (!bnep_control(bnep_frame, indent+2, length))
			return false;
		break;

	default:
		print_field("%*cExt Unknown(0x%02x|%s) len 0x%02x", indent,
				' ', type, extension ? "1" : "0", length);
		packet_hexdump(frame->data, length);
		l2cap_frame_pull(frame, frame, length);
	}

	if (extension)
		if (!bnep_eval_extension(bnep_frame, indent))
			return false;

	return true;
}
Beispiel #19
0
static bool avrcp_set_absolute_volume(struct avctp_frame *avctp_frame,
						uint8_t ctype, uint8_t len,
						uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint8_t value;

	if (!l2cap_frame_get_u8(frame, &value))
		return false;

	value &= 0x7F;
	print_field("%*cVolume: %.2f%% (%d/127)", (indent - 8),
						' ', value/1.27, value);

	return true;
}
Beispiel #20
0
static inline bool mcc_test(struct rfcomm_frame *rfcomm_frame, uint8_t indent)
{
	struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame;
	uint8_t data;

	printf("%*cTest Data: 0x ", indent, ' ');

	while (frame->size > 1) {
		if (!l2cap_frame_get_u8(frame, &data))
			return false;
		printf("%2.2x ", data);
	}

	printf("\n");
	return true;
}
Beispiel #21
0
static bool avrcp_get_capabilities(struct avctp_frame *avctp_frame,
					uint8_t ctype, uint8_t len,
					uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint8_t cap, count;
	int i;

	if (!l2cap_frame_get_u8(frame, &cap))
		return false;

	print_field("%*cCapabilityID: 0x%02x (%s)", (indent - 8), ' ', cap,
								cap2str(cap));

	if (len == 1)
		return true;

	if (!l2cap_frame_get_u8(frame, &count))
		return false;

	print_field("%*cCapabilityCount: 0x%02x", (indent - 8), ' ', count);

	switch (cap) {
	case 0x2:
		for (; count > 0; count--) {
			uint8_t company[3];

			if (!l2cap_frame_get_u8(frame, &company[0]) ||
				!l2cap_frame_get_u8(frame, &company[1]) ||
				!l2cap_frame_get_u8(frame, &company[2]))
				return false;

			print_field("%*c%s: 0x%02x%02x%02x", (indent - 8), ' ',
					cap2str(cap), company[0], company[1],
					company[2]);
		}
		break;
	case 0x3:
		for (i = 0; count > 0; count--, i++) {
			uint8_t event;

			if (!l2cap_frame_get_u8(frame, &event))
				return false;

			print_field("%*c%s: 0x%02x (%s)", (indent - 8), ' ',
					cap2str(cap), event, event2str(event));
		}
		break;
	default:
		packet_hexdump(frame->data, frame->size);
	}

	return true;
}
Beispiel #22
0
static bool avrcp_control_packet(struct avctp_frame *avctp_frame)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;

	uint8_t ctype, address, subunit, opcode, company[3], indent = 2;

	if (!l2cap_frame_get_u8(frame, &ctype) ||
				!l2cap_frame_get_u8(frame, &address) ||
				!l2cap_frame_get_u8(frame, &opcode))
		return false;

	print_field("AV/C: %s: address 0x%02x opcode 0x%02x",
				ctype2str(ctype), address, opcode);

	subunit = address >> 3;

	print_field("%*cSubunit: %s", indent, ' ', subunit2str(subunit));

	print_field("%*cOpcode: %s", indent, ' ', opcode2str(opcode));

	/* Skip non-panel subunit packets */
	if (subunit != 0x09) {
		packet_hexdump(frame->data, frame->size);
		return true;
	}

	/* Not implemented should not contain any operand */
	if (ctype == 0x8) {
		packet_hexdump(frame->data, frame->size);
		return true;
	}

	switch (opcode) {
	case 0x7c:
		return avrcp_passthrough_packet(avctp_frame);
	case 0x00:
		if (!l2cap_frame_get_u8(frame, &company[0]) ||
				!l2cap_frame_get_u8(frame, &company[1]) ||
				!l2cap_frame_get_u8(frame, &company[2]))
			return false;

		print_field("%*cCompany ID: 0x%02x%02x%02x", indent, ' ',
					company[0], company[1], company[2]);

		return avrcp_pdu_packet(avctp_frame, ctype, 10);
	default:
		packet_hexdump(frame->data, frame->size);
		return true;
	}
}
Beispiel #23
0
static bool uih_frame(struct rfcomm_frame *rfcomm_frame, uint8_t indent)
{
	uint8_t credits;
	struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame;
	struct rfcomm_lhdr *hdr = &rfcomm_frame->hdr;

	if (!RFCOMM_GET_CHANNEL(hdr->address))
		return mcc_frame(rfcomm_frame, indent);

	/* fetching credits from UIH frame */
	if (GET_PF(hdr->control)) {
		if (!l2cap_frame_get_u8(frame, &credits))
			return false;
		hdr->credits = credits;
		print_field("%*cCredits: %d", indent, ' ', hdr->credits);
	}

	packet_hexdump(frame->data, frame->size);
	return true;
}
Beispiel #24
0
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;
}
Beispiel #25
0
static bool bnep_control(struct bnep_frame *bnep_frame,
					uint8_t indent,	int hdr_len)
{
	uint8_t ctype;
	struct l2cap_frame *frame = &bnep_frame->l2cap_frame;
	const struct bnep_control_data *bnep_control_data = NULL;
	const char *type_str;
	int i;

	if (!l2cap_frame_get_u8(frame, &ctype))
		return false;

	for (i = 0; bnep_control_table[i].str; i++) {
		if (bnep_control_table[i].type == ctype) {
			bnep_control_data = &bnep_control_table[i];
			break;
		}
	}

	if (bnep_control_data)
		type_str = bnep_control_data->str;
	else
		type_str = "Unknown control type";

	print_field("%*c%s (0x%02x) ", indent, ' ', type_str, ctype);

	if (!bnep_control_data || !bnep_control_data->func) {
		packet_hexdump(frame->data, hdr_len - 1);
		l2cap_frame_pull(frame, frame, hdr_len - 1);
		goto done;
	}

	if (!bnep_control_data->func(bnep_frame, indent+2))
		return false;

done:
	return true;
}
Beispiel #26
0
static inline bool mcc_pn(struct rfcomm_frame *rfcomm_frame, uint8_t indent)
{
	struct l2cap_frame *frame = &rfcomm_frame->l2cap_frame;
	struct rfcomm_pn pn;

	/* rfcomm_pn struct is defined in rfcomm.h */

	if (!l2cap_frame_get_u8(frame, &pn.dlci))
		return false;

	if (!l2cap_frame_get_u8(frame, &pn.flow_ctrl))
		return false;

	if (!l2cap_frame_get_u8(frame, &pn.priority))
		return false;

	print_field("%*cdlci %d frame_type %d credit_flow %d pri %d", indent,
			' ', GET_PN_DLCI(pn.dlci), GET_FRM_TYPE(pn.flow_ctrl),
			GET_CRT_FLOW(pn.flow_ctrl), GET_PRIORITY(pn.priority));

	if (!l2cap_frame_get_u8(frame, &pn.ack_timer))
		return false;

	if (!l2cap_frame_get_le16(frame, &pn.mtu))
		return false;

	if (!l2cap_frame_get_u8(frame, &pn.max_retrans))
		return false;

	if (!l2cap_frame_get_u8(frame, &pn.credits))
		return false;

	print_field("%*cack_timer %d frame_size %d max_retrans %d credits %d",
			indent, ' ', pn.ack_timer, pn.mtu, pn.max_retrans,
			pn.credits);

	return true;
}
Beispiel #27
0
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;
}
Beispiel #28
0
static bool avrcp_get_player_value_text(struct avctp_frame *avctp_frame,
					uint8_t ctype, uint8_t len,
					uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	static uint8_t attr = 0;
	uint8_t num;

	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
		goto response;

	if (!l2cap_frame_get_u8(frame, &attr))
		return false;

	print_field("%*cAttributeID: 0x%02x (%s)", (indent - 8), ' ',
						attr, attr2str(attr));

	if (!l2cap_frame_get_u8(frame, &num))
		return false;

	print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num);

	for (; num > 0; num--) {
		uint8_t value;

		if (!l2cap_frame_get_u8(frame, &value))
			return false;

		print_field("%*cValueID: 0x%02x (%s)", (indent - 8),
				' ', value, value2str(attr, value));
	}

	return true;

response:
	if (!l2cap_frame_get_u8(frame, &num))
		return false;

	print_field("%*cValueCount: 0x%02x", (indent - 8), ' ', num);

	for (; num > 0; num--) {
		uint8_t value, len;
		uint16_t charset;

		if (!l2cap_frame_get_u8(frame, &value))
			return false;

		print_field("%*cValueID: 0x%02x (%s)", (indent - 8), ' ',
						value, value2str(attr, value));

		if (!l2cap_frame_get_be16(frame, &charset))
			return false;

		print_field("%*cCharsetIDID: 0x%02x (%s)", (indent - 8), ' ',
						charset, charset2str(charset));

		if (!l2cap_frame_get_u8(frame, &len))
			return false;

		print_field("%*cStringLength: 0x%02x", (indent - 8), ' ', len);

		printf("String: ");
		for (; len > 0; len--) {
			uint8_t c;

			if (!l2cap_frame_get_u8(frame, &c))
				return false;

			printf("%1c", isprint(c) ? c : '.');
		}
		printf("\n");
	}

	return true;
}
Beispiel #29
0
static bool avrcp_register_notification(struct avctp_frame *avctp_frame,
					uint8_t ctype, uint8_t len,
					uint8_t indent)
{
	struct l2cap_frame *frame = &avctp_frame->l2cap_frame;
	uint8_t event, status;
	uint16_t uid;
	uint32_t interval;
	uint64_t id;

	if (ctype > AVC_CTYPE_GENERAL_INQUIRY)
		goto response;

	if (!l2cap_frame_get_u8(frame, &event))
		return false;

	print_field("%*cEventID: 0x%02x (%s)", (indent - 8),
						' ', event, event2str(event));

	if (!l2cap_frame_get_be32(frame, &interval))
		return false;

	print_field("%*cInterval: 0x%08x (%u seconds)",
					(indent - 8), ' ', interval, interval);

	return true;

response:
	if (!l2cap_frame_get_u8(frame, &event))
		return false;

	print_field("%*cEventID: 0x%02x (%s)", (indent - 8),
						' ', event, event2str(event));

	switch (event) {
	case AVRCP_EVENT_PLAYBACK_STATUS_CHANGED:
		if (!l2cap_frame_get_u8(frame, &status))
			return false;

		print_field("%*cPlayStatus: 0x%02x (%s)", (indent - 8),
					' ', status, playstatus2str(status));
		break;
	case AVRCP_EVENT_TRACK_CHANGED:
		if (!l2cap_frame_get_be64(frame, &id))
			return false;

		print_field("%*cIdentifier: 0x%16" PRIx64 " (%" PRIu64 ")",
						(indent - 8), ' ', id, id);
		break;
	case AVRCP_EVENT_PLAYBACK_POS_CHANGED:
		if (!l2cap_frame_get_be32(frame, &interval))
			return false;

		print_field("%*cPosition: 0x%08x (%u miliseconds)",
					(indent - 8), ' ', interval, interval);
		break;
	case AVRCP_EVENT_BATT_STATUS_CHANGED:
		if (!l2cap_frame_get_u8(frame, &status))
			return false;

		print_field("%*cBatteryStatus: 0x%02x (%s)", (indent - 8),
					' ', status, status2str(status));

		break;
	case AVRCP_EVENT_SYSTEM_STATUS_CHANGED:
		if (!l2cap_frame_get_u8(frame, &status))
			return false;

		print_field("%*cSystemStatus: 0x%02x ", (indent - 8),
								' ', status);
		switch (status) {
		case 0x00:
			printf("(POWER_ON)\n");
			break;
		case 0x01:
			printf("(POWER_OFF)\n");
			break;
		case 0x02:
			printf("(UNPLUGGED)\n");
			break;
		default:
			printf("(UNKOWN)\n");
			break;
		}
		break;
	case AVRCP_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:
		if (!l2cap_frame_get_u8(frame, &status))
			return false;

		print_field("%*cAttributeCount: 0x%02x", (indent - 8),
								' ', status);

		for (; status > 0; status--) {
			uint8_t attr, value;

			if (!l2cap_frame_get_u8(frame, &attr))
				return false;

			print_field("%*cAttributeID: 0x%02x (%s)",
				(indent - 8), ' ', attr, attr2str(attr));

			if (!l2cap_frame_get_u8(frame, &value))
				return false;

			print_field("%*cValueID: 0x%02x (%s)", (indent - 8),
					' ', value, value2str(attr, value));
		}
		break;
	case AVRCP_EVENT_VOLUME_CHANGED:
		if (!l2cap_frame_get_u8(frame, &status))
			return false;

		status &= 0x7F;

		print_field("%*cVolume: %.2f%% (%d/127)", (indent - 8),
						' ', status/1.27, status);
		break;
	case AVRCP_EVENT_ADDRESSED_PLAYER_CHANGED:
		if (!l2cap_frame_get_be16(frame, &uid))
			return false;

		print_field("%*cPlayerID: 0x%04x (%u)", (indent - 8),
								' ', uid, uid);

		if (!l2cap_frame_get_be16(frame, &uid))
			return false;

		print_field("%*cUIDCounter: 0x%04x (%u)", (indent - 8),
								' ', uid, uid);
		break;
	case AVRCP_EVENT_UIDS_CHANGED:
		if (!l2cap_frame_get_be16(frame, &uid))
			return false;

		print_field("%*cUIDCounter: 0x%04x (%u)", (indent - 8),
								' ', uid, uid);
		break;
	}

	return true;
}
Beispiel #30
0
void bnep_packet(const struct l2cap_frame *frame)
{
	uint8_t type, indent = 1;
	struct bnep_frame bnep_frame;
	struct l2cap_frame *l2cap_frame;
	const struct bnep_data *bnep_data = NULL;
	const char *pdu_color, *pdu_str;
	int i;

	l2cap_frame_pull(&bnep_frame.l2cap_frame, frame, 0);
	l2cap_frame = &bnep_frame.l2cap_frame;

	if (!l2cap_frame_get_u8(l2cap_frame, &type))
		goto fail;

	bnep_frame.extension = GET_EXTENSION(type);
	bnep_frame.type = GET_PKT_TYPE(type);

	for (i = 0; bnep_table[i].str; i++) {
		if (bnep_table[i].type == bnep_frame.type) {
			bnep_data = &bnep_table[i];
			break;
		}
	}

	if (bnep_data) {
		if (bnep_data->func) {
			if (frame->in)
				pdu_color = COLOR_MAGENTA;
			else
				pdu_color = COLOR_BLUE;
		} else
			pdu_color = COLOR_WHITE_BG;
		pdu_str = bnep_data->str;
	} else {
		pdu_color = COLOR_WHITE_BG;
		pdu_str = "Unknown packet type";
	}

	print_indent(6, pdu_color, "BNEP: ", pdu_str, COLOR_OFF,
				" (0x%02x|%s)", bnep_frame.type,
				bnep_frame.extension ? "1" : "0");

	if (!bnep_data || !bnep_data->func) {
		packet_hexdump(l2cap_frame->data, l2cap_frame->size);
		return;
	}

	if (!bnep_data->func(&bnep_frame, indent, -1))
		goto fail;

	/* Extension info */
	if (bnep_frame.extension)
		if (!bnep_eval_extension(&bnep_frame, indent+2))
			goto fail;

	/* Control packet => No payload info */
	if (bnep_frame.type == BNEP_CONTROL)
		return;

	/* TODO: Handle BNEP IP packet */
	packet_hexdump(l2cap_frame->data, l2cap_frame->size);

	return;

fail:
	print_text(COLOR_ERROR, "frame too short");
	packet_hexdump(frame->data, frame->size);
}