Noob Confusion....

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
ebsy
Posts: 2
Joined: Sat Apr 13, 2013 4:33 pm

Noob Confusion....

Post by ebsy » Sat Apr 13, 2013 4:59 pm

So let me begin by confessing, that I seem to be waaaay out of my depth !
I moved from Arduino to AVR, and the whole USB business has left me spinning with information overload and far too many new doors to cope with.

Still, I am hoping that if I can get a simple example up and running, it'll be a good basis to start some proper learning.

Here's where I am at....

I started with this article for v-usb : http://codeandlife.com/2012/01/22/avr-a ... al-part-1/
and was doing well setting up an ATTiny45.
Included in the code I programmed it with is :

Code: Select all

USB_PUBLIC uchar usbFunctionSetup(uchar data[8]) {
   usbRequest_t *rq = (void *)data; // cast data to correct type
   switch(rq->bRequest) { // custom command is in the bRequest field
      case USB_LED_ON:
      PORTB |= (1<<3);         // turn LED on (ATTiny45 PB3)
      return 0;
      case USB_LED_OFF:
      PORTB &= ~(1<<3);                    // turn LED off (ATTiny45 PB3)
      return 0;
   }
   return 0; // should not get here
}



My problems start when it comes to the host-side coding.
The example on codeandlife works with C, and I am not too familar with that.
Hence after some googling, I found libusbdotnet, and thought I'd be more comofrtable working in c# which I have a 'little' experience of.

I've installed the libusbdotnet downloads and examples.
What I cannot understand, is how/when the above function (usbFunctionSetup) gets triggered by my c# code.
(my LED is not lighting up)
I can see that in the AVR code, usbFunctionSetup is called by usbProcessRx, when certain conditions are met ... but I really dont' understand all the code as yet.

I thought the LED would light even just on the Show.Info example, but I have tried a few other examples as well.
Like I said, I am now rather lost, dazed and confused as to what is happening on the host & AVR side sof things and how they all tie together!

I could give up and admit I am in too deep .... but I have to get USB working in my ATTiny's.
Hope someone will take pity and maybe point me in the right direction ?

Eternal thanks to that person !

Code: Select all

