Bladeren bron

Claim the interface before doing bulk transfers

Sam Lantinga 2 weken geleden
bovenliggende
commit
2bb51e1340
1 gewijzigde bestanden met toevoegingen van 55 en 52 verwijderingen
  1. 55 52
      src/hidapi/libusb/hid.c

+ 55 - 52
src/hidapi/libusb/hid.c

@@ -1337,64 +1337,67 @@ static bool is_ns2(unsigned short idVendor, unsigned short idProduct)
 	return false;
 }
 
-static bool ns2_find_bulk_out_endpoint(libusb_device_handle* handle, uint8_t* endpoint_out)
+static void init_ns2(libusb_device_handle *device_handle, const struct libusb_config_descriptor *conf_desc)
 {
-	struct libusb_config_descriptor* config;
-	if (libusb_get_config_descriptor(libusb_get_device(handle), 0, &config) != 0) {
-		return false;
-	}
-
-	for (int i = 0; i < config->bNumInterfaces; i++) {
-		const struct libusb_interface* iface = &config->interface[i];
-		for (int j = 0; j < iface->num_altsetting; j++) {
-			const struct libusb_interface_descriptor* altsetting = &iface->altsetting[j];
-			if (altsetting->bInterfaceNumber == 1) {
-				for (int k = 0; k < altsetting->bNumEndpoints; k++) {
-					const struct libusb_endpoint_descriptor* ep = &altsetting->endpoint[k];
+	int j, k, l, res;
+
+	for (j = 0; j < conf_desc->bNumInterfaces; j++) {
+		const struct libusb_interface *intf = &conf_desc->interface[j];
+		for (k = 0; k < intf->num_altsetting; k++) {
+			const struct libusb_interface_descriptor *intf_desc = &intf->altsetting[k];
+			if (intf_desc->bInterfaceNumber == 1) {
+				uint8_t endpoint = 0;
+				for (l = 0; l < intf_desc->bNumEndpoints; l++) {
+					const struct libusb_endpoint_descriptor* ep = &intf_desc->endpoint[l];
 					if ((ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK && (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) {
-						*endpoint_out = ep->bEndpointAddress;
-						libusb_free_config_descriptor(config);
-						return true;
+						endpoint = ep->bEndpointAddress;
+						break;
 					}
 				}
-			}
-		}
-	}
 
-	libusb_free_config_descriptor(config);
-	return false;
-}
+				if (endpoint) {
+					res = libusb_claim_interface(device_handle, intf_desc->bInterfaceNumber);
+					if (res < 0) {
+						LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
+						continue;
+					}
 
-static void init_ns2(libusb_device_handle *device_handle)
-{
-	const unsigned char DEFAULT_REPORT_DATA[] = {
-		0x03, 0x91, 0x00, 0x0d, 0x00, 0x08,
-		0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-	};
-	const unsigned char SET_LED_DATA[] = {
-		0x09, 0x91, 0x00, 0x07, 0x00, 0x08,
-		0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-	};
+					const unsigned char DEFAULT_REPORT_DATA[] = {
+						0x03, 0x91, 0x00, 0x0d, 0x00, 0x08,
+						0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+					};
+					const unsigned char SET_LED_DATA[] = {
+						0x09, 0x91, 0x00, 0x07, 0x00, 0x08,
+						0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+					};
+
+					int transferred;
+					res = libusb_bulk_transfer(device_handle,
+								endpoint,
+								(unsigned char*)DEFAULT_REPORT_DATA,
+								sizeof(DEFAULT_REPORT_DATA),
+								&transferred,
+								1000);
+					if (res < 0) {
+						LOG("can't set report data: %d\n", res);
+					}
 
-	uint8_t endpoint_out = 0;
-	if (!ns2_find_bulk_out_endpoint(device_handle, &endpoint_out)) {
-		return;
-	}
+					res = libusb_bulk_transfer(device_handle,
+								endpoint,
+								(unsigned char*)SET_LED_DATA,
+								sizeof(SET_LED_DATA),
+								&transferred,
+								1000);
+					if (res < 0) {
+						LOG("can't set LED data: %d\n", res);
+					}
 
-	int transferred;
-	libusb_bulk_transfer(device_handle,
-				endpoint_out,
-				(unsigned char*)DEFAULT_REPORT_DATA,
-				sizeof(DEFAULT_REPORT_DATA),
-				&transferred,
-				1000);
-
-	libusb_bulk_transfer(device_handle,
-				endpoint_out,
-				(unsigned char*)SET_LED_DATA,
-				sizeof(SET_LED_DATA),
-				&transferred,
-				1000);
+					libusb_release_interface(device_handle, intf_desc->bInterfaceNumber);
+					return;
+				}
+			}
+		}
+	}
 }
 
 static void calculate_device_quirks(hid_device *dev, unsigned short idVendor, unsigned short idProduct)
@@ -1458,9 +1461,9 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa
 		init_xboxone(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc);
 	}
 
-	/* Initialize NSO GameCube controllers */
+	/* Initialize Nintendo Switch 2 controllers */
 	if (is_ns2(desc.idVendor, desc.idProduct)) {
-		init_ns2(dev->device_handle);
+		init_ns2(dev->device_handle, conf_desc);
 	}
 
 	/* Store off the string descriptor indexes */