usb_rndis: accept incoming USB transfers up to 0x4000 size
As required by the spec. Then split them into multiple ethernet frames as needed. Fixes #17738. Change-Id: I71ebff0fe1fc5c8a342d6d06b26eda8e87115e04 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5312 Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
a806e3678a
commit
3ad6b5ecba
|
@ -74,6 +74,7 @@ RNDISDevice::RNDISDevice(usb_device device)
|
|||
fNotifyReadSem(-1),
|
||||
fNotifyWriteSem(-1),
|
||||
fNotifyControlSem(-1),
|
||||
fReadHeader(NULL),
|
||||
fLinkStateChangeSem(-1),
|
||||
fMediaConnectState(MEDIA_STATE_UNKNOWN),
|
||||
fDownstreamSpeed(0)
|
||||
|
@ -243,16 +244,12 @@ RNDISDevice::Read(uint8 *buffer, size_t *numBytes)
|
|||
return B_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
iovec vec[2];
|
||||
uint32 header[11] = { 0 };
|
||||
|
||||
vec[0].iov_base = &header;
|
||||
vec[0].iov_len = sizeof(header);
|
||||
|
||||
vec[1].iov_base = buffer;
|
||||
vec[1].iov_len = *numBytes;
|
||||
|
||||
status_t result = gUSBModule->queue_bulk_v(fReadEndpoint, vec, 2,
|
||||
// The read funcion can return only one packet at a time, but we can receive multiple ones in
|
||||
// a single USB transfer. So we need to buffer them, and check if we have something in our
|
||||
// buffer for each Read() call before scheduling a new USB transfer. This would be more
|
||||
// efficient if the network stack had a way to read multiple frames at once.
|
||||
if (fReadHeader == NULL) {
|
||||
status_t result = gUSBModule->queue_bulk(fReadEndpoint, fReadBuffer, sizeof(fReadBuffer),
|
||||
_ReadCallback, this);
|
||||
if (result != B_OK) {
|
||||
*numBytes = 0;
|
||||
|
@ -275,40 +272,47 @@ RNDISDevice::Read(uint8 *buffer, size_t *numBytes)
|
|||
return result;
|
||||
}
|
||||
}
|
||||
fReadHeader = (uint32*)fReadBuffer;
|
||||
}
|
||||
|
||||
// TODO buffering is needed if we receive multiple packets, OOB data, etc since each Read
|
||||
// call can only return one packet? (which isn't great and could be improved on network stack
|
||||
// side to reduce syscalls if we had a readmmsg device call or something similar...)
|
||||
|
||||
if (header[0] != REMOTE_NDIS_PACKET_MSG) {
|
||||
TRACE_ALWAYS("Received unexpected packet type %08" B_PRIx32 " on data link\n", header[0]);
|
||||
if (fReadHeader[0] != REMOTE_NDIS_PACKET_MSG) {
|
||||
TRACE_ALWAYS("Received unexpected packet type %08" B_PRIx32 " on data link\n",
|
||||
fReadHeader[0]);
|
||||
*numBytes = 0;
|
||||
fReadHeader = NULL;
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
if (header[1] != fActualLengthRead) {
|
||||
TRACE_ALWAYS("Received frame length %08" B_PRIx32 " but USB transfer length is %08"
|
||||
B_PRIx32 "\n", header[1], fActualLengthRead);
|
||||
if (fReadHeader[1] + ((uint8*)fReadHeader - fReadBuffer) > fActualLengthRead) {
|
||||
TRACE_ALWAYS("Received frame at %ld length %08" B_PRIx32 " out of bounds of receive buffer"
|
||||
"%08" B_PRIx32 "\n", (uint8*) fReadHeader - fReadBuffer, fReadHeader[1],
|
||||
fActualLengthRead);
|
||||
}
|
||||
|
||||
if (header[4] != 0 || header[5] != 0 || header[6] != 0) {
|
||||
if (fReadHeader[4] != 0 || fReadHeader[5] != 0 || fReadHeader[6] != 0) {
|
||||
TRACE_ALWAYS("Received frame has out of bound data: off %08" B_PRIx32 " len %08" B_PRIx32
|
||||
" count %08" B_PRIx32 "\n", header[4], header[5], header[6]);
|
||||
" count %08" B_PRIx32 "\n", fReadHeader[4], fReadHeader[5], fReadHeader[6]);
|
||||
}
|
||||
|
||||
if (header[7] != 0 || header[8] != 0) {
|
||||
if (fReadHeader[7] != 0 || fReadHeader[8] != 0) {
|
||||
TRACE_ALWAYS("Received frame has per-packet info: off %08" B_PRIx32 " len %08" B_PRIx32
|
||||
"\n", header[7], header[8]);
|
||||
"\n", fReadHeader[7], fReadHeader[8]);
|
||||
}
|
||||
|
||||
if (header[9] != 0) {
|
||||
TRACE_ALWAYS("Received frame has non-0 reserved fied %08x\n", header[9]);
|
||||
if (fReadHeader[9] != 0) {
|
||||
TRACE_ALWAYS("Received frame has non-0 reserved fied %08x\n", fReadHeader[9]);
|
||||
}
|
||||
|
||||
*numBytes = header[3];
|
||||
*numBytes = fReadHeader[3];
|
||||
memcpy(buffer, fReadHeader + 11, fReadHeader[3]);
|
||||
|
||||
TRACE("Received data packet len %08x data [off %08x len %08x]\n",
|
||||
header[1], header[2], header[3]);
|
||||
fReadHeader[1], fReceivHeader[2], fReadHeader[3]);
|
||||
|
||||
// Advance to next packet
|
||||
fReadHeader += fReadHeader[1];
|
||||
if ((uint8*)fReadHeader - fReadBuffer >= fActualLengthRead)
|
||||
fReadHeader = NULL;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,8 @@ static void _NotifyCallback(void *cookie, int32 status,
|
|||
sem_id fNotifyControlSem;
|
||||
|
||||
uint8 fNotifyBuffer[8];
|
||||
uint8 fReadBuffer[0x4000];
|
||||
uint32* fReadHeader;
|
||||
|
||||
// connection data
|
||||
sem_id fLinkStateChangeSem;
|
||||
|
|
Loading…
Reference in New Issue