static inline void usbProcessRx(uchar *data, uchar len)
{
usbRequest_t    *rq = (void *)data;

/* usbRxToken can be:
 * 0x2d 00101101 (USBPID_SETUP for setup data)
 * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer)
 * 0...0x0f for OUT on endpoint X
 */
    DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
    USB_RX_USER_HOOK(data, len)
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
    if(usbRxToken < 0x10){  /* OUT to endpoint != 0: endpoint number in usbRxToken */
        usbFunctionWriteOut(data, len);
        return;
    }
#endif
    if(usbRxToken == (uchar)USBPID_SETUP){
        if(len != 8)    /* Setup size must be always 8 bytes. Ignore otherwise. */
            return;
        usbMsgLen_t replyLen;
        usbTxBuf[0] = USBPID_DATA0;         /* initialize data toggling */
        usbTxLen = USBPID_NAK;              /* abort pending transmit */
        usbMsgFlags = 0;
        uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;
        if(type != USBRQ_TYPE_STANDARD){    /* standard requests are handled by driver */
            replyLen = usbFunctionSetup(data);
        }else{
            replyLen = usbDriverSetup(rq);
        }

vouvoume

Re: Noob Confusion....

Post by vouvoume » Sat Apr 13, 2013 6:06 pm

Hi.
Maybe you want to look into the VUSB template/example of tinyUSBboard.
There you will be provided with firmware and compatible host-side applications (linux, windows, both).
If someone wants to have a GUI template for/with GDK, he/she can also use this template.

http://matrixstorm.com/avr/tinyusbboard/#examples

("VUSB skeleton/example with corresponding linux, windows (delphi) and platform independent GTK libusb program")

Have fun!

ebsy
Posts: 2
Joined: Sat Apr 13, 2013 4:33 pm

Re: Noob Confusion....

Post by ebsy » Sat Apr 13, 2013 6:34 pm

Thanks for that.

Unfortunately I'm not sure if this particular approach is going to help.
From what I see, your avenue is requiring me to install and us GTK ?

Problem is that there are already so many compenents involved, v_usb, linusb.net, c, c#, and serval IDEs (ATmelStudio, VS) .... and GTK would be yet another layer adding to the confusion ?
(assumed from an initial look)

Having read the above back to myself, I may even now step further back and try and work out the c side of things, cutting out the c#.
1 less thing to clutter the horizon.

Of course, I'm open to being pursuaded ....

vouvoume

Re: Noob Confusion....

Post by vouvoume » Sat Apr 13, 2013 7:01 pm

Use the basic linux subdirectory. There is no GTK in it, it is pure libusb code.
(Therefor it is a console only application, but it focuses on the essential.)
If you use Windows install a GNU compatible compiler, like MinGW.

Best regards

Talib
Posts: 10
Joined: Fri Oct 22, 2010 12:10 pm

Re: Noob Confusion....

Post by Talib » Thu May 23, 2013 3:21 pm

Hi

I followed this tutorial: http://codeandlife.com/2012/01/22/avr-a ... al-part-1/
It is not C# but it gave me good start at understanding how the basic USB works (Control Messages). - See my (Roelf) comment on the third part of this tutorial if you do not understand the direction thing

I have started writing my own custom c# class for my own use. I will share it, but keep in mind I do not code for a living and all judgments on my coding style and methods should be educational and not just criticism.

USBClass.cs

Code: Select all

using System;
using System.Collections.Generic;
using LibUsbDotNet;
using LibUsbDotNet.Info;
using LibUsbDotNet.Main;

namespace USBTest
{
    /// <summary>
    /// The general class to obtain the TinyCon devices.
    /// </summary>
    static class TinyConUSBClass
    {
        const int VENDORID = 0x16C0;
        const int PRODUCTID = 0x05DC;

        public static List<TinyConDeviceClass> TinyConDevices = new List<TinyConDeviceClass>();

        /// <summary>
        /// Gets all the connected TinyCon devices and store them in TinyConDevices
        /// </summary>
        /// <returns>void</returns>
        public static void GetUSBDevices()
        {
            //Find devices matching the vendor and product ID
            UsbDeviceFinder USBFinder = new UsbDeviceFinder(VENDORID, PRODUCTID);
            //Using the registry create a list of those devices
           
            UsbRegDeviceList USBRegistryDevices = UsbDevice.AllDevices.FindAll(USBFinder);

            foreach (UsbRegistry USBReg in USBRegistryDevices)
            {
               TinyConDevices.Add(new TinyConDeviceClass(USBReg));
            }
        }

        /// <summary>
        /// Closes all the TinyCon devices and exits the USB driver
        /// </summary>
        public static void ExitUSB()
        {
            foreach (TinyConDeviceClass TinyCon in TinyConDevices)
                TinyCon.Close();

            UsbDevice.Exit();
        }
    }

    /// <summary>
    /// Using my own USB Request type as libusbdotnet's version seems to be incomplete
    /// </summary>
    public enum USBRequestType{
        RECIPIENT_DEVICE = 0,
        RECIPIENT_INTERFACE = 1,
        RECIPIENT_ENDPOINT = 2,
        RECIPIENT_OTHER = 3,
        TYPE_STANDARD = 0,
        TYPE_CLASS = 32,
        TYPE_VENDOR = 64,
        TRANSFER_DIRECTION_OUT = 0,
        TRANSFER_DIRECTION_IN = 128
    }

    /// <summary>
    /// The class for individual TinyCon devices.
    /// </summary>
    class TinyConDeviceClass
    {
        private UsbRegistry _USBRegistry;
        private UsbDevice _USBDevice = null;
        private char[] _USBBuffer = new char[64];

        private enum TinyConRequest
        {
            LED_STATE = 1
        }

        /// <summary>
        /// Is the TinyCon device open. (Read-only)
        /// </summary>
        public bool IsOpen
        {
            get
            {
                if (_USBDevice == null)
                    return false;
                return _USBDevice.IsOpen;
            }
        }

        /// <summary>
        /// Read TinyCon serial number. (Read-only)
        /// </summary>
        public string GetSerialNumber
        {
            get
            {
                if (_USBDevice == null)
                    return "Device not open.";
                return _USBDevice.Info.SerialString;
            }
        }

        public TinyConDeviceClass(UsbRegistry USBRegistry)
        {
            _USBRegistry = USBRegistry;
        }

        /// <summary>
        /// Open the TinyCon device.
        /// </summary>
        /// <returns>bool</returns>
        public bool Open()
        {
            if (!_USBRegistry.Open(out _USBDevice))
                return false;

            if (_USBDevice == null)
                return false;

            IUsbDevice wholeUsbDevice = _USBDevice as IUsbDevice;
            if (!ReferenceEquals(wholeUsbDevice, null))
            {
                // This is a "whole" USB device. Before it can be used,
                // the desired configuration and interface must be selected.

                // Select config #1
                wholeUsbDevice.SetConfiguration(1);

                // Claim interface #0.
                wholeUsbDevice.ClaimInterface(0);
            }

            return true;
        }

        /// <summary>
        /// Set the LED1 State.
        /// </summary>
        /// <param name="State">bool</param>
        /// <returns>bool</returns>
        public bool LEDState(bool State)
        {
            //object and length can be null/0 if no data packet is involved.
            UsbSetupPacket SetupPacket = new UsbSetupPacket((byte)(USBRequestType.RECIPIENT_DEVICE | USBRequestType.TYPE_VENDOR), (byte)TinyConRequest.LED_STATE, (short)(State ? 1 : 0), 0, 0);
            int LengthTransfered = 0;

            if (_USBDevice == null)
                return false;

            return _USBDevice.ControlTransfer(ref SetupPacket, null, 0, out LengthTransfered);
        }

        /// <summary>
        /// Closes the TinyCon device.
        /// </summary>
        public void Close()
        {
            if (_USBDevice != null)
            {
                _USBDevice.Close();
                _USBDevice = null;
            }
        }
    }
}



Please note the class is not complete, but it will give you an idea of what to to.

As for implementation:

Code: Select all

TinyConUSBClass.GetUSBDevices();

if (TinyConUSBClass.TinyConDevices.Count > 0)
{
    TinyConUSBClass.TinyConDevices[0].Open();
     Console.WriteLine("Serial Number: " + TinyConUSBClass.TinyConDevices[0].GetSerialNumber);
     TinyConUSBClass.TinyConDevices[0].LEDState(true);
}
//No need to call  TinyConUSBClass.TinyConDevices[0].Close(); as ExitUSB closes all devices
TinyConUSBClass.ExitUSB();


As you will note the class is set up so that if you have multiple same devices plugged into one host, they are easily enumerated.

PS Thinking of making the TinyConUSBClass not static and singleton, then I could implement a destructor that would call USBExit() automatically.

Post Reply