PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : VUSB Empfangs Problem usbFunctionSetup



coder44
25.04.2013, 14:28
Hallo leute,

ich habe ein Projekt gebaut mit einem ATmega168. LCD und USB und ein paar Taster u. RGB-LEDS sind vorhanden.
Nun will ich das Device per USB mit meinem PC verbinden. Soweit klappt auch alles wunderbar.
Ich habe beispielsweise in BASCOM alles zu laufen bekommen. Ich kann Daten vom Device lesen und auch Daten vom PC auf das Device senden.
Auf der PC Seite verwende ich LibUSBDotNet mit dem libusb Treiber. Mit der mitgelieferten Software "Test_Bulk" teste ich immer das senden und empfangen.

Nun wollte ich das Projekt umschreiben und in C zum laufen bekommen. Bisher klappt auch fast alles. Device wird vom PC erkannt, kann auch die Daten
mit dem PC vom Device lesen ABER ich kann keine Daten vom PC an das Device schicken. Dann erhalte ich immer die Fehlermeldung:

Win32Error:PipeTransferSubmit Ep 0x02
87:Falscher Parameter.

Hier mal mein Code...



#define F_CPU 12000000UL

#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/usbdrv.h"
#include "usbdrv/oddebug.h" /* This is also an example for using debug macros */

#include "lcd-routines.h"

#define farbe PORTB
#define rot 4
#define gruen 5
#define blau 3

#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))

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

PROGMEM const char usbHidReportDescriptor[] = { /* USB report descriptor */

0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x02, // COLLECTION (Application)

// Input Report
0x09, 0x01, // Usage ID - vendor defined
0x15, 0x00, // Logical Minimum (0)
0x25, 0xFF, // Logical Maximum (255)
0x75, 0x08, // Report Size (8 bits)
0x95, 0x01, // Report Count (8 fields)
0x81, 0x02, // Input (Data, Variable, Absolute)

// Output report
0x09, 0x01, // Usage ID - vendor defined
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8 bits)
0x95, 0x01, // Report Count (8 fields)
0x91, 0x02, // Output (Data, Variable, Absolute)

0xc0 // END_COLLECTION

};

/* The following variables store the status of the current data transfer */
static uchar currentAddress;
static uchar bytesRemaining;

static uchar inbuf[8], outbuf[8], outlen;
/* ------------------------------------------------------------------------- */

/* 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)
{
lcd_clear();
lcd_string("func read");
an(blau, 3);

if(len > bytesRemaining)
len = bytesRemaining;
eeprom_read_block(data, (uchar *)0 + currentAddress, len);
currentAddress += len;
bytesRemaining -= len;
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)
{
lcd_clear();
lcd_string("func write");
an(blau, 2);

if(bytesRemaining == 0)
return 1; /* end of transfer */
if(len > bytesRemaining)
len = bytesRemaining;
eeprom_write_block(data, (uchar *)0 + currentAddress, len);
lcd_clear();
lcd_string(data);
an(rot, 1);
currentAddress += len;
bytesRemaining -= len;
return bytesRemaining == 0; /* return 1 if this was the last chunk */
}

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

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
lcd_clear();
lcd_string("func setup");
an(rot, 1);


usbRequest_t *rq = (void *)data;

lcd_clear();
lcd_string(rq->bRequest);

}


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

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



void an(int col, int led)
{
SETBIT(PORTC, led);
SETBIT(PORTB, col);
_delay_ms(90);
CLEARBIT(PORTC, led);
CLEARBIT(PORTB, col);
}

int main(void)
{
DDRC = 0xff;
lcd_init();

SETBIT(DDRB, PB3);
CLEARBIT(DDRB, PB0);


lcd_string("System ready...");

uchar i;
wdt_enable(WDTO_1S);

odDebugInit();
DBG1(0x00, 0, 0);
usbInit();

an(blau, 1);

usbDeviceDisconnect();
i = 0;
while(--i){ /* fake USB disconnect for > 250 ms */
wdt_reset();
_delay_ms(1);
}
usbDeviceConnect();
sei();
DBG1(0x01, 0, 0);

for(;;){ /* main event loop */
DBG1(0x02, 0, 0);
wdt_reset();
usbPoll();

if(usbInterruptIsReady())
{
SETBIT(PORTC, 5);
SETBIT(PORTB, gruen);

inbuf[0] = 'a';
inbuf[1] = 'b';
inbuf[2] = 'c';
inbuf[3] = '\n';

usbSetInterrupt(inbuf, sizeof(inbuf)); //damit lese ich am PC "abc" aus

}
else
{
CLEARBIT(PORTC, 5);
CLEARBIT(PORTB, gruen);
}
}
return 0;
}


In meiner usbconfig.h ist folgends eingestellt:



#define USB_CFG_IOPORTNAME D

#define USB_CFG_DMINUS_BIT 3

#define USB_CFG_DPLUS_BIT 2

#define USB_CFG_CLOCK_KHZ (F_CPU/12000)

#define USB_CFG_CHECK_CRC 0



#define USB_CFG_HAVE_INTRIN_ENDPOINT 1

#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0

#define USB_CFG_EP3_NUMBER 3

#define USB_CFG_IMPLEMENT_HALT 0

