USBHost can handle an USBClient?

My configuration is fairly simple:
FEZ Spider 1.0 with NETMF 4.2 is provided some sensors, is debugged via RS232 and starts a CDC on its USBClientDP

It works very well when connected to my PC, establishing a COM connection with standard settings: 9600, No parity, 8 bit, one stop. Putty told me though, it is using XON/XOFF handshake, that I didn’t set.

If I connect it with the USBHost of another, identical FEZ Spider, I have:

  • the host notices the new device;
  • the driver tells me not to use the standard connection (I did and now I am using GHI.Premium.USBHost classes);
  • if I use a USBH_SerialUSB, it is created with None handshake and cannot be modified (Exception), therefore either I read rubbish or an exception is raised;
  • if I use a USBH_RawDevice, there is no way to configure it to read: every setting of the pipes will raise an exception during the read call. :wall:

Since I cannot believe to be the first to give it a try, how can I communicate between gadgeteers using a master/slave USB connection???

Hopefully these resources will help to get you on your way:

[ul]Example Raw Device with read/write, in our Community>Codeshare: https://www.ghielectronics.com/community/codeshare/entry/522 (I didn’t check but the assemblies/interface may be the 4.1 NETMF)
Place to see source code of gadgeteer drivers: gadgeteer.codeplex.comhttp://gadgeteer.codeplex.com/SourceControl/latest#Main/Modules/GHIElectronics/UsbHost/Software/UsbHost/UsbHost_42/UsbHost_42.cs
Link to the GHI 4.2 SDK APIs, follow links found on ghielectronics.com>Support>NETMF: Library Documentation[/ul]

Sorry, but we had a complete black out, and only today I had time to look into it.
Your example is indeed 4.1, but no problem: I know the conversion rules.

I like a lot the specific device class approach, instead of everything in the same source; nevertheless, encapsulated or not, that’s more or less the same code I was trying. BTW, why didn’t you feel the urge to write such a device handler from the start, before the kit hits the market with such a missing utility? ???

I recognize the USB as a CDC, create the pipes, configure the transfer and wait for reading.
At the very first reading I get an exception, that is:
{System.Exception}
_message: null
InnerException: null
m_HResult: 4294967295
m_innerException: null
m_stackTrace: {byte[24]}
Message: "Exception was thrown: System.Exception"
StackTrace: “GHI.Premium.USBHost.USBH_RawDevice+Pipe::TransferPipe_Helper\r\nGHI.Premium.USBHost.USBH_RawDevice+Pipe::TransferData\r\nJRC.RemoteSiren.USBClientController::ReaderThread\r\n”

The client prints out a text line every second over the USB channel.
Do you have the chance to give a try to such a connection, using two Spiders?

Thanks for your kind collaboration,

  D A Galliano

@ DAG -

I am not sure I can understand you, I think you are trying to setup one Spider which is config as USBClient ,and connect to another spider which is configed as USBHost?

I will try later but now I can answer the question above, that is Yes.
You can do a quick test like this:

  • Pick one Spider and enter to Bootloader mode, default it will be CDC VCOM.
  • Connect to another Spider which is configed as USBHost, it should work well as we are doing here to program a lot of spider module.

Finally, post your code if you can.

I am very happy to know that. HOW???

On Spider client I have configured the switches to Serial Debug; then, using an UsbClientDP, I initialized [em]USBC_CDC cdc[/em] as [em]USBClientController.StandardDevices.StartCDC()[/em]
When its state got Running, I started writing on it.

On Spider Host I have a UsbHost, which is not configured in the designer to avoid a warning message, but handled using
[em]USBHostController.DeviceConnectedEvent += DeviceConnectedEvent;[/em]
where
private void DeviceConnectedEvent(GHI.Premium.System.USBH_Device device)
{
Debug.Print(“Device connected”);

        switch (device.TYPE)
        {
            case USBH_DeviceType.Serial_CDC: // CDC connected
                if (UsbClient != null) return;
                UsbClient = new USBClientController(device);
                return;


}
}

