HID DESCRIPTOR more than 255 bytes

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
declan smith
Rank 1
Rank 1
Posts: 32
Joined: Fri Nov 02, 2012 3:26 pm

HID DESCRIPTOR more than 255 bytes

Post by declan smith » Fri Nov 02, 2012 3:34 pm

Hi all,
I tried to set USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH to 256 (or more), and this error I got in AVRStudio 4:

../usbdrv/usbdrv.c:174: warning: large integer implicitly truncated to unsigned type

It looks like descriptor length cannot more than 255 bytes.
How to fix this?

On Release 2012-01-09, it said:
Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255 bytes.

Help me please...

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

Re: HID DESCRIPTOR more than 255 bytes

Post by ulao » Fri Nov 02, 2012 8:25 pm

Yes it was fixed, I committed the bug. Can you show a bit more code? I think the issue is in the typing of the descriptor functions. Just add your main to the thread and I'll spot the error.

declan smith
Rank 1
Rank 1
Posts: 32
Joined: Fri Nov 02, 2012 3:26 pm

Re: HID DESCRIPTOR more than 255 bytes

Post by declan smith » Sat Nov 03, 2012 4:34 am

Thanks for your reply ulao (sorry if I wrong typed your name :oops: )
Here's the main code:

Code: Select all

//=========================================================================
//
// Project: PPM2USB, a AVR-based PPM to USB-Joystick Converter using V-USB.
// Author: Thomas Pfeifer
// Creation Date: 2010-09-10
//
// WWW: http://thomaspfeifer.net/ppm2usb_adapter.htm
//
// Copyright: (c) 2010, Thomas Pfeifer - http://www.thomaspfeifer.net
//
//            This software is free for non-commercial use. It may be copied,
//            modified, and redistributed provided that this copyright notice
//            is preserved on all copies.
//
//            You may NOT use this software, in whole or in part, in support
//            of any commercial product without the express consent of the
//            author.
//
//            There is no warranty or other guarantee of fitness of this
//            software for any purpose. It is provided solely "as is".
//
//=========================================================================

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h> /* for sei() */
#include <util/delay.h> /* for _delay_ms() */

#include <avr/pgmspace.h>  /* required by usbdrv.h */
#include "usbdrv.h"
#include "oddebug.h"
#include "ppm.h"

/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */

PROGMEM char usbHidReportDescriptor[208] = { // USB report descriptor, size must match usbconfig.h
// device 1
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x04,                    // USAGE (Joystick)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x01,                    //   USAGE_PAGE (Generic Desktop)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x85, 0x05,                    //   REPORT_ID (5)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
    0x46, 0xff, 0x00,              //   PHYSICAL_MAXIMUM (255)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x09, 0x34,                    //     USAGE (Ry)
    0x09, 0x41,                    //     USAGE (Vy)
    0x09, 0x32,                    //     USAGE (Z)
    0x09, 0x33,                    //     USAGE (Rx)
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x95, 0x06,                    //     REPORT_COUNT (6)
    0x81, 0x82,                    //     INPUT (Data,Var,Abs,Vol)
    0xc0,                          //   END_COLLECTION
    0x09, 0x04,                    //   USAGE (Joystick)
    0xa1, 0x00,                    //   COLLECTION (Physical)
    0x85, 0x05,                    //     REPORT_ID (5)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0x95, 0x01,                    //     REPORT_COUNT (1)
    0x75, 0x05,                    //     REPORT_SIZE (5)
    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
    0xc0,                          //   END_COLLECTION
    0xc0,                          // END_COLLECTION [b](73 bytes)[/b]

// device 2
    0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 0)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x00,                    //  COLLECTION (Physical)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x07,                    //   REPORT_COUNT (7)
    0x85, 0x01,                    //   REPORT_ID (1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
    0x46, 0xff, 0x00,              //   PHYSICAL_MAXIMUM (255)
    0x09, 0x30,                    //   USAGE (0x30)
    0x09, 0x31,                    //   USAGE (0x31)
    0x09, 0x32,                    //   USAGE (0x32)
    0x09, 0x33,                    //   USAGE (0x33)
    0x09, 0x34,                    //   USAGE (0x34)
    0x09, 0x35,                    //   USAGE (0x35)
    0x09, 0x36,                    //   USAGE (0x36)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0,                          //  END_COLLECTION 
    0xc0,                          // END_COLLECTION (45 bytes)

