Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/platform/psmove_winsupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,19 @@ windows_register_psmove(const char *move_addr_str, const HANDLE hRadio)
return 1;
}

/* Keep track of the number of times the loop iterates so we may timeout. */
int timeout_duration = 30; // seconds
int sleep_interval = 1000; // msec
int timeout_iterations = timeout_duration * 1000 / sleep_interval;
int loop_count = 0;

printf("\n" \
" Unplug the controller.\n" \
"\n"
" Now press the controller's PS button. The red status LED\n" \
" will start blinking. Whenever it goes off, press the\n" \
" PS button again. Repeat this until the status LED finally\n" \
" remains lit.\n"
"\n");
" remains lit. Press Ctrl+C to cancel anytime.\n");

while (1) {
BLUETOOTH_DEVICE_INFO device_info;
Expand Down Expand Up @@ -311,9 +316,16 @@ windows_register_psmove(const char *move_addr_str, const HANDLE hRadio)
WINPAIR_DEBUG("Bluetooth device matching the given address is not a Move Motion Controller");
}
}
if (loop_count >= timeout_iterations) {
printf("\n"
" A connection could not be established. This is not\n"
" unusual in Windows. Please refer to the README document\n"
" for your platform for more information. Press Ctrl+C to cancel.");
}

/* sleep for 1 second */
Sleep(1000);
loop_count++;
}

