In my last engagement I was facing the problem of updating SCMDM certificate. The preferred way was to do it from the Windows Mobile device. I was blogging about similar topic some time ago, so this will be the extension of the original article.

Find what you want to update

If you do simple query into the MY certificate store on your enrolled device.

<wap-provisioningdoc>
    <characteristic type="CertificateStore"> 
       <characteristic-query type="MY" />
    </characteristic>  
</wap-provisioningdoc>

You will get the something like the following result. There might be more certificates eventually, but we are interested in the SCMDM one. The most important information in here is the certificate hash. In this case it’s 64BB2D1FAD191B04D33D04781CE9ECC8F7D9BAE5. Let’s keep it for the future use.

In case that you want determine this hash automatically from application, it’s good to look for certificate with template name SCMDM2008MobileDevice. However, this template name is valid only for SCMDM 2008 RTM version, if you are running SCMDM 2008 with Service Pack 1, then the name of instance is also included. The template name looks like this SCMDMMobileDevice (mdm-prg), for the mdm-prg instance.

<wap-provisioningdoc>
  <characteristic type="CertificateStore">
    <characteristic type="MY">
      <characteristic type="64BB2D1FAD191B04D33D04781CE9ECC8F7D9BAE5">
        <parm name="EncodedCertificate" value="MIIE..shortened..3msMYf" datatype="binary" />
        <noparm name="Role" />
        <parm name="ValidFrom" value="2009-04-24T20:46:27Z" />
        <parm name="ValidTo" value="2010-04-24T20:46:27Z" />
        <parm name="IssuedBy" value="Contoso Assurance CA" />
        <parm name="IssuedTo" value="WM-pabans-52.amer.contoso.com" />
        <noparm name="TemplateName" />
        <characteristic type="PrivateKeyContainer">
          <parm name="ContainerName" value="MEEBAB1AFF" />
          <noparm name="ProviderName" />
          <parm name="ProviderType" value="1" />
          <parm name="KeySpec" value="2" />
        </characteristic>
        <characteristic type="RenewalInfo">
          <parm name="ServerName" value="rapp57.amer.contoso.com" />
          <parm name="Template" value="SCMDM2008MobileDevice" />
          <parm name="RequestPage" value="/certsrv/certfnsh.asp" />
          <parm name="PickupPage" value="/certsrv/certnew.cer" />
        </characteristic>
      </characteristic>
    </characteristic>
  </characteristic>
</wap-provisioningdoc>

Initiate renewal

Renewal request is initiated with following query to CertificateEnroller Configuration Service Provider. The RenewalCertificateHash parameter contains hash from the previous step.

<wap-provisioningdoc>
  <characteristic type="CertificateEnroller">
    <characteristic type="Operation">
      <characteristic type="RenewOperation">
        <characteristic type="Some-Unique-String-or-GUID">
          <parm name="RenewCertificateHash" value="64BB2D1FAD191B04D33D04781CE9ECC8F7D9BAE5"/>
        </characteristic>
      </characteristic>
    </characteristic>
  </characteristic>
</wap-provisioningdoc>

To determine result of the operation, you can either use the following query.

<wap-provisioningdoc>
    <characteristic type="CertificateEnroller">
        <characteristic type="Operation">
          <characteristic type="RenewOperation">
            <characteristic type="Same-Unique-String-from-the-previous-step">
              <parm-query name="Status" />
            </characteristic>
          </characteristic>
        </characteristic>
    </characteristic>
</wap-provisioningdoc>

Alternativelly you can check the \Windows\logfiles\GetCertificates\DeviceEnrollLog.txt

Windows Mobile Certificate Enrollment Log
Date: 2009-05-08
Time: 18:10:49Z
Device Name: WM-pabans-52
Domain\Username: (null)
Certificate Type Friendly Name: rapp57.amer.contoso.com_SCMDM2008MobileDevice
CA Server: rapp57.amer.contoso.com
Template: SCMDM2008MobileDevice
Request Page path/name: /certsrv/certfnsh.asp
Pickup Page path/name: /certsrv/certnew.cer
RequestID For Enrollment: 136756
Enrollment or Renewal: Renewal
Desktop Initiated: No
Silent Enrollment: No
Status Upon Completion: Successful
Error Code: The operation completed successfully.

