Пример #1
0
static int getMtuNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    ALOGV(__FUNCTION__);

    jint type = env->GetIntField(obj, field_mType);
    struct asocket *s = get_socketData(env, obj);

    if (type == TYPE_RFCOMM || !s)
        return L2CAP_MAX_MTU;

    struct l2cap_options opts;
    int optlen = sizeof(opts), err;
    err = getsockopt(s->fd, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen );
    if (!err) {
        return opts.omtu;
    } else {
        ALOGV("getsockopt() failed, throwing");
        jniThrowIOException(env, errno);
    }

    return L2CAP_MAX_MTU;
#endif
    jniThrowIOException(env, ENOSYS);
    return -1;
}
Пример #2
0
static void abortNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);
    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return;

    asocket_abort(s);

    ALOGV("...asocket_abort(%d) complete", s->fd);
    return;
#endif
    jniThrowIOException(env, ENOSYS);
}
Пример #3
0
static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
        jint length) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);

    int ret, total;
    jbyte *b;
    int sz;
    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return -1;
    if (jb == NULL) {
        jniThrowIOException(env, EINVAL);
        return -1;
    }
    sz = env->GetArrayLength(jb);
    if (offset < 0 || length < 0 || offset + length > sz) {
        jniThrowIOException(env, EINVAL);
        return -1;
    }

    b = env->GetByteArrayElements(jb, NULL);
    if (b == NULL) {
        jniThrowIOException(env, EINVAL);
        return -1;
    }

    total = 0;
    while (length > 0) {
        ret = asocket_write(s, &b[offset], length, -1);
        if (ret < 0) {
            jniThrowIOException(env, errno);
            env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
            return -1;
        }
        offset += ret;
        total += ret;
        length -= ret;
    }

    env->ReleaseByteArrayElements(jb, b, JNI_ABORT);  // no need to commit
    return (jint)total;

#endif
    jniThrowIOException(env, ENOSYS);
    return -1;
}
static void destroyNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    LOGV(__FUNCTION__);
    struct asocket *s = get_socketData(env, obj);
    int fd = s->fd;

    if (!s)
        return;

    asocket_destroy(s);

    LOGV("...asocket_destroy(%d) complete", fd);
    return;
#endif
    jniThrowIOException(env, ENOSYS);
}
Пример #5
0
static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
        jint length) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);

    int ret;
    jbyte *b;
    int sz;
    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return -1;
    if (jb == NULL) {
        jniThrowIOException(env, EINVAL);
        return -1;
    }
    sz = env->GetArrayLength(jb);
    if (offset < 0 || length < 0 || offset + length > sz) {
        jniThrowIOException(env, EINVAL);
        return -1;
    }

    b = env->GetByteArrayElements(jb, NULL);
    if (b == NULL) {
        jniThrowIOException(env, EINVAL);
        return -1;
    }

    ret = asocket_read(s, &b[offset], length, -1);
    if (ret < 0) {
        jniThrowIOException(env, errno);
        env->ReleaseByteArrayElements(jb, b, JNI_ABORT);
        return -1;
    }

    env->ReleaseByteArrayElements(jb, b, 0);
    return (jint)ret;

#endif
    jniThrowIOException(env, ENOSYS);
    return -1;
}
Пример #6
0
static jint availableNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);

    int available;
    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return -1;

    if (ioctl(s->fd, FIONREAD, &available) < 0) {
        jniThrowIOException(env, errno);
        return -1;
    }

    return available;

