struct bt_sco *bt_sco_new(const bdaddr_t *local_bdaddr) { struct bt_sco *sco; if (!local_bdaddr) return NULL; /* For now we support only one SCO connection per time */ if (sco_in_use) return NULL; sco = new0(struct bt_sco, 1); if (!sco) return NULL; bacpy(&sco->local_addr, local_bdaddr); if (!sco_listen(sco)) { free(sco); return NULL; } sco_in_use = true; return bt_sco_ref(sco); }
int main(int argc, char *argv[]) { GOptionContext *context; context = g_option_context_new(NULL); g_option_context_add_main_entries(context, options, NULL); if (!g_option_context_parse(context, &argc, &argv, NULL)) exit(EXIT_FAILURE); g_option_context_free(context); printf("accept=%d reject=%d discon=%d defer=%d sec=%d update_sec=%d" " prio=%d voice=0x%04x\n", opt_accept, opt_reject, opt_disconn, opt_defer, opt_sec, opt_update_sec, opt_priority, opt_voice); if (opt_psm || opt_cid) { if (argc > 1) l2cap_connect(opt_dev, argv[1], opt_addr_type, opt_psm, opt_cid, opt_disconn, opt_sec, opt_priority); else l2cap_listen(opt_dev, opt_addr_type, opt_psm, opt_cid, opt_defer, opt_reject, opt_disconn, opt_accept, opt_sec, opt_master); } if (opt_channel != -1) { if (argc > 1) rfcomm_connect(opt_dev, argv[1], opt_channel, opt_disconn, opt_sec); else rfcomm_listen(opt_dev, opt_channel, opt_defer, opt_reject, opt_disconn, opt_accept, opt_sec, opt_master); } if (opt_sco) { if (argc > 1) sco_connect(opt_dev, argv[1], opt_disconn, opt_voice); else sco_listen(opt_dev, opt_defer, opt_reject, opt_disconn, opt_accept, opt_voice); } signal(SIGTERM, sig_term); signal(SIGINT, sig_term); main_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(main_loop); g_main_loop_unref(main_loop); printf("Exiting\n"); exit(EXIT_SUCCESS); }
/* * User Request. * up is socket * m is either * optional mbuf chain containing message * ioctl command (PRU_CONTROL) * nam is either * optional mbuf chain containing an address * ioctl data (PRU_CONTROL) * ctl is optional mbuf chain containing socket options * l is pointer to process requesting action (if any) * * we are responsible for disposing of m and ctl if * they are mbuf chains */ static int sco_usrreq(struct socket *up, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *ctl, struct lwp *l) { struct sco_pcb *pcb = (struct sco_pcb *)up->so_pcb; struct sockaddr_bt *sa; struct mbuf *m0; int err = 0; DPRINTFN(2, "%s\n", prurequests[req]); KASSERT(req != PRU_ATTACH); KASSERT(req != PRU_DETACH); switch(req) { case PRU_CONTROL: return EOPNOTSUPP; case PRU_PURGEIF: return EOPNOTSUPP; } /* anything after here *requires* a pcb */ if (pcb == NULL) { err = EINVAL; goto release; } switch(req) { case PRU_DISCONNECT: soisdisconnecting(up); return sco_disconnect(pcb, up->so_linger); case PRU_ABORT: sco_disconnect(pcb, 0); soisdisconnected(up); sco_detach(up); return 0; case PRU_BIND: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); if (sa->bt_len != sizeof(struct sockaddr_bt)) return EINVAL; if (sa->bt_family != AF_BLUETOOTH) return EAFNOSUPPORT; return sco_bind(pcb, sa); case PRU_CONNECT: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); if (sa->bt_len != sizeof(struct sockaddr_bt)) return EINVAL; if (sa->bt_family != AF_BLUETOOTH) return EAFNOSUPPORT; soisconnecting(up); return sco_connect(pcb, sa); case PRU_PEERADDR: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); nam->m_len = sizeof(struct sockaddr_bt); return sco_peeraddr(pcb, sa); case PRU_SOCKADDR: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); nam->m_len = sizeof(struct sockaddr_bt); return sco_sockaddr(pcb, sa); case PRU_SHUTDOWN: socantsendmore(up); break; case PRU_SEND: KASSERT(m != NULL); if (m->m_pkthdr.len == 0) break; if (m->m_pkthdr.len > pcb->sp_mtu) { err = EMSGSIZE; break; } m0 = m_copypacket(m, M_DONTWAIT); if (m0 == NULL) { err = ENOMEM; break; } if (ctl) /* no use for that */ m_freem(ctl); sbappendrecord(&up->so_snd, m); return sco_send(pcb, m0); case PRU_SENSE: return 0; /* (no sense - Doh!) */ case PRU_RCVD: case PRU_RCVOOB: return EOPNOTSUPP; /* (no release) */ case PRU_LISTEN: return sco_listen(pcb); case PRU_ACCEPT: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); nam->m_len = sizeof(struct sockaddr_bt); return sco_peeraddr(pcb, sa); case PRU_CONNECT2: case PRU_SENDOOB: case PRU_FASTTIMO: case PRU_SLOWTIMO: case PRU_PROTORCV: case PRU_PROTOSEND: err = EOPNOTSUPP; break; default: UNKNOWN(req); err = EOPNOTSUPP; break; } release: if (m) m_freem(m); if (ctl) m_freem(ctl); return err; }
static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m, void *userdata) { pa_bluetooth_backend *b = userdata; pa_bluetooth_device *d; pa_bluetooth_transport *t; pa_bluetooth_profile_t p; DBusMessage *r; int fd; const char *sender, *path, PA_UNUSED *handler; DBusMessageIter arg_i; char *pathfd; struct transport_data *trd; if (!dbus_message_iter_init(m, &arg_i) || !pa_streq(dbus_message_get_signature(m), "oha{sv}")) { pa_log_error("Invalid signature found in NewConnection"); goto fail; } handler = dbus_message_get_path(m); if (pa_streq(handler, HSP_AG_PROFILE)) { p = PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT; } else if (pa_streq(handler, HSP_HS_PROFILE)) { p = PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY; } else { pa_log_error("Invalid handler"); goto fail; } pa_assert(dbus_message_iter_get_arg_type(&arg_i) == DBUS_TYPE_OBJECT_PATH); dbus_message_iter_get_basic(&arg_i, &path); d = pa_bluetooth_discovery_get_device_by_path(b->discovery, path); if (d == NULL) { pa_log_error("Device doesnt exist for %s", path); goto fail; } pa_assert_se(dbus_message_iter_next(&arg_i)); pa_assert(dbus_message_iter_get_arg_type(&arg_i) == DBUS_TYPE_UNIX_FD); dbus_message_iter_get_basic(&arg_i, &fd); pa_log_debug("dbus: NewConnection path=%s, fd=%d, profile %s", path, fd, pa_bluetooth_profile_to_string(p)); sender = dbus_message_get_sender(m); pathfd = pa_sprintf_malloc ("%s/fd%d", path, fd); t = pa_bluetooth_transport_new(d, sender, pathfd, p, NULL, 0); pa_xfree(pathfd); t->acquire = sco_acquire_cb; t->release = sco_release_cb; t->destroy = transport_destroy; t->set_speaker_gain = set_speaker_gain; t->set_microphone_gain = set_microphone_gain; trd = pa_xnew0(struct transport_data, 1); trd->rfcomm_fd = fd; trd->mainloop = b->core->mainloop; trd->rfcomm_io = trd->mainloop->io_new(b->core->mainloop, fd, PA_IO_EVENT_INPUT, rfcomm_io_callback, t); t->userdata = trd; sco_listen(t); pa_bluetooth_transport_put(t); pa_log_debug("Transport %s available for profile %s", t->path, pa_bluetooth_profile_to_string(t->profile)); pa_assert_se(r = dbus_message_new_method_return(m)); return r; fail: pa_assert_se(r = dbus_message_new_error(m, "org.bluez.Error.InvalidArguments", "Unable to handle new connection")); return r; }