mirror of
https://github.com/libretro/RetroArch
synced 2025-03-23 19:21:03 +00:00
(Apple) Rework gamepad connection management; fix BTstack support when building with the iOS 7 SDK.
This commit is contained in:
parent
fe8b6c3c0f
commit
fae300aaaf
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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,
|
@ -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,
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user