#endif
    jniThrowIOException(env, ENOSYS);
    return -1;
}
Пример #7
0
static void setAmpPolicyNative(JNIEnv *env, jobject obj, jint amppol) {
#ifdef HAVE_BLUETOOTH
    ALOGV(__FUNCTION__);

    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return;

    int err;
    err = setsockopt(s->fd, SOL_BLUETOOTH, BT_AMP_POLICY, &amppol, sizeof(amppol));
    if (err) {
        ALOGV("setsockopt() failed, throwing");
        jniThrowIOException(env, errno);
        return;
    }

    return;
#endif
    jniThrowIOException(env, ENOSYS);
}
Пример #8
0
static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);

    int fd;
    jint type;
    struct sockaddr *addr;
    socklen_t addr_sz;
    jstring addr_jstr;
    char addr_cstr[BTADDR_SIZE];
    bdaddr_t *bdaddr;
    jboolean auth;
    jboolean encrypt;

    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return NULL;

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

    switch (type) {
    case TYPE_RFCOMM:
        struct sockaddr_rc addr_rc;
        addr = (struct sockaddr *)&addr_rc;
        addr_sz = sizeof(addr_rc);
        bdaddr = &addr_rc.rc_bdaddr;
        memset(addr, 0, addr_sz);
        break;
    case TYPE_SCO:
        struct sockaddr_sco addr_sco;
        addr = (struct sockaddr *)&addr_sco;
        addr_sz = sizeof(addr_sco);
        bdaddr = &addr_sco.sco_bdaddr;
        memset(addr, 0, addr_sz);
        break;
    case TYPE_L2CAP:
    case TYPE_EL2CAP:
        struct sockaddr_l2 addr_l2;
        addr = (struct sockaddr *)&addr_l2;
        addr_sz = sizeof(addr_l2);
        bdaddr = &addr_l2.l2_bdaddr;
        memset(addr, 0, addr_sz);
        break;
    default:
        jniThrowIOException(env, ENOSYS);
        return NULL;
    }

    fd = asocket_accept(s, addr, &addr_sz, timeout);

    ALOGV("...accept(%d, %s) = %d (errno %d)",
            s->fd, TYPE_AS_STR(type), fd, errno);

    if (fd < 0) {
        jniThrowIOException(env, errno);
        return NULL;
    }

    /* Connected - return new BluetoothSocket */
    auth = env->GetBooleanField(obj, field_mAuth);
    encrypt = env->GetBooleanField(obj, field_mEncrypt);

    get_bdaddr_as_string(bdaddr, addr_cstr);

    addr_jstr = env->NewStringUTF(addr_cstr);
    return env->NewObject(class_BluetoothSocket, method_BluetoothSocket_ctor,
            type, fd, auth, encrypt, addr_jstr, -1);

#endif
    jniThrowIOException(env, ENOSYS);
    return NULL;
}
Пример #9
0
/* Returns errno instead of throwing, so java can check errno */
static int bindListenNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);

    jint type;
    socklen_t addr_sz;
    struct sockaddr *addr;
    bdaddr_t bdaddr = android_bluetooth_bdaddr_any();
    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return EINVAL;

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

    switch (type) {
    case TYPE_RFCOMM:
        struct sockaddr_rc addr_rc;
        addr = (struct sockaddr *)&addr_rc;
        addr_sz = sizeof(addr_rc);

        memset(addr, 0, addr_sz);
        addr_rc.rc_family = AF_BLUETOOTH;
        addr_rc.rc_channel = env->GetIntField(obj, field_mPort);
        memcpy(&addr_rc.rc_bdaddr, &bdaddr, sizeof(bdaddr_t));
        break;
    case TYPE_SCO:
        struct sockaddr_sco addr_sco;
        addr = (struct sockaddr *)&addr_sco;
        addr_sz = sizeof(addr_sco);

        memset(addr, 0, addr_sz);
        addr_sco.sco_family = AF_BLUETOOTH;
        memcpy(&addr_sco.sco_bdaddr, &bdaddr, sizeof(bdaddr_t));
        break;
    case TYPE_L2CAP:
    case TYPE_EL2CAP:
        struct sockaddr_l2 addr_l2;
        addr = (struct sockaddr *)&addr_l2;
        addr_sz = sizeof(addr_l2);

        memset(addr, 0, addr_sz);
        addr_l2.l2_family = AF_BLUETOOTH;
        addr_l2.l2_psm = env->GetIntField(obj, field_mPort);
        memcpy(&addr_l2.l2_bdaddr, &bdaddr, sizeof(bdaddr_t));
        break;
    default:
        return ENOSYS;
    }

    if (bind(s->fd, addr, addr_sz)) {
        ALOGV("...bind(%d) gave errno %d", s->fd, errno);
        return errno;
    }

    if (listen(s->fd, 1)) {
        ALOGV("...listen(%d) gave errno %d", s->fd, errno);
        return errno;
    }

    ALOGV("...bindListenNative(%d) success", s->fd);

    return 0;

