Setting Microsoft OS Descriptor

This section describes how to set the Microsoft OS Descriptor (MOD) for using Symbian MTP over USB services.

Before you start, you must:

The USB Device Working Group does not define the class and sub-class ID for MTP. To allow a Symbian device to plug into Windows and handle MTP requests without installing software or requiring user interactions, device creators must provide Microsoft OS Descriptor (MOD) support in their user implementations.

Two MODs must be supplied by the Symbian device: The OS string descriptor which stores vendor-specific information and the OS feature descriptor which contains the compatible ID (compat ID) and MTP sub-compatible ID (sub-compat ID). The compat ID is the class code for MTP. After getting a valid OS string descriptor, Windows will try to get the compat ID for MTP. The driver or class for MTP is finally loaded on Windows to handle MTP requests.

To enable Symbian MTP over USB, device creators must implement a MOD solution. The implementation is referred to as user implementation. The implementation can be built into a user binary such as EXE or DLL. The user binary must be started up or loaded any time before enabling the MTP over USB.

The following tasks must be completed in the user implementation:

  1. Load the USB Logical Device Driver (LDD) and open an LDD client.

    After the user binary is loaded, the LDD must be loaded and the LDD client must be opened. The string OS descriptor can then be written into the LDD in the next step.

  2. Set the OS string descriptor to the LDD.

    A USB device which supports MOD must contain an OS string descriptor. Windows sends a request to the device to retrieve the OS string descriptor from the LDD.

  3. Route device-directed requests to the user binary.

    In the next step, Windows will send a control request to the device to get the compat ID OS feature descriptor. This request is vendor-specific and device-directed and must be handled by device creators in their user implementation. To enable the USB Stack to route the request to the user binary, the user implementation must call RDevUsbcClient::SetDeviceControl(). Device-directed requests from the PC are all then routed to this instance of RDevUsbcClient.

  4. Provide an OS feature descriptor handler.

    Once a valid OS string descriptor is returned, Windows sends another control request to get the Microsoft extended compat ID OS feature descriptor.

    Once the compat ID has been returned to the PC it can load the right MTP driver and class to handle MTP requests.

    Note: The string OS descriptor is written into the LDD. The OS feature descriptor is returned by the user implementation at runtime.

For more information about device directed requests and other types of requests, refer to USB 2.0 Specification Chapter 9.3. For more information about the OS string descriptor and OS feature descriptor, refer to Microsoft OS Descriptors.


  1. Load the USB LDD–usbc.ldd and open a client of it.
    _LIT(KUsbLDDName, "eusbc"); //Name passed to User::LoadLogicalDevice()
    _LIT(KUsbLDDFreeName, "Usbc"); //Name passed to User::FreeLogicalDevice()
    
    TInt err = User::LoadLogicalDevice(KUsbLDDName); // Load the USB logical device
    
    if (err != KErrNone && err != KErrAlreadyExists)
       {
       User::Leave(err);
       }
    
    RDevUsbcClient ldd; //Create a client of the USB logical device
    
    User::LeaveIfError(ldd.Open(0)); //Open the client
    
    

  2. Set the OS string descriptor. OS string descriptor is stored in the USB device driver at the fixed index of 0xEE. It contains a request number that Windows uses to retrieve OS feature descriptors.
    /**
     * MTP OS string decsriptor definitions.
     */
    const TUint8 KMTPUsbOSStringIndex(0xEE); //OS string descriptor index
    _LIT16(KMTPUsbOSStringSignature, "MSFT100\xAE"); //qwSignature and bMS_VendorCode
    
    // Write the OS string descriptor to the LDD.
    User::LeaveIfError(ldd.SetStringDescriptor(KMTPUsbOSStringIndex, KMTPUsbOSStringSignature));
    
    
    qwSignature and bMS_VendorCode are two key fields which must be set. qwSignature is a Unicode character array which identifies the descriptor as an OS string descriptor. bMS_VendorCode is one byte field whose value is set by the vendor. This value is used by Windows to request the OS feature descriptor (compat ID and sub-compat ID).

  3. Route device-directed requests to the user binary. The user implementation must include the following to enable the USB Stack to route the device directed requests to the user binary.
    User::LeaveIfError(ldd.SetDeviceControl()); 
    
    Note: Only one instance of RDevUsbcClient can hold the device control at any given time.

  4. Provide the OS feature descriptor handler. Once a valid OS string descriptor has been returned, Windows retrieves the OS feature descriptor which it uses to load the appropriate USB driver. In this case, the OS feature descriptor contains the MTP compat ID and MTP sub-compat ID.
    // KMsOSFeatureDescriptor 
    _LIT8(KMsOSFeatureDescriptor, "\x28\x00\x00\x00\x00\x01\x04\x00\x01\x00\x00\x00\x00\x00\x00\x00" \
    //dwLength     |  bcdVersion | wIndex | bCount | Reserved      
    //4 characters |  2 chars    |  2     | 1      | 7
    
    "\x00\x01\x4D\x54\x50\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
    // bFirstInterfaceNumber | bInterfaceCount |compatibleID | subCompatibleID | Reserved
    // 1                     | 1               | 8           | 8               | 6
    
    const TInt KMODHeaderSize   = 0x10; //The first 16 characters of the feature descriptor
    const TInt KMODFunctionSize = 0x28;  
    
    TRequestStatus status;
    
    //aRequest is a structure for requests defined by a device creator
    //wLength is the field which specifies the length of the data to be transferred
    TInt length(aRequest.wLength); 
    
    if (length == KMODHeaderSize)
       {
       // The request is for the header. Return just the header
       ldd.Write(status, EEndpoint0, KMsOSFeatureDescriptor().Left(KMODHeaderSize), KMODHeaderSize, ETrue);
       }
    else if (length == KMODFunctionSize)
       {
       ldd.Write(status, EEndpoint0, KMsOSFeatureDescriptor(),KMODFunctionSize, ETrue);
       }
Related concepts
MTP USB Transport Overview
Related information
Symbian USB Manager