#define USB_CFG_SUPPRESS_INTR_CODE 0

#define USB_CFG_INTR_POLL_INTERVAL 10

#define USB_CFG_IS_SELF_POWERED 1

#define USB_CFG_MAX_BUS_POWER 50

#define USB_CFG_IMPLEMENT_FN_WRITE 1

#define USB_CFG_IMPLEMENT_FN_READ 1

#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0

#define USB_CFG_HAVE_FLOWCONTROL 0

#define USB_CFG_DRIVER_FLASH_PAGE 0

#define USB_CFG_LONG_TRANSFERS 0

#define USB_COUNT_SOF 0

#define USB_CFG_CHECK_DATA_TOGGLING 0

#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0

#define USB_USE_FAST_CRC 0

/* -------------------------- Device Description --------------------------- */

#define USB_CFG_VENDOR_ID 0x8f, 0x19 /* = 0x16c0 = 5824 = voti.nl */

#define USB_CFG_DEVICE_ID 0xe9, 0x17 /* obdev's shared PID for HIDs */

#define USB_CFG_DEVICE_VERSION 0x00, 0x01

#define USB_CFG_VENDOR_NAME 'o', 'b', 'd', 'e', 'v', '.', 'a', 't'
#define USB_CFG_VENDOR_NAME_LEN 8

#define USB_CFG_DEVICE_NAME 'D', 'a', 't', 'a', 'S', 't', 'o', 'r', 'e'
#define USB_CFG_DEVICE_NAME_LEN 9

#define USB_CFG_DEVICE_CLASS 0
#define USB_CFG_DEVICE_SUBCLASS 0

#define USB_CFG_INTERFACE_CLASS 3
#define USB_CFG_INTERFACE_SUBCLASS 0
#define USB_CFG_INTERFACE_PROTOCOL 0

#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 33


#define USB_CFG_DESCR_PROPS_DEVICE 0
#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
#define USB_CFG_DESCR_PROPS_STRINGS 0
#define USB_CFG_DESCR_PROPS_STRING_0 0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
#define USB_CFG_DESCR_PROPS_HID 0
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0


LCD und die LEDs funktionieren alle wunderbar. Nur das USB will nicht. :(
Ich hoffe jemand kann mir helfen warum ich keine Daten vom PC an das Device schicken kann.
Hab auch irgendwie das Gefühl das die Funktionen usbFunctionSetup und usbFunctionWrite überhaupt nicht aufgerufen werden. Mein LCD bleibt immer bei "System Ready" stehen.

Danke schon im vorraus für die Mühe.

Gruß
coder44

coder44
07.05.2013, 20:53
Hat niemand eine Idee oder ein Tipp für mich?

Mittlerweile hab ich das Project komplett neu erstellt ohne LCD und nur VUSB eingebunden.
Fehler immer noch der selbe. Die USBConfig habe ich auch schon etliche male verändert, auch den Descriptor geändert und auch ganz weg gelassen.

Was mir nur aufgefallen ist, ist das bei dem Bascom Code zwei Endpoints angezeigt werden beim Gerät, eins zum lesen und eins zum schreiben.
Nur bei dem AVR Code habe ich nur den einen Endpoint 1 (0x81) womit ich lesen kann. Der andere zum schreiben auf das Device fehlt.

markusj
08.05.2013, 01:18
Deine usbFunctionSetup behandelt write-Requests nicht korrekt. Genauer: Sie behandelt gar nichts. Du hast dir die Doku (http://vusb.wikidot.com/driver-api) angesehen?

mfG
Markus

coder44
09.05.2013, 09:26
Hallo,

danke für den Link zur Doku, die kannte ich noch nicht.

Behandelt werden sollte noch nichts, weil ich dachte das er trotzdem empfangen kann. Nur zwar noch nichts mit den Daten macht.
Hab meine usbFunctionSetup mal umgeschrieben:


usbMsgLen_t usbFunctionSetup(uchar setupData[8])
{
usbRequest_t *rq = (void *)setupData; // cast to structured data for parsing
switch(rq->bRequest){
case 1:
lcd_clear();
lcd_string(rq->wValue.bytes[0]); // evaluate low byte only
return 0; // no data block sent or received
}
return 0; // ignore all unknown requests
}

Hatte die Hoffnung das er mir auf dem Display nun irgendetwas anzeigt, aber leider vergebens.

Wenn ich in der usbFunctionSetup ganz am Anfang sage das er "Hallo" auf dem Display ausgeben soll, erscheint nichtmal das "Hallo".
Das heißt doch, das die Funktion erst garnicht aufgerufen wird?!

Gruß
coder44

markusj
09.05.2013, 10:54
Du solltest dir die Doku ganz dringend nochmal genauer durchlesen. Du gibst als Rückgabewert immer 0 zurück, und 0 ignoriert den Request. Ich bin sowieso erstaunt, dass der Lesevorgang überhaupt funktioniert. Wenn du dir die Beispiele zu usbFunctionRead und usbFunctionWrite ansiehst, dürfte dir auffallen, dass nachdem der Header geparst wurde, USB_NO_MSG zurückgegeben wird, was dem Treiber signalisiert die write/read-Funktion aufzurufen.

mfG
Markus