I’ve seen many intelligent apartment concepts and technologies, including Microsoft super apartment located here in Prague. In fact all these concepts are nothing but pile of silicon crap collected in one apartment with 15 different remote controllers laying around. I believe that final solution has to be one remote controller for all devices. I also believe that all devices should be powered by .NET Micro Framework. This means there must be a way how to connect Infra Red receiver with .NET Micro Framework.

How does the TV Remote work?

TV Remotes in these days uses infra-red beam modulated on given frequency. Modulated signal can transfer information that represents command button and address of the target device. So, it’s all about PWM modulation. Unfortunately, every electronics vendor is using different PWM format and communication protocol.

Luckily, most of the TV Remote controllers has something common. Every transfer starts with some starting sequence which is nothing else than “very” long pulse. Then two groups of bit’s are transferred, first group represents command and second group represents address. The length of address field and command field is different for every brand. See SB Projects for more details on communication protocols.

Sony SIRC protocol 430x98 Figure 1. Sony SIRC data transfer

Sony SIRC protocol

Protocol of the Sony devices is very simple to decode and uses reasonably fast pulse length, which makes it easy to implement in .NET Micro Framework. See figure 1. for typical Sony data transmission. Start sequence takes 2.4ms and then the data bits follows. Logical 1 is represented by pulse of 1200us while logical 0 is 600us long. Standard Sony data message consist of 12 bits (7 bits for command, 5 bits for address).

Since commands are more or less same for all devices, address field is important to recognize the target. Most common Sony commands and addresses are in the table. For complete list go to: www.hifi-remote.com/sony

Device Address Command Function
TV 1 0 Key 1
VCR 2 1 Key 2
Cassete 14 2 Key 3
CD 17 3 Key 4
    4 Key 5
    5 Key 6
    6 Key 7
    7 Key 8
    8 Key 9
    9 Key 0
    16 Channel Up
    17 Channel Down
    18 Volume Up
    19 Volume Down

Connecting the IR Receiver with CPU

Key part is the infra red receiver. There are many infra red receivers on the market and it’s price is about one dollar. It’s important to buy IR receiver for the right frequency, most remote controllers operates on 38Khz. Even if Sony standard is 40Khz, surpsinigly 38Khz receiver works very well.

I’ve started with popular IR receiver SFH5110-38 but then drop it, because this receiver is very sensitive to input voltage. Even if it should operate from 4.5 to 5.5 volts, when voltage is not at least 5.2V sensor is very unstable. SFH5110-38 powered from USB operated Tahoe-I was unusable.

Then I went for TSOP4838 IR receiver and everything was fine. All these IR receivers works on the same principle and have same pin-out. The control pin is tight high until the signal of 38Khz frequency arrives. Then the pin is grounded and remains grounded till the signal is present. As a verification of the communication, LED is connected between power and control pin. As the signal is being transferred LED flashes. Complete list of components:

  • 38Khz IR receiver TSOP4838 (or other)
  • Low current LED (2 mA)
  • Resistor before LED (~700 ohms)

Connection IR receiver 325x190 Figure 2. IR Receiver circuit

Using the SonyReceiver class

From the paragraph above is obvious that decoding TV Remote signal is nothing but measuring the pulses. Instead of writing class specifically for Sony TV Remotes, I’ve decided to create general “infrastructure” for future extensibility. All remote controllers are derived from TVRemoteReceiver abstract class, which triggers DataReceived event whenever the valid data are received.

abstract public class TVRemoteReceiver : IDisposable
{
    public Cpu.Pin ReceiverPin;
    public abstract void Dispose();
    public delegate void TVRemoteDataHandler(TVRemote sender, int command, int address);
    public event TVRemoteDataHandler DataReceived;
    protected virtual void OnDataReceived(int command, int address)
}

SonyReceiver class is just the filling for the