// device 3
    0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 0)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x00,                    //  COLLECTION (Physical)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x07,                    //   REPORT_COUNT (7)
    0x85, 0x03,                    //   REPORT_ID (3)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
    0x46, 0xff, 0x00,              //   PHYSICAL_MAXIMUM (255)
    0x09, 0x30,                    //   USAGE (0x30)
    0x09, 0x31,                    //   USAGE (0x31)
    0x09, 0x32,                    //   USAGE (0x32)
    0x09, 0x33,                    //   USAGE (0x33)
    0x09, 0x34,                    //   USAGE (0x34)
    0x09, 0x35,                    //   USAGE (0x35)
    0x09, 0x36,                    //   USAGE (0x36)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0,                          //  END_COLLECTION 
    0xc0,                          // END_COLLECTION (45 bytes)

// device 4
    0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 0)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x00,                    //  COLLECTION (Physical)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x07,                    //   REPORT_COUNT (7)
    0x85, 0x03,                    //   REPORT_ID (3)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
    0x46, 0xff, 0x00,              //   PHYSICAL_MAXIMUM (255)
    0x09, 0x30,                    //   USAGE (0x30)
    0x09, 0x31,                    //   USAGE (0x31)
    0x09, 0x32,                    //   USAGE (0x32)
    0x09, 0x33,                    //   USAGE (0x33)
    0x09, 0x34,                    //   USAGE (0x34)
    0x09, 0x35,                    //   USAGE (0x35)
    0x09, 0x36,                    //   USAGE (0x36)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0,                          //  END_COLLECTION 
    0xc0,                          // END_COLLECTION (45 bytes)

[b]// device 5 need 45 bytes
// device 6 need 45 bytes[/b]
};

static uchar idleRate;  /* repeat rate for keyboards, never used for mice */
static struct reportBuffer_t
{
   uint8_t  report_id;
   uint8_t  Vy;
   uint8_t  Ry;
   uint8_t  Rx;
   uint8_t   Z;
   uint8_t   Y;
   uint8_t   X;
   uint16_t Button;
} reportBuffer;
/* ------------------------------------------------------------------------- */
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
    usbRequest_t *rq = (void *)data;
    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
        DBG1(0x50, &rq->bRequest, 1);  /* debug output: print our request */
        if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
         if (rq->wValue.bytes[0] == 5)
         {reportBuffer.report_id = 0x05;} // set report ID so computer knows what data struct is sent
         usbMsgPtr = (void *)&reportBuffer;
            return sizeof(reportBuffer);
         }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
         usbMsgPtr = &idleRate;
         return 1;
            }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
            idleRate = rq->wValue.bytes[1];
        }
        }else{
        /* no vendor specific requests implemented */
    }
    return 0;  /* default for not implemented requests: return no data back to host */
}
/* ------------------------------------------------------------------------- */
int main(void) {
    wdt_enable(WDTO_1S);
    odDebugInit();
    DBG1(0x00, 0, 0);  /* debug output: main starts */
    ppmInit();
    usbInit();
    usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */
    uchar i = 0;
    while(--i){  /* fake USB disconnect for > 250 ms */
        wdt_reset();
        _delay_ms(1);
    }
    usbDeviceConnect();
    sei();
    DBG1(0x01, 0, 0);  /* debug output: main loop starts */
    uchar changed=0;
    ppmNewData=1;

    for(;;){ /* main event loop */
        DBG1(0x02, 0, 0);  /* debug output: main loop iterates */
        wdt_reset();
        usbPoll();
        if (ppmNewData) {
            ppmNewData=0;
            if (reportBuffer.Vy !=ppmGet(0)) {reportBuffer.Vy=ppmGet(0); changed=1;}
            if (reportBuffer.Ry !=ppmGet(1)) {reportBuffer.Ry=ppmGet(1); changed=1;}
            if (reportBuffer.Rx !=ppmGet(2)) {reportBuffer.Rx=ppmGet(2); changed=1;}
            if (reportBuffer.Z  !=ppmGet(3)) {reportBuffer.Z=ppmGet(3);  changed=1;}
            if (reportBuffer.Y  !=ppmGet(4)) {reportBuffer.Y=ppmGet(4);  changed=1;}
            if (reportBuffer.X  !=ppmGet(5)) {reportBuffer.X=ppmGet(5);  changed=1;}
            if (reportBuffer.Button !=ppmGet(6)) {reportBuffer.Button=ppmGet(6); changed=1;}
         if (changed) {
                if(usbInterruptIsReady()){
                    changed=0;
                    // called after every poll of the interrupt endpoint
                    DBG1(0x03, 0, 0);  // debug output: interrupt report prepared
                    usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
                }
            }
        }
    }
}


