v-usb + hidapi

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
SpulN
Posts: 2
Joined: Fri Dec 28, 2012 8:09 pm

v-usb + hidapi

Post by SpulN » Fri Dec 28, 2012 8:18 pm

Hi, all! Sorry for my english!
I have a problem. I can't read input report from hid device. I take hid-test example project as a base. This is a code for PC (hidapi library, hidtest.cpp)

Code: Select all

/*******************************************************
 Windows HID simplification

 Alan Ott
 Signal 11 Software

 8/22/2009

 Copyright 2009, All Rights Reserved.
 
 This contents of this file may be used by anyone
 for any reason without any conditions and may be
 used as a starting point for your own applications
 which use HIDAPI.
********************************************************/

#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include "hidapi.h"
#include <windows.h>

int main(int argc, char* argv[])
{
   int res;
   unsigned char buf[9];
   hid_device *handle;
   int i;

#ifdef WIN32
   UNREFERENCED_PARAMETER(argc);
   UNREFERENCED_PARAMETER(argv);
#endif

   handle = hid_open(0x16c0, 0x05df, NULL);
   if (!handle) {
      printf("unable to open device\n");
       return 1;
   }

   hid_set_nonblocking(handle, 1);
   
   res = 0;
   while (res == 0) {
      res = hid_read(handle, buf, sizeof(buf));
      if (res == 0)
         printf("waiting...\n");
      if (res < 0)
         printf("Unable to read()\n");
      Sleep(1000);
   }

   printf("Data read:\n   ");
   // Print out the returned buffer.
   for (i = 0; i < res; i++)
      printf("%02hhx ", buf[i]);
   printf("\n");

   hid_close(handle);

   /* Free static HIDAPI objects. */
   hid_exit();

   system("pause");
   return 0;
}

this is code for avr (mega8)

Code: Select all

/* Name: main.c
 * Project: hid-data, example how to use HID for data transfer
 * Author: Christian Starkjohann
 * Creation Date: 2008-04-11
 * Tabsize: 4
 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
 */

/*
This example should run on most AVRs with only little changes. No special
hardware resources except INT0 are used. You may have to change usbconfig.h for
different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
at least be connected to INT0 as well.
*/

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

#include <avr/pgmspace.h>   /* required by usbdrv.h */
#include "usbdrv.h"
#include "oddebug.h"        /* This is also an example for using debug macros */

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

PROGMEM const char usbHidReportDescriptor[32] = {    /* USB report descriptor */
        0x06, 0x9c, 0xff,     /* Usage Page (Vendor Defined)                     */
        0x09, 0x01,           /* Usage (Vendor Defined)                          */
        0xa1, 0x01,           /* Collection (Vendor Defined)                     */
        0x09, 0x02,           /*   Usage (Vendor Defined)                        */
        0x75, 0x08,           /*   Report Size (8)                               */
        0x95, 0x08,           /*   Report Count (8)       */
        0x15, 0x80,           /*   Logical Minimum (-128)                        */
        0x25, 0x7F,           /*   Logical Maximum (127)                         */
        0x81, 0x02,           /*   Input (Data, Variable, Absolute)              */
        0x09, 0x03,           /*   Usage (Vendor Defined)                        */
        0x75, 0x08,           /*   Report Size (8)                               */
        0x95, 0x08,           /*   Report Count (8)       */
        0x15, 0x00,           /*   Logical Minimum (0)                           */
        0x25, 0xff,           /*   Logical Maximum (255)                         */
        0x91, 0x02,           /*   Output (Data, Variable, Absolute)             */
        0xc0                  /* End Collection                                  */

};
/* Since we define only one feature report, we don't use report-IDs (which
 * would be the first byte of the report). The entire report consists of 128
 * opaque data bytes.
 */


/* ------------------------------------------------------------------------- */

/* usbFunctionRead() is called when the host requests a chunk of data from
 * the device. For more information see the documentation in usbdrv/usbdrv.h.
 */
uchar   usbFunctionRead(uchar *data, uchar len)
{
    data[1] = 0x01;
    data[2] = 0x02;
    data[3] = 0x03;
    data[4] = 0x04;
    return 8;
}

/* usbFunctionWrite() is called when the host sends a chunk of data to the
 * device. For more information see the documentation in usbdrv/usbdrv.h.
 */
uchar   usbFunctionWrite(uchar *data, uchar len)
{
    return 1;               /* end of transfer */
}

/* ------------------------------------------------------------------------- */

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;

    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* HID class request */
        if(rq->bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */
            /* since we have only one report type, we can ignore the report-ID */
            return USB_NO_MSG;  /* use usbFunctionRead() to obtain data */
        }else if(rq->bRequest == USBRQ_HID_SET_REPORT){
            /* since we have only one report type, we can ignore the report-ID */
            return USB_NO_MSG;  /* use usbFunctionWrite() to receive data from host */
        }
    }else{
        /* ignore vendor type requests, we don't use any */
    }
    return 0;
}

/* ------------------------------------------------------------------------- */

int main(void)
{
uchar   i;

    wdt_enable(WDTO_1S);
    /* Even if you don't use the watchdog, turn it off here. On newer devices,
     * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
     */
    /* RESET status: all port bits are inputs without pull-up.
     * That's the way we need D+ and D-. Therefore we don't need any
     * additional hardware initialization.
     */
    odDebugInit();
    DBG1(0x00, 0, 0);       /* debug output: main starts */
    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    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 */
    for(;;){                /* main event loop */
        DBG1(0x02, 0, 0);   /* debug output: main loop iterates */
        wdt_reset();
        usbPoll();
    }
    return 0;
}