free(move_addr);
Expand Down
83 changes: 62 additions & 21 deletions src/psmove.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ struct _PSMove {
/* The handle to the HIDAPI device */
hid_device *handle;

hid_device *handle_addr; // Only used by _WIN32. Needed by Win 8.1 to get BT address.

/* The handle to the moved client */
moved_client *client;
int remote_id;
Expand All @@ -274,6 +276,8 @@ struct _PSMove {
/* Device path of the controller */
char *device_path;

char *device_path_addr; // Only used by _WIN32. Needed by Win 8.1 to get BT address.

/* Nonzero if the value of the LEDs or rumble has changed */
unsigned char leds_dirty;

Expand Down Expand Up @@ -505,13 +509,11 @@ psmove_count_connected_hidapi()
while (cur_dev) {
#ifdef _WIN32
/**
* Windows Quirk: Ignore extraneous devices (each dev is enumerated
* 3 times, count only the one with "&col02#" in the path)
*
* We use col02 for enumeration, and col01 for connecting. We want to
* have col02 here, because after connecting to col01, it disappears.
* Windows Quirk: Each dev is enumerated 3 times.
* The one with "&col01#" in the path is the one we will get most of our data from. Only count this one.
* The one with "&col02#" in the path is the one we will get the bluetooth address from.
**/
if (strstr(cur_dev->path, "&col02#") == NULL) {
if (strstr(cur_dev->path, "&col01#") == NULL) {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess here the &col01# doesn't disappear, because we don't open it anymore?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original comment confused me because no device was actually opened until much later, and at that point it was the device with col01 in the path that was opened. However, in this new version, I took the comment at its word and made sure to open the col02 device first (the one used for getting the BT address) and then open the col01 device.

count--;
}
#endif
Expand Down Expand Up @@ -563,23 +565,46 @@ psmove_connect_internal(wchar_t *serial, char *path, int id)
if (serial != NULL && wcslen(serial) > 1) {
move->is_bluetooth = 1;
}
/* Windows Quirk: Use path instead of serial number by ignoring serial */
serial = NULL;
serial = NULL; // Set the serial to NULL, even if BT device, to use psmove_get_serial below.

/* XXX Ugly: Convert "col02" path to "col01" path (tested w/ BT and USB) */
/**
* In Windows, the device is enumerated 3 times, and each has slightly different behaviour.
* The devices' paths differ slightly (col01, col02, and col03).
* The device with col01 is the one we want to use for data.
* The device with col02 is the one we want to use for the bluetooth address.
* More testing remains to determine which device is best for which feature reports.
**/

/**
* We know this function (psmove_connect_internal) will only be called with the col01 path.
* We first copy that path then modify it to col02. That will be the path for our addr device.
* Connect to the addr device first, then connect to the main device.
**/
move->device_path_addr = strdup(path);
char *p;
psmove_return_val_if_fail((p = strstr(path, "&col02#")) != NULL, NULL);
p[5] = '1';
psmove_return_val_if_fail((p = strstr(path, "&0001#")) != NULL, NULL);
p[4] = '0';
#endif
psmove_return_val_if_fail((p = strstr(move->device_path_addr, "&col01#")) != NULL, NULL);
p[5] = '2';
psmove_return_val_if_fail((p = strstr(move->device_path_addr, "&0000#")) != NULL, NULL);
p[4] = '1';
move->handle_addr = hid_open_path(move->device_path_addr);
hid_set_nonblocking(move->handle_addr, 1);

move->device_path = strdup(path);
move->handle = hid_open_path(move->device_path);

#else
/* If not in Windows then we can rely on having only one device. */
if (path != NULL) {
move->device_path = strdup(path);
}
if (serial == NULL && path != NULL) {
move->handle = hid_open_path(path);
} else {
move->handle = hid_open(PSMOVE_VID, PSMOVE_PID, serial);
}

#endif

if (!move->handle) {
free(move);
return NULL;
Expand All @@ -598,11 +623,11 @@ psmove_connect_internal(wchar_t *serial, char *path, int id)
move->serial_number = (char*)calloc(PSMOVE_MAX_SERIAL_LENGTH, sizeof(char));
if (serial != NULL) {
wcstombs(move->serial_number, serial, PSMOVE_MAX_SERIAL_LENGTH);
} else {
move->serial_number = psmove_get_serial(move);
}

if (path != NULL) {
move->device_path = strdup(path);
}


/**
* Normalize "aa-bb-cc-dd-ee-ff" (OS X format) into "aa:bb:cc:dd:ee:ff"
Expand Down Expand Up @@ -837,7 +862,7 @@ psmove_connect_by_id(int id)
cur_dev = devs;
while (cur_dev) {
#ifdef _WIN32
if (strstr(cur_dev->path, "&col02#") != NULL) {
if (strstr(cur_dev->path, "&col01#") != NULL) {
#endif
if (count == id) {
move = psmove_connect_internal(cur_dev->serial_number,
Expand Down Expand Up @@ -881,7 +906,13 @@ _psmove_read_btaddrs(PSMove *move, PSMove_Data_BTAddr *host, PSMove_Data_BTAddr
/* Get Bluetooth address */
memset(btg, 0, sizeof(btg));
btg[0] = PSMove_Req_GetBTAddr;
res = hid_get_feature_report(move->handle, btg, sizeof(btg));

/* _WIN32 only has move->handle_addr for getting bluetooth address. */
if (move->handle_addr) {
res = hid_get_feature_report(move->handle_addr, btg, sizeof(btg));
} else {
res = hid_get_feature_report(move->handle, btg, sizeof(btg));
}

if (res == sizeof(btg)) {
if (controller != NULL) {
Expand Down Expand Up @@ -994,8 +1025,12 @@ psmove_set_btaddr(PSMove *move, PSMove_Data_BTAddr *addr)
for (i=0; i<6; i++) {
bts[1+i] = (*addr)[i];
}

res = hid_send_feature_report(move->handle, bts, sizeof(bts));
/* _WIN32 only has move->handle_addr for getting bluetooth address. */
if (move->handle_addr) {
res = hid_send_feature_report(move->handle_addr, bts, sizeof(bts));
} else {
res = hid_send_feature_report(move->handle, bts, sizeof(bts));
}

return (res == sizeof(bts));
}
Expand Down Expand Up @@ -2029,6 +2064,9 @@ psmove_disconnect(PSMove *move)
switch (move->type) {
case PSMove_HIDAPI:
hid_close(move->handle);
if (move->handle_addr) {// _WIN32 only
hid_close(move->handle_addr);
}
break;
case PSMove_MOVED:
// XXX: Close connection?
Expand All @@ -2045,6 +2083,9 @@ psmove_disconnect(PSMove *move)

free(move->serial_number);
free(move->device_path);
if (move->device_path_addr) { // _WIN32 only
free(move->device_path_addr);
}
free(move);

/* Bookkeeping of open handles (for psmove_reinit) */
Expand Down