This code works fine with 4 devices detected as expected, but I need 2 more devices.
That mean need 255 more bytes.
How can I achieved that?
Any suggestion welcome.
Last edited by declan smith on Tue Nov 06, 2012 3:39 pm, edited 3 times in total.

declan smith
Rank 1
Rank 1
Posts: 32
Joined: Fri Nov 02, 2012 3:26 pm

Re: HID DESCRIPTOR more than 255 bytes

Post by declan smith » Sun Nov 04, 2012 6:31 am

Hello :?: :shock:
Anybody home :?: :?

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

Re: HID DESCRIPTOR more than 255 bytes

Post by ulao » Mon Nov 05, 2012 2:35 pm

First you're going to have to learn a little patience. "Anybody home", really?

Second please use the "code" button so its not painful to read this. Make things easy for people to help you.

Third you code is a mess, things like if (rq->wValue.bytes[0] == 5) is really bad practices. Try to use the actual define names... At a quick glance you dont even have the basic functions ( i.e usbFunctionDescriptor ). Here is a quick example on how things are made to be readable.

Code: Select all

unsigned   usbFunctionDescriptor(struct usbRequest *rq)
{
   if ((rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_STANDARD)
      return 0;

   if (rq->bRequest == USBRQ_GET_DESCRIPTOR)
   {
      // USB spec 9.4.3, high byte is descriptor type
      switch (rq->wValue.bytes[1])
      {
         case USBDESCR_DEVICE:
            usbMsgPtr = rt_usbDeviceDescriptor;      
            return rt_usbDeviceDescriptorSize;
         case USBDESCR_HID_REPORT:
            usbMsgPtr = rt_usbHidReportDescriptor;
            return rt_usbHidReportDescriptorSize;
         case USBDESCR_CONFIG:
            usbMsgPtr = my_usbDescriptorConfiguration;
            return sizeof(my_usbDescriptorConfiguration);
      }
   }

   return 0;
}


If you based your code from a USB-V example i'd try another. I really think your problem is that code, it sure confuses me. My descriptor size is calculated automatically.

Code: Select all

   rt_usbDeviceDescriptor = (void*)usbDescrDevice;
   rt_usbDeviceDescriptorSize = getUsbDescrDevice_size();

Things are so much easier when the code is written well. Maybe someone else can give it a stab here?

declan smith
Rank 1
Rank 1
Posts: 32
Joined: Fri Nov 02, 2012 3:26 pm

Re: HID DESCRIPTOR more than 255 bytes

Post by declan smith » Tue Nov 06, 2012 10:54 am

Sorry for my bad :oops:

I'm not going to confused you with my code, as I'm new to V-USB and still figuring out how it works for my needs.
That's why I took the working example to start, and try to understand it.
I was asked to post my code here, so I posted it even it messed up because it's far from final (I won't ask if it's final, right?).

I need to implement 6 devices in 1 project using V-USB library which needs descriptor for each devices.
So my question is simple, how I can get more than 255 bytes in descriptor?
Or more simple is how can I cast the descriptor into "int" or is it possible to cast it into "int" as the usbHidReportDescriptor[] was "char" in default, that means max value is 255.

If it's not possible, then I can't use V-USB Library for my project. That's all.

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

Re: HID DESCRIPTOR more than 255 bytes

Post by ulao » Tue Nov 06, 2012 2:12 pm

So my question is simple, how I can get more than 255 bytes in descriptor?
There is no trick, just do it. Like I said find a better example.

Code: Select all

Or more simple is how can I cast the descriptor into "int" or is it possible to cast it into "int" as the usbHidReportDescriptor[] was "char" in default, that means max value is 255.
Again find a better example its so easy with the right code.

If it's not possible, then I can't use V-USB Library for my project. That's all.
I already told you its possible. Get one of the ever so common mouse or joystick examples.

declan smith
Rank 1
Rank 1
Posts: 32
Joined: Fri Nov 02, 2012 3:26 pm

Re: HID DESCRIPTOR more than 255 bytes

Post by declan smith » Tue Nov 06, 2012 3:33 pm

There is no trick, just do it. Like I said find a better example.

Like what? Any link to it?

I already told you its possible.

Possible if less than 255 bytes (as I knew so far)

Get one of the ever so common mouse or joystick examples.

mouse or joystick examples only needs under 255 bytes, so that's not answer of my question


But thanks anyway, I appreciated that you wasted your time to be the only one who care to answer my question :wink:

NB:
I succesfully implemented many projects including "this project" using LUFA Library, so I interested to try V-USB as it can be use for Generic Micro with no USB Peripheral. But unfortunately meet dead end.
So I guess I had to go back to LUFA Library until I find the answer.

I editted the above code inside the "PROGMEM char usbHidReportDescriptor[]" maybe somebody need it, but no need look the code below it :mrgreen:
It detected as 4 USB HID devices in Windows "Device Manager":
device 1 as HID-compliant game controller (joystick with 6 axis and 5 buttons using report ID 5)
device 2 to 4 as HID-compliant devices (7 report "IN" only, using report ID 1 to 3)

The "rq->wValue.bytes[0] " is the device report ID, to process the right report from Host.
In the above code I only try device 1 (report ID 5).

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

Re: HID DESCRIPTOR more than 255 bytes

Post by ulao » Tue Nov 06, 2012 6:30 pm

Like what? Any link to it?
So I guess you never even downloaded the package? The examples come with the download.

Possible if less than 255 bytes (as I knew so far)
no, possible if > 255. See this descriptor at post #35
http://www.microchip.com/forums/tm.aspx ... 25&mpage=2
that is the one I use.

mouse or joystick examples only needs under 255 bytes, so that's not answer of my question
One more time... please pay attention this time. Use a good example so you can be helped more easily. Your code is a mess I can not even begin to help you. My suggestion is to start with a better example then try to use a descriptor > 255. If you have troubles at that point then ask for help. These examples are in a much easier to read state. In other words , help us help you.

I stil think the issue with your code is that you are not redefining the usbFunctionDescriptor function as a >255 byte type. See in my example above how I did it as unsigned.

declan smith
Rank 1
Rank 1
Posts: 32
Joined: Fri Nov 02, 2012 3:26 pm

Re: HID DESCRIPTOR more than 255 bytes

Post by declan smith » Thu Nov 08, 2012 10:04 am

I think straight answer is better than wasting bandwidth told me to look for the "good example" which I didn't know which is "good" exactly because I'm new to this V-USB, and told me to try to use >255 then (which make me asking here in the first post),

including "Microchip" forum which no explanation about "AVR Studio" which I ask for at the first time,

and then example "part" of the code to altering the "original library" (use that will conflict the original usbFunctionDescriptor library default and that means altering ! and that's not newbie's doing)
This library supposed to be "direct use library" because it was told:
On Release 2012-01-09, it said:
Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255 bytes

That means supposed to be no altering in the original library.

So unless you had working code for descriptor > 255 in AVR Studio, I think it has to stop here.
And thanks a lot for the answers :wink:

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

Re: HID DESCRIPTOR more than 255 bytes

Post by ulao » Thu Nov 08, 2012 3:14 pm

I think straight answer is better than wasting bandwidth told me to look for the "good example" which I didn't know which is "good" exactly because I'm new to this V-USB, and told me to try to use >255 then (which make me asking here in the first post),
OK first off if you're going to attempt to correct someone try to use a translator that actually works. This comment does not even resemble that witch conveys a meaning full sentence.

The Microchip forum was just to show you the size of the descriptor I use and no more. If you tried harder to understand that would have been clear.

Your not conflicting the usbFunctionDescriptor, you are redefining it. For any c coder this would be quite clear. Many examples show you how its redefining done. Newbie or not your expected to know that. We are not here to teach you C.

That means supposed to be no altering in the original library.
No buddy said you had to allure any libraries. Its called a redefinition.

I'll say this one more time: Find an example in the provided download that included the function definitions. Modify it attempting to use a large descriptor. If you get errors post the errors and the main.c and we can show you how to make it work.

Post Reply