/* ------------------------------------------------------------------------- */

but when I run program from PC, the program write in console: waiting..., no data read from devace.

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

Re: v-usb + hidapi

Post by declan smith » Sat Dec 29, 2012 5:17 am

There's nothing wrong with your code as I tested it.

Here's your code with little mod for my test ( you set the report out but you didn't use it ? ) :

Code: Select all

/* Name: main.c
 * Project: hid-data, example how to use HID for data transfer
 * Author: Christian Starkjohann
 * Creation Date: 2008-04-11
 * Tabsize: 4
 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
 */

/*
This example should run on most AVRs with only little changes. No special
hardware resources except INT0 are used. You may have to change usbconfig.h for
different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
at least be connected to INT0 as well.
*/

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

#include <avr/pgmspace.h>   /* required by usbdrv.h */
#include "usbdrv.h"
#include "oddebug.h"        /* This is also an example for using debug macros */

static uint8_t buffer[16];

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

PROGMEM const char usbHidReportDescriptor[32] = {    /* USB report descriptor */
        0x06, 0x9c, 0xff,     /* Usage Page (Vendor Defined)                     */
        0x09, 0x01,           /* Usage (Vendor Defined)                          */
        0xa1, 0x01,           /* Collection (Vendor Defined)                     */
        0x09, 0x02,           /*   Usage (Vendor Defined)                        */
        0x75, 0x08,           /*   Report Size (8)                               */
        0x95, 0x08,           /*   Report Count (8)       */
        0x15, 0x80,           /*   Logical Minimum (-128)                        */
        0x25, 0x7F,           /*   Logical Maximum (127)                         */
        0x81, 0x02,           /*   Input (Data, Variable, Absolute)              */
        0x09, 0x03,           /*   Usage (Vendor Defined)                        */
        0x75, 0x08,           /*   Report Size (8)                               */
        0x95, 0x08,           /*   Report Count (8)       */
        0x15, 0x00,           /*   Logical Minimum (0)                           */
        0x25, 0xff,           /*   Logical Maximum (255)                         */
        0x91, 0x02,           /*   Output (Data, Variable, Absolute)             */
        0xc0                  /* End Collection                                  */

};
/* Since we define only one feature report, we don't use report-IDs (which
 * would be the first byte of the report). The entire report consists of 128
 * opaque data bytes.
 */


/* ------------------------------------------------------------------------- */

/* usbFunctionRead() is called when the host requests a chunk of data from
 * the device. For more information see the documentation in usbdrv/usbdrv.h.
 */
uchar   usbFunctionRead(uchar *data, uchar len)
{
    uint8_t i;

   for (i=0;i<len;++i) data[i]=buffer[i];

   return len;
}

/* usbFunctionWrite() is called when the host sends a chunk of data to the
 * device. For more information see the documentation in usbdrv/usbdrv.h.
 */
uchar   usbFunctionWrite(uchar *data, uchar len)
{
    uint8_t i;

   for (i=0;i<len;++i) buffer[i]=data[i];
      
   return 1;               /* end of transfer */
}

/* ------------------------------------------------------------------------- */

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;

    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* HID class request */
        if(rq->bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */
            /* since we have only one report type, we can ignore the report-ID */
            return USB_NO_MSG;  /* use usbFunctionRead() to obtain data */
        }else if(rq->bRequest == USBRQ_HID_SET_REPORT){
            /* since we have only one report type, we can ignore the report-ID */
            return USB_NO_MSG;  /* use usbFunctionWrite() to receive data from host */
        }
    }else{
        /* ignore vendor type requests, we don't use any */
    }
    return 0;
}

/* ------------------------------------------------------------------------- */

int main(void)
{
uchar   i;

    wdt_enable(WDTO_1S);
    /* Even if you don't use the watchdog, turn it off here. On newer devices,
     * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
     */
    /* RESET status: all port bits are inputs without pull-up.
     * That's the way we need D+ and D-. Therefore we don't need any
     * additional hardware initialization.
     */
    odDebugInit();
    DBG1(0x00, 0, 0);       /* debug output: main starts */
    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    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 */
    for(;;){                /* main event loop */
        DBG1(0x02, 0, 0);   /* debug output: main loop iterates */
        wdt_reset();
        usbPoll();
    }
    return 0;
}

/* ------------------------------------------------------------------------- */


And here's my test result:
The first read was when the device attach for the first time, so it read all zero,
the second read was from the data bytes inputted randomly,
the last read was data bytes send from static buffer.
So I tought your code was alright ( not sure about your usbconfig ). Maybe the host side ?

Image

SpulN
Posts: 2
Joined: Fri Dec 28, 2012 8:09 pm

Re: v-usb + hidapi

Post by SpulN » Sat Dec 29, 2012 7:32 am

May be same thing wrong with HIDAPI hid_read() function? Why it did't receve data from device?

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

Re: v-usb + hidapi

Post by declan smith » Sat Dec 29, 2012 4:13 pm

Try to change:
unsigned char buf[9];

to:
unsigned char buf[8];

Editted:

because you " return 8 " in the device side while ' res = hid_read(handle, buf, sizeof(buf))' will return " sizeof(buf) " which is also 8, so the " res " will return negatif value as I knew.

Add your code to show the return value with the printf, so you can be sure what value was returned.

Hope it's right.

Post Reply