Is there any code that shows how to use ch9 functions to retrieve a string based on its index from a connected device? The ch9 function documentation isn't very good and I can't seem to find an example of that anywhere (including the forums).
Thanks!
You can dowload Freescale USB stack at USB Stack Product Summary Page which contains many USB example codes. There are host and device examples and I suggest you to take a look at the HID examples. In the device example "usb_descriptor.c" file includes USB_STR_0, USB_STR_1 and USB_STR_2 decriptors corresponding to the string index 0,1 and 2. In the "usb_framework.c' file, look at the USB_Strd_Req_Get_Descriptor() function. In the host example "host_ch9.c" file, look at the _usb_host_ch9_get_descriptor() function.
Hi Derek,
Thank you for the quick reply. I was indeed referencing the USB stack. I am using the Host API.
According the the stack source, I have to use _usb_host_ch9_get_descriptor() to get a string descriptor, which is fine. However, the API documentation only mentions that it gets a descriptor and returns USB_OK on success. This is apparently incorrect as the source shows it will return USB_STATUS_TRANSFER_QUEUED. What is the next step? Is there something that indicates whether the transfer was successful or not? I can see _usb_host_get_transfer_status() in the Host API but that requires a pipe_handle and transfer number. Or, do I need to set up the bus somehow before I call _usb_host_ch9_get_descriptor()?
I have looked at the dev_list function but that also just checks for USB_STATUS_TRANSFER_QUEUED then exits.
The Host level API has _usb_host_send_setup(), but that is more primitive than the ch9 functions. I don't mind creating my own setup packet to get a string descriptor but I don't know why there isn't a HOST example of this (or I am clearly missing it somehow).
Based on what you said about HID, it looks like maybe I need to have a control callback registered in order to work with string descriptors. I will try setting that up.
Thanks!
Ok, I tried a few other options with the ch9 functions, and also tried _usb_hostdev_cntrl_request as shown in the msd example. It looks like callbacks get registered ok but they never get called. Is there something else that needs to be done? I really need to be able to read the string descriptors from a device.
I should clarify:
I want to be able to read the string descriptors without having to select an interface (and without using a class, just send and receive control requests). From the code, it looks like the ch9 get descriptor function will override the callback if the device hasn't moved into DEVSTATE_ENUM_OK state. It will enter the DEVSTATE_ENUM_OK state when it has interfaced. Also, _usb_hostdev_cntrl_request will give a device not found error if not in DEVSTATE_ENUM_OK state.
Thanks again!
Here is some code that only calls the callback on detach for some reason, and returns error 97, meaning TR failed. I still haven't been able to successfully create a control command or retrieve a string index from the device.
This is in the main device callback, under the attached event.
case USB_DEVICE_ATTACHED:
printf( "Device Attached\n" );
dev_ptr = (DEV_INSTANCE_PTR)usb_dev.dev_handle;
usb_dev.dev_state = USB_DEVICE_OTHER;
dev_ptr->state = DEVSTATE_ENUM_OK;
status = _usb_host_register_ch9_callback(
usb_dev.dev_handle,
usb_host_mass_device_cntrl,
usb_dev.intf_handle);
if(status != USB_OK) {
printf("Control callback registration ERROR: 0x%x\n", status);
}
/* Read device status to push it into DEVSTATE_ENUM_OK */
status = _usb_host_ch9_get_descriptor(usb_dev.dev_handle,
(REQ_GET_DESCRIPTOR << 8) | 3, 0x0409 , 0x40, buffer);
if(status != USB_STATUS_TRANSFER_QUEUED) {
printf("Get descriptor ERROR: 0x%x\n", status);
}
break;
This is the ch9 registered callback, that seems to only fire on detach (or on attach if I change the get_descriptor call to ..0, 0, 2, buffer, which is getstatus):
void usb_host_mass_device_cntrl
(
/* [IN] pointer to pipe */
_usb_pipe_handle pipe_handle,
/* [IN] user-defined parameter */
pointer user_parm,
/* [IN] buffer address */
uchar_ptr buffer,
/* [IN] length of data transferred */
uint_32 length_data_transfered,
/* [IN] status, hopefully USB_OK or USB_DONE */
uint_32 status
)
{
uint_8 count;
if(status == USB_OK) {
printf("Serial Number: ");
for(count = 0; count < length_data_transfered; count++) {
printf("%x-", buffer[count]);
}
printf("\n");
}
else {
printf("Callback Error: 0x%x\n", status);
}
}
Hello Farhan,
To make it quick, I have just changed the get device descriptor to get string descriptor
Here is what I have done in the host example of HID mouse in USB Stack 4.0.3 (seems 4.1.1 has some issues).
In the usb_host_cntrl_transaction_done()
case DEVSTATE_ADDR_SET: /* address set */
.............
// Get device descriptor
/* status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr,
USB_DESC_TYPE_DEV << 8,
0,
USB_DESC_LEN_DEV,
(uchar_ptr)&dev_inst_ptr->dev_descriptor);
*/
// change get device descriptor to get string descriptor
static uint_8 string[0xFF];
uint_8 index;
index = 1;
status = _usb_host_ch9_get_descriptor((pointer)dev_inst_ptr,
USB_DESC_TYPE_STR << 8 | index,
0x0409,
0xFF,
(uchar_ptr)&string);
// end of get string descriptor
case DEVSTATE_DEV_DESC: /* full device descriptor received */
/* Now lets get the first 9 bytes of the configuration
** descriptor
*/
desc.pntr = &dev_inst_ptr->buffer; <----- set a break point here to see the data in string[]
Ok, looked into it a little further. When a ch9 command for a string descriptor is sent, the program gets stuck inside khci_kinetis.c when Poll is called in the main loop. I checked the running code a few times and it keeps looping back to label "try_again" (line 334). This infinite loop prevents the program from getting to the attach event and when the device is detached, it breaks the loop and gives an error (because the rest of the program flow continues).
EDIT
Just for the heck of it, I tried a few different devices.
Sony 4GB USB drive (USM4GM) = Stuck in loop
Samsung Omnia 7 = Correctly gets strings
IBM USB Mouse = Correctly gets strings
Could you share the code that you got working above? I'm in need of this feature.
Thanks much.
RIck
If I modify the library the way you have stated then it won't pull the device descriptor anymore. Plus, I need the device descriptor in order to check the string descriptor index. I also tried inserting another level in-between DEVSTATE_DEV_DESC and DEVSTATE_GET_CFG9 to pull in the string descriptors, without disrupting the stack's ability to get device descriptor. It seems to always run into an issue, specifically, the callback isn't fired until the device is detached.
I don't understand what exactly is going on but it seems like any time I try to do a get descriptor on a string, the endpoint stalls or has some other problems even when using the code you described above. This probably translates to the callback firing on detach with an error. If I try any other control control command, it seems to work.
I can try that. So is there a normal way to access the string descriptors in the main program without having to modify the library? I am surprised at how difficult it is to do a simple string descriptor request.