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); }