JNIEXPORT jboolean JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_populateServiceRecordAttributeValuesImpl
  (JNIEnv *env, jobject peer, jlong localDeviceBTAddress, jlong remoteDeviceAddressLong, jlong sdpSession, jlong handle, jintArray attrIDs, jobject serviceRecord) {
    sdp_session_t* session = (sdp_session_t*)jlong2ptr(sdpSession);
    sdp_session_t* close_session_on_return = NULL;
    if (session != NULL) {
        debug("populateServiceRecordAttributeValuesImpl connected %p, recordHandle %li", session, handle);
    } else {
        debug("populateServiceRecordAttributeValuesImpl connects, recordHandle %li", handle);
        bdaddr_t localAddr;
        longToDeviceAddr(localDeviceBTAddress, &localAddr);
        bdaddr_t remoteAddress;
        longToDeviceAddr(remoteDeviceAddressLong, &remoteAddress);
        session = sdp_connect(&localAddr, &remoteAddress, SDP_RETRY_IF_BUSY);
        if (session == NULL) {
            debug("populateServiceRecordAttributeValuesImpl can't connect");
            return JNI_FALSE;
        }
        // Close session on exit
       close_session_on_return = session;
    }

    sdp_list_t *attr_list = NULL;
    jboolean isCopy = JNI_FALSE;
    jint* ids = (*env)->GetIntArrayElements(env, attrIDs, &isCopy);
    int i;
    for(i = 0; i < (*env)->GetArrayLength(env, attrIDs); i++) {
        uint16_t* id = (uint16_t*)malloc(sizeof(uint16_t));
        *id=(uint16_t)ids[i];
        attr_list = sdp_list_append(attr_list,id);
    }

    jboolean rc = JNI_FALSE;
    sdp_record_t *sdpRecord = sdp_service_attr_req(session, (uint32_t)handle, SDP_ATTR_REQ_INDIVIDUAL, attr_list);
    if (!sdpRecord) {
        debug("sdp_service_attr_req return error");
        rc = JNI_FALSE;
    } else {
        populateServiceRecord(env, serviceRecord, sdpRecord, attr_list);
        sdp_record_free(sdpRecord);
        rc = JNI_TRUE;
    }
    sdp_list_free(attr_list, free);
    if (close_session_on_return != NULL) {
        sdp_close(close_session_on_return);
    }

    return rc;
}
JNIEXPORT jstring JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_getRemoteDeviceVersionInfoImpl
(JNIEnv *env, jobject peer, jint deviceDescriptor, jlong remoteDeviceAddressLong) {
    struct hci_conn_info_req *conn_info;
    struct hci_version ver;
    char info[256];

    conn_info = (struct hci_conn_info_req*)malloc(sizeof(*conn_info) + sizeof(struct hci_conn_info));
    if (!conn_info) {
        throwRuntimeException(env, cOUT_OF_MEMORY);
        return NULL;
    }
    memset(conn_info, 0, sizeof(struct hci_conn_info));
    longToDeviceAddr(remoteDeviceAddressLong, &(conn_info->bdaddr));

    conn_info->type = ACL_LINK;
    if (ioctl((int)deviceDescriptor, HCIGETCONNINFO, (unsigned long) conn_info) < 0) {
        free(conn_info);
        throwRuntimeException(env, "Fail to get connection info");
        return NULL;
    }

    int error = hci_read_remote_version((int)deviceDescriptor, conn_info->conn_info->handle, &ver, READ_REMOTE_NAME_TIMEOUT);
    if (error < 0) {
        throwRuntimeException(env, "Can not get remote device info");
        free(conn_info);
        return NULL;
    }
    snprintf(info, 256, "manufacturer=%i,lmp_version=%i,lmp_sub_version=%i", ver.manufacturer, ver.lmp_ver, ver.lmp_subver);
    free(conn_info);
    return (*env)->NewStringUTF(env, info);
}
JNIEXPORT jstring JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_getRemoteDeviceFriendlyNameImpl
(JNIEnv *env, jobject peer, jint deviceDescriptor, jlong remoteAddress) {
    bdaddr_t address;
    longToDeviceAddr(remoteAddress, &address);
    char name[DEVICE_NAME_MAX_SIZE];
    int error = hci_read_remote_name(deviceDescriptor, &address, sizeof(name), name, READ_REMOTE_NAME_TIMEOUT);
    if (error < 0) {
        throwIOException(env, "Can not get remote device name");
        return NULL;
    }
    return (*env)->NewStringUTF(env, name);
}
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_getRemoteDeviceRSSIImpl
(JNIEnv *env, jobject peer, jint deviceDescriptor, jlong remoteDeviceAddressLong) {
    struct hci_request rq;
    struct hci_conn_info_req *conn_info;
    read_rssi_rp rssi_rp;

    conn_info = (struct hci_conn_info_req*)malloc(sizeof(*conn_info) + sizeof(struct hci_conn_info));
    if (!conn_info) {
        throwRuntimeException(env, cOUT_OF_MEMORY);
        return -1;
    }
    memset(conn_info, 0, sizeof(struct hci_conn_info));
    longToDeviceAddr(remoteDeviceAddressLong, &(conn_info->bdaddr));

    conn_info->type = ACL_LINK;
    if (ioctl((int)deviceDescriptor, HCIGETCONNINFO, (unsigned long) conn_info) < 0) {
        free(conn_info);
        throwRuntimeException(env, "Fail to get connection info");
        return -1;
    }

    memset(&rq, 0, sizeof(rq));
    rq.ogf    = OGF_STATUS_PARAM;
    rq.ocf    = OCF_READ_RSSI;
    rq.cparam = &conn_info->conn_info->handle;
    rq.clen   = 2;
    rq.rparam = &rssi_rp;
    rq.rlen   = READ_RSSI_RP_SIZE;

    if ((hci_send_req((int)deviceDescriptor, &rq, READ_REMOTE_NAME_TIMEOUT) < 0) || rssi_rp.status) {
        free(conn_info);
        throwRuntimeException(env, "Fail to send hci request");
        return -1;
    }
    free(conn_info);
    return rssi_rp.rssi;
}
Ejemplo n.º 5
0
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZDBus_connectionRfOpenClientConnectionImpl
  (JNIEnv* env, jobject peer, jlong localDeviceBTAddress, jlong address, jint channel, jboolean authenticate, jboolean encrypt, jint timeout) {
    debug("RFCOMM connect, channel %d", channel);

    // allocate socket
    int handle = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
    if (handle < 0) {
        throwIOException(env, "Failed to create socket. [%d] %s", errno, strerror(errno));
        return 0;
    }

    struct sockaddr_rc localAddr;
    //bind local address
    memset(&localAddr, 0, sizeof(localAddr));
    localAddr.rc_family = AF_BLUETOOTH;
    localAddr.rc_channel = 0;
    //bacpy(&localAddr.rc_bdaddr, BDADDR_ANY);
    longToDeviceAddr(localDeviceBTAddress, &localAddr.rc_bdaddr);


    if (bind(handle, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) {
        throwIOException(env, "Failed to  bind socket. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }

    // TODO verify how this works, I think device needs to paird before this can be setup.
    // Set link security options
    if (encrypt || authenticate) {
        int socket_opt = 0;
        socklen_t len = sizeof(socket_opt);
        if (getsockopt(handle, SOL_RFCOMM, RFCOMM_LM, &socket_opt, &len) < 0) {
            throwIOException(env, "Failed to read RFCOMM link mode. [%d] %s", errno, strerror(errno));
            close(handle);
            return 0;
        }
        //if (master) {
        //  socket_opt |= RFCOMM_LM_MASTER;
        //}
        if (authenticate) {
            socket_opt |= RFCOMM_LM_AUTH;
            debug("RFCOMM set authenticate");
        }
        if (encrypt) {
            socket_opt |= RFCOMM_LM_ENCRYPT;
        }
        //if (socket_opt != 0) {
        //  socket_opt |= RFCOMM_LM_SECURE;
        //}

        if ((socket_opt != 0) && setsockopt(handle, SOL_RFCOMM, RFCOMM_LM, &socket_opt, sizeof(socket_opt)) < 0) {
            throwIOException(env, "Failed to set RFCOMM link mode. [%d] %s", errno, strerror(errno));
            close(handle);
            return 0;
        }
    }

    struct sockaddr_rc remoteAddr;
    memset(&remoteAddr, 0, sizeof(remoteAddr));
    remoteAddr.rc_family = AF_BLUETOOTH;
    longToDeviceAddr(address, &remoteAddr.rc_bdaddr);
    remoteAddr.rc_channel = channel;

    // connect to server
    if (connect(handle, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr)) != 0) {
        throwIOException(env, "Failed to connect. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }
    debug("RFCOMM connected, handle %li", handle);
    return handle;
}
Ejemplo n.º 6
0
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_l2OpenClientConnectionImpl
  (JNIEnv* env, jobject peer, jlong localDeviceBTAddress, jlong address, jint channel, jboolean authenticate, jboolean encrypt, jint receiveMTU, jint transmitMTU, jint timeout) {
    debug("CONNECT connect, psm %d", channel);

    // allocate socket
    int handle = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
    if (handle < 0) {
        throwIOException(env, "Failed to create socket. [%d] %s", errno, strerror(errno));
        return 0;
    }

    struct sockaddr_l2 localAddr;
    //bind local address
    localAddr.l2_family = AF_BLUETOOTH;
    localAddr.l2_psm = 0;
    //bacpy(&localAddr.l2_bdaddr, BDADDR_ANY);
    longToDeviceAddr(localDeviceBTAddress, &localAddr.l2_bdaddr);

    if (bind(handle, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) {
        throwIOException(env, "Failed to bind socket. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }

    // Set link mtu and security options
    struct l2cap_options opt;
    socklen_t opt_len = sizeof(opt);
    memset(&opt, 0, opt_len);
    opt.imtu = receiveMTU;
    opt.omtu = (transmitMTU > 0)?transmitMTU:L2CAP_DEFAULT_MTU;
    opt.flush_to = L2CAP_DEFAULT_FLUSH_TO;
    Edebug("L2CAP set imtu %i, omtu %i", opt.imtu, opt.omtu);

    if (setsockopt(handle, SOL_L2CAP, L2CAP_OPTIONS, &opt, opt_len) < 0) {
        throwIOException(env, "Failed to set L2CAP mtu options. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }

    if (encrypt || authenticate) {
        int socket_opt = 0;
        socklen_t len = sizeof(socket_opt);
        if (getsockopt(handle, SOL_L2CAP, L2CAP_LM, &socket_opt, &len) < 0) {
            throwIOException(env, "Failed to read L2CAP link mode. [%d] %s", errno, strerror(errno));
            close(handle);
            return 0;
        }
        //if (master) {
        //  socket_opt |= L2CAP_LM_MASTER;
        //}
        if (authenticate) {
            socket_opt |= L2CAP_LM_AUTH;
            Edebug("L2CAP set authenticate");
        }
        if (encrypt) {
            socket_opt |= L2CAP_LM_ENCRYPT;
        }

        if ((socket_opt != 0) && setsockopt(handle, SOL_L2CAP, L2CAP_LM, &socket_opt, sizeof(socket_opt)) < 0) {
            throwIOException(env, "Failed to set L2CAP link mode. [%d] %s", errno, strerror(errno));
            close(handle);
            return 0;
        }
    }


    struct sockaddr_l2 remoteAddr;
    remoteAddr.l2_family = AF_BLUETOOTH;
    longToDeviceAddr(address, &remoteAddr.l2_bdaddr);
    remoteAddr.l2_psm = channel;

    // connect to server
    if (connect(handle, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr)) != 0) {
        throwIOException(env, "Failed to connect. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }
    debug("L2CAP connected, handle %li", handle);

    struct l2cap_options copt;
    if (!l2Get_options(env, handle, &copt)) {
        close(handle);
        return 0;
    }
    debug("L2CAP imtu %i, omtu %i", copt.imtu, copt.omtu);
    return handle;
}
JNIEXPORT jlong JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_l2ServerOpenImpl
  (JNIEnv* env, jobject peer, jlong localDeviceBTAddress, jboolean authorize, jboolean authenticate, jboolean encrypt, jboolean master, jboolean timeouts, jint backlog, jint receiveMTU, jint transmitMTU) {

    // allocate socket
    int handle = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
    if (handle < 0) {
        throwIOException(env, "Failed to create socket. [%d] %s", errno, strerror(errno));
        return 0;
    }

    struct sockaddr_l2 localAddr;
    //bind local address
    localAddr.l2_family = AF_BLUETOOTH;
    localAddr.l2_psm = 0;
    //bacpy(&localAddr.l2_bdaddr, BDADDR_ANY);
    longToDeviceAddr(localDeviceBTAddress, &localAddr.l2_bdaddr);

    if (bind(handle, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) {
        throwIOException(env, "Failed to bind socket. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }

    // Set link mtu and security options
    struct l2cap_options opt;
    socklen_t opt_len = sizeof(opt);
    memset(&opt, 0, opt_len);
    opt.imtu = receiveMTU;
    opt.omtu = (transmitMTU > 0)?transmitMTU:L2CAP_DEFAULT_MTU;
    opt.flush_to = L2CAP_DEFAULT_FLUSH_TO;
    Edebug("L2CAP set imtu %i, omtu %i", opt.imtu, opt.omtu);

    if (setsockopt(handle, SOL_L2CAP, L2CAP_OPTIONS, &opt, opt_len) < 0) {
        throwIOException(env, "Failed to set L2CAP mtu options. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }

    // Set link security options
    if (encrypt || authenticate || authorize || master) {
		int socket_opt = 0;
		socklen_t len = sizeof(socket_opt);
        if (getsockopt(handle, SOL_L2CAP, L2CAP_LM, &socket_opt, &len) < 0) {
            throwIOException(env, "Failed to read L2CAP server mode. [%d] %s", errno, strerror(errno));
            close(handle);
            return 0;
        }
		if (master) {
			socket_opt |= L2CAP_LM_MASTER;
		}
		if (authenticate) {
			socket_opt |= L2CAP_LM_AUTH;
			debug("L2CAP set authenticate");
		}
		if (encrypt) {
			socket_opt |= L2CAP_LM_ENCRYPT;
		}
		if (authorize) {
			socket_opt |= L2CAP_LM_SECURE;
		}

		if ((socket_opt != 0) && setsockopt(handle, SOL_L2CAP, L2CAP_LM, &socket_opt, sizeof(socket_opt)) < 0) {
			throwIOException(env, "Failed to set L2CAP server mode. [%d] %s", errno, strerror(errno));
            close(handle);
            return 0;
		}
    }

    // put socket into listening mode
    if (listen(handle, backlog) < 0) {
        throwIOException(env, "Failed to listen for L2CAP connections. [%d] %s", errno, strerror(errno));
        close(handle);
        return 0;
    }

    return handle;
}
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZ_runSearchServicesImpl
  (JNIEnv *env, jobject peer, jobject searchServicesThread, jlong localDeviceBTAddress, jobjectArray uuidValues, jlong remoteDeviceAddressLong) {

    // Prepare serviceDiscoveredCallback
    jclass peerClass = (*env)->GetObjectClass(env, peer);
    if (peerClass == NULL) {
        throwRuntimeException(env, "Fail to get Object Class");
        return SERVICE_SEARCH_ERROR;
    }

    jmethodID serviceDiscoveredCallback = getGetMethodID(env, peerClass, "serviceDiscoveredCallback", "(Lcom/intel/bluetooth/SearchServicesThread;JJ)Z");
    if (serviceDiscoveredCallback == NULL) {
        return SERVICE_SEARCH_ERROR;
    }

    sdp_list_t *uuidList = NULL;
    sdp_list_t *rsp_list = NULL;
    sdp_session_t *session = NULL;
    jint rc = SERVICE_SEARCH_ERROR;
    const uint16_t max_rec_num = 256;
    int serviceCount = 0;
    int error;

    // convert uuid set from java array to bluez sdp_list_t
    jsize uuidSetSize = (*env)->GetArrayLength(env, uuidValues);
    jsize i;
    debug("runSearchServicesImpl uuidSetSize %i", uuidSetSize);
    for(i = 0; i < uuidSetSize; i++) {
        jbyteArray byteArray = (jbyteArray)(*env)->GetObjectArrayElement(env, uuidValues, i);
        uuid_t* uuid =  (uuid_t*)malloc(sizeof(uuid_t));
        convertUUIDByteArrayToUUID(env, byteArray, uuid);
        uuidList = sdp_list_append(uuidList, uuid);
    }

    // convert remote device address from jlong to bluez bdaddr_t
    bdaddr_t remoteAddress;
    longToDeviceAddr(remoteDeviceAddressLong, &remoteAddress);

    bdaddr_t localAddr;
    longToDeviceAddr(localDeviceBTAddress, &localAddr);

    // connect to the device to retrieve services
    session = sdp_connect(&localAddr, &remoteAddress, SDP_RETRY_IF_BUSY);

    // if connection is not established throw an exception
    if (session == NULL) {
        rc = SERVICE_SEARCH_DEVICE_NOT_REACHABLE;
        goto searchServicesImplEnd;
    }

    // then ask the device for service record handles
    error = sdp_service_search_req(session, uuidList, max_rec_num, &(rsp_list));
    if (error) {
        debug("sdp_service_search_req error %i", error);
        rc = SERVICE_SEARCH_ERROR;
        goto searchServicesImplEnd;
    }
    Edebug("runSearchServicesImpl session %p %li", session, ptr2jlong(session));

    // Notify java about found services
    sdp_list_t* handle;
    for(handle = rsp_list; handle; handle = handle->next) {
        uint32_t record = *(uint32_t*)handle->data;
        jlong recordHandle = record;
        Edebug("runSearchServicesImpl serviceRecordHandle %li", recordHandle);
        jboolean isTerminated = (*env)->CallBooleanMethod(env, peer, serviceDiscoveredCallback, searchServicesThread, ptr2jlong(session), recordHandle);
        if ((*env)->ExceptionCheck(env)) {
            rc = SERVICE_SEARCH_ERROR;
            goto searchServicesImplEnd;
        } else if (isTerminated) {
            rc = SERVICE_SEARCH_TERMINATED;
            goto searchServicesImplEnd;
        }
        serviceCount ++;
    }
    debug("runSearchServicesImpl found %i", serviceCount);
    rc = SERVICE_SEARCH_COMPLETED;
searchServicesImplEnd:
    sdp_list_free(uuidList, free);
    sdp_list_free(rsp_list, free);
    if (session != NULL) {
        sdp_close(session);
    }
    return rc;
}