Today I started a trial move from 4.2 to the latest 4.3SDK (on EMX), and I’ve a few questions, perhaps asked/answered before but I haven’t been able to find them.
How do we configure to start headless? My 4.2 code was:
and it appears this has mostly been replaced by setting the controller Active Device:
Controller.ActiveDevice = ms;
How can I Stop() the controller without starting a new active device? Pass in a null?
In 4.2 doing a Write() to a USB Stream returned the number of bytes actually written, we have quite a bit of code to handle the case where this doesn’t equal the buffer size sent to tha call.
In 4.3 the Write() function is a void. How can we tell if the call succeeded fully or not?
1: GHI.Processor.Display.Disable(); If it returns true, a reboot is needed.
2: That function no longer exists.
3: You are correct, passing null disables it.
4: Write loops internally until all of the bytes have been written or the amount of time specified by WriteTimeout has passed. Write is void because the base System.IO.Stream class requires it to be.
So if the Write times out, we take an exception? Is this documented anywhere?
In the base class documentation for System.IO.Stream it says that on a successful Write the Position in the Stream is advanced by the number of bytes written, if an exception occurs the position within the Stream is unchanged.
However the GHI documentation says Position is Not Supported.
We need to know that the Write succeeded, and how many bytes were sent, or if it failed. The 4.2 method returning a count did this, the 4.3 method should support this with an exception and updated Position property, but it seems the current implementation gives us neither?
@ C-Born - Currently Write will throw an InvalidOperationException when it times out, but a coming SDK will add a more descriptive OperationTimedOutException. I will look into supporting position that is updated in writes and reads in a future SDK as well.
InvalidOperationException looks to be thrown from NativeStop only when USB client has not been started. Do you have a minimal example you can post that reliably shows the error?
@ John - the InvalidOperationException is thrown when I set the Controller.ActiveDevice property to null to disable it, as per your response to my question 3.
In the 4.2 code when switching the USB between raw stream and MassStorage modes, my code would use
USBClientController.Stop();
when I replaced those calls with
Controller.ActiveDevice = null;
the exception is thrown.
If I just set the Controller.ActiveDevice to the new device, things seem to work ok. However there are some areas of code where the timing isn’t clear due to thread interaction, and the previous code stops the device on one thread and the new device is then started on another, so the first thread has to disable the USB rather than starting a new device.
If setting the ActiveDevice to null is an invalid operation, is there another way to disable it?
@ C-Born - Setting ActiveDevice to null should work. If it doesn’t for you, can you post a complete and small example so we can try to reproduce the issue?
@ John - The original application switches between Raw and MassStorage, I started building a small demo of the problem, and at the stage below I started getting the invalid operation exceptions. This isn’t the exact problem, but it could have the same root cause.
Then again it could be my code is incorrect, there is not a lot of documentation available! I would have expected to find a DetachLogicalUnit() somewhere.
For me this takes the exception the second time through the loop, debugging over serial.
David
using System;
using System.Threading;
using Microsoft.SPOT;
using GHI.Usb.Client;
using GHI.Usb;
using GHI.IO.Storage;
public class Program
{
public static SDCard sd;
public static void Main()
{
// Assume SD card is connected
try
{
sd = new SDCard();
}
catch
{
throw new Exception("SD card not detected");
}
int i;
for (i = 1; i < 5; ++i)
{
Debug.Print("Attempt: " + i);
if (!DiskDriveMode(true))
break;
Thread.Sleep(10000);
if (!DiskDriveMode(false))
break;
Thread.Sleep(10000);
}
}
static MassStorage ms;
static bool DiskDriveMode(bool on)
{
if (on)
{
Debug.Print("Starting Mass Storage");
try
{
ms = new MassStorage();
Controller.ActiveDevice = ms;
ms.AttachLogicalUnit(sd, 0, "", "");
ms.EnableLogicalUnit(0);
}
catch (Exception ex)
{
Debug.Print("Start MS:: Exception: " + ex.Message);
return false;
}
}
else
{
Debug.Print("Stopping Mass Storage");
try
{
ms.DisableLogicalUnit(0);
Controller.ActiveDevice = null;
}
catch (Exception ex)
{
Debug.Print("Stop MS:: Exception: " + ex.Message);
return false;
}
}
return true;
}
}
@ John - Hopefully it is another manifestation of the same problem and your fix will work for our application too. Let me know if you want me to test anything on the full version.