Bug in Wiki (or) in "PowerSwitch" [solved]

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
laurentppol
Posts: 3
Joined: Wed Jul 21, 2010 10:50 pm

Bug in Wiki (or) in "PowerSwitch" [solved]

Post by laurentppol » Tue Jul 27, 2010 1:33 am

Hi, I'am trying to understand V-USB, so I have started with PowerSwitch as it is said to be "pure basics".
On my board I have an LCD, so I included (original) lcd.h/lcd.c (after configuring pins - works OK).
(my "target" is something like lcd2usb but this project does NOT work for me... :( )

Now the PowerSwitch: control transfers work OK (can send wIndex, wValue, even wLength is transferred to device), receive: works (at least default 2 byte return).

Now I want to send more data (4-8bytes). According to Wiki changed:
USB_CFG_IMPLEMENT_FN_READ to 1,

added:
usbMsgLen_t usbFunctionSetup(uchar setupData[8])
...
currentPosition = 0; // initialize position index
bytesRemaining = rq->wLength.word; // store the amount of data requested
if(bytesRemaining > sizeof(buffer)) // limit to buffer size
bytesRemaining = sizeof(buffer);
return USB_NO_MSG; // tell driver to use usbFunctionWrite()
...

added:
uchar usbFunctionWrite(uchar *data, uchar len)
{
uchar i;
if(len > bytesRemaining) // if this is the last incomplete chunk
len = bytesRemaining; // limit to the amount we can store
bytesRemaining -= len;
for(i = 0; i < len; i++)
buffer[currentPosition++] = data[i];
...
"blinkLED()"
...
return bytesRemaining == 0; // return 1 if we have all data
}

Problem #1: compiler says: there is NO USB_NO_MSG defined. After a quic search in other downloader project I have found it's declaraction. Copied to usbdrv.h.

So bug is in (current?) usbdrv.h or in Wiki?

Problem #2:
compile OK, but "blinkLED" NEVER get called.

I have located, that in this fragment of usbdv.c:
" /* 1: CLEAR_FEATURE, 3: SET_FEATURE, 7: SET_DESCRIPTOR */
/* 12: SYNCH_FRAME */
}
#undef SET_REPLY_LEN
}else{ /* not a standard request -- must be vendor or class request */
replyLen = usbFunctionSetup(data);
}
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
if(replyLen == 0xff){ /* use user-supplied read/write function */
if((rq->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_DEVICE_TO_HOST){
replyLen = rq->wLength.bytes[0]; /* IN transfers only */
}
flags &= ~USB_FLG_USE_DEFAULT_RW; /* we have no valid msg, use user supplied read/write functions */
}else /* The 'else' prevents that we limit a replyLen of 0xff to the maximum transfer len. */
#endif
if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0]) /* limit length to max */
replyLen = rq->wLength.bytes[0];
}
/* make sure that data packets which are sent as ACK to an OUT transfer are always zero sized */
}else{ /* DATA packet from out request */
blinkLED();

#if USB_CFG_IMPLEMENT_FN_WRITE
if(!(usbMsgFlags & USB_FLG_USE_DEFAULT_RW)){
uchar rval = usbFunctionWrite(data, len);
replyLen = 0xff;
if(rval == 0xff){ /* an error occurred */
usbMsgLen = 0xff; /* cancel potentially pending data packet for ACK */
usbTxLen = USBPID_STALL;
}else if(rval != 0){ /* This was the final package */
replyLen = 0; /* answer with a zero-sized data packet */
}
flags = 0; /* start with a DATA1 package, stay with user supplied write() function */
}
#endif
}
usbMsgFlags = flags;"

control NEVER reaches " }else{ /* DATA packet from out request */"

What is the problem, and what can I do to make it work?

laurentppol
Posts: 3
Joined: Wed Jul 21, 2010 10:50 pm

Re: Bug in Wiki (or) in "PowerSwitch" [solved]

Post by laurentppol » Fri Jul 30, 2010 10:39 pm

The BUGS (multiple - 4) are on HOST side of example program powerswitch.c:

Original code:

Code: Select all

if(strcmp(argv[1], "on") == 0){
            nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, PSCMD_ON, duration, port, (char *)buffer, sizeof(buffer), 5000);
        }else if(strcmp(argv[1], "off") == 0){
            nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, PSCMD_OFF, duration, port, (char *)buffer, sizeof(buffer), 5000);


Should be:

Code: Select all

if(strcmp(argv[1], "on") == 0){
            nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, PSCMD_ON, duration, port, (char *)buffer, 0, 5000);
        }else if(strcmp(argv[1], "off") == 0){
            nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, PSCMD_OFF, duration, port, (char *)buffer, 0, 5000);


Comment:
1). we don't really want transfer anything to device in THIS example (apart command, port and duration included in SETUP phase), so put length of data = 0 instead of sizeof(buffer) which will be correct for IN transfer ("status" command)..
2). change IN to OUT does NOT affect this project (look point 1) but SHOULD be OUT in case someone want to extend data transfer TO device (using DATA phase, as described in WiKi).

That comment (and solution costed me 3 afternoons...), wrrrr.

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Re: Bug in Wiki (or) in "PowerSwitch" [solved]

Post by christian » Mon Aug 02, 2010 1:49 pm

Note that PowerSwitch ships with a really old version of the driver. It has not been updated since the driver comes in a separate package now (see http://www.obdev.at/products/vusb/download.html). The wiki documentation refers to more recent versions.

Regarding USB_ENDPOINT_IN vs. USB_ENDPOINT_OUT in the host side software of PowerSwitch: This code was written for the very first version of V-USB (AVR-USB at that time). OUT transfers were not supported by that version and since we only want to transfer data in the setup block, an IN transfer can be used as well.

We don't update PowerSwitch for newer versions of V-USB because the driver ships with very simple examples now.

Post Reply