(Apple) Rework gamepad connection management; fix BTstack support when building with the iOS 7 SDK.

This commit is contained in:
meancoot 2013-10-03 17:43:41 -04:00
parent fe8b6c3c0f
commit fae300aaaf
10 changed files with 215 additions and 238 deletions

View File

@ -15,32 +15,25 @@
#include <IOKit/hid/IOHIDManager.h>
#include "apple/common/apple_input.h"
#include "apple/common/hidpad/hidpad.h"
struct hidpad_connection
struct apple_pad_connection
{
uint32_t slot;
struct hidpad_interface* interface;
void* hidpad;
IOHIDDeviceRef device;
uint8_t data[2048];
};
static IOHIDManagerRef g_hid_manager;
static struct hidpad_connection g_connected_pads[MAX_PADS];
void hidpad_send_control(struct hidpad_connection* connection, uint8_t* data, size_t size)
void apple_pad_send_control(struct apple_pad_connection* connection, uint8_t* data, size_t size)
{
IOHIDDeviceSetReport(connection->device, kIOHIDReportTypeOutput, 0x01, data, size);
IOHIDDeviceSetReport(connection->device, kIOHIDReportTypeOutput, 0x01, data + 1, size - 1);
}
// NOTE: I pieced this together through trial and error, any corrections are welcome
static void hid_device_input_callback(void* context, IOReturn result, void* sender, IOHIDValueRef value)
{
struct hidpad_connection* connection = context;
struct apple_pad_connection* connection = context;
IOHIDElementRef element = IOHIDValueGetElement(value);
uint32_t type = IOHIDElementGetType(element);
@ -97,16 +90,15 @@ static void hid_device_input_callback(void* context, IOReturn result, void* send
static void hid_device_removed(void* context, IOReturn result, void* sender)
{
struct hidpad_connection* connection = (struct hidpad_connection*)context;
struct apple_pad_connection* connection = (struct apple_pad_connection*)context;
if (connection && connection->slot < MAX_PADS)
if (connection && connection->slot < MAX_PLAYERS)
{
g_current_input_data.pad_buttons[connection->slot] = 0;
memset(g_current_input_data.pad_axis[connection->slot], 0, sizeof(g_current_input_data.pad_axis));
if (connection->interface)
connection->interface->disconnect(connection->hidpad);
memset(connection, 0, sizeof(*connection));
apple_joypad_disconnect(connection->slot);
free(connection);
}
IOHIDDeviceClose(sender, kIOHIDOptionsTypeNone);
@ -114,8 +106,8 @@ static void hid_device_removed(void* context, IOReturn result, void* sender)
static void hid_device_report(void* context, IOReturn result, void *sender, IOHIDReportType type, uint32_t reportID, uint8_t *report, CFIndex reportLength)
{
struct hidpad_connection* connection = (struct hidpad_connection*)context;
connection->interface->packet_handler(connection->hidpad, report, reportLength);
struct apple_pad_connection* connection = (struct apple_pad_connection*)context;
apple_joypad_packet(connection->slot, connection->data, reportLength + 1);
}
static void hid_manager_device_attached(void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
@ -123,24 +115,9 @@ static void hid_manager_device_attached(void* context, IOReturn result, void* se
bool is_pad = (IOHIDDeviceConformsTo(device, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) ||
IOHIDDeviceConformsTo(device, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad));
struct hidpad_connection* connection = 0;
if (is_pad)
{
for (int i = 0; i != MAX_PADS; i ++)
{
if (!g_connected_pads[i].device)
{
connection = &g_connected_pads[i];
connection->device = device;
connection->slot = i;
break;
}
}
if (!connection)
return;
}
struct apple_pad_connection* connection = calloc(1, sizeof(struct apple_pad_connection));
connection->device = device;
connection->slot = MAX_PLAYERS;
IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);
IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
@ -149,27 +126,14 @@ static void hid_manager_device_attached(void* context, IOReturn result, void* se
CFStringRef device_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
if (is_pad && device_name)
{
static const struct { const char* name; struct hidpad_interface* iface; } hidpad_map[] = {
{ "Nintendo RVL-CNT-01", &hidpad_wii },
{ "PLAYSTATION(R)3 Controller", &hidpad_ps3 },
{ 0, 0} };
char buffer[1024];
CFStringGetCString(device_name, buffer, 1024, kCFStringEncodingUTF8);
for (int i = 0; hidpad_map[i].name; i ++)
{
if (strstr(buffer, hidpad_map[i].name))
{
connection->interface = hidpad_map[i].iface;
IOHIDDeviceRegisterInputReportCallback(device, connection->data, 2048, hid_device_report, connection);
connection->hidpad = connection->interface->connect(connection, connection->slot);
return;
}
}
connection->slot = apple_joypad_connect(buffer, connection);
IOHIDDeviceRegisterInputReportCallback(device, connection->data + 1, sizeof(connection->data) - 1, hid_device_report, connection);
}
IOHIDDeviceRegisterInputValueCallback(device, hid_device_input_callback, connection);
else
IOHIDDeviceRegisterInputValueCallback(device, hid_device_input_callback, connection);
}
static void append_matching_dictionary(CFMutableArrayRef array, uint32_t page, uint32_t use)

View File

@ -16,10 +16,11 @@
#ifndef __APPLE_RARCH_INPUT_H__
#define __APPLE_RARCH_INPUT_H__
#include "general.h"
// Input responder
#define MAX_TOUCHES 16
#define MAX_KEYS 256
#define MAX_PADS 4
typedef struct
{
@ -38,10 +39,28 @@ typedef struct
uint32_t keys[MAX_KEYS];
uint32_t pad_buttons[MAX_PADS];
int16_t pad_axis[MAX_PADS][4];
uint32_t pad_buttons[MAX_PLAYERS];
int16_t pad_axis[MAX_PLAYERS][4];
} apple_input_data_t;
struct apple_pad_connection;
struct apple_pad_interface
{
void* (*connect)(struct apple_pad_connection* connection, uint32_t slot);
void (*disconnect)(void* device);
void (*packet_handler)(void* device, uint8_t *packet, uint16_t size);
};
// Joypad data
int32_t apple_joypad_connect(const char* name, struct apple_pad_connection* connection);
void apple_joypad_disconnect(uint32_t slot);
void apple_joypad_packet(uint32_t slot, uint8_t* data, uint32_t length);
// This is implemented in the platform specific portions of the input code
void apple_joypad_send_hid_control(struct apple_pad_connection* connection, uint8_t* data, size_t size);
// Input data for the main thread and the game thread
extern apple_input_data_t g_current_input_data; //< Main thread data
extern apple_input_data_t g_polled_input_data; //< Game thread data
@ -51,7 +70,6 @@ uint32_t apple_input_get_icade_buttons();
void apple_input_reset_icade_buttons();
void apple_input_handle_key_event(unsigned keycode, bool down);
extern int32_t apple_input_find_any_key();
extern int32_t apple_input_find_any_button(uint32_t port);
extern int32_t apple_input_find_any_axis(uint32_t port);

View File

@ -25,10 +25,77 @@
#endif
#include "apple/common/hidpad/wiimote.c"
#include "apple/common/hidpad/hidpad_ps3.c"
#include "apple/common/hidpad/hidpad_wii.c"
#include "apple/common/hidpad/apple_ps3_pad.c"
#include "apple/common/hidpad/apple_wii_pad.c"
typedef struct
{
bool used;
struct apple_pad_interface* iface;
void* data;
} joypad_slot_t;
static joypad_slot_t slots[MAX_PLAYERS];
static int32_t find_empty_slot()
{
for (int i = 0; i != MAX_PLAYERS; i ++)
if (!slots[i].used)
return i;
return -1;
}
int32_t apple_joypad_connect(const char* name, struct apple_pad_connection* connection)
{
int32_t slot = find_empty_slot();
if (slot >= 0 && slot < MAX_PLAYERS)
{
joypad_slot_t* s = &slots[slot];
s->used = true;
static const struct { const char* name; struct apple_pad_interface* iface; } pad_map[] = {
{ "Nintendo RVL-CNT-01", &apple_pad_wii },
{ "PLAYSTATION(R)3 Controller", &apple_pad_ps3 },
{ 0, 0} };
for (int i = 0; name && pad_map[i].name; i ++)
if (strstr(name, pad_map[i].name))
{
s->iface = pad_map[i].iface;
s->data = s->iface->connect(connection, slot);
}
}
return slot;
}
void apple_joypad_disconnect(uint32_t slot)
{
if (slot < MAX_PLAYERS && slots[slot].used)
{
joypad_slot_t* s = &slots[slot];
if (s->iface && s->data)
s->iface->disconnect(s->data);
s->used = false;
}
}
void apple_joypad_packet(uint32_t slot, uint8_t* data, uint32_t length)
{
if (slot < MAX_PLAYERS && slots[slot].used)
{
joypad_slot_t* s = &slots[slot];
if (s->iface && s->data)
s->iface->packet_handler(s->data, data, length);
}
}
// RetroArch joypad driver:
static bool apple_joypad_init(void)
{
return true;
@ -52,7 +119,7 @@ static bool apple_joypad_button(unsigned port, uint16_t joykey)
if (GET_HAT_DIR(joykey))
return false;
else // Check the button
return (port < MAX_PADS && joykey < 32) ? (g_polled_input_data.pad_buttons[port] & (1 << joykey)) != 0 : false;
return (port < MAX_PLAYERS && joykey < 32) ? (g_polled_input_data.pad_buttons[port] & (1 << joykey)) != 0 : false;
}
static int16_t apple_joypad_axis(unsigned port, uint32_t joyaxis)

View File

@ -18,13 +18,11 @@
#include <stdlib.h>
#include "boolean.h"
#include "apple/common/rarch_wrapper.h"
#include "hidpad.h"
#include "apple/common/apple_input.h"
struct hidpad_ps3_data
{
struct hidpad_connection* connection;
struct apple_pad_connection* connection;
uint8_t data[512];
@ -49,24 +47,19 @@ static void hidpad_ps3_send_control(struct hidpad_ps3_data* device)
};
report_buffer[11] = 1 << ((device->slot % 4) + 1);
#ifdef IOS
hidpad_send_control(device->connection, report_buffer, sizeof(report_buffer));
#else
hidpad_send_control(device->connection, report_buffer + 1, sizeof(report_buffer) - 1);
#endif
apple_pad_send_control(device->connection, report_buffer, sizeof(report_buffer));
}
static void* hidpad_ps3_connect(struct hidpad_connection* connection, uint32_t slot)
static void* hidpad_ps3_connect(struct apple_pad_connection* connection, uint32_t slot)
{
struct hidpad_ps3_data* device = malloc(sizeof(struct hidpad_ps3_data));
memset(device, 0, sizeof(*device));
struct hidpad_ps3_data* device = calloc(1, sizeof(struct hidpad_ps3_data));
device->connection = connection;
device->slot = slot;
// Magic packet to start reports
#ifdef IOS
static uint8_t data[] = {0x53, 0xF4, 0x42, 0x03, 0x00, 0x00};
hidpad_send_control(device->connection, data, 6);
apple_pad_send_control(device->connection, data, 6);
#endif
// Without this the digital buttons won't be reported
@ -122,18 +115,14 @@ static void hidpad_ps3_packet_handler(struct hidpad_ps3_data* device, uint8_t *p
device->have_led = true;
}
#ifdef IOS
memcpy(device->data, packet, size);
#else
memcpy(device->data + 1, packet, size);
#endif
g_current_input_data.pad_buttons[device->slot] = hidpad_ps3_get_buttons(device);
for (int i = 0; i < 4; i ++)
g_current_input_data.pad_axis[device->slot][i] = hidpad_ps3_get_axis(device, i);
}
struct hidpad_interface hidpad_ps3 =
struct apple_pad_interface apple_pad_ps3 =
{
(void*)&hidpad_ps3_connect,
(void*)&hidpad_ps3_disconnect,

View File

@ -21,12 +21,10 @@
#include "apple/common/rarch_wrapper.h"
#include "wiimote.h"
#include "hidpad.h"
static void* hidpad_wii_connect(struct hidpad_connection* connection, uint32_t slot)
static void* hidpad_wii_connect(struct apple_pad_connection* connection, uint32_t slot)
{
struct wiimote_t* device = malloc(sizeof(struct wiimote_t));
memset(device, 0, sizeof(struct wiimote_t));
struct wiimote_t* device = calloc(1, sizeof(struct wiimote_t));
device->connection = connection;
device->unid = slot;
@ -64,13 +62,8 @@ static int16_t hidpad_wii_get_axis(struct wiimote_t* device, unsigned axis)
static void hidpad_wii_packet_handler(struct wiimote_t* device, uint8_t *packet, uint16_t size)
{
#ifdef IOS
byte* msg = packet + 2;
switch (packet[1])
#else
byte* msg = packet + 1;
switch (packet[0])
#endif
{
case WM_RPT_BTN:
{
@ -105,7 +98,7 @@ static void hidpad_wii_packet_handler(struct wiimote_t* device, uint8_t *packet,
g_current_input_data.pad_axis[device->unid][i] = hidpad_wii_get_axis(device, i);
}
struct hidpad_interface hidpad_wii =
struct apple_pad_interface apple_pad_wii =
{
(void*)&hidpad_wii_connect,
(void*)&hidpad_wii_disconnect,

View File

@ -1,32 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __IOS_RARCH_HIDPAD_H__
#define __IOS_RARCH_HIDPAD_H__
struct hidpad_connection;
void hidpad_send_control(struct hidpad_connection* connection, uint8_t* data, size_t size);
struct hidpad_interface
{
void* (*connect)(struct hidpad_connection* connection, uint32_t slot);
void (*disconnect)(void* device);
void (*packet_handler)(void* device, uint8_t *packet, uint16_t size);
};
extern struct hidpad_interface hidpad_wii;
extern struct hidpad_interface hidpad_ps3;
#endif

View File

@ -358,11 +358,7 @@ int wiimote_send(struct wiimote_t* wm, byte report_type, byte* msg, int len)
printf("\n");
#endif
#ifdef IOS
hidpad_send_control(wm->connection, buf, len + 2);
#else
hidpad_send_control(wm->connection, buf + 1, len + 1);
#endif
apple_pad_send_control(wm->connection, buf, len + 2);
return 1;
}

View File

@ -41,8 +41,6 @@
#ifndef __WIIMOTE_H__
#define __WIIMOTE_H__
#include "hidpad.h"
#if defined(__cplusplus)
extern "C" {
#endif
@ -232,7 +230,7 @@ extern "C" {
typedef struct wiimote_t {
int unid; /**< user specified id */
struct hidpad_connection* connection;
struct apple_pad_connection* connection;
int state; /**< various state flags */
byte leds; /**< currently lit leds */
float battery_level; /**< battery level */

View File

@ -21,7 +21,6 @@
#include <string.h>
#include "apple/common/rarch_wrapper.h"
#include "apple/common/hidpad/hidpad.h"
#include "btdynamic.h"
#include "btpad.h"
#include "btpad_queue.h"
@ -29,13 +28,10 @@
// Private interface
enum btpad_state { BTPAD_EMPTY, BTPAD_CONNECTING, BTPAD_CONNECTED };
struct hidpad_connection
struct apple_pad_connection
{
uint32_t slot;
struct hidpad_interface* interface;
void* hidpad;
enum btpad_state state;
bool has_address;
@ -45,9 +41,9 @@ struct hidpad_connection
uint16_t channels[2]; //0: Control, 1: Interrupt
};
static struct hidpad_connection g_connected_pads[MAX_PADS];
static struct apple_pad_connection g_connections[MAX_PLAYERS];
void hidpad_send_control(struct hidpad_connection* connection, uint8_t* data, size_t size)
void apple_pad_send_control(struct apple_pad_connection* connection, uint8_t* data, size_t size)
{
bt_send_l2cap_ptr(connection->channels[0], data, size);
}
@ -66,55 +62,46 @@ void btpad_set_inquiry_state(bool on)
}
// Internal interface:
static int32_t btpad_find_slot_for(uint16_t handle, bd_addr_t address)
static struct apple_pad_connection* btpad_find_empty_connection()
{
for (int i = 0; i < MAX_PADS; i ++)
for (int i = 0; i != MAX_PLAYERS; i ++)
if (g_connections[i].state == BTPAD_EMPTY)
return &g_connections[i];
return 0;
}
static struct apple_pad_connection* btpad_find_connection_for(uint16_t handle, bd_addr_t address)
{
for (int i = 0; i < MAX_PLAYERS; i ++)
{
if (!g_connected_pads[i].handle && !g_connected_pads[i].has_address)
if (!g_connections[i].handle && !g_connections[i].has_address)
continue;
if (handle && g_connected_pads[i].handle && handle != g_connected_pads[i].handle)
if (handle && g_connections[i].handle && handle != g_connections[i].handle)
continue;
if (address && g_connected_pads[i].has_address && (BD_ADDR_CMP(address, g_connected_pads[i].address)))
if (address && g_connections[i].has_address && (BD_ADDR_CMP(address, g_connections[i].address)))
continue;
return i;
return &g_connections[i];
}
return -1;
return 0;
}
static int32_t btpad_find_slot_with_state(enum btpad_state state)
static void btpad_close_connection(struct apple_pad_connection* connection)
{
for (int i = 0; i < MAX_PADS; i ++)
if (g_connected_pads[i].state == state)
return i;
if (connection->handle)
btpad_queue_hci_disconnect(connection->handle, 0x15);
return -1;
memset(connection, 0, sizeof(struct apple_pad_connection));
}
static void btpad_disconnect_pad(uint32_t slot)
static void btpad_close_all_connections()
{
if (slot > MAX_PADS)
return;
if (g_connected_pads[slot].interface && g_connected_pads[slot].hidpad)
{
ios_add_log_message("BTpad: Disconnecting slot %d", slot);
g_connected_pads[slot].interface->disconnect(g_connected_pads[slot].hidpad);
}
if (g_connected_pads[slot].handle)
btpad_queue_hci_disconnect(g_connected_pads[slot].handle, 0x15);
memset(&g_connected_pads[slot], 0, sizeof(struct hidpad_connection));
}
static void btpad_disconnect_all_pads()
{
for (int i = 0; i < MAX_PADS; i ++)
btpad_disconnect_pad(i);
for (int i = 0; i < MAX_PLAYERS; i ++)
btpad_close_connection(&g_connections[i]);
}
void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
@ -140,7 +127,7 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
}
else if(packet[2] > HCI_STATE_WORKING)
{
btpad_disconnect_all_pads();
btpad_close_all_connections();
}
}
break;
@ -170,19 +157,18 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
{
bt_flip_addr_ptr(event_addr, &packet[3]);
const int32_t slot = btpad_find_slot_with_state(BTPAD_EMPTY);
if (slot >= 0)
struct apple_pad_connection* connection = btpad_find_empty_connection();
if (connection)
{
ios_add_log_message("BTpad: Inquiry found device (Slot %d)", slot);
ios_add_log_message("BTpad: Inquiry found device");
memset(connection, 0, sizeof(struct apple_pad_connection));
memcpy(g_connected_pads[slot].address, event_addr, sizeof(bd_addr_t));
memcpy(connection->address, event_addr, sizeof(bd_addr_t));
connection->has_address = true;
connection->state = BTPAD_CONNECTING;
g_connected_pads[slot].has_address = true;
g_connected_pads[slot].state = BTPAD_CONNECTING;
g_connected_pads[slot].slot = slot;
bt_send_cmd_ptr(l2cap_create_channel_ptr, g_connected_pads[slot].address, PSM_HID_CONTROL);
bt_send_cmd_ptr(l2cap_create_channel_ptr, g_connected_pads[slot].address, PSM_HID_INTERRUPT);
bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_CONTROL);
bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_INTERRUPT);
}
}
}
@ -190,8 +176,7 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
case HCI_EVENT_INQUIRY_COMPLETE:
{
// TODO: Check performance and battery effect of this
// This must be turned off during gameplay as it causes a ton of lag
inquiry_running = !inquiry_off;
if (inquiry_running)
@ -206,34 +191,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);
const int32_t slot = btpad_find_slot_for(handle, event_addr);
struct apple_pad_connection* connection = btpad_find_connection_for(handle, event_addr);
if (!packet[2])
{
if (slot < 0)
if (!connection)
{
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);
g_connected_pads[slot].handle = handle;
ios_add_log_message("BTpad: L2CAP channel opened: (PSM: %02X)", psm);
connection->handle = handle;
if (psm == PSM_HID_CONTROL)
g_connected_pads[slot].channels[0] = channel_id;
connection->channels[0] = channel_id;
else if (psm == PSM_HID_INTERRUPT)
g_connected_pads[slot].channels[1] = channel_id;
connection->channels[1] = channel_id;
else
ios_add_log_message("BTpad: Got unknown L2CAP PSM, ignoring (Slot: %d, PSM: %02X)", slot, psm);
ios_add_log_message("BTpad: Got unknown L2CAP PSM, ignoring (PSM: %02X)", psm);
if (g_connected_pads[slot].channels[0] && g_connected_pads[slot].channels[1])
if (connection->channels[0] && connection->channels[1])
{
ios_add_log_message("BTpad: Got both L2CAP channels, requesting name (Slot: %d)", slot);
btpad_queue_hci_remote_name_request(g_connected_pads[slot].address, 0, 0, 0);
ios_add_log_message("BTpad: Got both L2CAP channels, requesting name");
btpad_queue_hci_remote_name_request(connection->address, 0, 0, 0);
}
}
else
ios_add_log_message("BTpad: Got failed L2CAP 'Channel Opened' event (Slot %d, PSM: %02X, Status: %02X)", -1, psm, packet[2]);
ios_add_log_message("BTpad: Got failed L2CAP 'Channel Opened' event (PSM: %02X, Status: %02X)", psm, packet[2]);
}
break;
@ -244,26 +229,26 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
const uint32_t psm = READ_BT_16(packet, 10);
const uint32_t channel_id = READ_BT_16(packet, 12);
int32_t slot = btpad_find_slot_for(handle, event_addr);
if (slot < 0)
struct apple_pad_connection* connection = btpad_find_connection_for(handle, event_addr);
if (!connection)
{
slot = btpad_find_slot_with_state(BTPAD_EMPTY);
if (slot >= 0)
connection = btpad_find_empty_connection();
if (connection)
{
ios_add_log_message("BTpad: Got new incoming connection (Slot: %d)", slot);
ios_add_log_message("BTpad: Got new incoming connection");
memcpy(g_connected_pads[slot].address, event_addr, sizeof(bd_addr_t));
memset(connection, 0, sizeof(struct apple_pad_connection));
g_connected_pads[slot].has_address = true;
g_connected_pads[slot].handle = handle;
g_connected_pads[slot].state = BTPAD_CONNECTING;
g_connected_pads[slot].slot = slot;
memcpy(connection->address, event_addr, sizeof(bd_addr_t));
connection->has_address = true;
connection->handle = handle;
connection->state = BTPAD_CONNECTING;
}
else break;
}
ios_add_log_message("BTpad: Incoming L2CAP connection (Slot: %d, PSM: %02X)", slot, psm);
ios_add_log_message("BTpad: Incoming L2CAP connection (PSM: %02X)", psm);
bt_send_cmd_ptr(l2cap_accept_connection_ptr, channel_id);
}
break;
@ -271,25 +256,19 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
{
bt_flip_addr_ptr(event_addr, &packet[3]);
struct apple_pad_connection* connection = btpad_find_connection_for(0, event_addr);
const int32_t slot = btpad_find_slot_for(0, event_addr);
if (slot < 0)
if (!connection)
{
ios_add_log_message("BTpad: Got unexpected remote name, ignoring");
break;
}
ios_add_log_message("BTpad: Got %.200s (Slot: %d)", (char*)&packet[9], slot);
if (strncmp((char*)&packet[9], "PLAYSTATION(R)3 Controller", 26) == 0)
g_connected_pads[slot].interface = &hidpad_ps3;
else if (strncmp((char*)&packet[9], "Nintendo RVL-CNT-01", 19) == 0)
g_connected_pads[slot].interface = &hidpad_wii;
if (g_connected_pads[slot].interface)
{
g_connected_pads[slot].hidpad = g_connected_pads[slot].interface->connect(&g_connected_pads[slot], slot);
g_connected_pads[slot].state = BTPAD_CONNECTED;
}
ios_add_log_message("BTpad: Got %.200s", (char*)&packet[9]);
connection->slot = apple_joypad_connect((char*)packet + 9, connection);
connection->state = BTPAD_CONNECTED;
}
break;
@ -308,13 +287,13 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
if (!packet[2])
{
const int32_t slot = btpad_find_slot_for(handle, 0);
if (slot >= 0)
struct apple_pad_connection* connection = btpad_find_connection_for(handle, 0);
if (connection)
{
g_connected_pads[slot].handle = 0;
btpad_disconnect_pad(slot);
ios_add_log_message("BTpad: Device disconnected (Slot: %d)", slot);
connection->handle = 0;
apple_joypad_disconnect(connection->slot);
btpad_close_connection(connection);
}
}
else
@ -332,12 +311,12 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
}
else if (packet_type == L2CAP_DATA_PACKET)
{
for (int i = 0; i < MAX_PADS; i ++)
for (int i = 0; i < MAX_PLAYERS; i ++)
{
struct hidpad_connection* connection = &g_connected_pads[i];
struct apple_pad_connection* connection = &g_connections[i];
if (connection->hidpad && connection->interface && (connection->channels[0] == channel || connection->channels[1] == channel))
connection->interface->packet_handler(connection->hidpad, packet, size);
if (connection->state == BTPAD_CONNECTED && (connection->channels[0] == channel || connection->channels[1] == channel))
apple_joypad_packet(connection->slot, packet, size);
}
}
}

View File

@ -29,23 +29,28 @@
#include "file.h"
//#define HAVE_DEBUG_FILELOG
void ios_set_bluetooth_mode(NSString* mode)
{
#ifndef __IPHONE_7_0 // iOS7 iCade Support
apple_input_enable_icade([mode isEqualToString:@"icade"]);
btstack_set_poweron([mode isEqualToString:@"btstack"]);
#else
bool enabled = [mode isEqualToString:@"icade"];
apple_input_enable_icade(enabled);
[[RAGameView get] iOS7SetiCadeMode:enabled];
#endif
}
bool is_ios_7()
{
return [[UIDevice currentDevice].systemVersion compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending;
}
void ios_set_bluetooth_mode(NSString* mode)
{
if (!is_ios_7())
{
apple_input_enable_icade([mode isEqualToString:@"icade"]);
btstack_set_poweron([mode isEqualToString:@"btstack"]);
}
#ifdef __IPHONE_7_0 // iOS7 iCade Support
else
{
bool enabled = [mode isEqualToString:@"icade"];
apple_input_enable_icade(enabled);
[[RAGameView get] iOS7SetiCadeMode:enabled];
}
#endif
}
// Input helpers: This is kept here because it needs objective-c
static void handle_touch_event(NSArray* touches)
{