Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: USB Hid, Transferring bigger reports than 64 bytes ?

  1. #1

    USB Hid, Transferring bigger reports than 64 bytes ?

    I did some googling and found out that it is possible to transfer bigger reports than 64 bytes with somehow splitting data to multiple parts. I need to do this in one of my projects. Can this be done with teensy 3.0 ?
    Could this be done for example by simply editing this found in usb_rawhid.c:
    Code:
    int usb_rawhid_recv(void *buffer, uint32_t timeout)
    {
    	usb_packet_t *rx_packet;
    	uint32_t begin = millis();
    
    	while (1) {
    		if (!usb_configuration) return -1;
    		rx_packet = usb_rx(RAWHID_RX_ENDPOINT);
    		if (rx_packet) break;
    		if (millis() - begin > timeout || !timeout) return 0;
    		yield();
    	}
    	memcpy(buffer, rx_packet->buf, RAWHID_RX_SIZE);
    	usb_free(rx_packet);
    	return RAWHID_RX_SIZE;
    }
    Or do i need to dig deeper to usb_dev.c ?

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,932
    First you'll need to edit the HID descriptor to tell your PC the report is longer. The on the PC side, you'll need to change the code to transmit or request whatever length the report is. That should cause the HID driver to use multiple packets.

    If you make the report between 65 to 127 bytes, then it should be fairly easy to sort out which incoming packets are the first (always 64 bytes) and second (1 to 63 bytes). This can probably be done without touching usb_dev.c... just have 2 receive pointers. If a received packet has length 64, store the pointer (and discard/free any previous 64 byte packet). If the received packet is less than 64, and your other receive packet pointer isn't NULL, then the contents of both packets is a successful receive.

    If you use 128 or more, probably some tricky state machine code will be needed to know which packet is which... and you might need to add code in the SOF handling within usb_dev.c to reset that state machine, if you want to recover from the unlikely condition where some but not all of the packets arrive during a USB frame.

    For sending to the PC, it should be relatively easy. However, I would highly recommend you call usb_malloc() to obtain all the buffers for every packet you'll transmit before you call usb_tx() on any of them. The HID driver on the PC side might not react too well if you send only a partial message, which could happen if you need to wait for another buffer.

    You might want to allocate more buffers, by editing usb_desc.h.

    If you're really paranoid, you might think about disabling interrupts or perhaps just the USB interrupt while you're calling usb_tx().... to handle the very unlikely case where some library with excessively CPU hogging interrupts (like SoftwareSerial on AVR, which thankfully doesn't exist on ARM yet) might delay your second usb_tx() until the next frame. Not a big deal for just your own project where you know what interrupts you're using, but something to consider if this were ever to be published as a general purpose function.

    There may be other issues, but these are the things I can think of right now.
    Last edited by PaulStoffregen; 03-09-2013 at 04:35 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •