diff --git a/src/platform/psmove_winsupport.c b/src/platform/psmove_winsupport.c index 77fc62cf..28ff1462 100644 --- a/src/platform/psmove_winsupport.c +++ b/src/platform/psmove_winsupport.c @@ -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; @@ -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); diff --git a/src/psmove.c b/src/psmove.c index eec2637c..82488415 100644 --- a/src/psmove.c +++ b/src/psmove.c @@ -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; @@ -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; @@ -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) { count--; } #endif @@ -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; @@ -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" @@ -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, @@ -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) { @@ -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)); } @@ -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? @@ -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) */