/* Request that the ACL link to a given Bluetooth connection be high priority,
 * for improved coexistance support
 */
int android_set_high_priority(bdaddr_t *ba) {
    int ret;
    int fd = get_hci_sock();
    int acl_handle;

    if (fd < 0)
        return fd;

    acl_handle = get_acl_handle(fd, ba);
    if (acl_handle < 0) {
        ret = acl_handle;
        goto out;
    }

    ret = vendor_high_priority(fd, acl_handle);
    if (ret < 0)
        goto out;
    ret = write_flush_timeout(fd, acl_handle, 200);

out:
    close(fd);

    return ret;
}
Exemple #2
0
status_t
AclAssembly(net_buffer* nbuf, hci_id hid)
{
	status_t	error = B_OK;

	// Check ACL data packet. Driver should ensure report complete ACL packets
	if (nbuf->size < sizeof(struct hci_acl_header)) {
		debugf("Invalid ACL data packet, small length=%ld\n", nbuf->size);
		gBufferModule->free(nbuf);
		return (EMSGSIZE);
	}

	// Strip ACL data packet header
	NetBufferHeaderReader<struct hci_acl_header> aclHeader(nbuf);
	status_t status = aclHeader.Status();
	if (status < B_OK) {
		gBufferModule->free(nbuf);
		return ENOBUFS;
	}


	// Get ACL connection handle, PB flag and payload length
	aclHeader->handle = le16toh(aclHeader->handle);

	uint16 con_handle = get_acl_handle(aclHeader->handle);
	uint16 pb = get_acl_pb_flag(aclHeader->handle);
	uint16 length = le16toh(aclHeader->alen);

	aclHeader.Remove();

	debugf("ACL data packet, handle=%#x, PB=%#x, length=%d\n",
		con_handle, pb, length);

	// a) Ensure there is HCI connection
	// b) Get connection descriptor
	// c) veryfy the status of the connection

	HciConnection* conn = btCoreData->ConnectionByHandle(con_handle, hid);
	if (conn == NULL) {
		debugf("Uexpected handle=%#x does not exist!\n", con_handle);
		conn = btCoreData->AddConnection(con_handle, BT_ACL, BDADDR_NULL, hid);
	}

	// Verify connection state
	if (conn->status!= HCI_CONN_OPEN) {
		flowf("unexpected ACL data packet. Connection not open\n");
		gBufferModule->free(nbuf);
		return EHOSTDOWN;
	}


	// Process packet
	if (pb == HCI_ACL_PACKET_START) {
		if (conn->currentRxPacket != NULL) {
			debugf("Dropping incomplete L2CAP packet, got %ld want %d \n",
				conn->currentRxPacket->size, length );
			gBufferModule->free(conn->currentRxPacket);
			conn->currentRxPacket = NULL;
			conn->currentRxExpectedLength = 0;
		}

		// Get L2CAP header, ACL header was dimissed
		if (nbuf->size < sizeof(l2cap_hdr_t)) {
			debugf("Invalid L2CAP start fragment, small, length=%ld\n",
				nbuf->size);
			gBufferModule->free(nbuf);
			return (EMSGSIZE);
		}


		NetBufferHeaderReader<l2cap_hdr_t> l2capHeader(nbuf);
		status_t status = l2capHeader.Status();
		if (status < B_OK) {
			gBufferModule->free(nbuf);
			return ENOBUFS;
		}

		l2capHeader->length = le16toh(l2capHeader->length);
		l2capHeader->dcid = le16toh(l2capHeader->dcid);

		debugf("New L2CAP, handle=%#x length=%d\n", con_handle,
			le16toh(l2capHeader->length));

		// Start new L2CAP packet
		conn->currentRxPacket = nbuf;
		conn->currentRxExpectedLength = l2capHeader->length + sizeof(l2cap_hdr_t);


	} else if (pb == HCI_ACL_PACKET_FRAGMENT) {
		if (conn->currentRxPacket == NULL) {
			gBufferModule->free(nbuf);
			return (EINVAL);
		}

		// Add fragment to the L2CAP packet
		gBufferModule->merge(conn->currentRxPacket, nbuf, true);

	} else {
		debugf("invalid ACL data packet. Invalid PB flag=%#x\n", pb);
		gBufferModule->free(nbuf);
		return (EINVAL);
	}

	// substract the length of content of the ACL packet
	conn->currentRxExpectedLength -= length;

	if (conn->currentRxExpectedLength < 0) {

		debugf("Mismatch. Got %ld, expected %ld\n",
			conn->currentRxPacket->size, conn->currentRxExpectedLength);

		gBufferModule->free(conn->currentRxPacket);
		conn->currentRxPacket = NULL;
		conn->currentRxExpectedLength = 0;

	} else if (conn->currentRxExpectedLength == 0) {
		// OK, we have got complete L2CAP packet, so process it
		debugf("L2cap packet ready %ld bytes\n", conn->currentRxPacket->size);
		error = PostToUpper(conn, conn->currentRxPacket);
		// clean
		conn->currentRxPacket = NULL;
		conn->currentRxExpectedLength = 0;
	} else {
		debugf("Expected %ld current adds %d\n",
			conn->currentRxExpectedLength, length);
	}

	return error;
}