mirror of
https://github.com/libretro/RetroArch
synced 2025-02-19 12:41:00 +00:00
(iOS) BTstack fixups; start multiplayer support
This commit is contained in:
parent
c63074d04d
commit
8ea92fb004
@ -26,55 +26,84 @@
|
||||
#include "btpad_queue.h"
|
||||
#include "wiimote.h"
|
||||
|
||||
static btpad_connection_t btpad_connection;
|
||||
#define MAX_SLOTS 4
|
||||
static btpad_connection_t btpad_connection[MAX_SLOTS];
|
||||
static struct btpad_interface* btpad_iface[MAX_SLOTS];
|
||||
static void* btpad_device[MAX_SLOTS];
|
||||
|
||||
static bool btpad_connection_test(uint16_t handle, bd_addr_t address)
|
||||
static int32_t btpad_find_slot_for(uint16_t handle, bd_addr_t address)
|
||||
{
|
||||
if (handle && btpad_connection.handle && handle != btpad_connection.handle)
|
||||
return false;
|
||||
btpad_connection.handle = handle ? handle : btpad_connection.handle;
|
||||
|
||||
if (address && btpad_connection.has_address && (BD_ADDR_CMP(address, btpad_connection.address)))
|
||||
return false;
|
||||
|
||||
if (address)
|
||||
for (int i = 0; i < MAX_SLOTS; i ++)
|
||||
{
|
||||
btpad_connection.has_address = true;
|
||||
memcpy(btpad_connection.address, address, sizeof(bd_addr_t));
|
||||
if (!btpad_connection[i].handle && !btpad_connection[i].has_address)
|
||||
continue;
|
||||
|
||||
if (handle && btpad_connection[i].handle && handle != btpad_connection[i].handle)
|
||||
continue;
|
||||
|
||||
if (address && btpad_connection[i].has_address && (BD_ADDR_CMP(address, btpad_connection[i].address)))
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct btpad_interface* btpad_iface;
|
||||
static void* btpad_device;
|
||||
static int32_t btpad_find_slot_with_state(enum btpad_state state)
|
||||
{
|
||||
for (int i = 0; i < MAX_SLOTS; i ++)
|
||||
if (btpad_connection[i].state == state)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// MAIN THREAD ONLY
|
||||
uint32_t btpad_get_buttons()
|
||||
uint32_t btpad_get_buttons(/*uint32_t slot*/)
|
||||
{
|
||||
return (btpad_device && btpad_iface) ? btpad_iface->get_buttons(btpad_device) : 0;
|
||||
uint32_t slot = 0;
|
||||
|
||||
if (slot < MAX_SLOTS && btpad_device[slot] && btpad_iface[slot])
|
||||
return btpad_iface[slot]->get_buttons(btpad_device[slot]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t btpad_get_axis(unsigned axis)
|
||||
int16_t btpad_get_axis(/*uint32_t slot,*/ unsigned axis)
|
||||
{
|
||||
return (btpad_device && btpad_iface) ? btpad_iface->get_axis(btpad_device, axis) : 0;
|
||||
uint32_t slot = 0;
|
||||
|
||||
if (slot < MAX_SLOTS && btpad_device[slot] && btpad_iface[slot])
|
||||
return btpad_iface[slot]->get_axis(btpad_device[slot], axis);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btpad_disconnect_pad()
|
||||
static void btpad_disconnect_pad(uint32_t slot)
|
||||
{
|
||||
if (btpad_iface && btpad_device)
|
||||
if (slot > MAX_SLOTS)
|
||||
return;
|
||||
|
||||
if (btpad_iface[slot] && btpad_device[slot])
|
||||
{
|
||||
ios_add_log_message("BTpad: Disconnecting");
|
||||
ios_add_log_message("BTpad: Disconnecting slot %d", slot);
|
||||
|
||||
btpad_iface->disconnect(btpad_device);
|
||||
btpad_device = 0;
|
||||
btpad_iface = 0;
|
||||
btpad_iface[slot]->disconnect(btpad_device[slot]);
|
||||
btpad_device[slot] = 0;
|
||||
btpad_iface[slot] = 0;
|
||||
}
|
||||
|
||||
if (btpad_connection.handle)
|
||||
btpad_queue_hci_disconnect(btpad_connection.handle, 0x15);
|
||||
if (btpad_connection[slot].handle)
|
||||
btpad_queue_hci_disconnect(btpad_connection[slot].handle, 0x15);
|
||||
|
||||
memset(&btpad_connection, 0, sizeof(btpad_connection_t));
|
||||
memset(&btpad_connection[slot], 0, sizeof(btpad_connection_t));
|
||||
}
|
||||
|
||||
static void btpad_disconnect_all_pads()
|
||||
{
|
||||
for (int i = 0; i < MAX_SLOTS; i ++)
|
||||
btpad_disconnect_pad(i);
|
||||
}
|
||||
|
||||
void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
|
||||
@ -85,7 +114,8 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
{
|
||||
switch (packet[0])
|
||||
{
|
||||
case BTSTACK_EVENT_STATE:
|
||||
case BTSTACK_EVENT_STATE:
|
||||
{
|
||||
if (packet[2] == HCI_STATE_WORKING)
|
||||
{
|
||||
btpad_queue_reset();
|
||||
@ -94,32 +124,34 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
btpad_queue_l2cap_register_service(PSM_HID_CONTROL, 672); // TODO: Where did I get 672 for mtu?
|
||||
btpad_queue_l2cap_register_service(PSM_HID_INTERRUPT, 672);
|
||||
btpad_queue_hci_inquiry(HCI_INQUIRY_LAP, 3, 1);
|
||||
|
||||
btpad_queue_run(1);
|
||||
}
|
||||
else if(packet[2] > HCI_STATE_WORKING && btpad_iface && btpad_device)
|
||||
{
|
||||
btpad_disconnect_pad();
|
||||
btpad_queue_reset();
|
||||
btpad_disconnect_all_pads();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_STATUS:
|
||||
{
|
||||
btpad_queue_run(packet[3]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
{
|
||||
btpad_queue_run(packet[2]);
|
||||
|
||||
if (COMMAND_COMPLETE_EVENT(packet, (*hci_read_bd_addr_ptr)))
|
||||
{
|
||||
if (!packet[5])
|
||||
{
|
||||
bt_flip_addr_ptr(event_addr, &packet[6]);
|
||||
ios_add_log_message("BTpad: Local address is %s", bd_addr_to_str_ptr(event_addr));
|
||||
}
|
||||
else
|
||||
ios_add_log_message("BTpad: Failed to get local address (Status: %02X)", packet[5]);
|
||||
bt_flip_addr_ptr(event_addr, &packet[6]);
|
||||
if (!packet[5]) ios_add_log_message("BTpad: Local address is %s", bd_addr_to_str_ptr(event_addr));
|
||||
else ios_add_log_message("BTpad: Failed to get local address (Status: %02X)", packet[5]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case L2CAP_EVENT_SERVICE_REGISTERED:
|
||||
{
|
||||
@ -141,15 +173,23 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
if (packet[2])
|
||||
{
|
||||
bt_flip_addr_ptr(event_addr, &packet[3]);
|
||||
if (btpad_connection_test(0, event_addr))
|
||||
|
||||
const int32_t slot = btpad_find_slot_with_state(BTPAD_EMPTY);
|
||||
if (slot >= 0)
|
||||
{
|
||||
btpad_connection.state = BTPAD_WANT_INQ_COMPLETE;
|
||||
ios_add_log_message("BTpad: Inquiry found device (Slot %d)", slot);
|
||||
|
||||
btpad_connection.page_scan_repetition_mode = packet [3 + packet[2] * (6)];
|
||||
btpad_connection.class = READ_BT_24(packet, 3 + packet[2] * (6+1+1+1));
|
||||
btpad_connection.clock_offset = READ_BT_16(packet, 3 + packet[2] * (6+1+1+1+3)) & 0x7fff;
|
||||
memcpy(btpad_connection[slot].address, event_addr, sizeof(bd_addr_t));
|
||||
|
||||
ios_add_log_message("BTpad: Inquiry found device");
|
||||
btpad_connection[slot].has_address = true;
|
||||
btpad_connection[slot].state = BTPAD_CONNECTING;
|
||||
|
||||
btpad_connection[slot].page_scan_repetition_mode = packet [3 + packet[2] * (6)];
|
||||
btpad_connection[slot].class = READ_BT_24(packet, 3 + packet[2] * (6+1+1+1));
|
||||
btpad_connection[slot].clock_offset = READ_BT_16(packet, 3 + packet[2] * (6+1+1+1+3)) & 0x7fff;
|
||||
|
||||
btpad_queue_l2cap_create_channel(btpad_connection[slot].address, PSM_HID_CONTROL);
|
||||
btpad_queue_l2cap_create_channel(btpad_connection[slot].address, PSM_HID_INTERRUPT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,13 +197,7 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
|
||||
case HCI_EVENT_INQUIRY_COMPLETE:
|
||||
{
|
||||
if (btpad_connection.state == BTPAD_WANT_INQ_COMPLETE)
|
||||
{
|
||||
ios_add_log_message("BTpad: Got inquiry complete; connecting\n");
|
||||
btpad_queue_l2cap_create_channel(btpad_connection.address, PSM_HID_CONTROL);
|
||||
btpad_queue_l2cap_create_channel(btpad_connection.address, PSM_HID_INTERRUPT);
|
||||
}
|
||||
|
||||
// TODO: Check performance and batter effect of this
|
||||
btpad_queue_hci_inquiry(HCI_INQUIRY_LAP, 3, 1);
|
||||
}
|
||||
break;
|
||||
@ -175,32 +209,34 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
const uint16_t psm = READ_BT_16(packet, 11);
|
||||
const uint16_t channel_id = READ_BT_16(packet, 13);
|
||||
|
||||
if (!btpad_connection_test(handle, event_addr))
|
||||
{
|
||||
ios_add_log_message("BTpad: Incoming L2CAP connection not recognized; ignoring");
|
||||
break;
|
||||
}
|
||||
const int32_t slot = btpad_find_slot_for(handle, event_addr);
|
||||
|
||||
if (!packet[2])
|
||||
{
|
||||
ios_add_log_message("BTpad: L2CAP channel opened for psm: %02X", psm);
|
||||
if (slot < 0)
|
||||
{
|
||||
ios_add_log_message("BTpad: Got L2CAP 'Channel Opened' event for unrecognized device");
|
||||
break;
|
||||
}
|
||||
|
||||
ios_add_log_message("BTpad: L2CAP channel opened: (Slot: %d, PSM: %02X)", slot, psm);
|
||||
|
||||
if (psm == PSM_HID_CONTROL)
|
||||
btpad_connection.channels[0] = channel_id;
|
||||
btpad_connection[slot].channels[0] = channel_id;
|
||||
else if (psm == PSM_HID_INTERRUPT)
|
||||
btpad_connection.channels[1] = channel_id;
|
||||
btpad_connection[slot].channels[1] = channel_id;
|
||||
else
|
||||
ios_add_log_message("BTpad: Got unknown L2CAP PSM, ignoring (PSM: %02X)", psm);
|
||||
ios_add_log_message("BTpad: Got unknown L2CAP PSM, ignoring (Slot: %d, PSM: %02X)", slot, psm);
|
||||
|
||||
if (btpad_connection.channels[0] && btpad_connection.channels[1])
|
||||
if (btpad_connection[slot].channels[0] && btpad_connection[slot].channels[1])
|
||||
{
|
||||
ios_add_log_message("BTpad: Got both L2CAP channels, requesting name");
|
||||
btpad_queue_hci_remote_name_request(btpad_connection.address, btpad_connection.page_scan_repetition_mode,
|
||||
0, btpad_connection.clock_offset | 0x8000);
|
||||
ios_add_log_message("BTpad: Got both L2CAP channels, requesting name (Slot: %d)", slot);
|
||||
btpad_queue_hci_remote_name_request(btpad_connection[slot].address, btpad_connection[slot].page_scan_repetition_mode,
|
||||
0, btpad_connection[slot].clock_offset | 0x8000);
|
||||
}
|
||||
}
|
||||
else
|
||||
ios_add_log_message("BTpad: Failed to open L2CAP channel (PSM: %02X, Status: %02X)", psm, packet[2]);
|
||||
ios_add_log_message("BTpad: Got failed L2CAP 'Channel Opened' event (Slot %d, PSM: %02X, Status: %02X)", -1, psm, packet[2]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -213,26 +249,26 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
|
||||
const unsigned interrupt = (psm == PSM_HID_INTERRUPT) ? 1 : 0;
|
||||
|
||||
ios_add_log_message("BTpad: Incoming L2CAP connection for PSM: %02X", psm);
|
||||
|
||||
if (!btpad_connection_test(handle, event_addr))
|
||||
int32_t slot = btpad_find_slot_for(handle, event_addr);
|
||||
if (slot < 0)
|
||||
{
|
||||
ios_add_log_message("BTpad: Connection is for unregnized handle or address, denying");
|
||||
slot = btpad_find_slot_with_state(BTPAD_EMPTY);
|
||||
|
||||
// TODO: Check error code
|
||||
btpad_queue_l2cap_decline_connection(channel_id, 0x15);
|
||||
if (slot >= 0)
|
||||
{
|
||||
ios_add_log_message("BTpad: Got new incoming connection (Slot: %d)", slot);
|
||||
|
||||
break;
|
||||
memcpy(btpad_connection[slot].address, event_addr, sizeof(bd_addr_t));
|
||||
|
||||
btpad_connection[slot].has_address = true;
|
||||
btpad_connection[slot].handle = handle;
|
||||
btpad_connection[slot].state = BTPAD_CONNECTING;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
btpad_connection.channels[interrupt] = channel_id;
|
||||
ios_add_log_message("BTpad: Incoming L2CAP connection (Slot: %d, PSM: %02X)", slot, psm);
|
||||
btpad_queue_l2cap_accept_connection(channel_id);
|
||||
|
||||
if (btpad_connection.channels[0] && btpad_connection.channels[1])
|
||||
{
|
||||
ios_add_log_message("BTpad: Got both L2CAP channels, requesting name");
|
||||
btpad_queue_hci_remote_name_request(btpad_connection.address, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -240,30 +276,30 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
{
|
||||
bt_flip_addr_ptr(event_addr, &packet[3]);
|
||||
|
||||
if (!btpad_connection_test(0, event_addr))
|
||||
const int32_t slot = btpad_find_slot_for(0, event_addr);
|
||||
if (slot < 0)
|
||||
{
|
||||
ios_add_log_message("BTpad: Got unexpected remote name, ignoring");
|
||||
break;
|
||||
}
|
||||
|
||||
ios_add_log_message("BTpad: Got %200s", (char*)&packet[9]);
|
||||
ios_add_log_message("BTpad: Got %.200s (Slot: %d)", (char*)&packet[9], slot);
|
||||
if (strncmp((char*)&packet[9], "PLAYSTATION(R)3 Controller", 26) == 0)
|
||||
btpad_iface = &btpad_ps3;
|
||||
btpad_iface[slot] = &btpad_ps3;
|
||||
else if (strncmp((char*)&packet[9], "Nintendo RVL-CNT-01", 19) == 0)
|
||||
btpad_iface = &btpad_wii;
|
||||
btpad_iface[slot] = &btpad_wii;
|
||||
|
||||
if (btpad_iface)
|
||||
if (btpad_iface[slot])
|
||||
{
|
||||
btpad_device = btpad_iface->connect(&btpad_connection);
|
||||
btpad_connection.state = BTPAD_CONNECTED;
|
||||
btpad_device[slot] = btpad_iface[slot]->connect(&btpad_connection[slot]);
|
||||
btpad_connection[slot].state = BTPAD_CONNECTED;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
{
|
||||
ios_add_log_message("BTpad: Sending PIN");
|
||||
ios_add_log_message("BTpad: Sending WiiMote PIN");
|
||||
|
||||
bt_flip_addr_ptr(event_addr, &packet[2]);
|
||||
btpad_queue_hci_pin_code_request_reply(event_addr, &packet[2]);
|
||||
@ -272,6 +308,7 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
}
|
||||
}
|
||||
|
||||
if (btpad_device && btpad_iface)
|
||||
btpad_iface->packet_handler(btpad_device, packet_type, channel, packet, size);
|
||||
for (int i = 0; i < MAX_SLOTS; i ++)
|
||||
if (btpad_device[i] && btpad_iface[i] && (btpad_connection[i].channels[0] == channel || btpad_connection[i].channels[1] == channel))
|
||||
btpad_iface[i]->packet_handler(btpad_device[i], packet_type, channel, packet, size);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ uint32_t btpad_get_buttons();
|
||||
int16_t btpad_get_axis(unsigned axis);
|
||||
|
||||
// Private interface
|
||||
enum btpad_state { BTPAD_EMPTY, BTPAD_WANT_INQ_COMPLETE, BTPAD_CONNECTED };
|
||||
enum btpad_state { BTPAD_EMPTY, BTPAD_CONNECTING, BTPAD_CONNECTED };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include "btpad.h"
|
||||
#include "btpad_queue.h"
|
||||
|
||||
// NOTE: It seems that it is not needed to wait for the l2cap commands; TODO: Confirm
|
||||
// #define WAIT_FOR_L2CAP
|
||||
|
||||
struct btpad_queue_command
|
||||
{
|
||||
const hci_cmd_t* command;
|
||||
@ -55,6 +58,7 @@ struct btpad_queue_command
|
||||
bd_addr_t pin;
|
||||
} hci_pin_code_request_reply;
|
||||
|
||||
#ifdef WAIT_FOR_L2CAP
|
||||
struct
|
||||
{
|
||||
uint16_t psm;
|
||||
@ -77,6 +81,7 @@ struct btpad_queue_command
|
||||
uint16_t cid;
|
||||
uint8_t reason;
|
||||
} l2cap_decline_connection;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
@ -91,6 +96,7 @@ void btpad_queue_reset()
|
||||
{
|
||||
insert_position = 0;
|
||||
read_position = 0;
|
||||
can_run = 1;
|
||||
}
|
||||
|
||||
void btpad_queue_run(uint32_t count)
|
||||
@ -104,12 +110,6 @@ void btpad_queue_process()
|
||||
{
|
||||
for (; can_run && (insert_position != read_position); can_run --)
|
||||
{
|
||||
if (insert_position == read_position)
|
||||
{
|
||||
can_run ++;
|
||||
return;
|
||||
}
|
||||
|
||||
struct btpad_queue_command* cmd = &commands[read_position];
|
||||
|
||||
if (cmd->command == btstack_set_power_mode_ptr)
|
||||
@ -125,6 +125,7 @@ void btpad_queue_process()
|
||||
cmd->hci_remote_name_request.reserved, cmd->hci_remote_name_request.clock_offset);
|
||||
else if (cmd->command == hci_pin_code_request_reply_ptr)
|
||||
bt_send_cmd_ptr(cmd->command, cmd->hci_pin_code_request_reply.bd_addr, 6, cmd->hci_pin_code_request_reply.pin);
|
||||
#ifdef WAIT_FOR_L2CAP
|
||||
else if (cmd->command == l2cap_register_service_ptr)
|
||||
bt_send_cmd_ptr(cmd->command, cmd->l2cap_register_service.psm, cmd->l2cap_register_service.mtu);
|
||||
else if (cmd->command == l2cap_create_channel_ptr)
|
||||
@ -133,6 +134,7 @@ void btpad_queue_process()
|
||||
bt_send_cmd_ptr(cmd->command, cmd->l2cap_accept_connection.cid);
|
||||
else if (cmd->command == l2cap_decline_connection_ptr)
|
||||
bt_send_cmd_ptr(cmd->command, cmd->l2cap_decline_connection.cid, cmd->l2cap_decline_connection.reason);
|
||||
#endif
|
||||
|
||||
INCPOS(read);
|
||||
}
|
||||
@ -210,6 +212,8 @@ void btpad_queue_hci_pin_code_request_reply(bd_addr_t bd_addr, bd_addr_t pin)
|
||||
btpad_queue_process();
|
||||
}
|
||||
|
||||
// NOTE: It seems the l2cap commands don't need to wait
|
||||
#ifdef WAIT_FOR_L2CAP
|
||||
void btpad_queue_l2cap_register_service(uint16_t psm, uint16_t mtu)
|
||||
{
|
||||
struct btpad_queue_command* cmd = &commands[insert_position];
|
||||
@ -256,3 +260,24 @@ void btpad_queue_l2cap_decline_connection(uint16_t cid, uint8_t reason)
|
||||
INCPOS(insert);
|
||||
btpad_queue_process();
|
||||
}
|
||||
#else
|
||||
void btpad_queue_l2cap_register_service(uint16_t psm, uint16_t mtu)
|
||||
{
|
||||
bt_send_cmd_ptr(l2cap_register_service_ptr, psm, mtu);
|
||||
}
|
||||
|
||||
void btpad_queue_l2cap_create_channel(bd_addr_t bd_addr, uint16_t psm)
|
||||
{
|
||||
bt_send_cmd_ptr(l2cap_create_channel_ptr, bd_addr, psm);
|
||||
}
|
||||
|
||||
void btpad_queue_l2cap_accept_connection(uint16_t cid)
|
||||
{
|
||||
bt_send_cmd_ptr(l2cap_accept_connection_ptr, cid);
|
||||
}
|
||||
|
||||
void btpad_queue_l2cap_decline_connection(uint16_t cid, uint8_t reason)
|
||||
{
|
||||
bt_send_cmd_ptr(l2cap_decline_connection_ptr, cid, reason);
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user