I'm working on a device that connects to my PC using V-USB. The hardware mainly consists of an ATmega162 and an external EEPROM. Now I want to write some data from my computer, to the EEPROM. For this, I want to be able to send data from my PC to the device in blocks of at least 64 bytes.
Naturally, I have enabled and configured usbFunctionWrite(). This are my usbFunctionSetup() and usbFunctionWrite() functions:
Code: Select all
SB_PUBLIC uchar usbFunctionSetup(uint8_t data[8])
{
uint8_t len = 0;
packbuf->bmRequestType = data[0];
packbuf->bRequest = data[1];
packbuf->wValue = ((uint16_t)data[3] << 8) | data[2];
packbuf->wIndex = ((uint16_t)data[5] << 8) | data[4];
packbuf->wLength = ((uint16_t)data[7] << 8) | data[6];
if(packbuf->bmRequestType & 0x80)
{
// Messages with USB_ENDPOINT_IN
switch(packbuf->bRequest)
{
case MSG_READ_EEPROM:
break;
}
} else
{
// Messages with USB_ENDPOINT_OUT
switch(packbuf->bRequest)
{
case MSG_WRITE_EEPROM:
if(packbuf->wLength)
{
len = 0xff;
usb_buffer_init(packbuf->wLength);
}
snprintf(str, 40, "0x%x 0x%x 0x%x 0x%x", packbuf->bRequest, packbuf->wValue, packbuf->wIndex, packbuf->wLength);
menu_add_msg(str);
break;
}
}
return len;
}
uchar usbFunctionWrite(unsigned char *data, uint8_t len)
{
snprintf(str, 40, "%d %d", len, buf_bytes_remaining);
menu_add_msg(str);
if(buf_bytes_remaining == 0)
return 1;
PORTE = (PORTE & _BV(PE1)) ? PORTE & ~_BV(PE1) : PORTE | _BV(PE1);
if(packbuf->bRequest != MSG_WRITE_EEPROM)
return 1;
if(len > buf_bytes_remaining)
len = buf_bytes_remaining;
buf_bytes_remaining -= len;
for(uint16_t i = 0; i < len; i++)
{
rom_write_byte(rom_addr, data[i]);
rom_addr++;
}
snprintf(str, 40, "Last write to %d", (rom_addr - 1));
menu_add_msg(str);
return (buf_bytes_remaining == 0);
}
If value contained in bRequest equals MSG_WRITE_EEPROM, the payload data will be written to the EEPROM. The repeated calls to snprintf() and menu_add_msg() are used to print debug information to an LCD. packbuf is a global pointer to my own usb_message structure, which is similar to but not entirely the same as usbRequest_t. buf_bytes_remaining is an 16-bit unsigned integer. On the host (my PC), I use the following code to send data to my device:
Code: Select all
ret = usb_control_msg(devh, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, MSG_WRITE_EEPROM, 0, 0, (char*)buf, (uint16_t)16, usb_timeout);
std::cout << ret << " " << usb_strerror() << std::endl;
buf, in this case, is an array containing only the values 0x12.
Anyway, on to the problem. As long as I send 8 bytes or less in buf this works perfectly. usbFunctionSetup() receives my setup data and takes the right actions, usbFunctionWrite() is called once and the correct data is written to the EEPROM. However, as soon as I try to send more than 8 bytes (9 bytes, for example) usbFunctionWrite() still gets called only once and so only 8 bytes are written to the EEPROM. In addition, on the host I get the following output: "-71 error sending control message: Protocol error". My debug output shows that usbFunctionWrite() is initially called with the right values, namely buf_bytes_remaining = 9 and len = 8.
Obviously, this isn't the right behaviour. Unfortunately I have no idea how to track down this error, let alone solve it. Therefore I am turning to you guys in hope of a possible solutions. Thanks in advance