232 lines
5 KiB
C
232 lines
5 KiB
C
|
//
|
||
|
// usbendpoint.c
|
||
|
//
|
||
|
// USPi - An USB driver for Raspberry Pi written in C
|
||
|
// Copyright (C) 2014 R. Stange <rsta2@o2online.de>
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU General Public License as published by
|
||
|
// the Free Software Foundation, either version 3 of the License, or
|
||
|
// (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
//
|
||
|
#include <uspi/usbendpoint.h>
|
||
|
#include <uspi/assert.h>
|
||
|
|
||
|
void USBEndpoint (TUSBEndpoint *pThis, TUSBDevice *pDevice)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
pThis->m_pDevice = pDevice;
|
||
|
pThis->m_ucNumber = 0;
|
||
|
pThis->m_Type = EndpointTypeControl;
|
||
|
pThis->m_bDirectionIn = FALSE;
|
||
|
pThis->m_nMaxPacketSize = USB_DEFAULT_MAX_PACKET_SIZE;
|
||
|
pThis->m_nInterval = 1;
|
||
|
pThis->m_NextPID = USBPIDSetup;
|
||
|
|
||
|
assert (pThis->m_pDevice != 0);
|
||
|
}
|
||
|
|
||
|
void USBEndpoint2 (TUSBEndpoint *pThis, TUSBDevice *pDevice, const TUSBEndpointDescriptor *pDesc)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
pThis->m_pDevice = pDevice;
|
||
|
pThis->m_nInterval = 1;
|
||
|
|
||
|
assert (pThis->m_pDevice != 0);
|
||
|
|
||
|
assert (pDesc != 0);
|
||
|
assert (pDesc->bLength == sizeof *pDesc || pDesc->bLength == sizeof (TUSBAudioEndpointDescriptor));
|
||
|
assert (pDesc->bDescriptorType == DESCRIPTOR_ENDPOINT);
|
||
|
|
||
|
switch (pDesc->bmAttributes & 0x03)
|
||
|
{
|
||
|
case 2:
|
||
|
pThis->m_Type = EndpointTypeBulk;
|
||
|
pThis->m_NextPID = USBPIDData0;
|
||
|
break;
|
||
|
|
||
|
case 3:
|
||
|
pThis->m_Type = EndpointTypeInterrupt;
|
||
|
pThis->m_NextPID = USBPIDData0;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
assert (0); // endpoint configuration should be checked by function driver
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pThis->m_ucNumber = pDesc->bEndpointAddress & 0x0F;
|
||
|
pThis->m_bDirectionIn = pDesc->bEndpointAddress & 0x80 ? TRUE : FALSE;
|
||
|
pThis->m_nMaxPacketSize = pDesc->wMaxPacketSize;
|
||
|
|
||
|
if (pThis->m_Type == EndpointTypeInterrupt)
|
||
|
{
|
||
|
u8 ucInterval = pDesc->bInterval;
|
||
|
if (ucInterval < 1)
|
||
|
{
|
||
|
ucInterval = 1;
|
||
|
}
|
||
|
|
||
|
// see USB 2.0 spec chapter 9.6.6
|
||
|
if (USBDeviceGetSpeed (pThis->m_pDevice) != USBSpeedHigh)
|
||
|
{
|
||
|
pThis->m_nInterval = ucInterval;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (ucInterval > 16)
|
||
|
{
|
||
|
ucInterval = 16;
|
||
|
}
|
||
|
|
||
|
unsigned nValue = 1 << (ucInterval - 1);
|
||
|
|
||
|
pThis->m_nInterval = nValue / 8;
|
||
|
|
||
|
if (pThis->m_nInterval < 1)
|
||
|
{
|
||
|
pThis->m_nInterval = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void USBEndpointCopy (TUSBEndpoint *pThis, TUSBEndpoint *pEndpoint, TUSBDevice *pDevice)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
|
||
|
assert (pEndpoint != 0);
|
||
|
|
||
|
pThis->m_pDevice = pDevice;
|
||
|
assert (pThis->m_pDevice != 0);
|
||
|
|
||
|
pThis->m_ucNumber = pEndpoint->m_ucNumber;
|
||
|
pThis->m_Type = pEndpoint->m_Type;
|
||
|
pThis->m_bDirectionIn = pEndpoint->m_bDirectionIn;
|
||
|
pThis->m_nMaxPacketSize = pEndpoint->m_nMaxPacketSize;
|
||
|
pThis->m_nInterval = pEndpoint->m_nInterval;
|
||
|
pThis->m_NextPID = pEndpoint->m_NextPID;
|
||
|
}
|
||
|
|
||
|
void _USBEndpoint (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
pThis->m_pDevice = 0;
|
||
|
}
|
||
|
|
||
|
TUSBDevice *USBEndpointGetDevice (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
assert (pThis->m_pDevice != 0);
|
||
|
return pThis->m_pDevice;
|
||
|
}
|
||
|
|
||
|
u8 USBEndpointGetNumber (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
return pThis->m_ucNumber;
|
||
|
}
|
||
|
|
||
|
TEndpointType USBEndpointGetType (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
return pThis->m_Type;
|
||
|
}
|
||
|
|
||
|
boolean USBEndpointIsDirectionIn (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
return pThis->m_bDirectionIn;
|
||
|
}
|
||
|
|
||
|
void USBEndpointSetMaxPacketSize (TUSBEndpoint *pThis, u32 nMaxPacketSize)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
pThis->m_nMaxPacketSize = nMaxPacketSize;
|
||
|
}
|
||
|
|
||
|
u32 USBEndpointGetMaxPacketSize (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
return pThis->m_nMaxPacketSize;
|
||
|
}
|
||
|
|
||
|
unsigned USBEndpointGetInterval (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
assert (pThis->m_Type == EndpointTypeInterrupt);
|
||
|
|
||
|
return pThis->m_nInterval;
|
||
|
}
|
||
|
|
||
|
TUSBPID USBEndpointGetNextPID (TUSBEndpoint *pThis, boolean bStatusStage)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
if (bStatusStage)
|
||
|
{
|
||
|
assert (pThis->m_Type == EndpointTypeControl);
|
||
|
|
||
|
return USBPIDData1;
|
||
|
}
|
||
|
|
||
|
return pThis->m_NextPID;
|
||
|
}
|
||
|
|
||
|
void USBEndpointSkipPID (TUSBEndpoint *pThis, unsigned nPackets, boolean bStatusStage)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
assert ( pThis->m_Type == EndpointTypeControl
|
||
|
|| pThis->m_Type == EndpointTypeBulk
|
||
|
|| pThis->m_Type == EndpointTypeInterrupt);
|
||
|
|
||
|
if (!bStatusStage)
|
||
|
{
|
||
|
switch (pThis->m_NextPID)
|
||
|
{
|
||
|
case USBPIDSetup:
|
||
|
pThis->m_NextPID = USBPIDData1;
|
||
|
break;
|
||
|
|
||
|
case USBPIDData0:
|
||
|
if (nPackets & 1)
|
||
|
{
|
||
|
pThis->m_NextPID = USBPIDData1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case USBPIDData1:
|
||
|
if (nPackets & 1)
|
||
|
{
|
||
|
pThis->m_NextPID = USBPIDData0;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
assert (0);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert (pThis->m_Type == EndpointTypeControl);
|
||
|
|
||
|
pThis->m_NextPID = USBPIDSetup;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void USBEndpointResetPID (TUSBEndpoint *pThis)
|
||
|
{
|
||
|
assert (pThis != 0);
|
||
|
assert (pThis->m_Type == EndpointTypeBulk);
|
||
|
|
||
|
pThis->m_NextPID = USBPIDData0;
|
||
|
}
|