USB Host pipe issue

Hello,

I try to communicate with a DSLR via the USB interface with my G80 Development Board.
I used the following example as a basis: https://www.ghielectronics.com/community/codeshare/entry/939

When the program enters the CheckEvents() method and invokes the NativeTransfer() on inputPipe, the application freezes.

With the following instructions in comments, everything works correctly on the interruptPipe.

[quote]
if ((int)methodNativeTransfer.Invoke(inputPipe, new object[] { inputData, 0, inputData.Length, 0 }) > 0)
{
Debug.Print("Input data: " + inputData.ToString());
}[/quote]

Here is the code used for my DSLRDevice class:


using System;
using Microsoft.SPOT;
using GHI.Usb.Host;
using GHI.Usb.Descriptors;
using System.Reflection;

namespace CRVBox.Core.Device
{
    public class DSLRDevice : RawDevice
    {
        private const int classCode = 0x06;
        private const int subclassCode = 0x01;
        private const int protocolCode = 0x01;

        private const int inputPipeEndpoint = 0;
        private const int outputPipeEndpoint = 1;
        private const int interruptPipeEndpoint = 2;

        private RawDevice.Pipe inputPipe;
        private RawDevice.Pipe outputPipe;
        private RawDevice.Pipe interruptPipe;
        private byte[] inputData;
        private byte[] interruptData;

        static MethodInfo methodNativeTransfer = typeof(RawDevice.Pipe).GetMethod("NativeTransfer", BindingFlags.NonPublic | BindingFlags.Instance);

        public DSLRDevice(Controller.UnknownDeviceConnectedEventArgs paras) : base(paras.Id, paras.InterfaceIndex, paras.VendorId, paras.ProductId, paras.PortNumber, paras.Type)
        {
            var configuration = GetConfigurationDescriptor(0);

            foreach (Interface i in configuration.Interfaces)
            {
                if (i.ClassCode == classCode && i.SubclassCode == subclassCode && i.NumberEndpoints == 3 && i.ProtocolCode == protocolCode)
                {
                    SendSetupPacket(0x00, 0x09, configuration.Value, 0x00);

                    inputPipe = OpenPipe(i.Endpoints[inputPipeEndpoint]);
                    inputPipe.TransferTimeout = 0;

                    outputPipe = OpenPipe(i.Endpoints[outputPipeEndpoint]);
                    outputPipe.TransferTimeout = 0;

                    interruptPipe = OpenPipe(i.Endpoints[interruptPipeEndpoint]);
                    interruptPipe.TransferTimeout = 0;

                    inputData = new byte[inputPipe.Endpoint.MaximumPacketSize];
                    interruptData = new byte[interruptPipe.Endpoint.MaximumPacketSize];

                    //WorkerInterval = interruptPipe.Endpoint.Interval;
                    WorkerInterval = 1 * 1000;

                    break;
                }
            }
        }

        protected override void CheckEvents(object sender)
        {
            Debug.Print("CheckEvents() => IN");

            if (!CheckObjectState(false))
            {
                return;
            }

            try
            {
                if ((int)methodNativeTransfer.Invoke(inputPipe, new object[] { inputData, 0, inputData.Length, 0 }) > 0)
                {
                    Debug.Print("Input data: " + inputData.ToString());
                }

                if ((int)methodNativeTransfer.Invoke(interruptPipe, new object[] { interruptData, 0, interruptData.Length, 0 }) > 0)
                {
                    Debug.Print("Interrupt data: " + interruptData.ToString());
                }
            }
            catch (Exception e)
            {
                Debug.Print("Input Error: " + Controller.GetLastError().ToString());
                Debug.Print(e.Message);
            }

            Debug.Print("CheckEvents() => OUT");
        }
    }
}

Below is the capture done with a utility under Windows of the characteristics of the USB client device:
Interface Descriptor:

