All this is actually from @rshartog but I had to do a bit of cleanup to the commit history.
Summary: To allow the master to request more than one byte from the slave in a requestFrom() call, the USI_REQUEST_CALLBACK() call on line 613 of the current usiTwiSlave.c code should be moved to line 583.
Explanation: For the current code, the ISR routine correctly sends the execution through the “USI_SLAVE_SEND_DATA” case-branch for each byte sent from the slave to the master. With the USI_REQUEST_CALLBACK() on line 613, the callback routine is called for each byte that the master requests. Assuming the callback should queue the send data for the entire request, then the current code generates N bytes of data for each byte sent (N^2 bytes total) and only removes N bytes from the transmit buffer. This works when N==1, but if N>1 this quickly results in a transmit buffer overflow and execution hangs on line 406. (This behavior was observed by having the slave respond with the values of txHead and txTail until the slave hung on line 406.)
If you move USI_REQUEST_CALLBACK() to line 583, then the callback is called only once per master request (when the request is initially received).
One other related note: As written, the useable size of the rxBuf is actually TWI_RX_BUFFER_SIZE - 1. Same for txBuf/TWI_TX_BUFFER_SIZE. This is because the Head pointer cannot fully wrap back to the value of the Tail pointer. (Doing so would appear to be an empty buffer.) This detail might be important to someone who thinks they can use the entire buffer.
Sketches to stress-test the functionality have been provided.
All this is actually from @rshartog but I had to do a bit of cleanup to the commit history.
Summary: To allow the master to request more than one byte from the slave in a requestFrom() call, the USI_REQUEST_CALLBACK() call on line 613 of the current usiTwiSlave.c code should be moved to line 583.
Explanation: For the current code, the ISR routine correctly sends the execution through the “USI_SLAVE_SEND_DATA” case-branch for each byte sent from the slave to the master. With the USI_REQUEST_CALLBACK() on line 613, the callback routine is called for each byte that the master requests. Assuming the callback should queue the send data for the entire request, then the current code generates N bytes of data for each byte sent (N^2 bytes total) and only removes N bytes from the transmit buffer. This works when N==1, but if N>1 this quickly results in a transmit buffer overflow and execution hangs on line 406. (This behavior was observed by having the slave respond with the values of txHead and txTail until the slave hung on line 406.)
If you move USI_REQUEST_CALLBACK() to line 583, then the callback is called only once per master request (when the request is initially received).
One other related note: As written, the useable size of the rxBuf is actually TWI_RX_BUFFER_SIZE - 1. Same for txBuf/TWI_TX_BUFFER_SIZE. This is because the Head pointer cannot fully wrap back to the value of the Tail pointer. (Doing so would appear to be an empty buffer.) This detail might be important to someone who thinks they can use the entire buffer.
Sketches to stress-test the functionality have been provided.