Skip to content

Commit

Permalink
Merge pull request thp#149 from cboulay/win8.1x64
Browse files Browse the repository at this point in the history
Separation of feature reports across 3 devices in Win 8.1
  • Loading branch information
thp committed Apr 20, 2015
2 parents 1e2fa92 + efa7d2b commit 689884a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 23 deletions.
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) {
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

0 comments on commit 689884a

Please sign in to comment.