0x09 bLength
0x04 bDescriptorType
0x00 bInterfaceNumber
0x00 bAlternateSetting
0x03 bNumEndPoints
0x06 bInterfaceClass (Imaging Device Class)
0x01 bInterfaceSubClass
0x01 bInterfaceProtocol
0x00 iInterface

Endpoint Descriptor:

0x07 bLength
0x05 bDescriptorType
0x81 bEndpointAddress (IN Endpoint)
0x02 bmAttributes (Transfer: Bulk / Synch: None / Usage: Data)
0x0040 wMaxPacketSize (64 Bytes)
0x00 bInterval

Endpoint Descriptor:

0x07 bLength
0x05 bDescriptorType
0x02 bEndpointAddress (OUT Endpoint)
0x02 bmAttributes (Transfer: Bulk / Synch: None / Usage: Data)
0x0040 wMaxPacketSize (64 Bytes)
0x00 bInterval

Endpoint Descriptor:

0x07 bLength
0x05 bDescriptorType
0x83 bEndpointAddress (IN Endpoint)
0x03 bmAttributes (Transfer: Interrupt / Synch: None / Usage: Data)
0x0008 wMaxPacketSize (8 Bytes)
0x0A bInterval

And I find exactly the same values in my .NETMF application.

I really do not understand what happens, if someone has experience in this domain.

Thank you.

@ >David< - You shouldn’t be using reflection to get the NativeTransfer method. You should be going through the public instance method Pipe.Transfer instead.

I suspect, if it is working at all, since the last parameter you passed was 0, it’s waiting forever to send the data and it’s never completing so you lock up the board.

Hi John,

It was after reading the following subject that I used the reflection to call the NativeTransfer() method.
https://www.ghielectronics.com/community/forum/topic?id=23883

If I only use interruptPipe.Transfer()


if (interruptPipe.Transfer(interruptData) > 0)
{
    Debug.Print("Interrupt data: " + interruptData.ToString());
}

As in the post referenced above, the application waits for a response from the method, but does not freeze.
And if I do the same on the inputPipe, there the application freezes.

I tried with timeout, but the behavior is the same.

@ >David< - Alright. You should try not to use a non-zero timeout so you can cancel the request if needed instead of blocking forever.

The next thing to do would be to connect a USB analyzer if you have one to see what is going on. What specific device are you trying to communicate with?

Hmm, I do not have a USB scanner on hand, I’ll see how I can organize to get one.

The device to which I want to connect is a simple Nikon D3300 digital camera.

@ >David< - Let us know if you’re able to find an analyzer or not. If not, we’ll try and see if we have access to that camera.

So I decided to unpack my G400 Development Board.
Everything worked perfectly with it, I was able to send a GetDeviceInfo PTP command via the USB port, and I received a response from the device.

The problem must come from the G80.

Have you already started working on implementing the USB Host stack on the TinyCLR Core?

For now I will continue to work with the G400 Development Board.

@ >David< - I would refer to https://www.ghielectronics.com/community/forum/topic?id=24281 for information on features of TinyCLR.

Yes, I know this topic, however I would have liked to know if implantation was in progress or simply possibly planned.

It seems to me that there is nothing confidential about it.

Hum, sorry, I misspoke well.

In fact I would like to have further clarification on what was announced in the other topic.
Implementation of the USB Host is already in progress?
Or is it still under consideration?

This information is very important to me, I do not have the utility of the .NET MicroFramework platform without the support of the USB Host.

It will allow me to know if I still invest time in this platform or if I turn to another solution.

It’s been a long time since I stopped basing my decisions on hopes.
Most often we are disappointed.

1 Like

To me the discussion on TinyCLR OS versus netmf 4.3 as implemented is a distraction. While GHI haven’t committed to including or not that feature, it’s on their mind and if feasible, will arrive some time in the future that it’s far too early for anyone to predict.

What is more important is that you’ve identified a difference in behaviour in G80 and G400, and that is something GHI can take on board and look at. Lets not gloss over that.

1 Like