static void send_packet(void){ rfcomm_send(rfcomm_cid, (uint8_t*) test_data, test_data_len); test_track_sent(test_data_len); if (data_to_send <= test_data_len){ state = DONE; printf("SPP Streamer: enough data send, closing channel\n"); rfcomm_disconnect(rfcomm_cid); rfcomm_cid = 0; return; } data_to_send -= test_data_len; rfcomm_request_can_send_now_event(rfcomm_cid); }
static void hsp_run(void){ if (wait_ok) return; if (hsp_release_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_release_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hsp_disconnect_rfcomm){ hsp_disconnect_rfcomm = 0; hsp_establish_audio_connection = 0; rfcomm_disconnect(rfcomm_cid); return; } if (hsp_establish_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_establish_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hs_send_button_press){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hs_send_button_press = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } switch (hsp_state){ case HSP_SDP_QUERY_RFCOMM_CHANNEL: hsp_state = HSP_W4_SDP_QUERY_COMPLETE; sdp_client_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, SDP_Headset_AG); break; case HSP_AUDIO_CONNECTION_ESTABLISHED: case HSP_RFCOMM_CONNECTION_ESTABLISHED: if (hs_microphone_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_microphone_gain = -1; break; } if (hs_speaker_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, hs_speaker_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_speaker_gain = -1; break; } break; case HSP_W4_RFCOMM_DISCONNECTED: rfcomm_disconnect(rfcomm_cid); break; default: break; } }
/* * 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) * optionally protocol number (PRU_ATTACH) * message flags (PRU_RCVD) * ctl is either * optional mbuf chain containing socket options * optional interface pointer (PRU_CONTROL, PRU_PURGEIF) * l is pointer to process requesting action (if any) * * we are responsible for disposing of m and ctl if * they are mbuf chains */ int rfcomm_usrreq(struct socket *up, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *ctl, struct lwp *l) { struct rfcomm_dlc *pcb = up->so_pcb; struct sockaddr_bt *sa; struct mbuf *m0; int err = 0; DPRINTFN(2, "%s\n", prurequests[req]); switch (req) { case PRU_CONTROL: return EPASSTHROUGH; case PRU_PURGEIF: return EOPNOTSUPP; case PRU_ATTACH: if (up->so_lock == NULL) { mutex_obj_hold(bt_lock); up->so_lock = bt_lock; solock(up); } KASSERT(solocked(up)); if (pcb != NULL) return EINVAL; /* * Since we have nothing to add, we attach the DLC * structure directly to our PCB pointer. */ err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace); if (err) return err; err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb, &rfcomm_proto, up); if (err) return err; err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv)); if (err) { rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb); return err; } return 0; } if (pcb == NULL) { err = EINVAL; goto release; } switch(req) { case PRU_DISCONNECT: soisdisconnecting(up); return rfcomm_disconnect(pcb, up->so_linger); case PRU_ABORT: rfcomm_disconnect(pcb, 0); soisdisconnected(up); /* fall through to */ case PRU_DETACH: return rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb); 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 rfcomm_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 rfcomm_connect(pcb, sa); case PRU_PEERADDR: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); nam->m_len = sizeof(struct sockaddr_bt); return rfcomm_peeraddr(pcb, sa); case PRU_SOCKADDR: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); nam->m_len = sizeof(struct sockaddr_bt); return rfcomm_sockaddr(pcb, sa); case PRU_SHUTDOWN: socantsendmore(up); break; case PRU_SEND: KASSERT(m != NULL); if (ctl) /* no use for that */ m_freem(ctl); m0 = m_copypacket(m, M_DONTWAIT); if (m0 == NULL) return ENOMEM; sbappendstream(&up->so_snd, m); return rfcomm_send(pcb, m0); case PRU_SENSE: return 0; /* (no release) */ case PRU_RCVD: return rfcomm_rcvd(pcb, sbspace(&up->so_rcv)); case PRU_RCVOOB: return EOPNOTSUPP; /* (no release) */ case PRU_LISTEN: return rfcomm_listen(pcb); case PRU_ACCEPT: KASSERT(nam != NULL); sa = mtod(nam, struct sockaddr_bt *); nam->m_len = sizeof(struct sockaddr_bt); return rfcomm_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 void hsp_run(void){ if (wait_ok) return; if (hs_accept_sco_connection && hci_can_send_command_packet_now()){ hs_accept_sco_connection = 0; log_info("HSP: sending hci_accept_connection_request."); // remote supported feature eSCO is set if link type is eSCO // eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms, uint16_t max_latency; uint8_t retransmission_effort; uint16_t packet_types; if (hci_remote_esco_supported(rfcomm_handle)){ max_latency = 0x000c; retransmission_effort = 0x02; packet_types = 0x388; } else { max_latency = 0xffff; retransmission_effort = 0xff; packet_types = 0x003f; } uint16_t sco_voice_setting = hci_get_sco_voice_setting(); log_info("HFP: sending hci_accept_connection_request, sco_voice_setting %02x", sco_voice_setting); hci_send_cmd(&hci_accept_synchronous_connection, remote, 8000, 8000, max_latency, sco_voice_setting, retransmission_effort, packet_types); return; } if (hsp_release_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_release_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hsp_disconnect_rfcomm){ hsp_disconnect_rfcomm = 0; hsp_establish_audio_connection = 0; rfcomm_disconnect(rfcomm_cid); return; } if (hsp_establish_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_establish_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hs_send_button_press){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hs_send_button_press = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } switch (hsp_state){ case HSP_SDP_QUERY_RFCOMM_CHANNEL: hsp_state = HSP_W4_SDP_QUERY_COMPLETE; sdp_client_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, BLUETOOTH_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY_AG); break; case HSP_AUDIO_CONNECTION_ESTABLISHED: case HSP_RFCOMM_CONNECTION_ESTABLISHED: if (hs_microphone_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_microphone_gain = -1; break; } if (hs_speaker_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, hs_speaker_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_speaker_gain = -1; break; } break; case HSP_W4_RFCOMM_DISCONNECTED: rfcomm_disconnect(rfcomm_cid); break; default: break; } }