usbFunctionSetup and usbFunctionWrite in action?

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

usbFunctionSetup and usbFunctionWrite in action?

Post by stf92 » Fri Jan 24, 2014 12:13 pm

Hi: Any example of a usbFunctionSetup and usbFunctionWrite in action? Of course they are for the user to write them, but has some user tried to transfer data to the device via a control output transfer (8 bytes maximum if I understood it)?


stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by stf92 » Sat Jan 25, 2014 6:23 pm

Well, that won't do. What I need is source code. C source code of a usbFunctionSetup example. Thanks anyways.

ulao
Rank 4
Rank 4
Posts: 480
Joined: Mon Aug 25, 2008 8:45 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by ulao » Mon Jan 27, 2014 8:50 pm

When you download the v-usb code it comes with an example that demonstrates this in a command prompt. I wrote some code using PID. This is the set up.

Code: Select all

unsigned  usbFunctionSetup(uchar data[8])
{
   usbRequest_t    *rq = (void *)data;
   usbMsgPtr = reportBuffer;


   if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS)
   {    /* class request type */
      if(rq->bRequest == USBRQ_HID_GET_REPORT)
      {
         if (  rq->wValue.bytes[0] == 2 )
         {//PID Block Load Report
            char error=1;
            if (_FFB_effect_index>4) error =2;
            reportBuffer[0]=2; //report id 2
            reportBuffer[1]=_FFB_effect_index;//effect index
            reportBuffer[2]=error;//1 =  success:2 = full: 3 = error
         }                   
         return USB_NO_MSG;      
      }   
      else if (rq->bRequest == USBRQ_HID_SET_REPORT)
       {
           if (  rq->wValue.bytes[0] == 1 )  _setReport=1;//set effect  Report
         return USB_NO_MSG;
       }
   
   }
    return 0;
}


The Write is proprietary to what I use if for but you just need to analyze the data.
uchar usbFunctionWrite(uchar *data, uchar len)
{
if (data[0]==1 && _setReport ){ _setReport=0; ...}
...
}

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by stf92 » Tue Jan 28, 2014 8:56 am

Thanks for your post. Could you tell me what is wrong with the following attempt to transfer data from the PC to the device via a control OUT transfer?

Code: Select all

   for(i=0;i<8;i++){
        buffer[i]= i;
    }
   mode=0;     
   ret=usb_control_msg(d, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, mode, 0, 0, (char *)buffer, sizeof(buffer), 5000);   

in the host app. All this is only a test so if you find it meaningless don't care. In the device app:

Code: Select all

uchar usbFunctionWrite(uchar *data, uchar len){
    int i;

    for(i=0;i<len;i++){ // len expected to be 8.
        Send data[i] to a display driven by the device       
    }
   // The array data[8] here is buffer[8] in the host app.
    return 1;   // if we received it all (0 if not)
}

uchar usbFunctionSetup(uchar data[3]){
#define USB_NO_MSG      0xFF
   
    return  USB_NO_MSG;
}

Of course in a real app, in usbFunctionSetup I would save the setup context. The funny thing is that I do NOT use usbMsgPtr, in spite of the comment in usbdrv.h by the driver author. However, my code does not work. He says:

Code: Select all

extern uchar    *usbMsgPtr;
/* This variable may be used to pass transmit data to the driver from the
 * implementation of usbFunctionWrite(). It is also used internally by the
 * driver for standard control requests.
 */

NOTE: in your usbFunctionWrite, it seems data[0] is the field bmRequestType of the USB device request sent by the host and not the actual data to be transfered after the data stage transaction.

ulao
Rank 4
Rank 4
Posts: 480
Joined: Mon Aug 25, 2008 8:45 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by ulao » Tue Jan 28, 2014 4:25 pm

in your usbFunctionWrite, it seems data[0] is the field bmRequestType of the USB device request sent by the host and not the actual data to be transfered after the data stage transaction.
Correct, I'm leaving that up to you to figure out.

Your problem may be how you set up the pipes. Can you post your config in here?

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by stf92 » Tue Jan 28, 2014 7:24 pm

Thank you. I'm posting a link to the usbconfig.h file:
http://www.filedropper.com/usbconfig

You don't need either to register or login. Just press the 'Download this file' button. The uP in the device is an ATtiny85.

ulao
Rank 4
Rank 4
Posts: 480
Joined: Mon Aug 25, 2008 8:45 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by ulao » Tue Jan 28, 2014 9:54 pm

no, sorry your USB device descriptor config. Normaaly at the top of the main.c file, shows your Interface Descriptors and endpoints...

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by stf92 » Tue Jan 28, 2014 11:17 pm

This is usbdrv.c, the driver source (except the assembler part) which I post along with usbdrv.h:
http://www.filedropper.com/usbdrv
http://www.filedropper.com/usbdrv_1
At the top of usbdrv.c (first link) you'll find what you ask for. Thanks ulao.

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by stf92 » Wed Jan 29, 2014 1:02 pm

This is how usbProcessRx ends in my usbdrv.c:

