static err_t l2ca_recv_cb(void *arg, struct l2cap_pcb *pcb, struct pbuf *p, err_t err) { struct ds3wiibt_context *ctx = (struct ds3wiibt_context *)arg; if (ctx == NULL || pcb == NULL || err != ERR_OK) return -1; u8 *rd = p->payload; //LOG("RECV, PSM: 0x%02X len: %i |", l2cap_psm(pcb), p->len); //LOG(" 0x%X 0x%X 0x%X 0x%X 0x%X\n", rd[0], rd[1], rd[2], rd[3], rd[4]); switch (l2cap_psm(pcb)) { case HIDP_PSM: switch (rd[0]) { case 0x00: if (ctx->status == DS3WIIBT_STATUS_LISTENING) { send_output_report(ctx); ctx->status = DS3WIIBT_STATUS_CONNECTED; if (ctx->connect_cb) { ctx->connect_cb(ctx->usrdata); } } break; } break; case INTR_PSM: switch (rd[1]) { case 0x01: //Full report memcpy(&ctx->input, rd + 1, sizeof(ctx->input)); break; } break; } return ERR_OK; }
static err_t l2ca_disconnect_ind_cb(void *arg, struct l2cap_pcb *pcb, err_t err) { struct ds3wiibt_context *ctx = (struct ds3wiibt_context *)arg; if (ctx == NULL || pcb == NULL) return -1; //LOG("l2ca_disconnect_ind_cb, PSM: 0x%02X\n", l2cap_psm(pcb)); //We have received a disconnect request ctx->status = DS3WIIBT_STATUS_DISCONNECTING; switch (l2cap_psm(pcb)) { case HIDP_PSM: l2cap_close(ctx->ctrl_pcb); ctx->ctrl_pcb = NULL; break; case INTR_PSM: l2cap_close(ctx->data_pcb); ctx->data_pcb = NULL; break; } if ((ctx->ctrl_pcb == NULL) && (ctx->data_pcb == NULL)) { ctx->status = DS3WIIBT_STATUS_DISCONNECTED; if (ctx->disconnect_cb) { ctx->disconnect_cb(ctx->usrdata); } ds3wiibt_listen(ctx); } return ERR_OK; }
static err_t l2ca_connect_ind_cb(void *arg, struct l2cap_pcb *pcb, err_t err) { struct ds3wiibt_context *ctx = (struct ds3wiibt_context *)arg; if (ctx == NULL || pcb == NULL) return -1; //LOG("l2ca_connect_ind_cb, PSM: 0x%02X\n", l2cap_psm(pcb)); if (l2cap_psm(pcb) == HIDP_PSM) { /* Control PSM is connected */ l2cap_disconnect_ind(ctx->ctrl_pcb, l2ca_disconnect_ind_cb); l2cap_timeout_ind(ctx->ctrl_pcb, l2ca_timeout_ind_cb); l2cap_recv(ctx->ctrl_pcb, l2ca_recv_cb); } else if (l2cap_psm(pcb) == INTR_PSM) { /* Both Control PSM and Data PSM are connected */ l2cap_disconnect_ind(ctx->data_pcb, l2ca_disconnect_ind_cb); l2cap_timeout_ind(ctx->data_pcb, l2ca_timeout_ind_cb); l2cap_recv(ctx->data_pcb, l2ca_recv_cb); set_operational(ctx); } return ERR_OK; }
/* * l2cap_connected(): * * Called by L2CAP when a connection response was received. * Sends a L2CAP configuration request. * Initializes a search for other devices if the connection attempt failed. */ err_t l2cap_connected(void *arg, struct l2cap_pcb *l2cappcb, u16_t result, u16_t status) { struct sdp_pcb *sdppcb; struct rfcomm_pcb *rfcommpcb; u8_t ssp[] = {0x35, 0x03, 0x19, 0x11, 0x02}; /* Service search pattern with LAP UUID is default */ err_t ret; u8_t attrids[] = {0x35, 0x03, 0x09, 0x00, 0x04}; /* Attribute IDs to search for in data element sequence form */ if(result == L2CAP_CONN_SUCCESS) { LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: L2CAP connected pcb->state = %d\n", l2cappcb->state)); /* Tell L2CAP that we wish to be informed of a disconnection request */ l2cap_disconnect_ind(l2cappcb, l2cap_disconnected_ind); switch(l2cap_psm(l2cappcb)) { case SDP_PSM: LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: SDP L2CAP configured. Result = %d\n", result)); if((sdppcb = sdp_new(l2cappcb)) == NULL) { LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: Failed to create a SDP PCB\n")); return ERR_MEM; } l2cap_recv(l2cappcb, sdp_recv); ret = sdp_service_search_attrib_req(sdppcb, 0xFFFF, ssp, sizeof(ssp), attrids, sizeof(attrids), sdp_attributes_recv); return ret; case RFCOMM_PSM: LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: RFCOMM L2CAP configured. Result = %d CN = %d\n", result, bt_spp_state.cn)); l2cap_recv(l2cappcb, rfcomm_input); if((rfcommpcb = rfcomm_new(l2cappcb)) == NULL) { LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: Failed to create a RFCOMM PCB\n")); return ERR_MEM; } hci_link_key_not(link_key_not); /* Set function to be called if a new link key is created */ return rfcomm_connect(rfcommpcb, bt_spp_state.cn, rfcomm_connected); /* Connect with DLCI 0 */ default: return ERR_VAL; } } else { LWIP_DEBUGF(BT_SPP_DEBUG, ("l2cap_connected: L2CAP not connected. Redo inquiry\n")); l2cap_close(l2cappcb); bt_spp_start(); } return ERR_OK; }
static err_t l2ca_timeout_ind_cb(void *arg, struct l2cap_pcb *pcb, err_t err) { struct ds3wiibt_context *ctx = (struct ds3wiibt_context *)arg; if (ctx == NULL || pcb == NULL) return -1; //LOG("l2ca_timeout_ind_cb, PSM: 0x%02X\n", l2cap_psm(pcb)); //Disconnect? switch (l2cap_psm(pcb)) { case HIDP_PSM: break; case INTR_PSM: break; } return ERR_OK; }
static err_t l2ca_disconnect_cfm_cb(void *arg, struct l2cap_pcb *pcb) { struct ds3wiibt_context *ctx = (struct ds3wiibt_context *)arg; if (ctx == NULL || pcb == NULL) return -1; //LOG("l2ca_disconnect_cfm_cb, PSM: 0x%02X\n", l2cap_psm(pcb)); switch (l2cap_psm(pcb)) { case HIDP_PSM: l2cap_close(ctx->ctrl_pcb); ctx->ctrl_pcb = NULL; break; case INTR_PSM: l2cap_close(ctx->data_pcb); ctx->data_pcb = NULL; break; } return ERR_OK; }