Ejemplo n.º 1
0
static void initSocketNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);

    int fd;
    int lm = 0;
    int sndbuf, rcvbuf;
    jboolean auth;
    jboolean encrypt;
    jint type;
    char value[PROPERTY_VALUE_MAX] = "";

    type = env->GetIntField(obj, field_mType);

    switch (type) {
    case TYPE_RFCOMM:
        fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
        break;
    case TYPE_SCO_WBS:
    case TYPE_SCO:
        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
        break;
    case TYPE_L2CAP:
        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
        break;
    case TYPE_EL2CAP:
        fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP);
        break;
    default:
        jniThrowIOException(env, ENOSYS);
        return;
    }

    if (fd < 0) {
        ALOGV("socket() failed, throwing");
        jniThrowIOException(env, errno);
        return;
    }

    auth = env->GetBooleanField(obj, field_mAuth);
    encrypt = env->GetBooleanField(obj, field_mEncrypt);

    /* kernel does not yet support LM for SCO */

    /* By default we request to be the MASTER of connection */
    property_get("ro.bluetooth.request.master", value, "true");
    switch (type) {
    case TYPE_RFCOMM:
        lm |= auth ? RFCOMM_LM_AUTH : 0;
        lm |= encrypt ? RFCOMM_LM_ENCRYPT : 0;
        if (!strcmp("true", value)) {
            ALOGI("Setting Master socket option");
            lm |= RFCOMM_LM_MASTER;
        }
        break;
    case TYPE_L2CAP:
    case TYPE_EL2CAP:
        lm |= auth ? L2CAP_LM_AUTH : 0;
        lm |= encrypt ? L2CAP_LM_ENCRYPT : 0;
        if (!strcmp("true", value)) {
            ALOGI("Setting Master socket option");
            lm |= L2CAP_LM_MASTER;
        }
        break;
    }

    if (lm) {
        if (type == TYPE_RFCOMM) {
            if (setsockopt(fd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
                ALOGV("setsockopt(RFCOMM_LM) failed, throwing");
                close(fd);
                jniThrowIOException(env, errno);
                return;
            }
        } else if (type == TYPE_L2CAP || type == TYPE_EL2CAP) {
            if (setsockopt(fd, SOL_L2CAP, L2CAP_LM, &lm, sizeof(lm))) {
                ALOGV("setsockopt(L2CAP_LM) failed, throwing");
                close(fd);
                jniThrowIOException(env, errno);
                return;
            }
        }
    }

    if (type == TYPE_RFCOMM) {
        sndbuf = RFCOMM_SO_SNDBUF;
        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
            ALOGV("setsockopt(SO_SNDBUF) failed, throwing");
            close(fd);
            jniThrowIOException(env, errno);
            return;
        }
    }

    /* Setting L2CAP socket options */
    if (type == TYPE_L2CAP || type == TYPE_EL2CAP) {
        struct l2cap_options opts;
        int optlen = sizeof(opts), err;
        err = getsockopt(fd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen );
        if (!err) {
            /* setting MTU for [E]L2CAP */
            opts.omtu = opts.imtu = L2CAP_MAX_MTU;

            /* Enable ERTM for [E]L2CAP */
            if (type == TYPE_EL2CAP) {
                opts.flush_to = 0xffff; /* infinite */
                opts.mode = L2CAP_MODE_ERTM;
                opts.fcs = 1;
                opts.txwin_size = 64;
                opts.max_tx = 10;
            }
            err = setsockopt( fd, SOL_L2CAP, L2CAP_OPTIONS, &opts, optlen );
        }

        /* Set larger SNDBUF & RCVBUF for EL2CAP connections */
        if (type == TYPE_EL2CAP) {
            sndbuf = L2CAP_SO_SNDBUF;
            if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
                ALOGV("setsockopt(SO_SNDBUF) failed, throwing");
                close(fd);
                jniThrowIOException(env, errno);
                return;
            }

            rcvbuf = L2CAP_SO_RCVBUF;
            if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) {
                ALOGV("setsockopt(SO_RCVBUF) failed, throwing");
                close(fd);
                jniThrowIOException(env, errno);
                return;
           }
        }
    }


    ALOGV("...fd %d created (%s, lm = %x)", fd, TYPE_AS_STR(type), lm);

    initSocketFromFdNative(env, obj, fd);
    return;
#endif
    jniThrowIOException(env, ENOSYS);
}
static void initSocketNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    LOGV(__FUNCTION__);

    int fd;
    int lm = 0;
    int sndbuf;
    jboolean auth;
    jboolean encrypt;
    jint type;

    type = env->GetIntField(obj, field_mType);

    switch (type) {
    case TYPE_RFCOMM:
        fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
        break;
    case TYPE_SCO:
        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
        break;
    case TYPE_L2CAP:
        fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
        break;
    default:
        jniThrowIOException(env, ENOSYS);
        return;
    }

    if (fd < 0) {
        LOGV("socket() failed, throwing");
        jniThrowIOException(env, errno);
        return;
    }

    auth = env->GetBooleanField(obj, field_mAuth);
    encrypt = env->GetBooleanField(obj, field_mEncrypt);

    /* kernel does not yet support LM for SCO */
    switch (type) {
    case TYPE_RFCOMM:
        lm |= auth ? RFCOMM_LM_AUTH : 0;
        lm |= encrypt ? RFCOMM_LM_ENCRYPT : 0;
        lm |= (auth && encrypt) ? RFCOMM_LM_SECURE : 0;
        break;
    case TYPE_L2CAP:
        lm |= auth ? L2CAP_LM_AUTH : 0;
        lm |= encrypt ? L2CAP_LM_ENCRYPT : 0;
        lm |= (auth && encrypt) ? L2CAP_LM_SECURE : 0;
        break;
    }

    if (lm) {
        if (setsockopt(fd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) {
            LOGV("setsockopt(RFCOMM_LM) failed, throwing");
            jniThrowIOException(env, errno);
            return;
        }
    }

    if (type == TYPE_RFCOMM) {
        sndbuf = RFCOMM_SO_SNDBUF;
        if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) {
            LOGV("setsockopt(SO_SNDBUF) failed, throwing");
            jniThrowIOException(env, errno);
            return;
        }
    }

    LOGV("...fd %d created (%s, lm = %x)", fd, TYPE_AS_STR(type), lm);

    initSocketFromFdNative(env, obj, fd);
    return;
#endif
    jniThrowIOException(env, ENOSYS);
}