As suggested by Jeff, this is the device handling class:

public class USBClientController : USBH_Device
{
    private USBH_RawDevice raw;
    private USBH_RawDevice.Pipe readPipe, writePipe;
    private byte[] readBuffer = new byte[32];
    private byte[] writeBuffer = new byte[8];
    private Thread Client_Thread;
    bool terminateThread = false;

    public USBClientController(USBH_Device device)
        : base(device)
    {
        raw = new USBH_RawDevice(device);
        USBH_Descriptors.Configuration cd = raw.GetConfigurationDescriptors(0);

        writePipe = raw.OpenPipe(cd.interfaces[0].endpoints[1]); // to write settings (LEDs, strobe...)
        readPipe = raw.OpenPipe(cd.interfaces[0].endpoints[0]); // to read buttons
        readPipe.TransferTimeout = 0;

        raw.SendSetupTransfer(0x00, 0x09, cd.bConfigurationValue, 0x00);

        USBHostController.DeviceDisconnectedEvent += USBHostController_DeviceDisconnectedEvent;

        for (int i = 0; i < readBuffer.Length; i++)
            readBuffer[i] = 0;

        for (int i = 0; i < writeBuffer.Length; i++)
            writeBuffer[i] = 0;

        writeBuffer[1] = 0x08;

        Client_Thread = new Thread(ReaderThread);         // create the polling thread
        Client_Thread.Priority = ThreadPriority.Highest;  // we should read as fast as possible
        Client_Thread.Start();
    }

    void USBHostController_DeviceDisconnectedEvent(USBH_Device device)
    {
        terminateThread = true;
        USBHostController.DeviceDisconnectedEvent -= USBHostController_DeviceDisconnectedEvent;
    }

    private void ReaderThread()
    {
        // Read every bInterval
        while (!terminateThread)
        {
            Thread.Sleep(readPipe.PipeEndpoint.bInterval);

            try
            {
                [b]readPipe.TransferData(readBuffer, 0, readBuffer.Length);[/b]
            }
            catch(Exception ex)
            {
            }
        }
    }
}

The bold line is where I get the exception :frowning:

@ DAG -

I am not sure why you use UsbClient in there. It is simple by using

static USBH_SerialUSB serialUSB;
 static void DeviceConnectedEvent(USBH_Device device)
        {
            Debug.Print("Device connected " + device.TYPE);
           
            switch (device.TYPE)
            {
                case USBH_DeviceType.Serial_CDC: // FTDI connected
                    serialUSB = new USBH_SerialUSB(device, 9600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One);
                    serialUSB.Open();
                    Debug.Print("Serial_CDC - Port Opened");
                    break;
            }
        }

Then you can use serialUSB to comunicate with Spider which is configed as USB Client.

@ Dat -

And if a new CDC device is connected, should call Close() -> Dispose() -> set null if the object was created already.

I mean


if (UsbClient != null) return;

I don’t think it will work for the second time (but I am not sure, check it if you want).

I needed that control, because I am receiving endless connected events, and I want just one.
Of course, in case of disconnected device I clean up the connection to accept another one.

If I remove from the designer the usbHost connection, I receive just two connected events, though.

In any case, I start a thread to listen on the USB port created exactly as you suggest (the USBClientController was only a nice suggestion from your colleague), and all I receive is rubbish. The read call always returns to have read data for the whole buffer (256 bytes every 10 ms, when the client outputs about 80 bytes each second), but there is no sense in the bytes it read.
I checked the ports and noticed that CDC started a XON/XOFF connection and the host a None one. Is it the possible reason???

I made all the possible HW checks, exchanging the boards and the modules, and the behavior is always the same. I am not that expert of USB to know how to set up the serial connection and there is no reference to do that.

Please, help
:wall: