/* USBEthernet Teensy36 USB Host Ethernet library
* Copyright (c) 2019 Warren Watson.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
//ethernetDriver.cpp
#include <Arduino.h>
#include "usbEther.h"
#define print USBHost::print_
#define println USBHost::println_
// Big Endian/Little Endian
#define swap32(x) ((x >> 24) & 0xff) | \
((x << 8) & 0xff0000) | \
((x >> 8) & 0xff00) | \
((x << 24) & 0xff000000)
void ethernetController::init()
{
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
contribute_Transfers(mytransfers, sizeof(mytransfers)/sizeof(Transfer_t));
contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t));
driver_ready_for_device(this);
}
bool ethernetController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
{
println("ethernetController claim this=", (uint32_t)this, HEX);
// only claim at interface level
if (type != 1) return false;
if (len < 9+7+7+7) return false; // Interface descriptor + 3 endpoint decriptors
print_hexbytes(descriptors, len);
uint32_t numendpoint = descriptors[4];
if (numendpoint < 1) return false;
if (descriptors[5] != 255) return false; // bInterfaceClass, Vendor Specific
if (descriptors[6] != 255) return false; // bInterfaceSubClass, Vendor Specific
if (descriptors[7] != 0) return false; // bInterfaceProtocol, 0 = No class specific protocol required
uint8_t desc_index = 9;
uint8_t in_index = 0xff, out_index = 0xff, notify_index = 0xff;
println("numendpoint=", numendpoint, HEX);
while (numendpoint--) {
if ((descriptors[desc_index] != 7) || (descriptors[desc_index+1] != 5)) return false; // not an end point
if (descriptors[desc_index+3] == 2) { // Bulk end point
if (descriptors[desc_index+2] & 0x80)
in_index = desc_index;
else
out_index = desc_index;
} else {
if (descriptors[desc_index+3] == 3) { // Interrupt end point
if (descriptors[desc_index+2] & 0x80)
notify_index = desc_index;
}
}
desc_index += 7; // point to next one...
}
if ((in_index == 0xff) || (out_index == 0xff) || (notify_index == 0xff)) return false; // did not find end point
endpointIn = descriptors[in_index+2]; // bulk-in descriptor 1 81h
endpointOut = descriptors[out_index+2]; // bulk-out descriptor 2 02h
endpointNotifyIn = descriptors[notify_index+2]; // Notification descriptor 3 81h
println("endpointIn=", endpointIn, HEX);
println("endpointOut=", endpointOut, HEX);
println("endpointNotificationIn=", endpointNotifyIn, HEX);
uint32_t sizeIn = descriptors[in_index+4] | (descriptors[in_index+5] << 8);
println("packet size in (ethernetController) = ", sizeIn);
uint32_t sizeOut = descriptors[out_index+4] | (descriptors[out_index+5] << 8);
println("packet size out (ethernetController) = ", sizeOut);
uint32_t notifySizeIn = descriptors[notify_index+4] | (descriptors[notify_index+5] << 8);
println("packet notify in (ethernetController) = ", notifySizeIn);
packetSizeIn = sizeIn;
packetSizeOut = sizeOut;
packetSizeNotifyIn = notifySizeIn;
uint32_t intervalIn = descriptors[in_index+6];
uint32_t intervalOut = descriptors[out_index+6];
uint32_t notifyIntervalIn = descriptors[notify_index+6];
println("polling intervalIn = ", intervalIn);
println("polling intervalOut = ", intervalOut);
println("polling notifyIntervalIn = ", notifyIntervalIn);
datapipeIn = new_Pipe(dev, 2, endpointIn, 1, packetSizeIn, intervalIn);
datapipeOut = new_Pipe(dev, 2, endpointOut, 0, packetSizeOut, intervalOut);
notifypipeIn = new_Pipe(dev, 3, endpointNotifyIn, 1, packetSizeNotifyIn, notifyIntervalIn);
datapipeIn->callback_function = callbackIn;
datapipeOut->callback_function = callbackOut;
notifypipeIn->callback_function = callbackNotifyIn;
// mk_setup(setup, 0x21, 10, 0, 0, 0); // 10=SET_IDLE
// queue_Control_Transfer(dev, &setup, NULL, this);
ethernetOutCompleted = false;
ethernetInCompleted = false;
ethernetControlCompleted = false;
deviceAvailable = true;
return true;
}
void ethernetController::control(const Transfer_t *transfer)
{
println("control CallbackIn (ethernetController)");
print_hexbytes(report, 8);
ethernetControlCompleted = true;
}
void ethernetController::callbackIn(const Transfer_t *transfer)
{
println("ethernetController CallbackIn (static)");
if (transfer->driver) {
print("transfer->qtd.token = ");
println(transfer->qtd.token & 255);
((ethernetController *)(transfer->driver))->new_dataIn(transfer);
}
}
void ethernetController::callbackOut(const Transfer_t *transfer)
{
println("ethernetController CallbackOut (static)");
if (transfer->driver) {
print("transfer->qtd.token = ");
println(transfer->qtd.token & 255);
((ethernetController *)(transfer->driver))->new_dataOut(transfer);
}
}
void ethernetController::callbackNotifyIn(const Transfer_t *transfer)
{
println("ethernetController CallbackNotifyIn (static)");
if (transfer->driver) {
print("transfer->qtd.token = ");
println(transfer->qtd.token & 255);
((ethernetController *)(transfer->driver))->new_dataNotifyIn(transfer);
}
}
void ethernetController::disconnect()
{
deviceAvailable = false;
deviceInitialized = false;
println("Device Disconnected...");
}
void ethernetController::new_dataOut(const Transfer_t *transfer)
{
uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
println("ethernetController dataOut (static)", len, DEC);
print_hexbytes((uint8_t*)transfer->buffer, (len < 32)? len : 32 );
ethernetOutCompleted = true; // Last out transaction is completed.
}
void ethernetController::new_dataIn(const Transfer_t *transfer)
{
uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
println("ethernetController dataIn (static): ", len, DEC);
print_hexbytes((uint8_t*)transfer->buffer, (len < 32)? len : 32 );
ethernetInCompleted = true; // Last in transaction is completed.
}
void ethernetController::new_dataNotifyIn(const Transfer_t *transfer)
{
uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
println("ethernetController dataNotifyIn (static): ", len, DEC);
print_hexbytes((uint8_t*)transfer->buffer, (len < 32)? len : 32 );
}