Code: Select all

         }else{   /* not a standard request -- must be vendor or class request */
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
                uchar   len;
            replyLen = data[6];   /* if this is an OUT operation, the next token will reset usbMsgLen */
            if((len = usbFunctionSetup(data)) != 0xff){
               replyLen = len;
#if 1   /* USB-IO */
               flags = 0;   /* we have no valid msg, use read/write functions */
#endif
            }else{
               flags = 0;   /* we have no valid msg, use read/write functions */
            }
#else
            replyLen = usbFunctionSetup(data);
#endif
         }
      }
      usbMsgLen = replyLen;
      usbMsgFlags = flags;
   }else{   /* out request */
      usbWrite(data, len);
   }
}

You'll be able to see that no matter what the result of usbFunctionSetup is, whether 0xFF (0xFF is USB_NO_MSG) or not, usbMsgLen will never get USB_NO_MSG as its value. Suppose from the host application I call

Code: Select all

   ret=usb_control_msg(d, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, mode, 0, 0, (char *)buffer, sizeof(buffer), 5000);

When in usbPoll, control reaches

Code: Select all

void   usbPoll(void)
{
uchar   len;

   if((len = usbRxLen) > 0){
/* We could check CRC16 here -- but ACK has already been sent anyway. If you
 * need data integrity checks with this driver, check the CRC in your app
 * code and report errors back to the host. Since the ACK was already sent,
 * retries must be handled on application level.
 * unsigned crc = usbCrc16((uchar *)(unsigned)(usbAppBuf + 1), usbRxLen - 3);
 */
      len -= 3;   /* remove PID and CRC */
      if(len < 128){
         usbProcessRx((uchar *)(unsigned)(usbAppBuf + 1), len);
      }
      usbRxLen = 0;   /* mark rx buffer as available */
   }
   if(usbTxLen < 0){   /* TX system is idle */
      if(usbMsgLen != 0xff){
         usbBuildTxBlock();
      }else if(usbNewDeviceId){
         usbDeviceId = usbNewDeviceId;
#if 0   /* USB-IO */
         DBG1(1, &usbNewDeviceId, 1);
#endif
         usbNewDeviceId = 0;
      }
   }

and if usbTxLen < 0, usbBuildTxBlock will be called, even if there is nothing to transmit. I am looking at the Changelogs of newer versions to see where the bug was fixed.

ulao
Rank 4
Rank 4
Posts: 480
Joined: Mon Aug 25, 2008 8:45 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by ulao » Wed Jan 29, 2014 9:19 pm

Ok I see you didnt customize it, you left the default setup. Well I cant really help you go about it by answering your questions but consider.

1) You wont get this to work win only on endpoint. You need a control in and out. I also think ( don't quote me on this ) that you need the default that as well. Unless you are using the default and in that case your ok. So you really need two in one out. At very least one in and one out. Simply defining USB_CFG_IMPLEMENT_FN_WRITE does not do that AFAIK.

This is ugly,

Code: Select all

#if 1
#define   USB_CFG_HAVE_INTRIN_ENDPOINT   1
#else
#define   USB_CFG_HAVE_INTRIN_ENDPOINT   0
#endif

why not just

Code: Select all

#define   USB_CFG_HAVE_INTRIN_ENDPOINT   1 
//or
 #define   USB_CFG_HAVE_INTRIN_ENDPOINT   0

anyways I think you need 2 here but depends on how you use it.


plus the third. This is missing in the usbconfig, its very clear on the new stuff.

2) Your way out of date here and full of bugs. Creation Date: 2005-04-01 ? the newer version makes end point much easier. Consider checking out the newer code.

Other then that I'm afraid my knowledge and the way I set up my code is not enough to help you with your problem.

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by stf92 » Fri Jan 31, 2014 2:37 pm

Well this is code from Objective Development used by Yoshiyasu Takefuji in a Circuit Cellar article from 2008 to control a programmable power supply via USB. As I implemented the circuit as he gave it, I did not touch the usbconfig.h file except for some things, namely, he transferred the voltage value to the device using the value field in the usbControlMsg call. So he did not use usbFunctionWrite, doing everything from usbFunctionSetup. Whereas I wanted to use usbFunctionWrite to transfer 8 bytes to the device. For this, I only needed control transfers. No Interrupt or any other type of transfers. Hence, with only the endpoint 0 I was done (if I am not wrong).

Anyways, because I think something was wrong in the usbdrv.c file that wouldn't let me use usbFunctionWrite, I now want to make a fresh start and am using avrusb-20080418 for the project (I am not interested in the power supply thing, only want to see USB working with usbFunctionWrite and a control out message). Maybe later on I'll date to use the current obdev code, but for the moment I pretend maximum simplicity, because it's a matter of understanding what I am doing and the simpler the code the easier to understand. Thanks very much for the time you lent me, ulao.

ulao
Rank 4
Rank 4
Posts: 480
Joined: Mon Aug 25, 2008 8:45 pm

Re: usbFunctionSetup and usbFunctionWrite in action?

Post by ulao » Mon Feb 03, 2014 7:36 pm

I would agree a fresh start is best. A simpler version is always best for the programmer and the help.

Post Reply