Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
/*
 * 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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}