#endif
    return ENOSYS;
}
Пример #10
0
static void connectNative(JNIEnv *env, jobject obj) {
#ifdef HAVE_BLUETOOTH
    ALOGV("%s", __FUNCTION__);

    int ret;
    jint type;
    const char *c_address;
    jstring address;
    bdaddr_t bdaddress;
    socklen_t addr_sz;
    struct sockaddr *addr;
    struct asocket *s = get_socketData(env, obj);
    int retry = 0;

    if (!s)
        return;

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

    /* parse address into bdaddress */
    address = (jstring) env->GetObjectField(obj, field_mAddress);
    c_address = env->GetStringUTFChars(address, NULL);
    if (get_bdaddr(c_address, &bdaddress)) {
        env->ReleaseStringUTFChars(address, c_address);
        jniThrowIOException(env, EINVAL);
        return;
    }
    env->ReleaseStringUTFChars(address, c_address);

    switch (type) {
    case TYPE_RFCOMM:
        struct sockaddr_rc addr_rc;
        addr = (struct sockaddr *)&addr_rc;
        addr_sz = sizeof(addr_rc);

        memset(addr, 0, addr_sz);
        addr_rc.rc_family = AF_BLUETOOTH;
        addr_rc.rc_channel = env->GetIntField(obj, field_mPort);
        memcpy(&addr_rc.rc_bdaddr, &bdaddress, sizeof(bdaddr_t));

        break;
    case TYPE_SCO_WBS:
    case TYPE_SCO:
        struct sockaddr_sco addr_sco;
        addr = (struct sockaddr *)&addr_sco;
        addr_sz = sizeof(addr_sco);

        memset(addr, 0, addr_sz);
        addr_sco.sco_family = AF_BLUETOOTH;
        addr_sco.is_wbs = (type == TYPE_SCO_WBS);
        memcpy(&addr_sco.sco_bdaddr, &bdaddress, sizeof(bdaddr_t));

        break;
    case TYPE_L2CAP:
    case TYPE_EL2CAP:
        struct sockaddr_l2 addr_l2;
        addr = (struct sockaddr *)&addr_l2;
        addr_sz = sizeof(addr_l2);

        memset(addr, 0, addr_sz);
        addr_l2.l2_family = AF_BLUETOOTH;
        addr_l2.l2_psm = env->GetIntField(obj, field_mPort);
        memcpy(&addr_l2.l2_bdaddr, &bdaddress, sizeof(bdaddr_t));

        break;
    default:
        jniThrowIOException(env, ENOSYS);
        return;
    }

connect:
    ret = asocket_connect(s, addr, addr_sz, -1);
    ALOGV("...connect(%d, %s) = %d (errno %d)",
            s->fd, TYPE_AS_STR(type), ret, errno);

    if (ret && errno == EALREADY && retry < 2) {
        /* workaround for bug 5082381 (EALREADY on ACL collision):
         * retry the connect. Unfortunately we have to create a new fd.
         * It's not ideal to switch the fd underneath the object, but
         * is currently safe */
        ALOGD("Hit bug 5082381 (EALREADY on ACL collision), trying workaround");
        usleep(100000);
        retry++;
        abortNative(env, obj);
        destroyNative(env, obj);
        initSocketNative(env, obj);
        if (env->ExceptionOccurred()) {
            return;
        }
        s = get_socketData(env, obj); //Due to init socket ptr would be updated
        goto connect;
    }
    if (!ret && retry > 0)
        ALOGD("...workaround ok");

    if (ret)
        jniThrowIOException(env, errno);

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

    int ret;
    jint type;
    const char *c_address;
    jstring address;
    bdaddr_t bdaddress;
    socklen_t addr_sz;
    struct sockaddr *addr;
    struct asocket *s = get_socketData(env, obj);

    if (!s)
        return;

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

    /* parse address into bdaddress */
    address = (jstring) env->GetObjectField(obj, field_mAddress);
    c_address = env->GetStringUTFChars(address, NULL);
    if (get_bdaddr(c_address, &bdaddress)) {
        env->ReleaseStringUTFChars(address, c_address);
        jniThrowIOException(env, EINVAL);
        return;
    }
    env->ReleaseStringUTFChars(address, c_address);

    switch (type) {
    case TYPE_RFCOMM:
        struct sockaddr_rc addr_rc;
        addr = (struct sockaddr *)&addr_rc;
        addr_sz = sizeof(addr_rc);

        memset(addr, 0, addr_sz);
        addr_rc.rc_family = AF_BLUETOOTH;
        addr_rc.rc_channel = env->GetIntField(obj, field_mPort);
        memcpy(&addr_rc.rc_bdaddr, &bdaddress, sizeof(bdaddr_t));

        break;
    case TYPE_SCO:
        struct sockaddr_sco addr_sco;
        addr = (struct sockaddr *)&addr_sco;
        addr_sz = sizeof(addr_sco);

        memset(addr, 0, addr_sz);
        addr_sco.sco_family = AF_BLUETOOTH;
        memcpy(&addr_sco.sco_bdaddr, &bdaddress, sizeof(bdaddr_t));

        break;
    case TYPE_L2CAP:
        struct sockaddr_l2 addr_l2;
        addr = (struct sockaddr *)&addr_l2;
        addr_sz = sizeof(addr_l2);

        memset(addr, 0, addr_sz);
        addr_l2.l2_family = AF_BLUETOOTH;
        addr_l2.l2_psm = env->GetIntField(obj, field_mPort);
        memcpy(&addr_l2.l2_bdaddr, &bdaddress, sizeof(bdaddr_t));

        break;
    default:
        jniThrowIOException(env, ENOSYS);
        return;
    }

    ret = asocket_connect(s, addr, addr_sz, -1);
    LOGV("...connect(%d, %s) = %d (errno %d)",
            s->fd, TYPE_AS_STR(type), ret, errno);

    if (ret)
        jniThrowIOException(env, errno);

    return;
#endif
    jniThrowIOException(env, ENOSYS);
}