Factory Implementation

Media driver must implement a PDD factory class derived from DPhysicalDevice.

The PDD factory creates the main media driver objects.

The Device Driver Guide describes the general theory for implementing a derived class, while this section gives the specifics for the media driver.

In implementing your DPhysicalDevice derived class, you must, as a minimum, provide an implementation for the following four functions, defined as pure virtual in DPhysicalDevice:

The following function is virtual in DPhysicalDevice but has a default implementation that must be changed:

Install() - complete the initialisation of the PDD factory object

See also DPhysicalDevice::Install().

This PDD factory function is called after the PDD DLL has been successfully loaded, as a result of a call to User::LoadPhysicalDevice(), and the factory object has been successfully created on the kernel heap.

The function is a second stage constructor for the factory object, and allows any further initialisation of the factory object to be done. As a minimum, the function must set a name for the media driver's factory object. The name is important as it is the way in which the object will subsequently be found. The name should be of the form:

Media.<MDExt>

where <MDExt> is descriptive of the specific media. For example, Media.Ata, and Media.Iram.

When a DMedia object, created by the internal Symbian platform ELOCD.LDD logical device driver, attempts to mount a media device, i.e. to open a media driver, it does a search by name. This is a search through all loaded PDDs whose names match Media.*.

The following simple function is typical:

TInt DMyPhysicalDeviceMedia::Install()
    {
    _LIT(KDrvNm, "Media.MyName");
    return SetName(&KDrvNm);
    }
        

Create() - create the media driver object

See also DPhysicalDevice::Create().

This PDD factory function is called by the device driver framework to create, and return, the media driver object. This is an instance of a class derived from DMediaDriver. Note that, occasionally, you may find this object referred to as the physical channel.

Create() is called when initially mounting a media device, or accessing a removable media after an insertion event. Contrast this with Install(), which is only called once, when the PDD factory object is loaded.

Typically, Create() does the following:

  • Compares the build version of the media driver with the version requested, and returns KErrNotSupported if the versions are incompatible.

  • Creates an instance of the DMediaDriver derived class, the media driver object.

  • Initiates second-phase construction of the media driver object. Typically, this involves initialisation that is capable of failing. This may be done synchronously or asynchronously. You would probably do this asynchronously for removable media that is slow to power up, or for slow internal media, in which case, you would need to make sure that you attached a DFC queue during media driver initialisation. Although the device driver framework does not mandate any specific function name in which to implement this, the example code fragment suggests a function name of DoCreate().

  • Acknowledges creation of the media driver object. The way you do this depends on whether creation is done synchronously or asynchronously:

    • Synchronous creation - call DMediaDriver::OpenMediaDriverComplete() passing KErrNone, or an error code if appropriate, and then return KErrNone from Create(). Do not return any value other than KErrNone from Create(), otherwise the framework may call it again.

      Note that DMediaDriver::OpenMediaDriverComplete() can be called from within the media driver class, if that is the way the driver is designed, but Create() must still return KErrNone.

    • Asynchronous creation - return either KErrNone, if initiation of the operation was successful, or an error code, if the operation failed immediately. However, it is the responsibility of the media driver object to signal completion.

The following is a typical example:

TInt DMyPhysicalDeviceMedia::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* aInfo ,const TVersion &aVer)
    {
    // Check the build version of the media driver
    if (!Kern::QueryVersionSupported(iVersion,aVer))
        {
        return KErrNotSupported;
        }

    //Create my DMediaDriver derived object
    DMyMediaDriver* pD=new DMyMediaDriver (aMediaId);
    aChannel=pD;

    // Call my media driver’s second-stage constructor
    Tint r = KErrNoMemory;
    if(pD)
        {
        r = pD->DoCreate(aMediaId);
        }

    // Synchronous Creation (don’t do this if Asynchronous)…
    if(r == KErrNone)
        {
        pD->OpenMediaDriverComplete(KErrNone);
        }

    return r;
    }
        

Validate() - check that the PDD is suitable for use

See also DPhysicalDevice::Validate().

This PDD factory function is called by the kernel's device driver framework to check whether this PDD is suitable for use with the media type specified in the function.

A typical implementation of this function would perform the following steps:

  • Compare the build version of the media driver with the version requested

  • Confirm that this driver is responsible for the media type

The following is a very typical implementation:

TInt DMyPhysicalDeviceMedia::Validate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
    {
    // Check the build version of the media driver
    if (!Kern::QueryVersionSupported(iVersion,aVer))
        {
        return KErrNotSupported;
        }

    // Check that the given type of media is supported by this driver
    if (aUnit!=MEDIA_DEVICE_MYMEDIA)
        {
        return KErrNotSupported;
        }

    return KErrNone;
    }

        

Note that the value passed in via the aUnit argument is the unique media ID used when the media driver was registered. In other contexts, the argument may be denoted by the symobol aMediaId.

GetCaps() - return the capabilities of the Media Driver

See also DPhysicalDevice::GetCaps().

For media drivers, this PDD factory function is not used. However, an implementation is required because the function is defined as pure virtual in the DPhysicalDevice base class. Simply implement an empty function, for example:

void DMyPhysicalDeviceMedia::GetCaps(TDes8& /*aDes*/) const
//
// Return the media drivers capabilities.
//
    {
    }
        

Info() - set the priority of the media driver

See also DPhysicalDevice::Info().

This PDD factory function is intended to return information relating to the media driver. The function can, potentially, return many different types of information, depending on the value passed as the first parameter. However, the only type of information that Symbian platform currently requires is the priority of the media driver. The returned priority value is used by Symbian platform to decide the order in which media drivers are to be opened.

The default implementation just returns 0, and therefore needs to be overridden.

Under most circumstances, you can return the value KMediaDriverPriorityNormal. You can, however, return KMediaDriverPriorityHigh in circumstances where it is important that the driver is initialised before a lower priority driver.

The following code fragment is a typical implementation:

TInt DMyPhysicalDeviceMedia::Info(TInt aFunction, TAny* /*a1*/)
    {
    if (aFunction==EPriority)
        {
        return KMediaDriverPriorityNormal;
        }
    return KErrNotSupported;
    }
        

where EPriority indicates that priority information is required (this is an enum value of enum TInfoFunction, defined in DPhysicalDevice.