Transfering 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
epsilon_da
Rank 1
Rank 1
Posts: 29
Joined: Mon Oct 13, 2008 7:11 pm

Transfering more than 255 bytes.

Post by epsilon_da » Wed Jan 21, 2009 10:27 pm

Hi i need to transfer a big buffer from an ATmega32 to the computer.
For that i have redefined "bytesRemaining" variable from uchar to usbWord_t and made some simple changes to usbFunctionWrite and Read.

I test this writing 1800 bytes from the computer to the uC memory and reading it again.
The writing works perfectly because i turn on a led when the last value in the buffer is equal to what i send.
The reading doesnt work at more than 255 bytes.
When i try to transfer 1800 bytes (1800=0x708) it only transfers 8 bytes.
i think that it is being masked or stored in uchar somewhere in the driver, but the usbFunctionWrite is not.

Here is my code:




Code: Select all

uchar   usbFunctionWrite(uchar *data, uchar len)
{
   if(bytesRemaining.word == 0)
      return 1;
       
    if(len > bytesRemaining.word)
        len = bytesRemaining.byte[0];

   switch(transferType){
      case USB_HID_CUSTOM_RQ_ADC_BUFFER:
         memcpy(nextTransferByte, data, len);
         nextTransferByte += len;
         break;
      case USB_HID_CUSTOM_RQ_EEPROM:
          eeprom_write_block(data, (uchar *)0 + currentAddress, len);
          currentAddress += len;
         break;
   }

    bytesRemaining.word -= len;
    return (bytesRemaining.word == 0); // return 1 if this was the last chunk
}




Code: Select all

uchar   usbFunctionRead(uchar *data, uchar len)
{
   //uchar i;

    if(len > bytesRemaining.word)
        len = bytesRemaining.byte[0];

   switch(transferType){
      case USB_HID_CUSTOM_RQ_ADC_BUFFER:
         memcpy( data , nextTransferByte , len );
         //for (i=0 ; i < len ; i++){
         //   data[i] = nextTransferByte[i];
         //}
         nextTransferByte += len;
         break;
      case USB_HID_CUSTOM_RQ_EEPROM:
          eeprom_read_block(data, (uchar *)0 + currentAddress, len);
          currentAddress += len;
         break;
   }

    bytesRemaining.word -= len;
    return len;
}




Code: Select all

typedef union word{
    unsigned    word;
    uchar       byte[2];
}word_t;

static word_t    bytesRemaining;
static uchar   transferType;
static uchar    *nextTransferByte;
static uchar adcBuffer[ADC_BUFFER_SIZE];





Code: Select all

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

   switch(rq->bmRequestType & USBRQ_TYPE_MASK){
      case USBRQ_TYPE_CLASS:
        // "Class" specific requests
         switch(rq->bRequest){
            case USBRQ_HID_GET_REPORT:
               // wValue: ReportType (highbyte), ReportID (lowbyte)
               // we only have one report type, so don't look at wValue
               switch(rq->wIndex.bytes[0]){
                  case USB_HID_CUSTOM_RQ_ADC_BUFFER:
                     transferType = USB_HID_CUSTOM_RQ_ADC_BUFFER;
                     nextTransferByte = adcBuffer;
                     bytesRemaining.word = rq->wLength.word;
                     return USB_NO_MSG;  // use usbFunctionRead() to send data to the host
               }
                  // fallback and use usbFunctionRead() to obtain data
            case USBRQ_HID_SET_REPORT:
               switch(rq->wIndex.bytes[0]){
                  case USB_HID_CUSTOM_RQ_ADC_BUFFER:
                     transferType = USB_HID_CUSTOM_RQ_ADC_BUFFER;
                     nextTransferByte = adcBuffer;
                     bytesRemaining.word = rq->wLength.word;
                     return USB_NO_MSG;  // use usbFunctionWrite() to receive data from host

                  case USB_HID_CUSTOM_RQ_START_CONVERTION:
                     switch ( rq->wLength.bytes[0] )
                        {
                        case 0:
                           ADCSRA = ( ADCSRA_CONFIG | ADC_PRESCALER_0 );
                           break;
                        default:
                        case 1:
                           ADCSRA = ( ADCSRA_CONFIG | ADC_PRESCALER_1 );
                           break;
                        case 2:
                           ADCSRA = ( ADCSRA_CONFIG | ADC_PRESCALER_2 );
                           break;
                        }
                     ADMUX = ADMUX_CONFIG; // Reset ADMUX
                     SFIOR &= 0x1F;
                     adcBuffer_intr_pointer = adcBuffer;
                     adcBuffer_index = 0;
                     SBI( ADCSRA , ADEN );
                     SBI( LEDPORT , LED1 );
                        return 0;
                  

                  case USB_HID_CUSTOM_RQ_EEPROM:
                     transferType = USB_HID_CUSTOM_RQ_EEPROM;
                        bytesRemaining.byte[0] = rq->wLength.bytes[0];
                     bytesRemaining.byte[1] = 0;
                        currentAddress = 0;
                     //currentAddress2 = 0;
                        return USB_NO_MSG;  // use usbFunctionWrite() to receive data from host

                  case USB_HID_CUSTOM_RQ_LED:
                     LEDPORT = ((rq->wValue.bytes[0]<<2)& LEDMASK);
                     return 0;
               }
         }
         break;
   }
   return 0; // default for not implemented requests: return no data back to host
}



Is it possible for someone knowing better the driver to check wether only the usbFunctionRead() part is being masked?

Or i am missing something in my function?

epsilon_da
Rank 1
Rank 1
Posts: 29
Joined: Mon Oct 13, 2008 7:11 pm

Post by epsilon_da » Wed Jan 21, 2009 10:40 pm

Could it be caused by the differences between the return values of usbFunctionRead and usbFunctionWrite.

The first returns the length of the buffer. And the second returns True or False.

I can only suspect that for usbFunctionRead there is an "uchar" variable somewhere acumulating the return values of it, and then send to the computer the size of the transmitted buffer.

Post Reply