Skip to content

String Descriptor fails to write iManufacturer and iProduct #274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gigaj0ule opened this issue Nov 10, 2017 · 5 comments
Closed

String Descriptor fails to write iManufacturer and iProduct #274

gigaj0ule opened this issue Nov 10, 2017 · 5 comments

Comments

@gigaj0ule
Copy link

gigaj0ule commented Nov 10, 2017

It appears that iManufacturer and iProduct are not filled in for HID descriptor requests. This seems odd, as bool USBDeviceClass::sendStringDescriptor(const uint8_t *string, uint8_t maxlen){} seems to have the strings "Arduino LLC" and "Arduino Zero" passed to it successfully.


Connection Information:

Device current bus speed: FullSpeed
Device supports USB 1.1 specification
Device supports USB 2.0 specification
Device address: 0x0011
Current configuration value: 0x00
Number of open pipes: 0

Device Descriptor:

0x12 bLength
0x01 bDescriptorType
0x0200 bcdUSB
0xEF bDeviceClass (Miscellaneous device)
0x02 bDeviceSubClass
0x01 bDeviceProtocol
0x40 bMaxPacketSize0 (64 bytes)
0x1532 idVendor
0x0B00 idProduct
0x0100 bcdDevice
0x01 iManufacturer ""
0x02 iProduct ""

But what's especially strange is the PluggableUSB shortname is successfully set using the same function.

@gigaj0ule
Copy link
Author

gigaj0ule commented Nov 10, 2017

I fixed the problem;

It seems like in USBCore.cpp, the setup.wlength struct element was not representing the real length of the Product Name and Manufacturing Name descriptor strings. Using sizeof() instead of the struct elements solved the problem.

else if (USB_STRING_DESCRIPTOR_TYPE == t)
	{
		if (setup.wValueL == 0) {
			desc_addr = (const uint8_t*)&STRING_LANGUAGE;
		}
		else if (setup.wValueL == IPRODUCT /* 2 */) {
			return sendStringDescriptor(STRING_PRODUCT, 2*sizeof(STRING_PRODUCT));
		}
		else if (setup.wValueL == IMANUFACTURER /* 1 */) {
			return sendStringDescriptor(STRING_MANUFACTURER, 2*sizeof(STRING_MANUFACTURER));
		}
		else if (setup.wValueL == ISERIAL /* 3 */) {
			#ifdef PLUGGABLE_USB_ENABLED
			char name[ISERIAL_MAX_LEN];
			PluggableUSB().getShortName(name);
		
			return sendStringDescriptor((uint8_t*)name, setup.wLength);
			#endif
		}
		else {
			return false;
		}
		if (*desc_addr > setup.wLength) {
			desc_length = setup.wLength;
		}
	}

I will fork the core and make a pull request

@gigaj0ule gigaj0ule reopened this Nov 10, 2017
@gigaj0ule
Copy link
Author

Pull request is here:

#275

@awatterott
Copy link
Contributor

The 2nd parameter of sendStringDescriptor() is the maximum length and it is 2+sizeof("string"), because of the 2byte prefix and the string is stored as ACSII (1byte), but send as UTF-16 (2bytes).

@gigaj0ule
Copy link
Author

I accidentally wrote "was the problem", i mean't, "fixed the problem" :-)

The original code uses setup.wlength instead of 2*sizeof("string"), which is incorrect as setup.wlength doesn't always have the right number.

@cmaglie
Copy link
Member

cmaglie commented Nov 13, 2017

The setup.wLength field is the maximum length of the response that should be sent by the micro (even if the descriptor is longer it should be cut at setup.wLength, it's the host that controls this field here).
The code IMHO is correct as it is now.

boseji pushed a commit to go-ut/combined-ArduinoCore-samd that referenced this issue Feb 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants