Add svn:eol-style property to source files, so that the line endings are correctly converted to the target system's native end of line style.
This commit is contained in:
parent
e331b531c6
commit
071e02c6b6
839 changed files with 274562 additions and 274562 deletions
|
@ -1,446 +1,446 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_CDC_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_CDC_DRIVER
|
||||
#include "CDC.h"
|
||||
|
||||
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return CDC_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_NoCDCInterfaceFound;
|
||||
}
|
||||
|
||||
CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;
|
||||
|
||||
while (FoundEndpoints != (CDC_FOUND_NOTIFICATION_IN | CDC_FOUND_DATAPIPE_IN | CDC_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
if (FoundEndpoints & CDC_FOUND_NOTIFICATION_IN)
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_NoCDCInterfaceFound;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FoundEndpoints = 0;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_NoCDCInterfaceFound;
|
||||
}
|
||||
}
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
CDCInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
|
||||
|
||||
FoundEndpoints |= CDC_FOUND_NOTIFICATION_IN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
|
||||
CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= CDC_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
|
||||
CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR);
|
||||
CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR);
|
||||
CDCInterfaceInfo->State.IsActive = true;
|
||||
return CDC_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == CDC_CONTROL_CLASS) &&
|
||||
(CurrentInterface->SubClass == CDC_CONTROL_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == CDC_CONTROL_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == CDC_DATA_CLASS) &&
|
||||
(CurrentInterface->SubClass == CDC_DATA_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == CDC_DATA_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
|
||||
!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsINReceived())
|
||||
{
|
||||
USB_Request_Header_t Notification;
|
||||
Pipe_Read_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if ((Notification.bRequest == NOTIF_SerialState) &&
|
||||
(Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)))
|
||||
{
|
||||
Pipe_Read_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
|
||||
sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
|
||||
NO_STREAM_CALLBACK);
|
||||
|
||||
}
|
||||
|
||||
Pipe_ClearIN();
|
||||
|
||||
EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetLineEncoding,
|
||||
.wValue = 0,
|
||||
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = sizeof(CDCInterfaceInfo->State.LineEncoding),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(&CDCInterfaceInfo->State.LineEncoding);
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetControlLineState,
|
||||
.wValue = CDCInterfaceInfo->State.ControlLineStates.HostToDevice,
|
||||
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(NULL);
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Duration)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SendBreak,
|
||||
.wValue = Duration,
|
||||
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(NULL);
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, char* Data, const uint16_t Length)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
|
||||
Pipe_Unfreeze();
|
||||
ErrorCode = Pipe_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Data)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
{
|
||||
Pipe_ClearOUT();
|
||||
|
||||
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Pipe_Write_Byte(Data);
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return 0;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsINReceived())
|
||||
{
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
{
|
||||
Pipe_ClearIN();
|
||||
Pipe_Freeze();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_Freeze();
|
||||
return Pipe_BytesInPipe();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_Freeze();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
uint8_t ReceivedByte = 0;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return 0;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ReceivedByte = Pipe_Read_Byte();
|
||||
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
Pipe_ClearIN();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return ReceivedByte;
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
return PIPE_READYWAIT_NoError;
|
||||
|
||||
bool BankFull = !(Pipe_IsReadWriteAllowed());
|
||||
|
||||
Pipe_ClearOUT();
|
||||
|
||||
if (BankFull)
|
||||
{
|
||||
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearOUT();
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar_Blocking, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
static int CDC_Host_putchar(char c, FILE* Stream)
|
||||
{
|
||||
return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
|
||||
}
|
||||
|
||||
static int CDC_Host_getchar(FILE* Stream)
|
||||
{
|
||||
if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))))
|
||||
return _FDEV_EOF;
|
||||
|
||||
return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
static int CDC_Host_getchar_Blocking(FILE* Stream)
|
||||
{
|
||||
while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))))
|
||||
{
|
||||
if (USB_HostState == HOST_STATE_Unattached)
|
||||
return _FDEV_EOF;
|
||||
|
||||
CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
|
||||
USB_USBTask();
|
||||
}
|
||||
|
||||
return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
void CDC_Host_Event_Stub(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_CDC_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_CDC_DRIVER
|
||||
#include "CDC.h"
|
||||
|
||||
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return CDC_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_NoCDCInterfaceFound;
|
||||
}
|
||||
|
||||
CDCInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;
|
||||
|
||||
while (FoundEndpoints != (CDC_FOUND_NOTIFICATION_IN | CDC_FOUND_DATAPIPE_IN | CDC_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
if (FoundEndpoints & CDC_FOUND_NOTIFICATION_IN)
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_NoCDCInterfaceFound;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FoundEndpoints = 0;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_NoCDCInterfaceFound;
|
||||
}
|
||||
}
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return CDC_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
CDCInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
CDCInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
|
||||
|
||||
FoundEndpoints |= CDC_FOUND_NOTIFICATION_IN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
CDCInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
|
||||
CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= CDC_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
CDCInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
|
||||
CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR);
|
||||
CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR);
|
||||
CDCInterfaceInfo->State.IsActive = true;
|
||||
return CDC_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == CDC_CONTROL_CLASS) &&
|
||||
(CurrentInterface->SubClass == CDC_CONTROL_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == CDC_CONTROL_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == CDC_DATA_CLASS) &&
|
||||
(CurrentInterface->SubClass == CDC_DATA_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == CDC_DATA_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
|
||||
!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsINReceived())
|
||||
{
|
||||
USB_Request_Header_t Notification;
|
||||
Pipe_Read_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if ((Notification.bRequest == NOTIF_SerialState) &&
|
||||
(Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)))
|
||||
{
|
||||
Pipe_Read_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
|
||||
sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
|
||||
NO_STREAM_CALLBACK);
|
||||
|
||||
}
|
||||
|
||||
Pipe_ClearIN();
|
||||
|
||||
EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetLineEncoding,
|
||||
.wValue = 0,
|
||||
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = sizeof(CDCInterfaceInfo->State.LineEncoding),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(&CDCInterfaceInfo->State.LineEncoding);
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetControlLineState,
|
||||
.wValue = CDCInterfaceInfo->State.ControlLineStates.HostToDevice,
|
||||
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(NULL);
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Duration)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SendBreak,
|
||||
.wValue = Duration,
|
||||
.wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(NULL);
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, char* Data, const uint16_t Length)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
|
||||
Pipe_Unfreeze();
|
||||
ErrorCode = Pipe_Write_Stream_LE(Data, Length, NO_STREAM_CALLBACK);
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Data)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
{
|
||||
Pipe_ClearOUT();
|
||||
|
||||
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Pipe_Write_Byte(Data);
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return 0;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsINReceived())
|
||||
{
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
{
|
||||
Pipe_ClearIN();
|
||||
Pipe_Freeze();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_Freeze();
|
||||
return Pipe_BytesInPipe();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_Freeze();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
uint8_t ReceivedByte = 0;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return 0;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ReceivedByte = Pipe_Read_Byte();
|
||||
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
Pipe_ClearIN();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return ReceivedByte;
|
||||
}
|
||||
|
||||
uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
return PIPE_READYWAIT_NoError;
|
||||
|
||||
bool BankFull = !(Pipe_IsReadWriteAllowed());
|
||||
|
||||
Pipe_ClearOUT();
|
||||
|
||||
if (BankFull)
|
||||
{
|
||||
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearOUT();
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream)
|
||||
{
|
||||
*Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar_Blocking, _FDEV_SETUP_RW);
|
||||
fdev_set_udata(Stream, CDCInterfaceInfo);
|
||||
}
|
||||
|
||||
static int CDC_Host_putchar(char c, FILE* Stream)
|
||||
{
|
||||
return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
|
||||
}
|
||||
|
||||
static int CDC_Host_getchar(FILE* Stream)
|
||||
{
|
||||
if (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))))
|
||||
return _FDEV_EOF;
|
||||
|
||||
return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
static int CDC_Host_getchar_Blocking(FILE* Stream)
|
||||
{
|
||||
while (!(CDC_Host_BytesReceived((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))))
|
||||
{
|
||||
if (USB_HostState == HOST_STATE_Unattached)
|
||||
return _FDEV_EOF;
|
||||
|
||||
CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
|
||||
USB_USBTask();
|
||||
}
|
||||
|
||||
return CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
|
||||
}
|
||||
|
||||
void CDC_Host_Event_Stub(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,336 +1,336 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/CDC.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassCDC
|
||||
* @defgroup Group_USBClassCDCHost CDC Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/CDC.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the CDC USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __CDC_CLASS_HOST_H__
|
||||
#define __CDC_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/CDC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_CDC_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/CDC.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief CDC Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the CDC class driver functions as the CDCInterfaceInfo parameter. This
|
||||
* stores each CDC interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the CDC interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the CDC interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the CDC interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the CDC interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t NotificationPipeNumber; /**< Pipe number of the CDC interface's IN notification endpoint, if used */
|
||||
bool NotificationPipeDoubleBank; /** Indicates if the CDC interface's notification pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref CDC_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t ControlInterfaceNumber; /**< Interface index of the CDC-ACM control interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the CDC interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the CDC interface's OUT data pipe */
|
||||
uint16_t NotificationPipeSize; /**< Size in bytes of the CDC interface's IN notification pipe, if used */
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_*
|
||||
* masks - to notify the device of changes to these values, call the
|
||||
* \ref CDC_Host_SendControlLineStateChange() function.
|
||||
*/
|
||||
uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of CDC_CONTROL_LINE_IN_*
|
||||
* masks. This value is updated each time \ref CDC_Host_USBTask() is called.
|
||||
*/
|
||||
} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
|
||||
uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
|
||||
* CDCDevice_CDC_LineCodingFormats_t enum
|
||||
*/
|
||||
uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
|
||||
* CDCDevice_LineCodingParity_t enum
|
||||
*/
|
||||
uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
|
||||
} LineEncoding; /** Line encoding used in the virtual serial port, for the device's information. This is generally
|
||||
* only used if the virtual serial port data is to be reconstructed on a physical UART. When set
|
||||
* by the host application, the \ref CDC_Host_SetLineEncoding() function must be called to push
|
||||
* the changes to the device.
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_CDC_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref CDC_Host_ConfigurePipes() function. */
|
||||
enum CDCHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
CDC_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
CDC_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
CDC_ENUMERROR_NoCDCInterfaceFound = 2, /**< A compatible CDC interface was not found in the device's Configuration Descriptor */
|
||||
CDC_ENUMERROR_EndpointsNotFound = 3, /**< Compatible CDC endpoints were not found in the device's CDC interface */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** General management task for a given CDC host class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state
|
||||
*/
|
||||
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Host interface configuration routine, to configure a given CDC host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given CDC Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the device.
|
||||
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
|
||||
* the Addressed state.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref CDCHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sets the line encoding for the attached device's virtual serial port. This should be called when the LineEncoding
|
||||
* values of the interface have been changed to push the new settings to the USB device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a Serial Control Line State Change notification to the device. This should be called when the virtual serial
|
||||
* control lines (DTR, RTS, etc.) have changed states. Line states persist until they are cleared via a second
|
||||
* notification. This should be called each time the CDC class driver's ControlLineStates.HostToDevice value is updated
|
||||
* to push the new states to the USB device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a Send Break request to the device. This is generally used to seperate data data or to indicate a special condition
|
||||
* to the receiving device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
* \param[in] Duration Duration of the break, in milliseconds
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a given string to the attached USB device, if connected. If a device is not connected when the function is called, the
|
||||
* string is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
|
||||
* \ref CDC_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single pipe packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
* \param[in] Data Pointer to the string to send to the device
|
||||
* \param[in] Length Size in bytes of the string to send to the device
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, char* Data, const uint16_t Length)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
|
||||
* byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
|
||||
* \ref CDC_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single pipe packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
* \param[in] Data Byte of data to send to the device
|
||||
*
|
||||
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Determines the number of bytes received by the CDC interface from the device, waiting to be read.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return Total number of buffered bytes received from the device
|
||||
*/
|
||||
uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
|
||||
* returns 0. The \ref CDC_Host_BytesReceived() function should be queried before data is received to ensure that no data
|
||||
* underflow occurs.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return Next received byte from the device, or 0 if no data received
|
||||
*/
|
||||
uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Creates a standard characer stream for the given CDC Device instance so that it can be used with all the regular
|
||||
* functions in the avr-libc <stdio.h> library that accept a FILE stream as a destination (e.g. fprintf). The created
|
||||
* stream is bidirectional and can be used for both input and output functions.
|
||||
*
|
||||
* \note The created stream can be given as stdout if desired to direct the standard output from all <stdio.h> functions
|
||||
* to the given CDC interface.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/** Identical to CDC_Host_CreateStream(), except that reads are blocking until the calling stream function terminates
|
||||
* the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/** CDC class driver event for a control line state change on a CDC host interface. This event fires each time the device notifies
|
||||
* the host of a control line state change (containing the virtual serial control line states, such as DCD) and may be hooked in the
|
||||
* user program by declaring a handler function with the same name and parameters listed here. The new control line states
|
||||
* are available in the ControlLineStates.DeviceToHost value inside the CDC host interface structure passed as a parameter, set as
|
||||
* a mask of CDC_CONTROL_LINE_IN_* masks.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*/
|
||||
void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define CDC_CONTROL_CLASS 0x02
|
||||
#define CDC_CONTROL_SUBCLASS 0x02
|
||||
#define CDC_CONTROL_PROTOCOL 0x01
|
||||
#define CDC_DATA_CLASS 0x0A
|
||||
#define CDC_DATA_SUBCLASS 0x00
|
||||
#define CDC_DATA_PROTOCOL 0x00
|
||||
|
||||
#define CDC_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define CDC_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
#define CDC_FOUND_NOTIFICATION_IN (1 << 2)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_CDC_CLASS_HOST_C)
|
||||
static int CDC_Host_putchar(char c, FILE* Stream);
|
||||
static int CDC_Host_getchar(FILE* Stream);
|
||||
static int CDC_Host_getchar_Blocking(FILE* Stream);
|
||||
|
||||
void CDC_Host_Event_Stub(void);
|
||||
void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Host_Event_Stub);
|
||||
static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB CDC Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/CDC.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassCDC
|
||||
* @defgroup Group_USBClassCDCHost CDC Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/CDC.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the CDC USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __CDC_CLASS_HOST_H__
|
||||
#define __CDC_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/CDC.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_CDC_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/CDC.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief CDC Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the CDC class driver functions as the CDCInterfaceInfo parameter. This
|
||||
* stores each CDC interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the CDC interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the CDC interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the CDC interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the CDC interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t NotificationPipeNumber; /**< Pipe number of the CDC interface's IN notification endpoint, if used */
|
||||
bool NotificationPipeDoubleBank; /** Indicates if the CDC interface's notification pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref CDC_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t ControlInterfaceNumber; /**< Interface index of the CDC-ACM control interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the CDC interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the CDC interface's OUT data pipe */
|
||||
uint16_t NotificationPipeSize; /**< Size in bytes of the CDC interface's IN notification pipe, if used */
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_*
|
||||
* masks - to notify the device of changes to these values, call the
|
||||
* \ref CDC_Host_SendControlLineStateChange() function.
|
||||
*/
|
||||
uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of CDC_CONTROL_LINE_IN_*
|
||||
* masks. This value is updated each time \ref CDC_Host_USBTask() is called.
|
||||
*/
|
||||
} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
|
||||
uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
|
||||
* CDCDevice_CDC_LineCodingFormats_t enum
|
||||
*/
|
||||
uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
|
||||
* CDCDevice_LineCodingParity_t enum
|
||||
*/
|
||||
uint8_t DataBits; /**< Bits of data per character of the virtual serial port */
|
||||
} LineEncoding; /** Line encoding used in the virtual serial port, for the device's information. This is generally
|
||||
* only used if the virtual serial port data is to be reconstructed on a physical UART. When set
|
||||
* by the host application, the \ref CDC_Host_SetLineEncoding() function must be called to push
|
||||
* the changes to the device.
|
||||
*/
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_CDC_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref CDC_Host_ConfigurePipes() function. */
|
||||
enum CDCHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
CDC_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
CDC_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
CDC_ENUMERROR_NoCDCInterfaceFound = 2, /**< A compatible CDC interface was not found in the device's Configuration Descriptor */
|
||||
CDC_ENUMERROR_EndpointsNotFound = 3, /**< Compatible CDC endpoints were not found in the device's CDC interface */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** General management task for a given CDC host class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state
|
||||
*/
|
||||
void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Host interface configuration routine, to configure a given CDC host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given CDC Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the device.
|
||||
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
|
||||
* the Addressed state.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref CDCHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sets the line encoding for the attached device's virtual serial port. This should be called when the LineEncoding
|
||||
* values of the interface have been changed to push the new settings to the USB device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a Serial Control Line State Change notification to the device. This should be called when the virtual serial
|
||||
* control lines (DTR, RTS, etc.) have changed states. Line states persist until they are cleared via a second
|
||||
* notification. This should be called each time the CDC class driver's ControlLineStates.HostToDevice value is updated
|
||||
* to push the new states to the USB device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a Send Break request to the device. This is generally used to seperate data data or to indicate a special condition
|
||||
* to the receiving device.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
* \param[in] Duration Duration of the break, in milliseconds
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a given string to the attached USB device, if connected. If a device is not connected when the function is called, the
|
||||
* string is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
|
||||
* \ref CDC_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single pipe packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
* \param[in] Data Pointer to the string to send to the device
|
||||
* \param[in] Length Size in bytes of the string to send to the device
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, char* Data, const uint16_t Length)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
|
||||
* byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
|
||||
* \ref CDC_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
|
||||
* packed into a single pipe packet, increasing data throughput.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
* \param[in] Data Byte of data to send to the device
|
||||
*
|
||||
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo, const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Determines the number of bytes received by the CDC interface from the device, waiting to be read.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return Total number of buffered bytes received from the device
|
||||
*/
|
||||
uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
|
||||
* returns 0. The \ref CDC_Host_BytesReceived() function should be queried before data is received to ensure that no data
|
||||
* underflow occurs.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return Next received byte from the device, or 0 if no data received
|
||||
*/
|
||||
uint8_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Creates a standard characer stream for the given CDC Device instance so that it can be used with all the regular
|
||||
* functions in the avr-libc <stdio.h> library that accept a FILE stream as a destination (e.g. fprintf). The created
|
||||
* stream is bidirectional and can be used for both input and output functions.
|
||||
*
|
||||
* \note The created stream can be given as stdout if desired to direct the standard output from all <stdio.h> functions
|
||||
* to the given CDC interface.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/** Identical to CDC_Host_CreateStream(), except that reads are blocking until the calling stream function terminates
|
||||
* the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state
|
||||
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed
|
||||
*/
|
||||
void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo, FILE* Stream);
|
||||
|
||||
/** CDC class driver event for a control line state change on a CDC host interface. This event fires each time the device notifies
|
||||
* the host of a control line state change (containing the virtual serial control line states, such as DCD) and may be hooked in the
|
||||
* user program by declaring a handler function with the same name and parameters listed here. The new control line states
|
||||
* are available in the ControlLineStates.DeviceToHost value inside the CDC host interface structure passed as a parameter, set as
|
||||
* a mask of CDC_CONTROL_LINE_IN_* masks.
|
||||
*
|
||||
* \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state
|
||||
*/
|
||||
void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define CDC_CONTROL_CLASS 0x02
|
||||
#define CDC_CONTROL_SUBCLASS 0x02
|
||||
#define CDC_CONTROL_PROTOCOL 0x01
|
||||
#define CDC_DATA_CLASS 0x0A
|
||||
#define CDC_DATA_SUBCLASS 0x00
|
||||
#define CDC_DATA_PROTOCOL 0x00
|
||||
|
||||
#define CDC_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define CDC_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
#define CDC_FOUND_NOTIFICATION_IN (1 << 2)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_CDC_CLASS_HOST_C)
|
||||
static int CDC_Host_putchar(char c, FILE* Stream);
|
||||
static int CDC_Host_getchar(FILE* Stream);
|
||||
static int CDC_Host_getchar_Blocking(FILE* Stream);
|
||||
|
||||
void CDC_Host_Event_Stub(void);
|
||||
void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
|
||||
ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Host_Event_Stub);
|
||||
static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,362 +1,362 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_HID_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_HID_DRIVER
|
||||
#include "HID.h"
|
||||
|
||||
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return HID_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
USB_Descriptor_Interface_t* CurrentHIDInterface;
|
||||
|
||||
do
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return HID_ENUMERROR_NoHIDInterfaceFound;
|
||||
}
|
||||
|
||||
CurrentHIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
|
||||
} while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
|
||||
(CurrentHIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
|
||||
|
||||
HIDInterfaceInfo->State.InterfaceNumber = CurrentHIDInterface->InterfaceNumber;
|
||||
HIDInterfaceInfo->State.SupportsBootProtocol = (CurrentHIDInterface->SubClass != HID_NON_BOOT_PROTOCOL);
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return HID_ENUMERROR_NoHIDDescriptorFound;
|
||||
}
|
||||
|
||||
HIDInterfaceInfo->State.HIDReportSize = DESCRIPTOR_CAST(ConfigDescriptorData, USB_HID_Descriptor_t).HIDReportLength;
|
||||
|
||||
while (FoundEndpoints != (HID_FOUND_DATAPIPE_IN | HID_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
if (FoundEndpoints & HID_FOUND_DATAPIPE_IN)
|
||||
break;
|
||||
|
||||
return HID_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(HIDInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
HIDInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
HIDInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= HID_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(HIDInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
HIDInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
HIDInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
|
||||
|
||||
FoundEndpoints |= HID_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
HIDInterfaceInfo->State.LargestReportSize = 8;
|
||||
HIDInterfaceInfo->State.IsActive = true;
|
||||
return HID_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if (CurrentInterface->Class == HID_INTERFACE_CLASS)
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_NextHID(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_HID)
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
else
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, const uint8_t ReportID, void* Buffer)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetReport,
|
||||
.wValue = ((REPORT_ITEM_TYPE_In + 1) << 8) | ReportID,
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, REPORT_ITEM_TYPE_In),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, void* Buffer)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
uint16_t ReportSize;
|
||||
uint8_t* BufferPos = Buffer;
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
if (!(HIDInterfaceInfo->State.UsingBootProtocol))
|
||||
{
|
||||
uint8_t ReportID = 0;
|
||||
|
||||
if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
|
||||
{
|
||||
ReportID = Pipe_Read_Byte();
|
||||
*(BufferPos++) = ReportID;
|
||||
}
|
||||
|
||||
ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, REPORT_ITEM_TYPE_In);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ReportSize = Pipe_BytesInPipe();
|
||||
}
|
||||
|
||||
if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearIN();
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
const uint8_t ReportID,
|
||||
#endif
|
||||
void* Buffer, const uint16_t ReportSize)
|
||||
{
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
if (HIDInterfaceInfo->State.DeviceUsesOUTPipe)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (ReportID)
|
||||
Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NO_STREAM_CALLBACK);
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearOUT();
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetReport,
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
.wValue = ((REPORT_ITEM_TYPE_Out + 1) << 8) | ReportID,
|
||||
#else
|
||||
.wValue = ((REPORT_ITEM_TYPE_Out + 1) << 8),
|
||||
#endif
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = ReportSize,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
bool ReportReceived;
|
||||
|
||||
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ReportReceived = Pipe_IsINReceived();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return ReportReceived;
|
||||
}
|
||||
|
||||
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetProtocol,
|
||||
.wValue = 0,
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
|
||||
return HID_ERROR_LOGICAL;
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
HIDInterfaceInfo->State.LargestReportSize = 8;
|
||||
HIDInterfaceInfo->State.UsingBootProtocol = true;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetDescriptor,
|
||||
.wValue = (DTYPE_Report << 8),
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = HIDInterfaceInfo->State.HIDReportSize,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
if (HIDInterfaceInfo->State.UsingBootProtocol)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetProtocol,
|
||||
.wValue = 1,
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
HIDInterfaceInfo->State.UsingBootProtocol = false;
|
||||
}
|
||||
|
||||
if (HIDInterfaceInfo->Config.HIDParserData == NULL)
|
||||
return HID_ERROR_LOGICAL;
|
||||
|
||||
if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
|
||||
HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
|
||||
{
|
||||
return HID_ERROR_LOGICAL | ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
|
||||
HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_HID_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_HID_DRIVER
|
||||
#include "HID.h"
|
||||
|
||||
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return HID_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
USB_Descriptor_Interface_t* CurrentHIDInterface;
|
||||
|
||||
do
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return HID_ENUMERROR_NoHIDInterfaceFound;
|
||||
}
|
||||
|
||||
CurrentHIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
|
||||
} while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
|
||||
(CurrentHIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
|
||||
|
||||
HIDInterfaceInfo->State.InterfaceNumber = CurrentHIDInterface->InterfaceNumber;
|
||||
HIDInterfaceInfo->State.SupportsBootProtocol = (CurrentHIDInterface->SubClass != HID_NON_BOOT_PROTOCOL);
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_NextHID) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return HID_ENUMERROR_NoHIDDescriptorFound;
|
||||
}
|
||||
|
||||
HIDInterfaceInfo->State.HIDReportSize = DESCRIPTOR_CAST(ConfigDescriptorData, USB_HID_Descriptor_t).HIDReportLength;
|
||||
|
||||
while (FoundEndpoints != (HID_FOUND_DATAPIPE_IN | HID_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
if (FoundEndpoints & HID_FOUND_DATAPIPE_IN)
|
||||
break;
|
||||
|
||||
return HID_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(HIDInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
HIDInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
HIDInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= HID_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(HIDInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
HIDInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
HIDInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
|
||||
|
||||
FoundEndpoints |= HID_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
HIDInterfaceInfo->State.LargestReportSize = 8;
|
||||
HIDInterfaceInfo->State.IsActive = true;
|
||||
return HID_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if (CurrentInterface->Class == HID_INTERFACE_CLASS)
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_NextHID(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_HID)
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
else
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, const uint8_t ReportID, void* Buffer)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetReport,
|
||||
.wValue = ((REPORT_ITEM_TYPE_In + 1) << 8) | ReportID,
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, REPORT_ITEM_TYPE_In),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, void* Buffer)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
uint16_t ReportSize;
|
||||
uint8_t* BufferPos = Buffer;
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
if (!(HIDInterfaceInfo->State.UsingBootProtocol))
|
||||
{
|
||||
uint8_t ReportID = 0;
|
||||
|
||||
if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
|
||||
{
|
||||
ReportID = Pipe_Read_Byte();
|
||||
*(BufferPos++) = ReportID;
|
||||
}
|
||||
|
||||
ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, REPORT_ITEM_TYPE_In);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ReportSize = Pipe_BytesInPipe();
|
||||
}
|
||||
|
||||
if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearIN();
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
const uint8_t ReportID,
|
||||
#endif
|
||||
void* Buffer, const uint16_t ReportSize)
|
||||
{
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
if (HIDInterfaceInfo->State.DeviceUsesOUTPipe)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (ReportID)
|
||||
Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NO_STREAM_CALLBACK);
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearOUT();
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetReport,
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
.wValue = ((REPORT_ITEM_TYPE_Out + 1) << 8) | ReportID,
|
||||
#else
|
||||
.wValue = ((REPORT_ITEM_TYPE_Out + 1) << 8),
|
||||
#endif
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = ReportSize,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
bool ReportReceived;
|
||||
|
||||
Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ReportReceived = Pipe_IsINReceived();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return ReportReceived;
|
||||
}
|
||||
|
||||
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetProtocol,
|
||||
.wValue = 0,
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
|
||||
return HID_ERROR_LOGICAL;
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
HIDInterfaceInfo->State.LargestReportSize = 8;
|
||||
HIDInterfaceInfo->State.UsingBootProtocol = true;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetDescriptor,
|
||||
.wValue = (DTYPE_Report << 8),
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = HIDInterfaceInfo->State.HIDReportSize,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
if (HIDInterfaceInfo->State.UsingBootProtocol)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetProtocol,
|
||||
.wValue = 1,
|
||||
.wIndex = HIDInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
HIDInterfaceInfo->State.UsingBootProtocol = false;
|
||||
}
|
||||
|
||||
if (HIDInterfaceInfo->Config.HIDParserData == NULL)
|
||||
return HID_ERROR_LOGICAL;
|
||||
|
||||
if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
|
||||
HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
|
||||
{
|
||||
return HID_ERROR_LOGICAL | ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
|
||||
HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,312 +1,312 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/HID.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassHID
|
||||
* @defgroup Group_USBClassHIDHost HID Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/HID.c
|
||||
* - LUFA/Drivers/USB/Class/Host/HIDParser.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the HID USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HID_CLASS_HOST_H__
|
||||
#define __HID_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/HID.h"
|
||||
#include "HIDParser.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_HID_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/HID.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Error code for some HID Host functions, indicating a logical (and not hardware) error */
|
||||
#define HID_ERROR_LOGICAL 0x80
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief HID Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the HID class driver functions as the HIDInterfaceInfo parameter. This
|
||||
* stores each HID interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the HID interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the HID interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the HID interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the HID interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t HIDInterfaceProtocol; /**< HID interface protocol value to match against if a specific
|
||||
* boot subclass protocol is required, either \ref HID_BOOT_MOUSE_PROTOCOL,
|
||||
* \ref HID_BOOT_KEYBOARD_PROTOCOL or \ref HID_NON_BOOT_PROTOCOL if any
|
||||
* HID device should be enumerated by the interface
|
||||
*/
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
HID_ReportInfo_t* HIDParserData; /**< HID parser data to store the parsed HID report data, when boot protocol
|
||||
* is not used
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined,
|
||||
* this method is unavailable.
|
||||
*/
|
||||
#endif
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref HID_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t InterfaceNumber; /**< Interface index of the HID interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the HID interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the HID interface's OUT data pipe */
|
||||
|
||||
bool SupportsBootProtocol; /**< Indicates if the current interface instance supports the HID Boot
|
||||
* Protocol when enabled via \ref HID_Host_SetBootProtocol()
|
||||
*/
|
||||
bool DeviceUsesOUTPipe; /**< Indicates if the current interface instance uses a separate OUT data pipe for
|
||||
* OUT reports, or if OUT reports are sent via the control pipe instead.
|
||||
*/
|
||||
bool UsingBootProtocol; /**< Indicates that the interface is currently initialized in Boot Protocol mode */
|
||||
uint16_t HIDReportSize; /**< Size in bytes of the HID report descriptor in the device */
|
||||
|
||||
uint8_t LargestReportSize; /**< Largest report the device will send, in bytes */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_HID_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref HID_Host_ConfigurePipes() function. */
|
||||
enum HIDHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
HID_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
HID_ENUMERROR_NoHIDInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor */
|
||||
HID_ENUMERROR_NoHIDDescriptorFound = 3, /**< The HID descriptor was not found in the device's HID interface */
|
||||
HID_ENUMERROR_EndpointsNotFound = 4, /**< Compatible HID endpoints were not found in the device's HID interface */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given HID host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given HID Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the
|
||||
* device. This should be called once after the stack has enumerated the attached device, while the host state
|
||||
* machine is in the Addressed state.
|
||||
*
|
||||
* \note Once the device pipes are configured, the HID device's reporting protocol <b>must</b> be set via a call
|
||||
* to either the \ref HID_Host_SetBootProtocol() or \ref HID_Host_SetReportProtocol() function.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref HIDHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
|
||||
/** Receives a HID IN report from the attached HID device, when a report has been received on the HID IN Data pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
* \n\n
|
||||
*
|
||||
* \note The destination buffer should be large enough to accommodate the largest report that the attached device
|
||||
* can generate.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] Buffer Buffer to store the received report into
|
||||
*
|
||||
* \return An error code from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, void* Buffer)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
/** Receives a HID IN report from the attached device, by the report ID.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
* \n\n
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] ReportID Report ID of the received report if ControlRequest is false, set by the to the Report ID to fetch
|
||||
* \param[in] Buffer Buffer to store the received report into
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, const uint8_t ReportID,
|
||||
void* Buffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
#endif
|
||||
|
||||
/** Sends an OUT report to the currently attached HID device, using the device's OUT pipe if available or the device's
|
||||
* Control pipe if not.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
* \n\n
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, the ReportID parameter is removed
|
||||
* from the parameter list of this function.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] ReportID Report ID of the report to send to the device, or 0 if the device does not use report IDs
|
||||
* \param[in] Buffer Buffer containing the report to send to the attached device
|
||||
* \param[in] ReportSize Report size in bytes to send to the attached device
|
||||
*
|
||||
* \return An error code from the \ref USB_Host_SendControlErrorCodes_t enum if the DeviceUsesOUTPipe flag is set in
|
||||
* the interface's state structure, a value from the \ref Pipe_Stream_RW_ErrorCodes_t enum otherwise
|
||||
*/
|
||||
uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
const uint8_t ReportID,
|
||||
#endif
|
||||
void* Buffer, const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
#else
|
||||
ATTR_NON_NULL_PTR_ARG(2);
|
||||
#endif
|
||||
|
||||
/** Determines if a HID IN report has been received from the attached device on the data IN pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*
|
||||
* \return Boolean true if a report has been received, false otherwise
|
||||
*/
|
||||
bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Switches the attached HID device's reporting protocol over to the Boot Report protocol mode, on supported devices.
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method must still be called
|
||||
* to explicitly place the attached device into boot protocol mode before use.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*
|
||||
* \return \ref HID_ERROR_LOGICAL if the device does not support Boot Protocol mode, a value from the
|
||||
* \ref USB_Host_SendControlErrorCodes_t enum otherwise
|
||||
*/
|
||||
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
/** Switches the attached HID device's reporting protocol over to the standard Report protocol mode. This also retrieves
|
||||
* and parses the device's HID report descriptor, so that the size of each report can be determined in advance.
|
||||
*
|
||||
* \note Whether this function is used or not, the \ref CALLBACK_HIDParser_FilterHIDReportItem() callback from the HID
|
||||
* Report Parser this function references <b>must</b> be implemented in the user code.
|
||||
* \n\n
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum if an error occurs while retrieving the HID
|
||||
* Report descriptor or the setting of the Report protocol, \ref HID_ERROR_LOGICAL if the HID interface does
|
||||
* not have a valid \ref HID_ReportInfo_t structure set in its configuration, a mask of \ref HID_ERROR_LOGICAL
|
||||
* and a value from the \ref HID_Parse_ErrorCodes_t otherwise
|
||||
*/
|
||||
uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Human Interface Class host class interface, required for the correct operation of
|
||||
* the interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*/
|
||||
static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo);
|
||||
static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
(void)HIDInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define HID_INTERFACE_CLASS 0x03
|
||||
|
||||
#define HID_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define HID_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_HID_CLASS_HOST_C)
|
||||
static uint8_t DComp_HID_Host_NextHIDInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_NextHID(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB HID Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/HID.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassHID
|
||||
* @defgroup Group_USBClassHIDHost HID Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/HID.c
|
||||
* - LUFA/Drivers/USB/Class/Host/HIDParser.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the HID USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HID_CLASS_HOST_H__
|
||||
#define __HID_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/HID.h"
|
||||
#include "HIDParser.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_HID_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/HID.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Error code for some HID Host functions, indicating a logical (and not hardware) error */
|
||||
#define HID_ERROR_LOGICAL 0x80
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief HID Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the HID class driver functions as the HIDInterfaceInfo parameter. This
|
||||
* stores each HID interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the HID interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the HID interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the HID interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the HID interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t HIDInterfaceProtocol; /**< HID interface protocol value to match against if a specific
|
||||
* boot subclass protocol is required, either \ref HID_BOOT_MOUSE_PROTOCOL,
|
||||
* \ref HID_BOOT_KEYBOARD_PROTOCOL or \ref HID_NON_BOOT_PROTOCOL if any
|
||||
* HID device should be enumerated by the interface
|
||||
*/
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
HID_ReportInfo_t* HIDParserData; /**< HID parser data to store the parsed HID report data, when boot protocol
|
||||
* is not used
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined,
|
||||
* this method is unavailable.
|
||||
*/
|
||||
#endif
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref HID_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t InterfaceNumber; /**< Interface index of the HID interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the HID interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the HID interface's OUT data pipe */
|
||||
|
||||
bool SupportsBootProtocol; /**< Indicates if the current interface instance supports the HID Boot
|
||||
* Protocol when enabled via \ref HID_Host_SetBootProtocol()
|
||||
*/
|
||||
bool DeviceUsesOUTPipe; /**< Indicates if the current interface instance uses a separate OUT data pipe for
|
||||
* OUT reports, or if OUT reports are sent via the control pipe instead.
|
||||
*/
|
||||
bool UsingBootProtocol; /**< Indicates that the interface is currently initialized in Boot Protocol mode */
|
||||
uint16_t HIDReportSize; /**< Size in bytes of the HID report descriptor in the device */
|
||||
|
||||
uint8_t LargestReportSize; /**< Largest report the device will send, in bytes */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_HID_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref HID_Host_ConfigurePipes() function. */
|
||||
enum HIDHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
HID_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
HID_ENUMERROR_NoHIDInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor */
|
||||
HID_ENUMERROR_NoHIDDescriptorFound = 3, /**< The HID descriptor was not found in the device's HID interface */
|
||||
HID_ENUMERROR_EndpointsNotFound = 4, /**< Compatible HID endpoints were not found in the device's HID interface */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given HID host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given HID Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the
|
||||
* device. This should be called once after the stack has enumerated the attached device, while the host state
|
||||
* machine is in the Addressed state.
|
||||
*
|
||||
* \note Once the device pipes are configured, the HID device's reporting protocol <b>must</b> be set via a call
|
||||
* to either the \ref HID_Host_SetBootProtocol() or \ref HID_Host_SetReportProtocol() function.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref HIDHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
|
||||
/** Receives a HID IN report from the attached HID device, when a report has been received on the HID IN Data pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
* \n\n
|
||||
*
|
||||
* \note The destination buffer should be large enough to accommodate the largest report that the attached device
|
||||
* can generate.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] Buffer Buffer to store the received report into
|
||||
*
|
||||
* \return An error code from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, void* Buffer)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
/** Receives a HID IN report from the attached device, by the report ID.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
* \n\n
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] ReportID Report ID of the received report if ControlRequest is false, set by the to the Report ID to fetch
|
||||
* \param[in] Buffer Buffer to store the received report into
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo, const uint8_t ReportID,
|
||||
void* Buffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
#endif
|
||||
|
||||
/** Sends an OUT report to the currently attached HID device, using the device's OUT pipe if available or the device's
|
||||
* Control pipe if not.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
* \n\n
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, the ReportID parameter is removed
|
||||
* from the parameter list of this function.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
* \param[in] ReportID Report ID of the report to send to the device, or 0 if the device does not use report IDs
|
||||
* \param[in] Buffer Buffer containing the report to send to the attached device
|
||||
* \param[in] ReportSize Report size in bytes to send to the attached device
|
||||
*
|
||||
* \return An error code from the \ref USB_Host_SendControlErrorCodes_t enum if the DeviceUsesOUTPipe flag is set in
|
||||
* the interface's state structure, a value from the \ref Pipe_Stream_RW_ErrorCodes_t enum otherwise
|
||||
*/
|
||||
uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
const uint8_t ReportID,
|
||||
#endif
|
||||
void* Buffer, const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1)
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
#else
|
||||
ATTR_NON_NULL_PTR_ARG(2);
|
||||
#endif
|
||||
|
||||
/** Determines if a HID IN report has been received from the attached device on the data IN pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*
|
||||
* \return Boolean true if a report has been received, false otherwise
|
||||
*/
|
||||
bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Switches the attached HID device's reporting protocol over to the Boot Report protocol mode, on supported devices.
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method must still be called
|
||||
* to explicitly place the attached device into boot protocol mode before use.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*
|
||||
* \return \ref HID_ERROR_LOGICAL if the device does not support Boot Protocol mode, a value from the
|
||||
* \ref USB_Host_SendControlErrorCodes_t enum otherwise
|
||||
*/
|
||||
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
|
||||
/** Switches the attached HID device's reporting protocol over to the standard Report protocol mode. This also retrieves
|
||||
* and parses the device's HID report descriptor, so that the size of each report can be determined in advance.
|
||||
*
|
||||
* \note Whether this function is used or not, the \ref CALLBACK_HIDParser_FilterHIDReportItem() callback from the HID
|
||||
* Report Parser this function references <b>must</b> be implemented in the user code.
|
||||
* \n\n
|
||||
*
|
||||
* \note When the HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum if an error occurs while retrieving the HID
|
||||
* Report descriptor or the setting of the Report protocol, \ref HID_ERROR_LOGICAL if the HID interface does
|
||||
* not have a valid \ref HID_ReportInfo_t structure set in its configuration, a mask of \ref HID_ERROR_LOGICAL
|
||||
* and a value from the \ref HID_Parse_ErrorCodes_t otherwise
|
||||
*/
|
||||
uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Human Interface Class host class interface, required for the correct operation of
|
||||
* the interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state
|
||||
*/
|
||||
static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo);
|
||||
static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
|
||||
{
|
||||
(void)HIDInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define HID_INTERFACE_CLASS 0x03
|
||||
|
||||
#define HID_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define HID_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_HID_CLASS_HOST_C)
|
||||
static uint8_t DComp_HID_Host_NextHIDInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_NextHID(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,353 +1,353 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#include "HIDParser.h"
|
||||
|
||||
uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)
|
||||
{
|
||||
HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];
|
||||
HID_StateTable_t* CurrStateTable = &StateTable[0];
|
||||
HID_CollectionPath_t* CurrCollectionPath = NULL;
|
||||
HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0];
|
||||
uint16_t UsageList[HID_USAGE_STACK_DEPTH];
|
||||
uint8_t UsageListSize = 0;
|
||||
HID_MinMax_t UsageMinMax = {0, 0};
|
||||
|
||||
memset(ParserData, 0x00, sizeof(HID_ReportInfo_t));
|
||||
memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t));
|
||||
memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
|
||||
|
||||
ParserData->TotalDeviceReports = 1;
|
||||
|
||||
while (ReportSize)
|
||||
{
|
||||
uint8_t HIDReportItem = *ReportData;
|
||||
uint32_t ReportItemData = 0;
|
||||
|
||||
ReportData++;
|
||||
ReportSize--;
|
||||
|
||||
switch (HIDReportItem & DATA_SIZE_MASK)
|
||||
{
|
||||
case DATA_SIZE_4:
|
||||
ReportItemData = *((uint32_t*)ReportData);
|
||||
ReportSize -= 4;
|
||||
ReportData += 4;
|
||||
break;
|
||||
case DATA_SIZE_2:
|
||||
ReportItemData = *((uint16_t*)ReportData);
|
||||
ReportSize -= 2;
|
||||
ReportData += 2;
|
||||
break;
|
||||
case DATA_SIZE_1:
|
||||
ReportItemData = *((uint8_t*)ReportData);
|
||||
ReportSize -= 1;
|
||||
ReportData += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (HIDReportItem & (TYPE_MASK | TAG_MASK))
|
||||
{
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
|
||||
if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1])
|
||||
return HID_PARSE_HIDStackOverflow;
|
||||
|
||||
memcpy((CurrStateTable + 1),
|
||||
CurrStateTable,
|
||||
sizeof(HID_ReportItem_t));
|
||||
|
||||
CurrStateTable++;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_POP):
|
||||
if (CurrStateTable == &StateTable[0])
|
||||
return HID_PARSE_HIDStackUnderflow;
|
||||
|
||||
CurrStateTable--;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
|
||||
CurrStateTable->Attributes.Usage.Page = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):
|
||||
CurrStateTable->Attributes.Logical.Minimum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):
|
||||
CurrStateTable->Attributes.Logical.Maximum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):
|
||||
CurrStateTable->Attributes.Physical.Minimum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):
|
||||
CurrStateTable->Attributes.Physical.Maximum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):
|
||||
CurrStateTable->Attributes.Unit.Exponent = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):
|
||||
CurrStateTable->Attributes.Unit.Type = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
|
||||
CurrStateTable->Attributes.BitSize = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
|
||||
CurrStateTable->ReportCount = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
|
||||
CurrStateTable->ReportID = ReportItemData;
|
||||
|
||||
if (ParserData->UsingReportIDs)
|
||||
{
|
||||
CurrReportIDInfo = NULL;
|
||||
|
||||
for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++)
|
||||
{
|
||||
if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID)
|
||||
{
|
||||
CurrReportIDInfo = &ParserData->ReportIDSizes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrReportIDInfo == NULL)
|
||||
{
|
||||
if (ParserData->TotalDeviceReports == HID_MAX_REPORT_IDS)
|
||||
return HID_PARSE_InsufficientReportIDItems;
|
||||
|
||||
CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports++];
|
||||
memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
|
||||
}
|
||||
}
|
||||
|
||||
ParserData->UsingReportIDs = true;
|
||||
|
||||
CurrReportIDInfo->ReportID = CurrStateTable->ReportID;
|
||||
break;
|
||||
case (TYPE_LOCAL | TAG_LOCAL_USAGE):
|
||||
if (UsageListSize == HID_USAGE_STACK_DEPTH)
|
||||
return HID_PARSE_UsageListOverflow;
|
||||
|
||||
UsageList[UsageListSize++] = ReportItemData;
|
||||
break;
|
||||
case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
|
||||
UsageMinMax.Minimum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
|
||||
UsageMinMax.Maximum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_MAIN | TAG_MAIN_COLLECTION):
|
||||
if (CurrCollectionPath == NULL)
|
||||
{
|
||||
CurrCollectionPath = &ParserData->CollectionPaths[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;
|
||||
|
||||
CurrCollectionPath = &ParserData->CollectionPaths[1];
|
||||
|
||||
while (CurrCollectionPath->Parent != NULL)
|
||||
{
|
||||
if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1])
|
||||
return HID_PARSE_InsufficientCollectionPaths;
|
||||
|
||||
CurrCollectionPath++;
|
||||
}
|
||||
|
||||
CurrCollectionPath->Parent = ParentCollectionPath;
|
||||
}
|
||||
|
||||
CurrCollectionPath->Type = ReportItemData;
|
||||
CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;
|
||||
|
||||
if (UsageListSize)
|
||||
{
|
||||
CurrCollectionPath->Usage.Usage = UsageList[0];
|
||||
|
||||
for (uint8_t i = 0; i < UsageListSize; i++)
|
||||
UsageList[i] = UsageList[i + 1];
|
||||
|
||||
UsageListSize--;
|
||||
}
|
||||
else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
|
||||
{
|
||||
CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++;
|
||||
}
|
||||
|
||||
break;
|
||||
case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
|
||||
if (CurrCollectionPath == NULL)
|
||||
return HID_PARSE_UnexpectedEndCollection;
|
||||
|
||||
CurrCollectionPath = CurrCollectionPath->Parent;
|
||||
break;
|
||||
case (TYPE_MAIN | TAG_MAIN_INPUT):
|
||||
case (TYPE_MAIN | TAG_MAIN_OUTPUT):
|
||||
case (TYPE_MAIN | TAG_MAIN_FEATURE):
|
||||
for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)
|
||||
{
|
||||
HID_ReportItem_t NewReportItem;
|
||||
|
||||
memcpy(&NewReportItem.Attributes,
|
||||
&CurrStateTable->Attributes,
|
||||
sizeof(HID_ReportItem_Attributes_t));
|
||||
|
||||
NewReportItem.ItemFlags = ReportItemData;
|
||||
NewReportItem.CollectionPath = CurrCollectionPath;
|
||||
NewReportItem.ReportID = CurrStateTable->ReportID;
|
||||
|
||||
if (UsageListSize)
|
||||
{
|
||||
NewReportItem.Attributes.Usage.Usage = UsageList[0];
|
||||
|
||||
for (uint8_t i = 0; i < UsageListSize; i++)
|
||||
UsageList[i] = UsageList[i + 1];
|
||||
|
||||
UsageListSize--;
|
||||
}
|
||||
else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
|
||||
{
|
||||
NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++;
|
||||
}
|
||||
|
||||
uint8_t ItemTag = (HIDReportItem & TAG_MASK);
|
||||
|
||||
if (ItemTag == TAG_MAIN_INPUT)
|
||||
NewReportItem.ItemType = REPORT_ITEM_TYPE_In;
|
||||
else if (ItemTag == TAG_MAIN_OUTPUT)
|
||||
NewReportItem.ItemType = REPORT_ITEM_TYPE_Out;
|
||||
else
|
||||
NewReportItem.ItemType = REPORT_ITEM_TYPE_Feature;
|
||||
|
||||
NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType];
|
||||
|
||||
CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize;
|
||||
|
||||
if (ParserData->LargestReportSizeBits < NewReportItem.BitOffset)
|
||||
ParserData->LargestReportSizeBits = NewReportItem.BitOffset;
|
||||
|
||||
if (!(ReportItemData & IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem))
|
||||
{
|
||||
if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)
|
||||
return HID_PARSE_InsufficientReportItems;
|
||||
|
||||
memcpy(&ParserData->ReportItems[ParserData->TotalReportItems],
|
||||
&NewReportItem, sizeof(HID_ReportItem_t));
|
||||
|
||||
ParserData->TotalReportItems++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((HIDReportItem & TYPE_MASK) == TYPE_MAIN)
|
||||
{
|
||||
UsageMinMax.Minimum = 0;
|
||||
UsageMinMax.Maximum = 0;
|
||||
UsageListSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(ParserData->TotalReportItems))
|
||||
return HID_PARSE_NoUnfilteredReportItems;
|
||||
|
||||
return HID_PARSE_Successful;
|
||||
}
|
||||
|
||||
bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
{
|
||||
uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
|
||||
uint16_t CurrentBit = ReportItem->BitOffset;
|
||||
uint32_t BitMask = (1 << 0);
|
||||
|
||||
ReportItem->PreviousValue = ReportItem->Value;
|
||||
ReportItem->Value = 0;
|
||||
|
||||
if (ReportItem->ReportID)
|
||||
{
|
||||
if (ReportItem->ReportID != ReportData[0])
|
||||
return false;
|
||||
|
||||
ReportData++;
|
||||
}
|
||||
|
||||
while (DataBitsRem--)
|
||||
{
|
||||
if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))
|
||||
ReportItem->Value |= BitMask;
|
||||
|
||||
CurrentBit++;
|
||||
BitMask <<= 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void USB_SetHIDReportItemInfo(uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
{
|
||||
uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
|
||||
uint16_t CurrentBit = ReportItem->BitOffset;
|
||||
uint32_t BitMask = (1 << 0);
|
||||
|
||||
if (ReportItem->ReportID)
|
||||
{
|
||||
ReportData[0] = ReportItem->ReportID;
|
||||
ReportData++;
|
||||
}
|
||||
|
||||
ReportItem->PreviousValue = ReportItem->Value;
|
||||
|
||||
while (DataBitsRem--)
|
||||
{
|
||||
if (ReportItem->Value & (1 << (CurrentBit % 8)))
|
||||
ReportData[CurrentBit / 8] |= BitMask;
|
||||
|
||||
CurrentBit++;
|
||||
BitMask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData, const uint8_t ReportID, const uint8_t ReportType)
|
||||
{
|
||||
for (uint8_t i = 0; i < HID_MAX_REPORT_IDS; i++)
|
||||
{
|
||||
uint16_t ReportSizeBits = ParserData->ReportIDSizes[i].ReportSizeBits[ReportType];
|
||||
|
||||
if (ParserData->ReportIDSizes[i].ReportID == ReportID)
|
||||
return ((ReportSizeBits >> 3) + ((ReportSizeBits & 0x07) ? 1 : 0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#include "HIDParser.h"
|
||||
|
||||
uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)
|
||||
{
|
||||
HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];
|
||||
HID_StateTable_t* CurrStateTable = &StateTable[0];
|
||||
HID_CollectionPath_t* CurrCollectionPath = NULL;
|
||||
HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0];
|
||||
uint16_t UsageList[HID_USAGE_STACK_DEPTH];
|
||||
uint8_t UsageListSize = 0;
|
||||
HID_MinMax_t UsageMinMax = {0, 0};
|
||||
|
||||
memset(ParserData, 0x00, sizeof(HID_ReportInfo_t));
|
||||
memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t));
|
||||
memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
|
||||
|
||||
ParserData->TotalDeviceReports = 1;
|
||||
|
||||
while (ReportSize)
|
||||
{
|
||||
uint8_t HIDReportItem = *ReportData;
|
||||
uint32_t ReportItemData = 0;
|
||||
|
||||
ReportData++;
|
||||
ReportSize--;
|
||||
|
||||
switch (HIDReportItem & DATA_SIZE_MASK)
|
||||
{
|
||||
case DATA_SIZE_4:
|
||||
ReportItemData = *((uint32_t*)ReportData);
|
||||
ReportSize -= 4;
|
||||
ReportData += 4;
|
||||
break;
|
||||
case DATA_SIZE_2:
|
||||
ReportItemData = *((uint16_t*)ReportData);
|
||||
ReportSize -= 2;
|
||||
ReportData += 2;
|
||||
break;
|
||||
case DATA_SIZE_1:
|
||||
ReportItemData = *((uint8_t*)ReportData);
|
||||
ReportSize -= 1;
|
||||
ReportData += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (HIDReportItem & (TYPE_MASK | TAG_MASK))
|
||||
{
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
|
||||
if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1])
|
||||
return HID_PARSE_HIDStackOverflow;
|
||||
|
||||
memcpy((CurrStateTable + 1),
|
||||
CurrStateTable,
|
||||
sizeof(HID_ReportItem_t));
|
||||
|
||||
CurrStateTable++;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_POP):
|
||||
if (CurrStateTable == &StateTable[0])
|
||||
return HID_PARSE_HIDStackUnderflow;
|
||||
|
||||
CurrStateTable--;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
|
||||
CurrStateTable->Attributes.Usage.Page = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):
|
||||
CurrStateTable->Attributes.Logical.Minimum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):
|
||||
CurrStateTable->Attributes.Logical.Maximum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):
|
||||
CurrStateTable->Attributes.Physical.Minimum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):
|
||||
CurrStateTable->Attributes.Physical.Maximum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):
|
||||
CurrStateTable->Attributes.Unit.Exponent = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):
|
||||
CurrStateTable->Attributes.Unit.Type = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
|
||||
CurrStateTable->Attributes.BitSize = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
|
||||
CurrStateTable->ReportCount = ReportItemData;
|
||||
break;
|
||||
case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
|
||||
CurrStateTable->ReportID = ReportItemData;
|
||||
|
||||
if (ParserData->UsingReportIDs)
|
||||
{
|
||||
CurrReportIDInfo = NULL;
|
||||
|
||||
for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++)
|
||||
{
|
||||
if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID)
|
||||
{
|
||||
CurrReportIDInfo = &ParserData->ReportIDSizes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrReportIDInfo == NULL)
|
||||
{
|
||||
if (ParserData->TotalDeviceReports == HID_MAX_REPORT_IDS)
|
||||
return HID_PARSE_InsufficientReportIDItems;
|
||||
|
||||
CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports++];
|
||||
memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
|
||||
}
|
||||
}
|
||||
|
||||
ParserData->UsingReportIDs = true;
|
||||
|
||||
CurrReportIDInfo->ReportID = CurrStateTable->ReportID;
|
||||
break;
|
||||
case (TYPE_LOCAL | TAG_LOCAL_USAGE):
|
||||
if (UsageListSize == HID_USAGE_STACK_DEPTH)
|
||||
return HID_PARSE_UsageListOverflow;
|
||||
|
||||
UsageList[UsageListSize++] = ReportItemData;
|
||||
break;
|
||||
case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
|
||||
UsageMinMax.Minimum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
|
||||
UsageMinMax.Maximum = ReportItemData;
|
||||
break;
|
||||
case (TYPE_MAIN | TAG_MAIN_COLLECTION):
|
||||
if (CurrCollectionPath == NULL)
|
||||
{
|
||||
CurrCollectionPath = &ParserData->CollectionPaths[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;
|
||||
|
||||
CurrCollectionPath = &ParserData->CollectionPaths[1];
|
||||
|
||||
while (CurrCollectionPath->Parent != NULL)
|
||||
{
|
||||
if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1])
|
||||
return HID_PARSE_InsufficientCollectionPaths;
|
||||
|
||||
CurrCollectionPath++;
|
||||
}
|
||||
|
||||
CurrCollectionPath->Parent = ParentCollectionPath;
|
||||
}
|
||||
|
||||
CurrCollectionPath->Type = ReportItemData;
|
||||
CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;
|
||||
|
||||
if (UsageListSize)
|
||||
{
|
||||
CurrCollectionPath->Usage.Usage = UsageList[0];
|
||||
|
||||
for (uint8_t i = 0; i < UsageListSize; i++)
|
||||
UsageList[i] = UsageList[i + 1];
|
||||
|
||||
UsageListSize--;
|
||||
}
|
||||
else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
|
||||
{
|
||||
CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++;
|
||||
}
|
||||
|
||||
break;
|
||||
case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
|
||||
if (CurrCollectionPath == NULL)
|
||||
return HID_PARSE_UnexpectedEndCollection;
|
||||
|
||||
CurrCollectionPath = CurrCollectionPath->Parent;
|
||||
break;
|
||||
case (TYPE_MAIN | TAG_MAIN_INPUT):
|
||||
case (TYPE_MAIN | TAG_MAIN_OUTPUT):
|
||||
case (TYPE_MAIN | TAG_MAIN_FEATURE):
|
||||
for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)
|
||||
{
|
||||
HID_ReportItem_t NewReportItem;
|
||||
|
||||
memcpy(&NewReportItem.Attributes,
|
||||
&CurrStateTable->Attributes,
|
||||
sizeof(HID_ReportItem_Attributes_t));
|
||||
|
||||
NewReportItem.ItemFlags = ReportItemData;
|
||||
NewReportItem.CollectionPath = CurrCollectionPath;
|
||||
NewReportItem.ReportID = CurrStateTable->ReportID;
|
||||
|
||||
if (UsageListSize)
|
||||
{
|
||||
NewReportItem.Attributes.Usage.Usage = UsageList[0];
|
||||
|
||||
for (uint8_t i = 0; i < UsageListSize; i++)
|
||||
UsageList[i] = UsageList[i + 1];
|
||||
|
||||
UsageListSize--;
|
||||
}
|
||||
else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
|
||||
{
|
||||
NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++;
|
||||
}
|
||||
|
||||
uint8_t ItemTag = (HIDReportItem & TAG_MASK);
|
||||
|
||||
if (ItemTag == TAG_MAIN_INPUT)
|
||||
NewReportItem.ItemType = REPORT_ITEM_TYPE_In;
|
||||
else if (ItemTag == TAG_MAIN_OUTPUT)
|
||||
NewReportItem.ItemType = REPORT_ITEM_TYPE_Out;
|
||||
else
|
||||
NewReportItem.ItemType = REPORT_ITEM_TYPE_Feature;
|
||||
|
||||
NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType];
|
||||
|
||||
CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize;
|
||||
|
||||
if (ParserData->LargestReportSizeBits < NewReportItem.BitOffset)
|
||||
ParserData->LargestReportSizeBits = NewReportItem.BitOffset;
|
||||
|
||||
if (!(ReportItemData & IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem))
|
||||
{
|
||||
if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)
|
||||
return HID_PARSE_InsufficientReportItems;
|
||||
|
||||
memcpy(&ParserData->ReportItems[ParserData->TotalReportItems],
|
||||
&NewReportItem, sizeof(HID_ReportItem_t));
|
||||
|
||||
ParserData->TotalReportItems++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((HIDReportItem & TYPE_MASK) == TYPE_MAIN)
|
||||
{
|
||||
UsageMinMax.Minimum = 0;
|
||||
UsageMinMax.Maximum = 0;
|
||||
UsageListSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(ParserData->TotalReportItems))
|
||||
return HID_PARSE_NoUnfilteredReportItems;
|
||||
|
||||
return HID_PARSE_Successful;
|
||||
}
|
||||
|
||||
bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
{
|
||||
uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
|
||||
uint16_t CurrentBit = ReportItem->BitOffset;
|
||||
uint32_t BitMask = (1 << 0);
|
||||
|
||||
ReportItem->PreviousValue = ReportItem->Value;
|
||||
ReportItem->Value = 0;
|
||||
|
||||
if (ReportItem->ReportID)
|
||||
{
|
||||
if (ReportItem->ReportID != ReportData[0])
|
||||
return false;
|
||||
|
||||
ReportData++;
|
||||
}
|
||||
|
||||
while (DataBitsRem--)
|
||||
{
|
||||
if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))
|
||||
ReportItem->Value |= BitMask;
|
||||
|
||||
CurrentBit++;
|
||||
BitMask <<= 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void USB_SetHIDReportItemInfo(uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
{
|
||||
uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
|
||||
uint16_t CurrentBit = ReportItem->BitOffset;
|
||||
uint32_t BitMask = (1 << 0);
|
||||
|
||||
if (ReportItem->ReportID)
|
||||
{
|
||||
ReportData[0] = ReportItem->ReportID;
|
||||
ReportData++;
|
||||
}
|
||||
|
||||
ReportItem->PreviousValue = ReportItem->Value;
|
||||
|
||||
while (DataBitsRem--)
|
||||
{
|
||||
if (ReportItem->Value & (1 << (CurrentBit % 8)))
|
||||
ReportData[CurrentBit / 8] |= BitMask;
|
||||
|
||||
CurrentBit++;
|
||||
BitMask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData, const uint8_t ReportID, const uint8_t ReportType)
|
||||
{
|
||||
for (uint8_t i = 0; i < HID_MAX_REPORT_IDS; i++)
|
||||
{
|
||||
uint16_t ReportSizeBits = ParserData->ReportIDSizes[i].ReportSizeBits[ReportType];
|
||||
|
||||
if (ParserData->ReportIDSizes[i].ReportID == ReportID)
|
||||
return ((ReportSizeBits >> 3) + ((ReportSizeBits & 0x07) ? 1 : 0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,355 +1,355 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief USB Human Interface Device (HID) Class report descriptor parser.
|
||||
*
|
||||
* This file allows for the easy parsing of complex HID report descriptors, which describes the data that
|
||||
* a HID device transmits to the host. It also provides an easy API for extracting and processing the data
|
||||
* elements inside a HID report sent from an attached HID device.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USB
|
||||
* @defgroup Group_HIDParser HID Report Parser
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/HIDParser.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Functions, macros, variables, enums and types related to the parsing of HID class device report descriptors.
|
||||
*
|
||||
* The processed HID report is presented back to the user application as a flat structure containing each report
|
||||
* item's IN, OUT and FEATURE items along with each item's attributes.
|
||||
*
|
||||
* This library portion also allows for easy setting and retrieval of data from a HID report, including devices
|
||||
* with multiple reports on the one HID interface.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HIDPARSER_H__
|
||||
#define __HIDPARSER_H__
|
||||
|
||||
/* Macros: */
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#define __INCLUDE_FROM_HID_DRIVER
|
||||
|
||||
/* Includes: */
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "HIDReportData.h"
|
||||
#include "../Common/HID.h"
|
||||
|
||||
#include "../../../../Common/Common.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macros: */
|
||||
#if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum stack depth of the state table. A larger state table
|
||||
* allows for more PUSH/POP report items to be nested, but consumes more memory. By default
|
||||
* this is set to 2 levels (allowing non-nested PUSH items) but this can be overridden by
|
||||
* defining HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the
|
||||
* define to the compiler using the -D compiler switch.
|
||||
*/
|
||||
#define HID_STATETABLE_STACK_DEPTH 2
|
||||
#endif
|
||||
|
||||
#if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum stack depth of the usage table. A larger usage table
|
||||
* allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than
|
||||
* one, but requires more stack space. By default this is set to 8 levels (allowing for a report
|
||||
* item with a count of 8) but this can be overridden by defining HID_USAGE_STACK_DEPTH to another
|
||||
* value in the user project makefile, passing the define to the compiler using the -D compiler
|
||||
* switch.
|
||||
*/
|
||||
#define HID_USAGE_STACK_DEPTH 8
|
||||
#endif
|
||||
|
||||
#if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be
|
||||
* processed in the report item descriptor. A large value allows for more COLLECTION items to be
|
||||
* processed, but consumes more memory. By default this is set to 5 collections, but this can be
|
||||
* overridden by defining HID_MAX_COLLECTIONS to another value in the user project makefile, passing
|
||||
* the define to the compiler using the -D compiler switch.
|
||||
*/
|
||||
#define HID_MAX_COLLECTIONS 10
|
||||
#endif
|
||||
|
||||
#if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum number of report items (IN, OUT or FEATURE) that can be processed
|
||||
* in the report item descriptor and stored in the user HID Report Info structure. A large value allows
|
||||
* for more report items to be stored, but consumes more memory. By default this is set to 20 items,
|
||||
* but this can be overridden by defining HID_MAX_REPORTITEMS to another value in the user project
|
||||
* makefile, and passing the define to the compiler using the -D compiler switch.
|
||||
*/
|
||||
#define HID_MAX_REPORTITEMS 20
|
||||
#endif
|
||||
|
||||
#if !defined(HID_MAX_REPORT_IDS) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum number of unique report IDs that can be processed in the report item
|
||||
* descriptor for the report size information array in the user HID Report Info structure. A large value
|
||||
* allows for more report ID report sizes to be stored, but consumes more memory. By default this is set
|
||||
* to 5 items, but this can be overridden by defining HID_MAX_REPORT_IDS to another value in the user project
|
||||
* makefile, and passing the define to the compiler using the -D compiler switch. Note that IN, OUT and FEATURE
|
||||
* items sharing the same report ID consume only one size item in the array.
|
||||
*/
|
||||
#define HID_MAX_REPORT_IDS 10
|
||||
#endif
|
||||
|
||||
/** Returns the value a given HID report item (once its value has been fetched via \ref USB_GetHIDReportItemInfo())
|
||||
* left-aligned to the given data type. This allows for signed data to be interpreted correctly, by shifting the data
|
||||
* leftwards until the data's sign bit is in the correct position.
|
||||
*
|
||||
* \param[in] reportitem HID Report Item whose retrieved value is to be aligned
|
||||
* \param[in] type Data type to align the HID report item's value to
|
||||
*
|
||||
* \return Left-aligned data of the given report item's pre-retrived value for the given datatype
|
||||
*/
|
||||
#define HID_ALIGN_DATA(reportitem, type) ((type)(reportitem->Value << ((8 * sizeof(type)) - reportitem->Attributes.BitSize)))
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes in the return value of the \ref USB_ProcessHIDReport() function */
|
||||
enum HID_Parse_ErrorCodes_t
|
||||
{
|
||||
HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */
|
||||
HID_PARSE_HIDStackOverflow = 1, /**< More than \ref HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */
|
||||
HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */
|
||||
HID_PARSE_InsufficientReportItems = 3, /**< More than \ref HID_MAX_REPORTITEMS report items in the report. */
|
||||
HID_PARSE_UnexpectedEndCollection = 4, /**< An END COLLECTION item found without matching COLLECTION item. */
|
||||
HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */
|
||||
HID_PARSE_UsageListOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */
|
||||
HID_PARSE_InsufficientReportIDItems = 7, /**< More than \ref HID_MAX_REPORT_IDS report IDs in the device. */
|
||||
HID_PARSE_NoUnfilteredReportItems = 8, /**< All report items from the device were filtered by the filtering callback routine. */
|
||||
};
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief HID Parser Report Item Min/Max Structure.
|
||||
*
|
||||
* Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Minimum; /**< Minimum value for the attribute. */
|
||||
uint32_t Maximum; /**< Maximum value for the attribute. */
|
||||
} HID_MinMax_t;
|
||||
|
||||
/** \brief HID Parser Report Item Unit Structure.
|
||||
*
|
||||
* Type define for the Unit attributes of a report item.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Type; /**< Unit type (refer to HID specifications for details). */
|
||||
uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */
|
||||
} HID_Unit_t;
|
||||
|
||||
/** \brief HID Parser Report Item Usage Structure.
|
||||
*
|
||||
* Type define for the Usage attributes of a report item.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t Page; /**< Usage page of the report item. */
|
||||
uint16_t Usage; /**< Usage of the report item. */
|
||||
} HID_Usage_t;
|
||||
|
||||
/** \brief HID Parser Report Item Collection Path Structure.
|
||||
*
|
||||
* Type define for a COLLECTION object. Contains the collection attributes and a reference to the
|
||||
* parent collection if any.
|
||||
*/
|
||||
typedef struct CollectionPath
|
||||
{
|
||||
uint8_t Type; /**< Collection type (e.g. "Generic Desktop"). */
|
||||
HID_Usage_t Usage; /**< Collection usage. */
|
||||
struct CollectionPath* Parent; /**< Reference to parent collection, or NULL if root collection. */
|
||||
} HID_CollectionPath_t;
|
||||
|
||||
/** \brief HID Parser Report Item Attributes Structure.
|
||||
*
|
||||
* Type define for all the data attributes of a report item, except flags.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BitSize; /**< Size in bits of the report item's data. */
|
||||
|
||||
HID_Usage_t Usage; /**< Usage of the report item. */
|
||||
HID_Unit_t Unit; /**< Unit type and exponent of the report item. */
|
||||
HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */
|
||||
HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */
|
||||
} HID_ReportItem_Attributes_t;
|
||||
|
||||
/** \brief HID Parser Report Item Details Structure.
|
||||
*
|
||||
* Type define for a report item (IN, OUT or FEATURE) layout attributes and other details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */
|
||||
uint8_t ItemType; /**< Report item type, a value in HID_ReportItemTypes_t. */
|
||||
uint16_t ItemFlags; /**< Item data flags, such as constant/variable, etc. */
|
||||
uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */
|
||||
HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */
|
||||
|
||||
HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */
|
||||
|
||||
uint32_t Value; /**< Current value of the report item - use \ref HID_ALIGN_DATA() when processing
|
||||
* a retrieved value so that it is aligned to a specific type.
|
||||
*/
|
||||
uint32_t PreviousValue; /**< Previous value of the report item. */
|
||||
} HID_ReportItem_t;
|
||||
|
||||
/** \brief HID Parser Report Size Structure.
|
||||
*
|
||||
* Type define for a report item size information structure, to retain the size of a device's reports by ID.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t ReportID; /** Report ID of the report within the HID interface */
|
||||
uint16_t ReportSizeBits[3]; /** Total number of bits in each report type for the given Report ID,
|
||||
* indexed by the \ref HID_ReportItemTypes_t enum
|
||||
*/
|
||||
} HID_ReportSizeInfo_t;
|
||||
|
||||
/** \brief HID Parser State Structure.
|
||||
*
|
||||
* Type define for a complete processed HID report, including all report item data and collections.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t TotalReportItems; /**< Total number of report items stored in the
|
||||
* ReportItems array.
|
||||
*/
|
||||
HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including
|
||||
* all IN, OUT and FEATURE items.
|
||||
*/
|
||||
HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced
|
||||
* by the report items.
|
||||
*/
|
||||
uint8_t TotalDeviceReports; /**< Number of reports within the HID interface */
|
||||
HID_ReportSizeInfo_t ReportIDSizes[HID_MAX_REPORT_IDS]; /**< Report sizes for each report in the interface */
|
||||
uint16_t LargestReportSizeBits; /**< Largest report that the attached device will generate, in bits */
|
||||
bool UsingReportIDs; /**< Indicates if the device has at least one REPORT ID
|
||||
* element in its HID report descriptor.
|
||||
*/
|
||||
} HID_ReportInfo_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Function to process a given HID report returned from an attached device, and store it into a given
|
||||
* \ref HID_ReportInfo_t structure.
|
||||
*
|
||||
* \param[in] ReportData Buffer containing the device's HID report table
|
||||
* \param[in] ReportSize Size in bytes of the HID report table
|
||||
* \param[out] ParserData Pointer to a \ref HID_ReportInfo_t instance for the parser output
|
||||
*
|
||||
* \return A value in the \ref HID_Parse_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Extracts the given report item's value out of the given HID report and places it into the Value
|
||||
* member of the report item's \ref HID_ReportItem_t structure.
|
||||
*
|
||||
* When called, this copies the report item's Value element to it's PreviousValue element for easy
|
||||
* checking to see if an item's value has changed before processing a report.
|
||||
*
|
||||
* \param[in] ReportData Buffer containing an IN or FEATURE report from an attached device
|
||||
* \param[in,out] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array
|
||||
*
|
||||
* \returns Boolean true if the item to retrieve was located in the given report, false otherwise
|
||||
*/
|
||||
bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the given report item's value out of the Value member of the report item's
|
||||
* \ref HID_ReportItem_t structure and places it into the correct position in the HID report
|
||||
* buffer. The report buffer is assumed to have the appropriate bits cleared before calling
|
||||
* this function (i.e., the buffer should be explicitly cleared before report values are added).
|
||||
*
|
||||
* When called, this copies the report item's Value element to it's PreviousValue element for easy
|
||||
* checking to see if an item's value has changed before sending a report.
|
||||
*
|
||||
* If the device has multiple HID reports, the first byte in the report is set to the report ID of the given item.
|
||||
*
|
||||
* \param[out] ReportData Buffer holding the current OUT or FEATURE report data
|
||||
* \param[in] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array
|
||||
*/
|
||||
void USB_SetHIDReportItemInfo(uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the size of a given HID report in bytes from it's Report ID.
|
||||
*
|
||||
* \param[in] ParserData Pointer to a \ref HID_ReportInfo_t instance containing the parser output
|
||||
* \param[in] ReportID Report ID of the report whose size is to be retrieved
|
||||
* \param[in] ReportType Type of the report whose size is to be determined, a valued from the
|
||||
* \ref HID_ReportItemTypes_t enum
|
||||
*
|
||||
* \return Size of the report in bytes, or 0 if the report does not exist
|
||||
*/
|
||||
uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData, const uint8_t ReportID,
|
||||
const uint8_t ReportType) ATTR_CONST ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Callback routine for the HID Report Parser. This callback <b>must</b> be implemented by the user code when
|
||||
* the parser is used, to determine what report IN, OUT and FEATURE item's information is stored into the user
|
||||
* HID_ReportInfo_t structure. This can be used to filter only those items the application will be using, so that
|
||||
* no RAM is wasted storing the attributes for report items which will never be referenced by the application.
|
||||
*
|
||||
* \param[in] CurrentItem Pointer to the current report item for user checking
|
||||
*
|
||||
* \return Boolean true if the item should be stored into the HID_ReportInfo_t structure, false if it should be ignored
|
||||
*/
|
||||
bool CALLBACK_HIDParser_FilterHIDReportItem(HID_ReportItem_t* CurrentItem);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Type Defines: */
|
||||
typedef struct
|
||||
{
|
||||
HID_ReportItem_Attributes_t Attributes;
|
||||
uint8_t ReportCount;
|
||||
uint8_t ReportID;
|
||||
} HID_StateTable_t;
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief USB Human Interface Device (HID) Class report descriptor parser.
|
||||
*
|
||||
* This file allows for the easy parsing of complex HID report descriptors, which describes the data that
|
||||
* a HID device transmits to the host. It also provides an easy API for extracting and processing the data
|
||||
* elements inside a HID report sent from an attached HID device.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USB
|
||||
* @defgroup Group_HIDParser HID Report Parser
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/HIDParser.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Functions, macros, variables, enums and types related to the parsing of HID class device report descriptors.
|
||||
*
|
||||
* The processed HID report is presented back to the user application as a flat structure containing each report
|
||||
* item's IN, OUT and FEATURE items along with each item's attributes.
|
||||
*
|
||||
* This library portion also allows for easy setting and retrieval of data from a HID report, including devices
|
||||
* with multiple reports on the one HID interface.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HIDPARSER_H__
|
||||
#define __HIDPARSER_H__
|
||||
|
||||
/* Macros: */
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#define __INCLUDE_FROM_HID_DRIVER
|
||||
|
||||
/* Includes: */
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "HIDReportData.h"
|
||||
#include "../Common/HID.h"
|
||||
|
||||
#include "../../../../Common/Common.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macros: */
|
||||
#if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum stack depth of the state table. A larger state table
|
||||
* allows for more PUSH/POP report items to be nested, but consumes more memory. By default
|
||||
* this is set to 2 levels (allowing non-nested PUSH items) but this can be overridden by
|
||||
* defining HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the
|
||||
* define to the compiler using the -D compiler switch.
|
||||
*/
|
||||
#define HID_STATETABLE_STACK_DEPTH 2
|
||||
#endif
|
||||
|
||||
#if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum stack depth of the usage table. A larger usage table
|
||||
* allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than
|
||||
* one, but requires more stack space. By default this is set to 8 levels (allowing for a report
|
||||
* item with a count of 8) but this can be overridden by defining HID_USAGE_STACK_DEPTH to another
|
||||
* value in the user project makefile, passing the define to the compiler using the -D compiler
|
||||
* switch.
|
||||
*/
|
||||
#define HID_USAGE_STACK_DEPTH 8
|
||||
#endif
|
||||
|
||||
#if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be
|
||||
* processed in the report item descriptor. A large value allows for more COLLECTION items to be
|
||||
* processed, but consumes more memory. By default this is set to 5 collections, but this can be
|
||||
* overridden by defining HID_MAX_COLLECTIONS to another value in the user project makefile, passing
|
||||
* the define to the compiler using the -D compiler switch.
|
||||
*/
|
||||
#define HID_MAX_COLLECTIONS 10
|
||||
#endif
|
||||
|
||||
#if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum number of report items (IN, OUT or FEATURE) that can be processed
|
||||
* in the report item descriptor and stored in the user HID Report Info structure. A large value allows
|
||||
* for more report items to be stored, but consumes more memory. By default this is set to 20 items,
|
||||
* but this can be overridden by defining HID_MAX_REPORTITEMS to another value in the user project
|
||||
* makefile, and passing the define to the compiler using the -D compiler switch.
|
||||
*/
|
||||
#define HID_MAX_REPORTITEMS 20
|
||||
#endif
|
||||
|
||||
#if !defined(HID_MAX_REPORT_IDS) || defined(__DOXYGEN__)
|
||||
/** Constant indicating the maximum number of unique report IDs that can be processed in the report item
|
||||
* descriptor for the report size information array in the user HID Report Info structure. A large value
|
||||
* allows for more report ID report sizes to be stored, but consumes more memory. By default this is set
|
||||
* to 5 items, but this can be overridden by defining HID_MAX_REPORT_IDS to another value in the user project
|
||||
* makefile, and passing the define to the compiler using the -D compiler switch. Note that IN, OUT and FEATURE
|
||||
* items sharing the same report ID consume only one size item in the array.
|
||||
*/
|
||||
#define HID_MAX_REPORT_IDS 10
|
||||
#endif
|
||||
|
||||
/** Returns the value a given HID report item (once its value has been fetched via \ref USB_GetHIDReportItemInfo())
|
||||
* left-aligned to the given data type. This allows for signed data to be interpreted correctly, by shifting the data
|
||||
* leftwards until the data's sign bit is in the correct position.
|
||||
*
|
||||
* \param[in] reportitem HID Report Item whose retrieved value is to be aligned
|
||||
* \param[in] type Data type to align the HID report item's value to
|
||||
*
|
||||
* \return Left-aligned data of the given report item's pre-retrived value for the given datatype
|
||||
*/
|
||||
#define HID_ALIGN_DATA(reportitem, type) ((type)(reportitem->Value << ((8 * sizeof(type)) - reportitem->Attributes.BitSize)))
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes in the return value of the \ref USB_ProcessHIDReport() function */
|
||||
enum HID_Parse_ErrorCodes_t
|
||||
{
|
||||
HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */
|
||||
HID_PARSE_HIDStackOverflow = 1, /**< More than \ref HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */
|
||||
HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */
|
||||
HID_PARSE_InsufficientReportItems = 3, /**< More than \ref HID_MAX_REPORTITEMS report items in the report. */
|
||||
HID_PARSE_UnexpectedEndCollection = 4, /**< An END COLLECTION item found without matching COLLECTION item. */
|
||||
HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */
|
||||
HID_PARSE_UsageListOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */
|
||||
HID_PARSE_InsufficientReportIDItems = 7, /**< More than \ref HID_MAX_REPORT_IDS report IDs in the device. */
|
||||
HID_PARSE_NoUnfilteredReportItems = 8, /**< All report items from the device were filtered by the filtering callback routine. */
|
||||
};
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief HID Parser Report Item Min/Max Structure.
|
||||
*
|
||||
* Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Minimum; /**< Minimum value for the attribute. */
|
||||
uint32_t Maximum; /**< Maximum value for the attribute. */
|
||||
} HID_MinMax_t;
|
||||
|
||||
/** \brief HID Parser Report Item Unit Structure.
|
||||
*
|
||||
* Type define for the Unit attributes of a report item.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Type; /**< Unit type (refer to HID specifications for details). */
|
||||
uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */
|
||||
} HID_Unit_t;
|
||||
|
||||
/** \brief HID Parser Report Item Usage Structure.
|
||||
*
|
||||
* Type define for the Usage attributes of a report item.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t Page; /**< Usage page of the report item. */
|
||||
uint16_t Usage; /**< Usage of the report item. */
|
||||
} HID_Usage_t;
|
||||
|
||||
/** \brief HID Parser Report Item Collection Path Structure.
|
||||
*
|
||||
* Type define for a COLLECTION object. Contains the collection attributes and a reference to the
|
||||
* parent collection if any.
|
||||
*/
|
||||
typedef struct CollectionPath
|
||||
{
|
||||
uint8_t Type; /**< Collection type (e.g. "Generic Desktop"). */
|
||||
HID_Usage_t Usage; /**< Collection usage. */
|
||||
struct CollectionPath* Parent; /**< Reference to parent collection, or NULL if root collection. */
|
||||
} HID_CollectionPath_t;
|
||||
|
||||
/** \brief HID Parser Report Item Attributes Structure.
|
||||
*
|
||||
* Type define for all the data attributes of a report item, except flags.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t BitSize; /**< Size in bits of the report item's data. */
|
||||
|
||||
HID_Usage_t Usage; /**< Usage of the report item. */
|
||||
HID_Unit_t Unit; /**< Unit type and exponent of the report item. */
|
||||
HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */
|
||||
HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */
|
||||
} HID_ReportItem_Attributes_t;
|
||||
|
||||
/** \brief HID Parser Report Item Details Structure.
|
||||
*
|
||||
* Type define for a report item (IN, OUT or FEATURE) layout attributes and other details.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */
|
||||
uint8_t ItemType; /**< Report item type, a value in HID_ReportItemTypes_t. */
|
||||
uint16_t ItemFlags; /**< Item data flags, such as constant/variable, etc. */
|
||||
uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */
|
||||
HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */
|
||||
|
||||
HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */
|
||||
|
||||
uint32_t Value; /**< Current value of the report item - use \ref HID_ALIGN_DATA() when processing
|
||||
* a retrieved value so that it is aligned to a specific type.
|
||||
*/
|
||||
uint32_t PreviousValue; /**< Previous value of the report item. */
|
||||
} HID_ReportItem_t;
|
||||
|
||||
/** \brief HID Parser Report Size Structure.
|
||||
*
|
||||
* Type define for a report item size information structure, to retain the size of a device's reports by ID.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t ReportID; /** Report ID of the report within the HID interface */
|
||||
uint16_t ReportSizeBits[3]; /** Total number of bits in each report type for the given Report ID,
|
||||
* indexed by the \ref HID_ReportItemTypes_t enum
|
||||
*/
|
||||
} HID_ReportSizeInfo_t;
|
||||
|
||||
/** \brief HID Parser State Structure.
|
||||
*
|
||||
* Type define for a complete processed HID report, including all report item data and collections.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t TotalReportItems; /**< Total number of report items stored in the
|
||||
* ReportItems array.
|
||||
*/
|
||||
HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including
|
||||
* all IN, OUT and FEATURE items.
|
||||
*/
|
||||
HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced
|
||||
* by the report items.
|
||||
*/
|
||||
uint8_t TotalDeviceReports; /**< Number of reports within the HID interface */
|
||||
HID_ReportSizeInfo_t ReportIDSizes[HID_MAX_REPORT_IDS]; /**< Report sizes for each report in the interface */
|
||||
uint16_t LargestReportSizeBits; /**< Largest report that the attached device will generate, in bits */
|
||||
bool UsingReportIDs; /**< Indicates if the device has at least one REPORT ID
|
||||
* element in its HID report descriptor.
|
||||
*/
|
||||
} HID_ReportInfo_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Function to process a given HID report returned from an attached device, and store it into a given
|
||||
* \ref HID_ReportInfo_t structure.
|
||||
*
|
||||
* \param[in] ReportData Buffer containing the device's HID report table
|
||||
* \param[in] ReportSize Size in bytes of the HID report table
|
||||
* \param[out] ParserData Pointer to a \ref HID_ReportInfo_t instance for the parser output
|
||||
*
|
||||
* \return A value in the \ref HID_Parse_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t USB_ProcessHIDReport(const uint8_t* ReportData, uint16_t ReportSize, HID_ReportInfo_t* const ParserData)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Extracts the given report item's value out of the given HID report and places it into the Value
|
||||
* member of the report item's \ref HID_ReportItem_t structure.
|
||||
*
|
||||
* When called, this copies the report item's Value element to it's PreviousValue element for easy
|
||||
* checking to see if an item's value has changed before processing a report.
|
||||
*
|
||||
* \param[in] ReportData Buffer containing an IN or FEATURE report from an attached device
|
||||
* \param[in,out] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array
|
||||
*
|
||||
* \returns Boolean true if the item to retrieve was located in the given report, false otherwise
|
||||
*/
|
||||
bool USB_GetHIDReportItemInfo(const uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the given report item's value out of the Value member of the report item's
|
||||
* \ref HID_ReportItem_t structure and places it into the correct position in the HID report
|
||||
* buffer. The report buffer is assumed to have the appropriate bits cleared before calling
|
||||
* this function (i.e., the buffer should be explicitly cleared before report values are added).
|
||||
*
|
||||
* When called, this copies the report item's Value element to it's PreviousValue element for easy
|
||||
* checking to see if an item's value has changed before sending a report.
|
||||
*
|
||||
* If the device has multiple HID reports, the first byte in the report is set to the report ID of the given item.
|
||||
*
|
||||
* \param[out] ReportData Buffer holding the current OUT or FEATURE report data
|
||||
* \param[in] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array
|
||||
*/
|
||||
void USB_SetHIDReportItemInfo(uint8_t* ReportData, HID_ReportItem_t* const ReportItem)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the size of a given HID report in bytes from it's Report ID.
|
||||
*
|
||||
* \param[in] ParserData Pointer to a \ref HID_ReportInfo_t instance containing the parser output
|
||||
* \param[in] ReportID Report ID of the report whose size is to be retrieved
|
||||
* \param[in] ReportType Type of the report whose size is to be determined, a valued from the
|
||||
* \ref HID_ReportItemTypes_t enum
|
||||
*
|
||||
* \return Size of the report in bytes, or 0 if the report does not exist
|
||||
*/
|
||||
uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData, const uint8_t ReportID,
|
||||
const uint8_t ReportType) ATTR_CONST ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Callback routine for the HID Report Parser. This callback <b>must</b> be implemented by the user code when
|
||||
* the parser is used, to determine what report IN, OUT and FEATURE item's information is stored into the user
|
||||
* HID_ReportInfo_t structure. This can be used to filter only those items the application will be using, so that
|
||||
* no RAM is wasted storing the attributes for report items which will never be referenced by the application.
|
||||
*
|
||||
* \param[in] CurrentItem Pointer to the current report item for user checking
|
||||
*
|
||||
* \return Boolean true if the item should be stored into the HID_ReportInfo_t structure, false if it should be ignored
|
||||
*/
|
||||
bool CALLBACK_HIDParser_FilterHIDReportItem(HID_ReportItem_t* CurrentItem);
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Type Defines: */
|
||||
typedef struct
|
||||
{
|
||||
HID_ReportItem_Attributes_t Attributes;
|
||||
uint8_t ReportCount;
|
||||
uint8_t ReportID;
|
||||
} HID_StateTable_t;
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,141 +1,141 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Constants for HID report item attributes.
|
||||
*
|
||||
* HID report item constants for report item attributes. Refer to the HID specification for
|
||||
* details on each flag's meaning when applied to an IN, OUT or FEATURE item.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_HIDParser
|
||||
* @defgroup Group_HIDIOFConst Input/Output/Feature Masks
|
||||
*
|
||||
* Masks indicating the type of Input, Output of Feature HID report item.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HIDREPORTDATA_H__
|
||||
#define __HIDREPORTDATA_H__
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** HID_ReportItem_t.ItemFlags flag for constant data. */
|
||||
#define IOF_CONSTANT (1 << 0)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for data. */
|
||||
#define IOF_DATA (0 << 0)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for variable data. */
|
||||
#define IOF_VARIABLE (1 << 1)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for array data. */
|
||||
#define IOF_ARRAY (0 << 1)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for relative data. */
|
||||
#define IOF_RELATIVE (1 << 2)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for absolute data. */
|
||||
#define IOF_ABSOLUTE (0 << 2)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for wrapped value data. */
|
||||
#define IOF_WRAP (1 << 3)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for non-wrapped value data. */
|
||||
#define IOF_NOWRAP (0 << 3)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for non linear data. */
|
||||
#define IOF_NONLINEAR (1 << 4)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for linear data. */
|
||||
#define IOF_LINEAR (0 << 4)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for no preferred state. */
|
||||
#define IOF_NOPREFERRED (1 << 5)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for preferred state items. */
|
||||
#define IOF_PREFERREDSTATE (0 << 5)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for null state items. */
|
||||
#define IOF_NULLSTATE (1 << 6)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for no null position data. */
|
||||
#define IOF_NONULLPOSITION (0 << 6)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for buffered bytes. */
|
||||
#define IOF_BUFFEREDBYTES (1 << 8)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for bit field data. */
|
||||
#define IOF_BITFIELD (0 << 8)
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define DATA_SIZE_MASK 0x03
|
||||
#define TYPE_MASK 0x0C
|
||||
#define TAG_MASK 0xF0
|
||||
|
||||
#define DATA_SIZE_0 0x00
|
||||
#define DATA_SIZE_1 0x01
|
||||
#define DATA_SIZE_2 0x02
|
||||
#define DATA_SIZE_4 0x03
|
||||
|
||||
#define TYPE_MAIN 0x00
|
||||
#define TYPE_GLOBAL 0x04
|
||||
#define TYPE_LOCAL 0x08
|
||||
|
||||
#define TAG_MAIN_INPUT 0x80
|
||||
#define TAG_MAIN_OUTPUT 0x90
|
||||
#define TAG_MAIN_COLLECTION 0xA0
|
||||
#define TAG_MAIN_FEATURE 0xB0
|
||||
#define TAG_MAIN_ENDCOLLECTION 0xC0
|
||||
|
||||
#define TAG_GLOBAL_USAGEPAGE 0x00
|
||||
#define TAG_GLOBAL_LOGICALMIN 0x10
|
||||
#define TAG_GLOBAL_LOGICALMAX 0x20
|
||||
#define TAG_GLOBAL_PHYSMIN 0x30
|
||||
#define TAG_GLOBAL_PHYSMAX 0x40
|
||||
#define TAG_GLOBAL_UNITEXP 0x50
|
||||
#define TAG_GLOBAL_UNIT 0x60
|
||||
#define TAG_GLOBAL_REPORTSIZE 0x70
|
||||
#define TAG_GLOBAL_REPORTID 0x80
|
||||
#define TAG_GLOBAL_REPORTCOUNT 0x90
|
||||
#define TAG_GLOBAL_PUSH 0xA0
|
||||
#define TAG_GLOBAL_POP 0xB0
|
||||
|
||||
#define TAG_LOCAL_USAGE 0x00
|
||||
#define TAG_LOCAL_USAGEMIN 0x10
|
||||
#define TAG_LOCAL_USAGEMAX 0x20
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Constants for HID report item attributes.
|
||||
*
|
||||
* HID report item constants for report item attributes. Refer to the HID specification for
|
||||
* details on each flag's meaning when applied to an IN, OUT or FEATURE item.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_HIDParser
|
||||
* @defgroup Group_HIDIOFConst Input/Output/Feature Masks
|
||||
*
|
||||
* Masks indicating the type of Input, Output of Feature HID report item.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __HIDREPORTDATA_H__
|
||||
#define __HIDREPORTDATA_H__
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** HID_ReportItem_t.ItemFlags flag for constant data. */
|
||||
#define IOF_CONSTANT (1 << 0)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for data. */
|
||||
#define IOF_DATA (0 << 0)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for variable data. */
|
||||
#define IOF_VARIABLE (1 << 1)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for array data. */
|
||||
#define IOF_ARRAY (0 << 1)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for relative data. */
|
||||
#define IOF_RELATIVE (1 << 2)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for absolute data. */
|
||||
#define IOF_ABSOLUTE (0 << 2)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for wrapped value data. */
|
||||
#define IOF_WRAP (1 << 3)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for non-wrapped value data. */
|
||||
#define IOF_NOWRAP (0 << 3)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for non linear data. */
|
||||
#define IOF_NONLINEAR (1 << 4)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for linear data. */
|
||||
#define IOF_LINEAR (0 << 4)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for no preferred state. */
|
||||
#define IOF_NOPREFERRED (1 << 5)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for preferred state items. */
|
||||
#define IOF_PREFERREDSTATE (0 << 5)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for null state items. */
|
||||
#define IOF_NULLSTATE (1 << 6)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for no null position data. */
|
||||
#define IOF_NONULLPOSITION (0 << 6)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for buffered bytes. */
|
||||
#define IOF_BUFFEREDBYTES (1 << 8)
|
||||
|
||||
/** HID_ReportItem_t.ItemFlags flag for bit field data. */
|
||||
#define IOF_BITFIELD (0 << 8)
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define DATA_SIZE_MASK 0x03
|
||||
#define TYPE_MASK 0x0C
|
||||
#define TAG_MASK 0xF0
|
||||
|
||||
#define DATA_SIZE_0 0x00
|
||||
#define DATA_SIZE_1 0x01
|
||||
#define DATA_SIZE_2 0x02
|
||||
#define DATA_SIZE_4 0x03
|
||||
|
||||
#define TYPE_MAIN 0x00
|
||||
#define TYPE_GLOBAL 0x04
|
||||
#define TYPE_LOCAL 0x08
|
||||
|
||||
#define TAG_MAIN_INPUT 0x80
|
||||
#define TAG_MAIN_OUTPUT 0x90
|
||||
#define TAG_MAIN_COLLECTION 0xA0
|
||||
#define TAG_MAIN_FEATURE 0xB0
|
||||
#define TAG_MAIN_ENDCOLLECTION 0xC0
|
||||
|
||||
#define TAG_GLOBAL_USAGEPAGE 0x00
|
||||
#define TAG_GLOBAL_LOGICALMIN 0x10
|
||||
#define TAG_GLOBAL_LOGICALMAX 0x20
|
||||
#define TAG_GLOBAL_PHYSMIN 0x30
|
||||
#define TAG_GLOBAL_PHYSMAX 0x40
|
||||
#define TAG_GLOBAL_UNITEXP 0x50
|
||||
#define TAG_GLOBAL_UNIT 0x60
|
||||
#define TAG_GLOBAL_REPORTSIZE 0x70
|
||||
#define TAG_GLOBAL_REPORTID 0x80
|
||||
#define TAG_GLOBAL_REPORTCOUNT 0x90
|
||||
#define TAG_GLOBAL_PUSH 0xA0
|
||||
#define TAG_GLOBAL_POP 0xB0
|
||||
|
||||
#define TAG_LOCAL_USAGE 0x00
|
||||
#define TAG_LOCAL_USAGEMIN 0x10
|
||||
#define TAG_LOCAL_USAGEMAX 0x20
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,186 +1,186 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_MIDI_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_MIDI_DRIVER
|
||||
#include "MIDI.h"
|
||||
|
||||
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return MIDI_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return MIDI_ENUMERROR_NoStreamingInterfaceFound;
|
||||
}
|
||||
|
||||
while (FoundEndpoints != (MIDI_FOUND_DATAPIPE_IN | MIDI_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return MIDI_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
MIDIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= MIDI_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
MIDIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= MIDI_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
MIDIInterfaceInfo->State.IsActive = true;
|
||||
return MIDI_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == MIDI_STREAMING_CLASS) &&
|
||||
(CurrentInterface->SubClass == MIDI_STREAMING_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == MIDI_STREAMING_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if ((EndpointType == EP_TYPE_BULK) && !(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
if (USB_HostState != HOST_STATE_Configured)
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
|
||||
if (Pipe_BytesInPipe())
|
||||
{
|
||||
Pipe_ClearOUT();
|
||||
|
||||
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return PIPE_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
|
||||
if (Pipe_IsReadWriteAllowed())
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
Pipe_ClearOUT();
|
||||
}
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipeNumber);
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
return false;
|
||||
|
||||
Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
Pipe_ClearIN();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_MIDI_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_MIDI_DRIVER
|
||||
#include "MIDI.h"
|
||||
|
||||
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return MIDI_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return MIDI_ENUMERROR_NoStreamingInterfaceFound;
|
||||
}
|
||||
|
||||
while (FoundEndpoints != (MIDI_FOUND_DATAPIPE_IN | MIDI_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return MIDI_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
MIDIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= MIDI_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
MIDIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
MIDIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= MIDI_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
MIDIInterfaceInfo->State.IsActive = true;
|
||||
return MIDI_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == MIDI_STREAMING_CLASS) &&
|
||||
(CurrentInterface->SubClass == MIDI_STREAMING_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == MIDI_STREAMING_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if ((EndpointType == EP_TYPE_BULK) && !(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
if (USB_HostState != HOST_STATE_Configured)
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
|
||||
if (Pipe_BytesInPipe())
|
||||
{
|
||||
Pipe_ClearOUT();
|
||||
|
||||
if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return PIPE_READYWAIT_NoError;
|
||||
}
|
||||
|
||||
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
|
||||
if (Pipe_IsReadWriteAllowed())
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
Pipe_ClearOUT();
|
||||
}
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, MIDI_EventPacket_t* const Event)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipeNumber);
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
return false;
|
||||
|
||||
Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NO_STREAM_CALLBACK);
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
Pipe_ClearIN();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,204 +1,204 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MIDI.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMIDI
|
||||
* @defgroup Group_USBClassMIDIHost MIDI Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/MIDI.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the MIDI USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __MIDI_CLASS_HOST_H__
|
||||
#define __MIDI_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MIDI.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MIDI_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MIDI.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief MIDI Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the MIDI class driver functions as the MIDIInterfaceInfo parameter. This
|
||||
* stores each MIDI interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the MIDI interface's streaming IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the MIDI interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the MIDI interface's streaming OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the MIDI interface's OUT data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's OUT data pipe */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MIDI_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref MIDI_Host_ConfigurePipes() function. */
|
||||
enum MIDIHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
MIDI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
MIDI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
MIDI_ENUMERROR_NoStreamingInterfaceFound = 2, /**< A compatible MIDI interface was not found in the device's Configuration Descriptor */
|
||||
MIDI_ENUMERROR_EndpointsNotFound = 3, /**< Compatible MIDI data endpoints were not found in the device's MIDI interface */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given MIDI host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given MIDI Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the device.
|
||||
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
|
||||
* the Addressed state.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref MIDIHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a MIDI event packet to the device. If no device is connected, the event packet is discarded.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[in] Event Pointer to a populated USB_MIDI_EventPacket_t structure containing the MIDI event to send
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Flushes the MIDI send buffer, sending any queued MIDI events to the device. This should be called to override the
|
||||
* \ref MIDI_Host_SendEventPacket() function's packing behaviour, to flush queued events. Events are queued into the
|
||||
* pipe bank until either the pipe bank is full, or \ref MIDI_Host_Flush() is called. This allows for multiple MIDI
|
||||
* events to be packed into a single pipe packet, increasing data throughput.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo);
|
||||
|
||||
/** Receives a MIDI event packet from the device.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[out] Event Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed
|
||||
*
|
||||
* \return Boolean true if a MIDI event packet was received, false otherwise
|
||||
*/
|
||||
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given MIDI host class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state
|
||||
*/
|
||||
static inline void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo);
|
||||
static inline void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
(void)MIDIInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define MIDI_STREAMING_CLASS 0x01
|
||||
#define MIDI_STREAMING_SUBCLASS 0x03
|
||||
#define MIDI_STREAMING_PROTOCOL 0x00
|
||||
|
||||
#define MIDI_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define MIDI_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_MIDI_CLASS_HOST_C)
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB MIDI Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MIDI.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMIDI
|
||||
* @defgroup Group_USBClassMIDIHost MIDI Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/MIDI.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the MIDI USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __MIDI_CLASS_HOST_H__
|
||||
#define __MIDI_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MIDI.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MIDI_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MIDI.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief MIDI Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the MIDI class driver functions as the MIDIInterfaceInfo parameter. This
|
||||
* stores each MIDI interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the MIDI interface's streaming IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the MIDI interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the MIDI interface's streaming OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the MIDI interface's OUT data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the MIDI Streaming Data interface's OUT data pipe */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MIDI_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref MIDI_Host_ConfigurePipes() function. */
|
||||
enum MIDIHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
MIDI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
MIDI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
MIDI_ENUMERROR_NoStreamingInterfaceFound = 2, /**< A compatible MIDI interface was not found in the device's Configuration Descriptor */
|
||||
MIDI_ENUMERROR_EndpointsNotFound = 3, /**< Compatible MIDI data endpoints were not found in the device's MIDI interface */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given MIDI host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given MIDI Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the device.
|
||||
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
|
||||
* the Addressed state.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref MIDIHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a MIDI event packet to the device. If no device is connected, the event packet is discarded.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[in] Event Pointer to a populated USB_MIDI_EventPacket_t structure containing the MIDI event to send
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Flushes the MIDI send buffer, sending any queued MIDI events to the device. This should be called to override the
|
||||
* \ref MIDI_Host_SendEventPacket() function's packing behaviour, to flush queued events. Events are queued into the
|
||||
* pipe bank until either the pipe bank is full, or \ref MIDI_Host_Flush() is called. This allows for multiple MIDI
|
||||
* events to be packed into a single pipe packet, increasing data throughput.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo);
|
||||
|
||||
/** Receives a MIDI event packet from the device.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state
|
||||
* \param[out] Event Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed
|
||||
*
|
||||
* \return Boolean true if a MIDI event packet was received, false otherwise
|
||||
*/
|
||||
bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
|
||||
MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given MIDI host class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state
|
||||
*/
|
||||
static inline void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo);
|
||||
static inline void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
|
||||
{
|
||||
(void)MIDIInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define MIDI_STREAMING_CLASS 0x01
|
||||
#define MIDI_STREAMING_SUBCLASS 0x03
|
||||
#define MIDI_STREAMING_PROTOCOL 0x00
|
||||
|
||||
#define MIDI_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define MIDI_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_MIDI_CLASS_HOST_C)
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,339 +1,339 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MassStorage.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMS
|
||||
* @defgroup Group_USBClassMassStorageHost Mass Storage Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/MassStorage.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Mass Storage USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __MS_CLASS_HOST_H__
|
||||
#define __MS_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MassStorage.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MassStorage.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Error code for some Mass Storage Host functions, indicating a logical (and not hardware) error */
|
||||
#define MS_ERROR_LOGICAL_CMD_FAILED 0x80
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief Mass Storage Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the Mass Storage class driver functions as the MSInterfaceInfo parameter. This
|
||||
* stores each Mass Storage interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the Mass Storage interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the Mass Storage interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the Mass Storage interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the Mass Storage interface's OUT data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref MS_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t InterfaceNumber; /**< Interface index of the Mass Storage interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the Mass Storage interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the Mass Storage interface's OUT data pipe */
|
||||
|
||||
uint32_t TransactionTag; /**< Current transaction tag for data synchronizing of packets */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MS_Host_t;
|
||||
|
||||
/** \brief SCSI Device LUN Capacity Structure.
|
||||
*
|
||||
* SCSI capacity structure, to hold the total capacity of the device in both the number
|
||||
* of blocks in the current LUN, and the size of each block. This structure is filled by
|
||||
* the device when the MassStore_ReadCapacity() function is called.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device */
|
||||
uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN */
|
||||
} SCSI_Capacity_t;
|
||||
|
||||
/* Enums: */
|
||||
enum MSHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
MS_ENUMERROR_NoMSInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor */
|
||||
MS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Mass Storage endpoints were not found in the device's interfaces */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given Mass Storage host interface instance using the
|
||||
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Mass
|
||||
* Storage Host instance's state values and configures the pipes required to communicate with the interface if it
|
||||
* is found within the device. This should be called once after the stack has enumerated the attached device, while
|
||||
* the host state machine is in the Addressed state.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref MSHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a MASS STORAGE RESET control request to the attached device, resetting the Mass Storage Interface
|
||||
* and readying it for the next Mass Storage command.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a GET MAX LUN control request to the attached device, retrieving the index of the highest LUN (Logical
|
||||
* UNit, a logical drive) in the device. This value can then be used in the other functions of the Mass Storage
|
||||
* Host mode Class driver to address a specific LUN within the device.
|
||||
*
|
||||
* \note Some devices do not support this request, and will STALL it when issued. To get around this,
|
||||
* on unsupported devices the max LUN index will be reported as zero and no error will be returned
|
||||
* if the device STALLs the request.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[out] MaxLUNIndex Pointer to a location where the highest LUN index value should be stored
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, uint8_t* const MaxLUNIndex)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the Mass Storage device's inquiry data for the specified LUN, indicating the device characteristics and
|
||||
* properties.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[out] InquiryData Location where the read inquiry data should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED
|
||||
*/
|
||||
uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
SCSI_Inquiry_Response_t* const InquiryData) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a TEST UNIT READY command to the device, to determine if it is ready to accept other SCSI commands.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex)
|
||||
ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Retrieves the total capacity of the attached USB Mass Storage device, in blocks, and block size.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[out] DeviceCapacity Pointer to the location where the capacity information should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
SCSI_Capacity_t* const DeviceCapacity) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Retrieves the device sense data, indicating the current device state and error codes for the previously
|
||||
* issued command.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[out] SenseData Pointer to the location where the sense information should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
SCSI_Request_Sense_Response_t* const SenseData) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Issues a PREVENT MEDIUM REMOVAL command, to logically (or, depending on the type of device, physically) lock
|
||||
* the device from removal so that blocks of data on the medium can be read or altered.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[in] PreventRemoval Boolean true if the device should be locked from removal, false otherwise
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
const bool PreventRemoval) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Reads blocks of data from the attached Mass Storage device's medium.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[in] BlockAddress Starting block address within the device to read from
|
||||
* \param[in] Blocks Total number of blocks to read
|
||||
* \param[in] BlockSize Size in bytes of each block within the device
|
||||
* \param[out] BlockBuffer Pointer to where the read data from the device should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
const uint32_t BlockAddress, const uint8_t Blocks, const uint16_t BlockSize,
|
||||
void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
|
||||
|
||||
/** Writes blocks of data to the attached Mass Storage device's medium.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[in] BlockAddress Starting block address within the device to write to
|
||||
* \param[in] Blocks Total number of blocks to read
|
||||
* \param[in] BlockSize Size in bytes of each block within the device
|
||||
* \param[in] BlockBuffer Pointer to where the data to write should be sourced from
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
const uint32_t BlockAddress, const uint8_t Blocks, const uint16_t BlockSize,
|
||||
const void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Mass Storage host class interface, required for the correct operation of
|
||||
* the interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state
|
||||
*/
|
||||
static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo);
|
||||
static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
|
||||
{
|
||||
(void)MSInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define MASS_STORE_CLASS 0x08
|
||||
#define MASS_STORE_SUBCLASS 0x06
|
||||
#define MASS_STORE_PROTOCOL 0x50
|
||||
|
||||
#define REQ_MassStorageReset 0xFF
|
||||
#define REQ_GetMaxLUN 0xFE
|
||||
|
||||
#define CBW_SIGNATURE 0x43425355UL
|
||||
#define CSW_SIGNATURE 0x53425355UL
|
||||
|
||||
#define COMMAND_DIRECTION_DATA_OUT (0 << 7)
|
||||
#define COMMAND_DIRECTION_DATA_IN (1 << 7)
|
||||
|
||||
#define COMMAND_DATA_TIMEOUT_MS 10000
|
||||
|
||||
#define MS_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define MS_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_MS_CLASS_HOST_C)
|
||||
static uint8_t DComp_NextMSInterface(void* const CurrentDescriptor);
|
||||
static uint8_t DComp_NextMSInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
|
||||
static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
|
||||
MS_CommandBlockWrapper_t* const SCSICommandBlock,
|
||||
const void* const BufferPtr);
|
||||
static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo);
|
||||
static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
|
||||
MS_CommandBlockWrapper_t* const SCSICommandBlock, void* BufferPtr);
|
||||
static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
|
||||
MS_CommandStatusWrapper_t* const SCSICommandStatus);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB Mass Storage Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/MassStorage.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassMS
|
||||
* @defgroup Group_USBClassMassStorageHost Mass Storage Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/MassStorage.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Mass Storage USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __MS_CLASS_HOST_H__
|
||||
#define __MS_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/MassStorage.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_MS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/MassStorage.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Error code for some Mass Storage Host functions, indicating a logical (and not hardware) error */
|
||||
#define MS_ERROR_LOGICAL_CMD_FAILED 0x80
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief Mass Storage Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the Mass Storage class driver functions as the MSInterfaceInfo parameter. This
|
||||
* stores each Mass Storage interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the Mass Storage interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the Mass Storage interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the Mass Storage interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the Mass Storage interface's OUT data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref MS_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t InterfaceNumber; /**< Interface index of the Mass Storage interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the Mass Storage interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the Mass Storage interface's OUT data pipe */
|
||||
|
||||
uint32_t TransactionTag; /**< Current transaction tag for data synchronizing of packets */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_MS_Host_t;
|
||||
|
||||
/** \brief SCSI Device LUN Capacity Structure.
|
||||
*
|
||||
* SCSI capacity structure, to hold the total capacity of the device in both the number
|
||||
* of blocks in the current LUN, and the size of each block. This structure is filled by
|
||||
* the device when the MassStore_ReadCapacity() function is called.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device */
|
||||
uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN */
|
||||
} SCSI_Capacity_t;
|
||||
|
||||
/* Enums: */
|
||||
enum MSHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
MS_ENUMERROR_NoMSInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor */
|
||||
MS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Mass Storage endpoints were not found in the device's interfaces */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given Mass Storage host interface instance using the
|
||||
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Mass
|
||||
* Storage Host instance's state values and configures the pipes required to communicate with the interface if it
|
||||
* is found within the device. This should be called once after the stack has enumerated the attached device, while
|
||||
* the host state machine is in the Addressed state.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref MSHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a MASS STORAGE RESET control request to the attached device, resetting the Mass Storage Interface
|
||||
* and readying it for the next Mass Storage command.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a GET MAX LUN control request to the attached device, retrieving the index of the highest LUN (Logical
|
||||
* UNit, a logical drive) in the device. This value can then be used in the other functions of the Mass Storage
|
||||
* Host mode Class driver to address a specific LUN within the device.
|
||||
*
|
||||
* \note Some devices do not support this request, and will STALL it when issued. To get around this,
|
||||
* on unsupported devices the max LUN index will be reported as zero and no error will be returned
|
||||
* if the device STALLs the request.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[out] MaxLUNIndex Pointer to a location where the highest LUN index value should be stored
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, uint8_t* const MaxLUNIndex)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the Mass Storage device's inquiry data for the specified LUN, indicating the device characteristics and
|
||||
* properties.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[out] InquiryData Location where the read inquiry data should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED
|
||||
*/
|
||||
uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
SCSI_Inquiry_Response_t* const InquiryData) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a TEST UNIT READY command to the device, to determine if it is ready to accept other SCSI commands.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex)
|
||||
ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Retrieves the total capacity of the attached USB Mass Storage device, in blocks, and block size.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[out] DeviceCapacity Pointer to the location where the capacity information should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
SCSI_Capacity_t* const DeviceCapacity) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Retrieves the device sense data, indicating the current device state and error codes for the previously
|
||||
* issued command.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[out] SenseData Pointer to the location where the sense information should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
SCSI_Request_Sense_Response_t* const SenseData) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Issues a PREVENT MEDIUM REMOVAL command, to logically (or, depending on the type of device, physically) lock
|
||||
* the device from removal so that blocks of data on the medium can be read or altered.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[in] PreventRemoval Boolean true if the device should be locked from removal, false otherwise
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
const bool PreventRemoval) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Reads blocks of data from the attached Mass Storage device's medium.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[in] BlockAddress Starting block address within the device to read from
|
||||
* \param[in] Blocks Total number of blocks to read
|
||||
* \param[in] BlockSize Size in bytes of each block within the device
|
||||
* \param[out] BlockBuffer Pointer to where the read data from the device should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
const uint32_t BlockAddress, const uint8_t Blocks, const uint16_t BlockSize,
|
||||
void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
|
||||
|
||||
/** Writes blocks of data to the attached Mass Storage device's medium.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state
|
||||
* \param[in] LUNIndex LUN index within the device the command is being issued to
|
||||
* \param[in] BlockAddress Starting block address within the device to write to
|
||||
* \param[in] Blocks Total number of blocks to read
|
||||
* \param[in] BlockSize Size in bytes of each block within the device
|
||||
* \param[in] BlockBuffer Pointer to where the data to write should be sourced from
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
|
||||
*/
|
||||
uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo, const uint8_t LUNIndex,
|
||||
const uint32_t BlockAddress, const uint8_t Blocks, const uint16_t BlockSize,
|
||||
const void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Mass Storage host class interface, required for the correct operation of
|
||||
* the interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state
|
||||
*/
|
||||
static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo);
|
||||
static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
|
||||
{
|
||||
(void)MSInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define MASS_STORE_CLASS 0x08
|
||||
#define MASS_STORE_SUBCLASS 0x06
|
||||
#define MASS_STORE_PROTOCOL 0x50
|
||||
|
||||
#define REQ_MassStorageReset 0xFF
|
||||
#define REQ_GetMaxLUN 0xFE
|
||||
|
||||
#define CBW_SIGNATURE 0x43425355UL
|
||||
#define CSW_SIGNATURE 0x53425355UL
|
||||
|
||||
#define COMMAND_DIRECTION_DATA_OUT (0 << 7)
|
||||
#define COMMAND_DIRECTION_DATA_IN (1 << 7)
|
||||
|
||||
#define COMMAND_DATA_TIMEOUT_MS 10000
|
||||
|
||||
#define MS_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define MS_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_MS_CLASS_HOST_C)
|
||||
static uint8_t DComp_NextMSInterface(void* const CurrentDescriptor);
|
||||
static uint8_t DComp_NextMSInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
|
||||
static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
|
||||
MS_CommandBlockWrapper_t* const SCSICommandBlock,
|
||||
const void* const BufferPtr);
|
||||
static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo);
|
||||
static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
|
||||
MS_CommandBlockWrapper_t* const SCSICommandBlock, void* BufferPtr);
|
||||
static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
|
||||
MS_CommandStatusWrapper_t* const SCSICommandStatus);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,250 +1,250 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_PRINTER_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_PRINTER_DRIVER
|
||||
#include "Printer.h"
|
||||
|
||||
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
|
||||
return PRNT_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return PRNT_ENUMERROR_NoPrinterInterfaceFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Interface_t* PrinterInterface = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t);
|
||||
|
||||
PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
|
||||
PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
|
||||
|
||||
while (FoundEndpoints != (PRNT_FOUND_DATAPIPE_IN | PRNT_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return PRNT_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
PRNTInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= PRNT_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
PRNTInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= PRNT_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
PRNTInterfaceInfo->State.IsActive = true;
|
||||
return PRNT_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_NextPRNTInterface(void* CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == PRINTER_CLASS) &&
|
||||
(DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == PRINTER_SUBCLASS) &&
|
||||
(DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PRINTER_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (EndpointType == EP_TYPE_BULK)
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
|
||||
{
|
||||
if (PRNTInterfaceInfo->State.AlternateSetting)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetInterface,
|
||||
.wValue = PRNTInterfaceInfo->State.AlternateSetting,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint8_t* const PortStatus)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetPortStatus,
|
||||
.wValue = 0,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = sizeof(uint8_t),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(PortStatus);
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SoftReset,
|
||||
.wValue = 0,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(NULL);
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, void* PrinterCommands, uint16_t CommandSize)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(PrinterCommands, CommandSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearOUT();
|
||||
while (!(Pipe_IsOUTReady()))
|
||||
{
|
||||
if (USB_HostState == HOST_STATE_Unattached)
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, char* DeviceIDString, uint16_t BufferSize)
|
||||
{
|
||||
uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
|
||||
uint16_t DeviceIDStringLength = 0;
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetDeviceID,
|
||||
.wValue = 0,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = sizeof(DeviceIDStringLength),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
if (!(DeviceIDStringLength))
|
||||
{
|
||||
DeviceIDString[0] = 0x00;
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength);
|
||||
|
||||
if (DeviceIDStringLength > BufferSize)
|
||||
DeviceIDStringLength = BufferSize;
|
||||
|
||||
USB_ControlRequest.wLength = DeviceIDStringLength;
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
|
||||
|
||||
DeviceIDString[DeviceIDStringLength - 2] = 0x00;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_PRINTER_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_PRINTER_DRIVER
|
||||
#include "Printer.h"
|
||||
|
||||
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
|
||||
return PRNT_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return PRNT_ENUMERROR_NoPrinterInterfaceFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Interface_t* PrinterInterface = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t);
|
||||
|
||||
PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
|
||||
PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
|
||||
|
||||
while (FoundEndpoints != (PRNT_FOUND_DATAPIPE_IN | PRNT_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return PRNT_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
PRNTInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= PRNT_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
PRNTInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= PRNT_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
PRNTInterfaceInfo->State.IsActive = true;
|
||||
return PRNT_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_NextPRNTInterface(void* CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == PRINTER_CLASS) &&
|
||||
(DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == PRINTER_SUBCLASS) &&
|
||||
(DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PRINTER_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (EndpointType == EP_TYPE_BULK)
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
|
||||
{
|
||||
if (PRNTInterfaceInfo->State.AlternateSetting)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SetInterface,
|
||||
.wValue = PRNTInterfaceInfo->State.AlternateSetting,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint8_t* const PortStatus)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetPortStatus,
|
||||
.wValue = 0,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = sizeof(uint8_t),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(PortStatus);
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SoftReset,
|
||||
.wValue = 0,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = 0,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
return USB_Host_SendControlRequest(NULL);
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, void* PrinterCommands, uint16_t CommandSize)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(PrinterCommands, CommandSize, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
Pipe_ClearOUT();
|
||||
while (!(Pipe_IsOUTReady()))
|
||||
{
|
||||
if (USB_HostState == HOST_STATE_Unattached)
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, char* DeviceIDString, uint16_t BufferSize)
|
||||
{
|
||||
uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
|
||||
uint16_t DeviceIDStringLength = 0;
|
||||
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetDeviceID,
|
||||
.wValue = 0,
|
||||
.wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
|
||||
.wLength = sizeof(DeviceIDStringLength),
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
if (!(DeviceIDStringLength))
|
||||
{
|
||||
DeviceIDString[0] = 0x00;
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength);
|
||||
|
||||
if (DeviceIDStringLength > BufferSize)
|
||||
DeviceIDStringLength = BufferSize;
|
||||
|
||||
USB_ControlRequest.wLength = DeviceIDStringLength;
|
||||
|
||||
if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
|
||||
return ErrorCode;
|
||||
|
||||
memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
|
||||
|
||||
DeviceIDString[DeviceIDStringLength - 2] = 0x00;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,233 +1,233 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB Printer Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB Printer Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/Printer.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassPrinter
|
||||
* @defgroup Group_USBClassPrinterHost Printer Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/Printer.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Printer USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __PRINTER_CLASS_HOST_H__
|
||||
#define __PRINTER_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/Printer.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/Printer.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief Printer Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the Printer class driver functions as the PRNTInterfaceInfo parameter. This
|
||||
* stores each Printer interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the Printer interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the Printer interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the Printer interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the Printer interface's OUT data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref PRNT_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t InterfaceNumber; /**< Interface index of the Printer interface within the attached device */
|
||||
uint8_t AlternateSetting; /**< Alternate setting within the Printer Interface in the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the Printer interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the Printer interface's OUT data pipe */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_PRNT_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
enum PRNTHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
PRNT_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
PRNT_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
PRNT_ENUMERROR_NoPrinterInterfaceFound = 2, /**< A compatible Printer interface was not found in the device's Configuration Descriptor */
|
||||
PRNT_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Printer endpoints were not found in the device's interfaces */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given Printer host interface instance using the
|
||||
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Printer
|
||||
* instance's state values and configures the pipes required to communicate with the interface if it is found within
|
||||
* the device. This should be called once after the stack has enumerated the attached device, while the host state
|
||||
* machine is in the Addressed state.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref PRNTHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Configures the printer to enable Bidirectional mode, if it is not already in this mode. This should be called
|
||||
* once the connected device's configuration has been set, to ensure the printer is ready to accept commands.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Retrieves the status of the virtual Printer port's inbound status lines. The result can then be masked against the
|
||||
* PRNT_PORTSTATUS_* macros to determine the printer port's status.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[out] PortStatus Location where the retrieved port status should be stored
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint8_t* const PortStatus)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Soft-resets the attached printer, readying it for new commands.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends the given raw data stream to the attached printer's input endpoint. This should contain commands that the
|
||||
* printer is able to understand - for example, PCL data. Not all printers accept all printer languages; see
|
||||
* \ref PRNT_Host_GetDeviceID() for details on determining acceptable languages for an attached printer.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[in] PrinterCommands Pointer to a buffer containing the raw command stream to send to the printer
|
||||
* \param[in] CommandSize Size in bytes of the command stream to be sent
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, void* PrinterCommands,
|
||||
uint16_t CommandSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the attached printer device's ID string, formatted according to IEEE 1284. This string is sent as a
|
||||
* Unicode string from the device and is automatically converted to an ASCII encoded C string by this function, thus
|
||||
* the maximum reportable string length is two less than the size given (to accommodate the Unicode string length
|
||||
* bytes which are removed).
|
||||
*
|
||||
* This string, when supported, contains the model, manufacturer and acceptable printer languages for the attached device.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[out] DeviceIDString Pointer to a buffer where the Device ID string should be stored, in ASCII format
|
||||
* \param[in] BufferSize Size in bytes of the buffer allocated for the Device ID string
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, char* DeviceIDString,
|
||||
uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Printer host class interface, required for the correct operation of
|
||||
* the interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
*/
|
||||
static inline void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo);
|
||||
static inline void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
|
||||
{
|
||||
(void)PRNTInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define PRINTER_CLASS 0x07
|
||||
#define PRINTER_SUBCLASS 0x01
|
||||
#define PRINTER_PROTOCOL 0x02
|
||||
|
||||
#define REQ_GetDeviceID 0
|
||||
#define REQ_GetPortStatus 1
|
||||
#define REQ_SoftReset 2
|
||||
|
||||
#define PRNT_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define PRNT_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_PRINTER_CLASS_HOST_C)
|
||||
static uint8_t DComp_NextPRNTInterface(void* const CurrentDescriptor);
|
||||
static uint8_t DComp_NextPRNTInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB Printer Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB Printer Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/Printer.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassPrinter
|
||||
* @defgroup Group_USBClassPrinterHost Printer Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/Printer.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Printer USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __PRINTER_CLASS_HOST_H__
|
||||
#define __PRINTER_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/Printer.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/Printer.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief Printer Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the Printer class driver functions as the PRNTInterfaceInfo parameter. This
|
||||
* stores each Printer interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the Printer interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the Printer interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the Printer interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the Printer interface's OUT data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref PRNT_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t InterfaceNumber; /**< Interface index of the Printer interface within the attached device */
|
||||
uint8_t AlternateSetting; /**< Alternate setting within the Printer Interface in the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the Printer interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the Printer interface's OUT data pipe */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_PRNT_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
enum PRNTHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
PRNT_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
PRNT_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
PRNT_ENUMERROR_NoPrinterInterfaceFound = 2, /**< A compatible Printer interface was not found in the device's Configuration Descriptor */
|
||||
PRNT_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Printer endpoints were not found in the device's interfaces */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given Printer host interface instance using the
|
||||
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Printer
|
||||
* instance's state values and configures the pipes required to communicate with the interface if it is found within
|
||||
* the device. This should be called once after the stack has enumerated the attached device, while the host state
|
||||
* machine is in the Addressed state.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref PRNTHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Configures the printer to enable Bidirectional mode, if it is not already in this mode. This should be called
|
||||
* once the connected device's configuration has been set, to ensure the printer is ready to accept commands.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Retrieves the status of the virtual Printer port's inbound status lines. The result can then be masked against the
|
||||
* PRNT_PORTSTATUS_* macros to determine the printer port's status.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[out] PortStatus Location where the retrieved port status should be stored
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, uint8_t* const PortStatus)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Soft-resets the attached printer, readying it for new commands.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends the given raw data stream to the attached printer's input endpoint. This should contain commands that the
|
||||
* printer is able to understand - for example, PCL data. Not all printers accept all printer languages; see
|
||||
* \ref PRNT_Host_GetDeviceID() for details on determining acceptable languages for an attached printer.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[in] PrinterCommands Pointer to a buffer containing the raw command stream to send to the printer
|
||||
* \param[in] CommandSize Size in bytes of the command stream to be sent
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, void* PrinterCommands,
|
||||
uint16_t CommandSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Retrieves the attached printer device's ID string, formatted according to IEEE 1284. This string is sent as a
|
||||
* Unicode string from the device and is automatically converted to an ASCII encoded C string by this function, thus
|
||||
* the maximum reportable string length is two less than the size given (to accommodate the Unicode string length
|
||||
* bytes which are removed).
|
||||
*
|
||||
* This string, when supported, contains the model, manufacturer and acceptable printer languages for the attached device.
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
* \param[out] DeviceIDString Pointer to a buffer where the Device ID string should be stored, in ASCII format
|
||||
* \param[in] BufferSize Size in bytes of the buffer allocated for the Device ID string
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo, char* DeviceIDString,
|
||||
uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Printer host class interface, required for the correct operation of
|
||||
* the interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state
|
||||
*/
|
||||
static inline void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo);
|
||||
static inline void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
|
||||
{
|
||||
(void)PRNTInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define PRINTER_CLASS 0x07
|
||||
#define PRINTER_SUBCLASS 0x01
|
||||
#define PRINTER_PROTOCOL 0x02
|
||||
|
||||
#define REQ_GetDeviceID 0
|
||||
#define REQ_GetPortStatus 1
|
||||
#define REQ_SoftReset 2
|
||||
|
||||
#define PRNT_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define PRNT_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_PRINTER_CLASS_HOST_C)
|
||||
static uint8_t DComp_NextPRNTInterface(void* const CurrentDescriptor);
|
||||
static uint8_t DComp_NextPRNTInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,467 +1,467 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_RNDIS_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_RNDIS_DRIVER
|
||||
#include "RNDIS.h"
|
||||
|
||||
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return RNDIS_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
|
||||
}
|
||||
|
||||
RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;
|
||||
|
||||
while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN)
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FoundEndpoints = 0;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.NotificationPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
|
||||
}
|
||||
}
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
|
||||
|
||||
FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
RNDISInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= RNDIS_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RNDISInterfaceInfo->State.IsActive = true;
|
||||
return RNDIS_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == RNDIS_CONTROL_CLASS) &&
|
||||
(CurrentInterface->SubClass == RNDIS_CONTROL_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == RNDIS_CONTROL_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == RNDIS_DATA_CLASS) &&
|
||||
(CurrentInterface->SubClass == RNDIS_DATA_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == RNDIS_DATA_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
|
||||
!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SendEncapsulatedCommand,
|
||||
.wValue = 0,
|
||||
.wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = Length,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
|
||||
static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetEncapsulatedResponse,
|
||||
.wValue = 0,
|
||||
.wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = Length,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
RNDIS_KeepAlive_Message_t KeepAliveMessage;
|
||||
RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
|
||||
|
||||
KeepAliveMessage.MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
|
||||
KeepAliveMessage.MessageLength = sizeof(RNDIS_KeepAlive_Message_t);
|
||||
KeepAliveMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
|
||||
sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
|
||||
sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
RNDIS_Initialize_Message_t InitMessage;
|
||||
RNDIS_Initialize_Complete_t InitMessageResponse;
|
||||
|
||||
InitMessage.MessageType = REMOTE_NDIS_INITIALIZE_MSG;
|
||||
InitMessage.MessageLength = sizeof(RNDIS_Initialize_Message_t);
|
||||
InitMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
InitMessage.MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
|
||||
InitMessage.MinorVersion = REMOTE_NDIS_VERSION_MINOR;
|
||||
InitMessage.MaxTransferSize = RNDISInterfaceInfo->Config.HostMaxPacketSize;
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
|
||||
sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
|
||||
sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
|
||||
return RNDIS_COMMAND_FAILED;
|
||||
|
||||
RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t Length)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
struct
|
||||
{
|
||||
RNDIS_Set_Message_t SetMessage;
|
||||
uint8_t ContigiousBuffer[Length];
|
||||
} SetMessageData;
|
||||
|
||||
RNDIS_Set_Complete_t SetMessageResponse;
|
||||
|
||||
SetMessageData.SetMessage.MessageType = REMOTE_NDIS_SET_MSG;
|
||||
SetMessageData.SetMessage.MessageLength = sizeof(RNDIS_Set_Message_t) + Length;
|
||||
SetMessageData.SetMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
SetMessageData.SetMessage.Oid = Oid;
|
||||
SetMessageData.SetMessage.InformationBufferLength = Length;
|
||||
SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
|
||||
SetMessageData.SetMessage.DeviceVcHandle = 0;
|
||||
|
||||
memcpy(&SetMessageData.ContigiousBuffer, Buffer, Length);
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
|
||||
SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
|
||||
sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
|
||||
return RNDIS_COMMAND_FAILED;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t MaxLength)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
RNDIS_Query_Message_t QueryMessage;
|
||||
|
||||
struct
|
||||
{
|
||||
RNDIS_Query_Complete_t QueryMessageResponse;
|
||||
uint8_t ContigiousBuffer[MaxLength];
|
||||
} QueryMessageResponseData;
|
||||
|
||||
QueryMessage.MessageType = REMOTE_NDIS_QUERY_MSG;
|
||||
QueryMessage.MessageLength = sizeof(RNDIS_Query_Message_t);
|
||||
QueryMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
QueryMessage.Oid = Oid;
|
||||
QueryMessage.InformationBufferLength = 0;
|
||||
QueryMessage.InformationBufferOffset = 0;
|
||||
QueryMessage.DeviceVcHandle = 0;
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
|
||||
sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
|
||||
sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
|
||||
return RNDIS_COMMAND_FAILED;
|
||||
|
||||
memcpy(Buffer, &QueryMessageResponseData.ContigiousBuffer, MaxLength);
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
bool PacketWaiting;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
|
||||
Pipe_Unfreeze();
|
||||
|
||||
PacketWaiting = Pipe_IsINReceived();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PacketWaiting;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t* PacketLength)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
{
|
||||
if (Pipe_IsINReceived())
|
||||
Pipe_ClearIN();
|
||||
|
||||
*PacketLength = 0;
|
||||
Pipe_Freeze();
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
RNDIS_Packet_Message_t DeviceMessage;
|
||||
|
||||
if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
|
||||
NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
*PacketLength = (uint16_t)DeviceMessage.DataLength;
|
||||
|
||||
Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
|
||||
NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK);
|
||||
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
Pipe_ClearIN();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t PacketLength)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
RNDIS_Packet_Message_t DeviceMessage;
|
||||
|
||||
memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
|
||||
DeviceMessage.MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
DeviceMessage.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength);
|
||||
DeviceMessage.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
|
||||
DeviceMessage.DataLength = PacketLength;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
|
||||
NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Pipe_Write_Stream_LE(Buffer, PacketLength, NO_STREAM_CALLBACK);
|
||||
Pipe_ClearOUT();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_RNDIS_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_RNDIS_DRIVER
|
||||
#include "RNDIS.h"
|
||||
|
||||
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* ConfigDescriptorData)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
|
||||
return RNDIS_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
|
||||
}
|
||||
|
||||
RNDISInterfaceInfo->State.ControlInterfaceNumber = DESCRIPTOR_CAST(ConfigDescriptorData, USB_Descriptor_Interface_t).InterfaceNumber;
|
||||
|
||||
while (FoundEndpoints != (RNDIS_FOUND_NOTIFICATION_IN | RNDIS_FOUND_DATAPIPE_IN | RNDIS_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
if (FoundEndpoints & RNDIS_FOUND_NOTIFICATION_IN)
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FoundEndpoints = 0;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.NotificationPipeNumber);
|
||||
Pipe_DisablePipe();
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_NoRNDISInterfaceFound;
|
||||
}
|
||||
}
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
|
||||
DComp_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return RNDIS_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
RNDISInterfaceInfo->Config.NotificationPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
RNDISInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
|
||||
|
||||
FoundEndpoints |= RNDIS_FOUND_NOTIFICATION_IN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
RNDISInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= RNDIS_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
RNDISInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
RNDISInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= RNDIS_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RNDISInterfaceInfo->State.IsActive = true;
|
||||
return RNDIS_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == RNDIS_CONTROL_CLASS) &&
|
||||
(CurrentInterface->SubClass == RNDIS_CONTROL_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == RNDIS_CONTROL_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == RNDIS_DATA_CLASS) &&
|
||||
(CurrentInterface->SubClass == RNDIS_DATA_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == RNDIS_DATA_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
|
||||
!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_SendEncapsulatedCommand,
|
||||
.wValue = 0,
|
||||
.wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = Length,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
|
||||
static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length)
|
||||
{
|
||||
USB_ControlRequest = (USB_Request_Header_t)
|
||||
{
|
||||
.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
.bRequest = REQ_GetEncapsulatedResponse,
|
||||
.wValue = 0,
|
||||
.wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
|
||||
.wLength = Length,
|
||||
};
|
||||
|
||||
Pipe_SelectPipe(PIPE_CONTROLPIPE);
|
||||
return USB_Host_SendControlRequest(Buffer);
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
RNDIS_KeepAlive_Message_t KeepAliveMessage;
|
||||
RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
|
||||
|
||||
KeepAliveMessage.MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
|
||||
KeepAliveMessage.MessageLength = sizeof(RNDIS_KeepAlive_Message_t);
|
||||
KeepAliveMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
|
||||
sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
|
||||
sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
RNDIS_Initialize_Message_t InitMessage;
|
||||
RNDIS_Initialize_Complete_t InitMessageResponse;
|
||||
|
||||
InitMessage.MessageType = REMOTE_NDIS_INITIALIZE_MSG;
|
||||
InitMessage.MessageLength = sizeof(RNDIS_Initialize_Message_t);
|
||||
InitMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
InitMessage.MajorVersion = REMOTE_NDIS_VERSION_MAJOR;
|
||||
InitMessage.MinorVersion = REMOTE_NDIS_VERSION_MINOR;
|
||||
InitMessage.MaxTransferSize = RNDISInterfaceInfo->Config.HostMaxPacketSize;
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
|
||||
sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
|
||||
sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (InitMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
|
||||
return RNDIS_COMMAND_FAILED;
|
||||
|
||||
RNDISInterfaceInfo->State.DeviceMaxPacketSize = InitMessageResponse.MaxTransferSize;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t Length)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
struct
|
||||
{
|
||||
RNDIS_Set_Message_t SetMessage;
|
||||
uint8_t ContigiousBuffer[Length];
|
||||
} SetMessageData;
|
||||
|
||||
RNDIS_Set_Complete_t SetMessageResponse;
|
||||
|
||||
SetMessageData.SetMessage.MessageType = REMOTE_NDIS_SET_MSG;
|
||||
SetMessageData.SetMessage.MessageLength = sizeof(RNDIS_Set_Message_t) + Length;
|
||||
SetMessageData.SetMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
SetMessageData.SetMessage.Oid = Oid;
|
||||
SetMessageData.SetMessage.InformationBufferLength = Length;
|
||||
SetMessageData.SetMessage.InformationBufferOffset = (sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
|
||||
SetMessageData.SetMessage.DeviceVcHandle = 0;
|
||||
|
||||
memcpy(&SetMessageData.ContigiousBuffer, Buffer, Length);
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
|
||||
SetMessageData.SetMessage.MessageLength)) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
|
||||
sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (SetMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
|
||||
return RNDIS_COMMAND_FAILED;
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer, uint16_t MaxLength)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
RNDIS_Query_Message_t QueryMessage;
|
||||
|
||||
struct
|
||||
{
|
||||
RNDIS_Query_Complete_t QueryMessageResponse;
|
||||
uint8_t ContigiousBuffer[MaxLength];
|
||||
} QueryMessageResponseData;
|
||||
|
||||
QueryMessage.MessageType = REMOTE_NDIS_QUERY_MSG;
|
||||
QueryMessage.MessageLength = sizeof(RNDIS_Query_Message_t);
|
||||
QueryMessage.RequestId = RNDISInterfaceInfo->State.RequestID++;
|
||||
|
||||
QueryMessage.Oid = Oid;
|
||||
QueryMessage.InformationBufferLength = 0;
|
||||
QueryMessage.InformationBufferOffset = 0;
|
||||
QueryMessage.DeviceVcHandle = 0;
|
||||
|
||||
if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
|
||||
sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
|
||||
sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (QueryMessageResponseData.QueryMessageResponse.Status != REMOTE_NDIS_STATUS_SUCCESS)
|
||||
return RNDIS_COMMAND_FAILED;
|
||||
|
||||
memcpy(Buffer, &QueryMessageResponseData.ContigiousBuffer, MaxLength);
|
||||
|
||||
return HOST_SENDCONTROL_Successful;
|
||||
}
|
||||
|
||||
bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
bool PacketWaiting;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
|
||||
Pipe_Unfreeze();
|
||||
|
||||
PacketWaiting = Pipe_IsINReceived();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PacketWaiting;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t* PacketLength)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_SetPipeToken(PIPE_TOKEN_IN);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (!(Pipe_IsReadWriteAllowed()))
|
||||
{
|
||||
if (Pipe_IsINReceived())
|
||||
Pipe_ClearIN();
|
||||
|
||||
*PacketLength = 0;
|
||||
Pipe_Freeze();
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
RNDIS_Packet_Message_t DeviceMessage;
|
||||
|
||||
if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
|
||||
NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
*PacketLength = (uint16_t)DeviceMessage.DataLength;
|
||||
|
||||
Pipe_Discard_Stream(DeviceMessage.DataOffset - (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
|
||||
NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_Read_Stream_LE(Buffer, *PacketLength, NO_STREAM_CALLBACK);
|
||||
|
||||
if (!(Pipe_BytesInPipe()))
|
||||
Pipe_ClearIN();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t PacketLength)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
|
||||
return PIPE_READYWAIT_DeviceDisconnected;
|
||||
|
||||
RNDIS_Packet_Message_t DeviceMessage;
|
||||
|
||||
memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
|
||||
DeviceMessage.MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
DeviceMessage.MessageLength = (sizeof(RNDIS_Packet_Message_t) + PacketLength);
|
||||
DeviceMessage.DataOffset = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
|
||||
DeviceMessage.DataLength = PacketLength;
|
||||
|
||||
Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
|
||||
NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
{
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Pipe_Write_Stream_LE(Buffer, PacketLength, NO_STREAM_CALLBACK);
|
||||
Pipe_ClearOUT();
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,283 +1,283 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/RNDIS.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassRNDIS
|
||||
* @defgroup Group_USBClassRNDISHost RNDIS Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/RNDIS.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Microsoft RNDIS Ethernet
|
||||
* USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __RNDIS_CLASS_HOST_H__
|
||||
#define __RNDIS_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/RNDIS.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_RNDIS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/RNDIS.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief RNDIS Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the RNDIS class driver functions as the RNDISInterfaceInfo parameter. This
|
||||
* stores each RNDIS interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the RNDIS interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the RNDIS interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the RNDIS interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the RNDIS interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t NotificationPipeNumber; /**< Pipe number of the RNDIS interface's IN notification endpoint, if used */
|
||||
bool NotificationPipeDoubleBank; /** Indicates if the RNDIS interface's notification pipe should use double banking */
|
||||
|
||||
uint32_t HostMaxPacketSize; /**< Maximum size of a packet which can be buffered by the host */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref RNDIS_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t ControlInterfaceNumber; /**< Interface index of the RNDIS control interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the RNDIS interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the RNDIS interface's OUT data pipe */
|
||||
uint16_t NotificationPipeSize; /**< Size in bytes of the RNDIS interface's IN notification pipe, if used */
|
||||
|
||||
uint32_t DeviceMaxPacketSize; /**< Maximum size of a packet which can be buffered by the attached RNDIS device */
|
||||
|
||||
uint32_t RequestID; /**< Request ID counter to give a unique ID for each command/response pair */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_RNDIS_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref RNDIS_Host_ConfigurePipes() function. */
|
||||
enum RNDISHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
RNDIS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
RNDIS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
RNDIS_ENUMERROR_NoRNDISInterfaceFound = 2, /**< A compatible RNDIS interface was not found in the device's Configuration Descriptor */
|
||||
RNDIS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible RNDIS endpoints were not found in the device's RNDIS interface */
|
||||
};
|
||||
|
||||
/* Macros: */
|
||||
/** Additional error code for RNDIS functions when a device returns a logical command failure */
|
||||
#define RNDIS_COMMAND_FAILED 0xC0
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given RNDIS host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given RNDIS Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the device.
|
||||
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
|
||||
* the Addressed state.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref RNDISHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods
|
||||
* of long inactivity.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Initializes the attached RNDIS device's RNDIS interface. This should be called after the device's pipes have been
|
||||
* configured via the call to \ref RNDIS_Host_ConfigurePipes().
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sets a given RNDIS property of an attached RNDIS device.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] Oid OID number of the parameter to set
|
||||
* \param[in] Buffer Pointer to where the property data is to be sourced from
|
||||
* \param[in] Length Length in bytes of the property data to sent to the device
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer,
|
||||
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Gets a given RNDIS property of an attached RNDIS device.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] Oid OID number of the parameter to get
|
||||
* \param[in] Buffer Pointer to where the property data is to be written to
|
||||
* \param[in] MaxLength Length in bytes of the destination buffer size
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer,
|
||||
uint16_t MaxLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Determines if a packet is currently waiting for the host to read in and process.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*
|
||||
* \return Boolean true if a packet is waiting to be read in by the host, false otherwise
|
||||
*/
|
||||
|
||||
bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo);
|
||||
|
||||
/** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
|
||||
* only the packet contents for processing by the host in the nominated buffer.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[out] Buffer Pointer to a buffer where the packer data is to be written to
|
||||
* \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored
|
||||
*
|
||||
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t* PacketLength)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] Buffer Pointer to a buffer where the packer data is to be read from
|
||||
* \param[in] PacketLength Length in bytes of the packet to send
|
||||
*
|
||||
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t PacketLength)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given RNDIS host class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*/
|
||||
static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo);
|
||||
static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
(void)RNDISInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define RNDIS_CONTROL_CLASS 0x02
|
||||
#define RNDIS_CONTROL_SUBCLASS 0x02
|
||||
#define RNDIS_CONTROL_PROTOCOL 0xFF
|
||||
#define RNDIS_DATA_CLASS 0x0A
|
||||
#define RNDIS_DATA_SUBCLASS 0x00
|
||||
#define RNDIS_DATA_PROTOCOL 0x00
|
||||
|
||||
#define RNDIS_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define RNDIS_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
#define RNDIS_FOUND_NOTIFICATION_IN (1 << 2)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_RNDIS_CLASS_HOST_C)
|
||||
static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB RNDIS Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/RNDIS.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassRNDIS
|
||||
* @defgroup Group_USBClassRNDISHost RNDIS Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/RNDIS.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Microsoft RNDIS Ethernet
|
||||
* USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __RNDIS_CLASS_HOST_H__
|
||||
#define __RNDIS_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/RNDIS.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_RNDIS_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/RNDIS.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** \brief RNDIS Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the RNDIS class driver functions as the RNDISInterfaceInfo parameter. This
|
||||
* stores each RNDIS interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the RNDIS interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the RNDIS interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the RNDIS interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the RNDIS interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t NotificationPipeNumber; /**< Pipe number of the RNDIS interface's IN notification endpoint, if used */
|
||||
bool NotificationPipeDoubleBank; /** Indicates if the RNDIS interface's notification pipe should use double banking */
|
||||
|
||||
uint32_t HostMaxPacketSize; /**< Maximum size of a packet which can be buffered by the host */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref RNDIS_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
uint8_t ControlInterfaceNumber; /**< Interface index of the RNDIS control interface within the attached device */
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the RNDIS interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the RNDIS interface's OUT data pipe */
|
||||
uint16_t NotificationPipeSize; /**< Size in bytes of the RNDIS interface's IN notification pipe, if used */
|
||||
|
||||
uint32_t DeviceMaxPacketSize; /**< Maximum size of a packet which can be buffered by the attached RNDIS device */
|
||||
|
||||
uint32_t RequestID; /**< Request ID counter to give a unique ID for each command/response pair */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_RNDIS_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref RNDIS_Host_ConfigurePipes() function. */
|
||||
enum RNDISHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
RNDIS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
RNDIS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
RNDIS_ENUMERROR_NoRNDISInterfaceFound = 2, /**< A compatible RNDIS interface was not found in the device's Configuration Descriptor */
|
||||
RNDIS_ENUMERROR_EndpointsNotFound = 3, /**< Compatible RNDIS endpoints were not found in the device's RNDIS interface */
|
||||
};
|
||||
|
||||
/* Macros: */
|
||||
/** Additional error code for RNDIS functions when a device returns a logical command failure */
|
||||
#define RNDIS_COMMAND_FAILED 0xC0
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given RNDIS host interface instance using the Configuration
|
||||
* Descriptor read from an attached USB device. This function automatically updates the given RNDIS Host instance's
|
||||
* state values and configures the pipes required to communicate with the interface if it is found within the device.
|
||||
* This should be called once after the stack has enumerated the attached device, while the host state machine is in
|
||||
* the Addressed state.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref RNDISHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods
|
||||
* of long inactivity.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Initializes the attached RNDIS device's RNDIS interface. This should be called after the device's pipes have been
|
||||
* configured via the call to \ref RNDIS_Host_ConfigurePipes().
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sets a given RNDIS property of an attached RNDIS device.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] Oid OID number of the parameter to set
|
||||
* \param[in] Buffer Pointer to where the property data is to be sourced from
|
||||
* \param[in] Length Length in bytes of the property data to sent to the device
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer,
|
||||
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Gets a given RNDIS property of an attached RNDIS device.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] Oid OID number of the parameter to get
|
||||
* \param[in] Buffer Pointer to where the property data is to be written to
|
||||
* \param[in] MaxLength Length in bytes of the destination buffer size
|
||||
*
|
||||
* \return A value from the USB_Host_SendControlErrorCodes_t enum or RNDIS_COMMAND_FAILED if the device returned a
|
||||
* logical command failure
|
||||
*/
|
||||
uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, uint32_t Oid, void* Buffer,
|
||||
uint16_t MaxLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Determines if a packet is currently waiting for the host to read in and process.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*
|
||||
* \return Boolean true if a packet is waiting to be read in by the host, false otherwise
|
||||
*/
|
||||
|
||||
bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo);
|
||||
|
||||
/** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
|
||||
* only the packet contents for processing by the host in the nominated buffer.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[out] Buffer Pointer to a buffer where the packer data is to be written to
|
||||
* \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored
|
||||
*
|
||||
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t* PacketLength)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
* \param[in] Buffer Pointer to a buffer where the packer data is to be read from
|
||||
* \param[in] PacketLength Length in bytes of the packet to send
|
||||
*
|
||||
* \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo, void* Buffer, uint16_t PacketLength)
|
||||
ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given RNDIS host class interface, required for the correct operation of the interface. This should
|
||||
* be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state
|
||||
*/
|
||||
static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo);
|
||||
static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
|
||||
{
|
||||
(void)RNDISInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define RNDIS_CONTROL_CLASS 0x02
|
||||
#define RNDIS_CONTROL_SUBCLASS 0x02
|
||||
#define RNDIS_CONTROL_PROTOCOL 0xFF
|
||||
#define RNDIS_DATA_CLASS 0x0A
|
||||
#define RNDIS_DATA_SUBCLASS 0x00
|
||||
#define RNDIS_DATA_PROTOCOL 0x00
|
||||
|
||||
#define RNDIS_FOUND_DATAPIPE_IN (1 << 0)
|
||||
#define RNDIS_FOUND_DATAPIPE_OUT (1 << 1)
|
||||
#define RNDIS_FOUND_NOTIFICATION_IN (1 << 2)
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_RNDIS_CLASS_HOST_C)
|
||||
static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
|
||||
void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,413 +1,413 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_SI_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_SI_DRIVER
|
||||
#include "StillImage.h"
|
||||
|
||||
uint8_t SImage_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
|
||||
return SI_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return SI_ENUMERROR_NoSIInterfaceFound;
|
||||
}
|
||||
|
||||
while (FoundEndpoints != (SI_FOUND_EVENTS_IN | SI_FOUND_DATAPIPE_IN | SI_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return SI_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(SIInterfaceInfo->Config.EventsPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
SIInterfaceInfo->Config.EventsPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
SIInterfaceInfo->State.EventsPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
|
||||
|
||||
FoundEndpoints |= SI_FOUND_EVENTS_IN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
SIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
SIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= SI_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
SIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
SIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= SI_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SIInterfaceInfo->State.IsActive = true;
|
||||
return SI_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
uint8_t DComp_SI_Host_NextSIInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == STILL_IMAGE_CLASS) &&
|
||||
(CurrentInterface->SubClass == STILL_IMAGE_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == STILL_IMAGE_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
|
||||
(!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress))))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
if (SIInterfaceInfo->State.IsSessionOpen)
|
||||
PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
|
||||
|
||||
if (ParamBytes)
|
||||
{
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Pipe_ClearOUT();
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
|
||||
{
|
||||
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
while (!(Pipe_IsReadWriteAllowed()))
|
||||
{
|
||||
if (USB_INT_HasOccurred(USB_INT_HSOFI))
|
||||
{
|
||||
USB_INT_Clear(USB_INT_HSOFI);
|
||||
TimeoutMSRem--;
|
||||
|
||||
if (!(TimeoutMSRem))
|
||||
{
|
||||
return PIPE_RWSTREAM_Timeout;
|
||||
}
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsStalled())
|
||||
{
|
||||
USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
return PIPE_RWSTREAM_PipeStalled;
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsStalled())
|
||||
{
|
||||
USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
return PIPE_RWSTREAM_PipeStalled;
|
||||
}
|
||||
|
||||
if (USB_HostState == HOST_STATE_Unattached)
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
}
|
||||
|
||||
Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK);
|
||||
|
||||
if (PIMAHeader->Type == CType_ResponseBlock)
|
||||
{
|
||||
uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
|
||||
|
||||
if (ParamBytes)
|
||||
Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_ClearIN();
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_ClearOUT();
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* SIInterfaceInfo)
|
||||
{
|
||||
bool IsEventReceived = false;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_BytesInPipe())
|
||||
IsEventReceived = true;
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return IsEventReceived;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(SI_PIMA_Container_t), NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_ClearIN();
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
SIInterfaceInfo->State.TransactionID = 0;
|
||||
SIInterfaceInfo->State.IsSessionOpen = false;
|
||||
|
||||
SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
|
||||
{
|
||||
.DataLength = PIMA_COMMAND_SIZE(1),
|
||||
.Type = CType_CommandBlock,
|
||||
.Code = 0x1002,
|
||||
.Params = {1},
|
||||
};
|
||||
|
||||
if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
|
||||
return SI_ERROR_LOGICAL_CMD_FAILED;
|
||||
|
||||
SIInterfaceInfo->State.IsSessionOpen = true;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
|
||||
{
|
||||
.DataLength = PIMA_COMMAND_SIZE(1),
|
||||
.Type = CType_CommandBlock,
|
||||
.Code = 0x1003,
|
||||
.Params = {1},
|
||||
};
|
||||
|
||||
if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
SIInterfaceInfo->State.IsSessionOpen = false;
|
||||
|
||||
if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
|
||||
return SI_ERROR_LOGICAL_CMD_FAILED;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation,
|
||||
const uint8_t TotalParams, uint32_t* Params)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
|
||||
{
|
||||
.DataLength = PIMA_COMMAND_SIZE(TotalParams),
|
||||
.Type = CType_CommandBlock,
|
||||
.Code = Operation,
|
||||
};
|
||||
|
||||
memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);
|
||||
|
||||
if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
SI_PIMA_Container_t PIMABlock;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
|
||||
return SI_ERROR_LOGICAL_CMD_FAILED;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#define __INCLUDE_FROM_USB_DRIVER
|
||||
#include "../../HighLevel/USBMode.h"
|
||||
#if defined(USB_CAN_BE_HOST)
|
||||
|
||||
#define __INCLUDE_FROM_SI_CLASS_HOST_C
|
||||
#define __INCLUDE_FROM_SI_DRIVER
|
||||
#include "StillImage.h"
|
||||
|
||||
uint8_t SImage_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor)
|
||||
{
|
||||
uint8_t FoundEndpoints = 0;
|
||||
|
||||
memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));
|
||||
|
||||
if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
|
||||
return SI_ENUMERROR_InvalidConfigDescriptor;
|
||||
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return SI_ENUMERROR_NoSIInterfaceFound;
|
||||
}
|
||||
|
||||
while (FoundEndpoints != (SI_FOUND_EVENTS_IN | SI_FOUND_DATAPIPE_IN | SI_FOUND_DATAPIPE_OUT))
|
||||
{
|
||||
if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
|
||||
DComp_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
|
||||
{
|
||||
return SI_ENUMERROR_EndpointsNotFound;
|
||||
}
|
||||
|
||||
USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
|
||||
|
||||
if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(SIInterfaceInfo->Config.EventsPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
SIInterfaceInfo->Config.EventsPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
SIInterfaceInfo->State.EventsPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS);
|
||||
|
||||
FoundEndpoints |= SI_FOUND_EVENTS_IN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
|
||||
{
|
||||
Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
SIInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
SIInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= SI_FOUND_DATAPIPE_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pipe_ConfigurePipe(SIInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
|
||||
EndpointData->EndpointAddress, EndpointData->EndpointSize,
|
||||
SIInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
|
||||
SIInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
|
||||
|
||||
FoundEndpoints |= SI_FOUND_DATAPIPE_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SIInterfaceInfo->State.IsActive = true;
|
||||
return SI_ENUMERROR_NoError;
|
||||
}
|
||||
|
||||
uint8_t DComp_SI_Host_NextSIInterface(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Interface_t);
|
||||
|
||||
if ((CurrentInterface->Class == STILL_IMAGE_CLASS) &&
|
||||
(CurrentInterface->SubClass == STILL_IMAGE_SUBCLASS) &&
|
||||
(CurrentInterface->Protocol == STILL_IMAGE_PROTOCOL))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
|
||||
{
|
||||
if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
|
||||
{
|
||||
USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,
|
||||
USB_Descriptor_Endpoint_t);
|
||||
|
||||
uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);
|
||||
|
||||
if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
|
||||
(!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress))))
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Found;
|
||||
}
|
||||
}
|
||||
else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
|
||||
{
|
||||
return DESCRIPTOR_SEARCH_Fail;
|
||||
}
|
||||
|
||||
return DESCRIPTOR_SEARCH_NotFound;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
if (SIInterfaceInfo->State.IsSessionOpen)
|
||||
PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
|
||||
|
||||
if (ParamBytes)
|
||||
{
|
||||
if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
Pipe_ClearOUT();
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
|
||||
{
|
||||
uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
while (!(Pipe_IsReadWriteAllowed()))
|
||||
{
|
||||
if (USB_INT_HasOccurred(USB_INT_HSOFI))
|
||||
{
|
||||
USB_INT_Clear(USB_INT_HSOFI);
|
||||
TimeoutMSRem--;
|
||||
|
||||
if (!(TimeoutMSRem))
|
||||
{
|
||||
return PIPE_RWSTREAM_Timeout;
|
||||
}
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsStalled())
|
||||
{
|
||||
USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
return PIPE_RWSTREAM_PipeStalled;
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_IsStalled())
|
||||
{
|
||||
USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
return PIPE_RWSTREAM_PipeStalled;
|
||||
}
|
||||
|
||||
if (USB_HostState == HOST_STATE_Unattached)
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
}
|
||||
|
||||
Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK);
|
||||
|
||||
if (PIMAHeader->Type == CType_ResponseBlock)
|
||||
{
|
||||
uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
|
||||
|
||||
if (ParamBytes)
|
||||
Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_ClearIN();
|
||||
}
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_ClearOUT();
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer, const uint16_t Bytes)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* SIInterfaceInfo)
|
||||
{
|
||||
bool IsEventReceived = false;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return false;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
if (Pipe_BytesInPipe())
|
||||
IsEventReceived = true;
|
||||
|
||||
Pipe_Freeze();
|
||||
|
||||
return IsEventReceived;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return PIPE_RWSTREAM_DeviceDisconnected;
|
||||
|
||||
Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipeNumber);
|
||||
Pipe_Unfreeze();
|
||||
|
||||
ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(SI_PIMA_Container_t), NO_STREAM_CALLBACK);
|
||||
|
||||
Pipe_ClearIN();
|
||||
Pipe_Freeze();
|
||||
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
SIInterfaceInfo->State.TransactionID = 0;
|
||||
SIInterfaceInfo->State.IsSessionOpen = false;
|
||||
|
||||
SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
|
||||
{
|
||||
.DataLength = PIMA_COMMAND_SIZE(1),
|
||||
.Type = CType_CommandBlock,
|
||||
.Code = 0x1002,
|
||||
.Params = {1},
|
||||
};
|
||||
|
||||
if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
|
||||
return SI_ERROR_LOGICAL_CMD_FAILED;
|
||||
|
||||
SIInterfaceInfo->State.IsSessionOpen = true;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
|
||||
{
|
||||
.DataLength = PIMA_COMMAND_SIZE(1),
|
||||
.Type = CType_CommandBlock,
|
||||
.Code = 0x1003,
|
||||
.Params = {1},
|
||||
};
|
||||
|
||||
if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
SIInterfaceInfo->State.IsSessionOpen = false;
|
||||
|
||||
if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
|
||||
return SI_ERROR_LOGICAL_CMD_FAILED;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation,
|
||||
const uint8_t TotalParams, uint32_t* Params)
|
||||
{
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
uint8_t ErrorCode;
|
||||
|
||||
SI_PIMA_Container_t PIMABlock = (SI_PIMA_Container_t)
|
||||
{
|
||||
.DataLength = PIMA_COMMAND_SIZE(TotalParams),
|
||||
.Type = CType_CommandBlock,
|
||||
.Code = Operation,
|
||||
};
|
||||
|
||||
memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);
|
||||
|
||||
if ((ErrorCode = SImage_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
uint8_t ErrorCode;
|
||||
SI_PIMA_Container_t PIMABlock;
|
||||
|
||||
if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
|
||||
return HOST_SENDCONTROL_DeviceDisconnected;
|
||||
|
||||
if ((ErrorCode = SImage_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
|
||||
return ErrorCode;
|
||||
|
||||
if ((PIMABlock.Type != CType_ResponseBlock) || (PIMABlock.Code != 0x2001))
|
||||
return SI_ERROR_LOGICAL_CMD_FAILED;
|
||||
|
||||
return PIPE_RWSTREAM_NoError;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,323 +1,323 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB Still Image Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB Still Image Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/StillImage.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassSI
|
||||
* @defgroup Group_USBClassStillImageHost Still Image Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/StillImage.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Still Image USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __SI_CLASS_HOST_H__
|
||||
#define __SI_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/StillImage.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_SI_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/StillImage.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Error code for some Still Image Host functions, indicating a logical (and not hardware) error */
|
||||
#define SI_ERROR_LOGICAL_CMD_FAILED 0x80
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief Still Image Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the Still Image class driver functions as the SIInterfaceInfo parameter. This
|
||||
* stores each Still Image interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the Still Image interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the Still Image interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the Still Image interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the Still Image interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t EventsPipeNumber; /**< Pipe number of the Still Image interface's IN events endpoint, if used */
|
||||
bool EventsPipeDoubleBank; /** Indicates if the Still Image interface's events data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref SImage_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the Still Image interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the Still Image interface's OUT data pipe */
|
||||
uint16_t EventsPipeSize; /**< Size in bytes of the Still Image interface's IN events pipe */
|
||||
|
||||
bool IsSessionOpen; /**< Indicates if a PIMA session is currently open with the attached device */
|
||||
uint32_t TransactionID; /**< Transaction ID for the next transaction to send to the device */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_SI_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref SImage_Host_ConfigurePipes() function. */
|
||||
enum SIHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
SI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
SI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
SI_ENUMERROR_NoSIInterfaceFound = 2, /**< A compatible Still Image interface was not found in the device's
|
||||
* Configuration Descriptor
|
||||
*/
|
||||
SI_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Still Image data endpoints were not found in the
|
||||
* device's Still Image interface
|
||||
*/
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given Still Image host interface instance using the
|
||||
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Still
|
||||
* Image Host instance's state values and configures the pipes required to communicate with the interface if it is
|
||||
* found within the device. This should be called once after the stack has enumerated the attached device, while
|
||||
* the host state machine is in the Addressed state.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref SIHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Opens a new PIMA session with the attached device. This should be used before any session-orientated PIMA commands
|
||||
* are issued to the device. Only one session can be open at the one time.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Closes an already opened PIMA session with the attached device. This should be used after all session-orientated
|
||||
* PIMA commands have been issued to the device.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a raw PIMA block header to the device, filling out the transaction ID automatically. This can be used to send
|
||||
* arbitrary PIMA blocks to the device with or without parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] PIMAHeader Pointer to a PIMA container structure that is to be sent
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader);
|
||||
|
||||
/** Receives a raw PIMA block header to the device. This can be used to receive arbitrary PIMA blocks from the device with
|
||||
* or without parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[out] PIMAHeader Pointer to a PIMA container structure where the received block is to be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader);
|
||||
|
||||
/** Sends a given PIMA command to the attached device, filling out the PIMA command header's Transaction ID automatically.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] Operation PIMA operation code to issue to the device
|
||||
* \param[in] TotalParams Total number of 32-bit parameters to send to the device in the issued command block
|
||||
* \param[in] Params Pointer to an array of 32-bit values containing the parameters to send in the command block
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation,
|
||||
const uint8_t TotalParams, uint32_t* Params) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Receives and checks a response block from the attached PIMA device, once a command has been issued and all data
|
||||
* associated with the command has been transferred.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Indicates if the device has issued a PIMA event block to the host via the asynchronous events pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return Boolean true if an event is waiting to be read, false otherwise
|
||||
*/
|
||||
bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Receives an asynchronous event block from the device via the asynchronous events pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[out] PIMAHeader Pointer to a PIMA container structure where the event should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
|
||||
SI_PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Sends arbitrary data to the attached device, for use in the data phase of PIMA commands which require data
|
||||
* transfer beyond the regular PIMA command block parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] Buffer Pointer to a buffer where the data to send has been stored
|
||||
* \param[in] Bytes Length in bytes of the data in the buffer to send to the attached device
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer,
|
||||
const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Receives arbitrary data from the attached device, for use in the data phase of PIMA commands which require data
|
||||
* transfer beyond the regular PIMA command block parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[out] Buffer Pointer to a buffer where the received data is to be stored
|
||||
* \param[in] Bytes Length in bytes of the data to read
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer,
|
||||
const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Still Image host class interface, required for the correct operation of the
|
||||
* interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*/
|
||||
static inline void SImage_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo);
|
||||
static inline void SImage_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
(void)SIInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define STILL_IMAGE_CLASS 0x06
|
||||
#define STILL_IMAGE_SUBCLASS 0x01
|
||||
#define STILL_IMAGE_PROTOCOL 0x01
|
||||
|
||||
#define SI_FOUND_EVENTS_IN (1 << 0)
|
||||
#define SI_FOUND_DATAPIPE_IN (1 << 1)
|
||||
#define SI_FOUND_DATAPIPE_OUT (1 << 2)
|
||||
|
||||
#define COMMAND_DATA_TIMEOUT_MS 10000
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_SI_CLASS_HOST_C)
|
||||
static uint8_t DComp_SI_Host_NextSIInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Host mode driver for the library USB Still Image Class driver.
|
||||
*
|
||||
* Host mode driver for the library USB Still Image Class driver.
|
||||
*
|
||||
* \note This file should not be included directly. It is automatically included as needed by the class driver
|
||||
* dispatch header located in LUFA/Drivers/USB/Class/StillImage.h.
|
||||
*/
|
||||
|
||||
/** \ingroup Group_USBClassSI
|
||||
* @defgroup Group_USBClassStillImageHost Still Image Class Host Mode Driver
|
||||
*
|
||||
* \section Sec_Dependencies Module Source Dependencies
|
||||
* The following files must be built with any user project that uses this module:
|
||||
* - LUFA/Drivers/USB/Class/Host/StillImage.c
|
||||
*
|
||||
* \section Module Description
|
||||
* Host Mode USB Class driver framework interface, for the Still Image USB Class driver.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __SI_CLASS_HOST_H__
|
||||
#define __SI_CLASS_HOST_H__
|
||||
|
||||
/* Includes: */
|
||||
#include "../../USB.h"
|
||||
#include "../Common/StillImage.h"
|
||||
|
||||
/* Enable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if !defined(__INCLUDE_FROM_SI_DRIVER)
|
||||
#error Do not include this file directly. Include LUFA/Drivers/Class/StillImage.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** Error code for some Still Image Host functions, indicating a logical (and not hardware) error */
|
||||
#define SI_ERROR_LOGICAL_CMD_FAILED 0x80
|
||||
|
||||
/* Type Defines: */
|
||||
/** \brief Still Image Class Host Mode Configuration and State Structure.
|
||||
*
|
||||
* Class state structure. An instance of this structure should be made within the user application,
|
||||
* and passed to each of the Still Image class driver functions as the SIInterfaceInfo parameter. This
|
||||
* stores each Still Image interface's configuration and state information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const struct
|
||||
{
|
||||
uint8_t DataINPipeNumber; /**< Pipe number of the Still Image interface's IN data pipe */
|
||||
bool DataINPipeDoubleBank; /** Indicates if the Still Image interface's IN data pipe should use double banking */
|
||||
|
||||
uint8_t DataOUTPipeNumber; /**< Pipe number of the Still Image interface's OUT data pipe */
|
||||
bool DataOUTPipeDoubleBank; /** Indicates if the Still Image interface's OUT data pipe should use double banking */
|
||||
|
||||
uint8_t EventsPipeNumber; /**< Pipe number of the Still Image interface's IN events endpoint, if used */
|
||||
bool EventsPipeDoubleBank; /** Indicates if the Still Image interface's events data pipe should use double banking */
|
||||
} Config; /**< Config data for the USB class interface within the device. All elements in this section
|
||||
* <b>must</b> be set or the interface will fail to enumerate and operate correctly.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
|
||||
* after \ref SImage_Host_ConfigurePipes() is called and the Host state machine is in the
|
||||
* Configured state
|
||||
*/
|
||||
|
||||
uint16_t DataINPipeSize; /**< Size in bytes of the Still Image interface's IN data pipe */
|
||||
uint16_t DataOUTPipeSize; /**< Size in bytes of the Still Image interface's OUT data pipe */
|
||||
uint16_t EventsPipeSize; /**< Size in bytes of the Still Image interface's IN events pipe */
|
||||
|
||||
bool IsSessionOpen; /**< Indicates if a PIMA session is currently open with the attached device */
|
||||
uint32_t TransactionID; /**< Transaction ID for the next transaction to send to the device */
|
||||
} State; /**< State data for the USB class interface within the device. All elements in this section
|
||||
* <b>may</b> be set to initial values, but may also be ignored to default to sane values when
|
||||
* the interface is enumerated.
|
||||
*/
|
||||
} USB_ClassInfo_SI_Host_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error codes returned by the \ref SImage_Host_ConfigurePipes() function. */
|
||||
enum SIHost_EnumerationFailure_ErrorCodes_t
|
||||
{
|
||||
SI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully */
|
||||
SI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor */
|
||||
SI_ENUMERROR_NoSIInterfaceFound = 2, /**< A compatible Still Image interface was not found in the device's
|
||||
* Configuration Descriptor
|
||||
*/
|
||||
SI_ENUMERROR_EndpointsNotFound = 3, /**< Compatible Still Image data endpoints were not found in the
|
||||
* device's Still Image interface
|
||||
*/
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Host interface configuration routine, to configure a given Still Image host interface instance using the
|
||||
* Configuration Descriptor read from an attached USB device. This function automatically updates the given Still
|
||||
* Image Host instance's state values and configures the pipes required to communicate with the interface if it is
|
||||
* found within the device. This should be called once after the stack has enumerated the attached device, while
|
||||
* the host state machine is in the Addressed state.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor
|
||||
* \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor
|
||||
*
|
||||
* \return A value from the \ref SIHost_EnumerationFailure_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, uint16_t ConfigDescriptorSize,
|
||||
void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
/** Opens a new PIMA session with the attached device. This should be used before any session-orientated PIMA commands
|
||||
* are issued to the device. Only one session can be open at the one time.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Closes an already opened PIMA session with the attached device. This should be used after all session-orientated
|
||||
* PIMA commands have been issued to the device.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Sends a raw PIMA block header to the device, filling out the transaction ID automatically. This can be used to send
|
||||
* arbitrary PIMA blocks to the device with or without parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] PIMAHeader Pointer to a PIMA container structure that is to be sent
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader);
|
||||
|
||||
/** Receives a raw PIMA block header to the device. This can be used to receive arbitrary PIMA blocks from the device with
|
||||
* or without parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[out] PIMAHeader Pointer to a PIMA container structure where the received block is to be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader);
|
||||
|
||||
/** Sends a given PIMA command to the attached device, filling out the PIMA command header's Transaction ID automatically.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] Operation PIMA operation code to issue to the device
|
||||
* \param[in] TotalParams Total number of 32-bit parameters to send to the device in the issued command block
|
||||
* \param[in] Params Pointer to an array of 32-bit values containing the parameters to send in the command block
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, const uint16_t Operation,
|
||||
const uint8_t TotalParams, uint32_t* Params) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Receives and checks a response block from the attached PIMA device, once a command has been issued and all data
|
||||
* associated with the command has been transferred.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Indicates if the device has issued a PIMA event block to the host via the asynchronous events pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*
|
||||
* \return Boolean true if an event is waiting to be read, false otherwise
|
||||
*/
|
||||
bool SImage_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Receives an asynchronous event block from the device via the asynchronous events pipe.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[out] PIMAHeader Pointer to a PIMA container structure where the event should be stored
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
|
||||
* returned a logical command failure
|
||||
*/
|
||||
uint8_t SImage_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
|
||||
SI_PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
|
||||
ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Sends arbitrary data to the attached device, for use in the data phase of PIMA commands which require data
|
||||
* transfer beyond the regular PIMA command block parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[in] Buffer Pointer to a buffer where the data to send has been stored
|
||||
* \param[in] Bytes Length in bytes of the data in the buffer to send to the attached device
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer,
|
||||
const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/** Receives arbitrary data from the attached device, for use in the data phase of PIMA commands which require data
|
||||
* transfer beyond the regular PIMA command block parameters.
|
||||
*
|
||||
* \note This function must only be called when the Host state machine is in the HOST_STATE_Configured state or the
|
||||
* call will fail.
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
* \param[out] Buffer Pointer to a buffer where the received data is to be stored
|
||||
* \param[in] Bytes Length in bytes of the data to read
|
||||
*
|
||||
* \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum
|
||||
*/
|
||||
uint8_t SImage_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, void* Buffer,
|
||||
const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
|
||||
|
||||
/* Inline Functions: */
|
||||
/** General management task for a given Still Image host class interface, required for the correct operation of the
|
||||
* interface. This should be called frequently in the main program loop, before the master USB management task
|
||||
* \ref USB_USBTask().
|
||||
*
|
||||
* \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state
|
||||
*/
|
||||
static inline void SImage_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo);
|
||||
static inline void SImage_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
|
||||
{
|
||||
(void)SIInterfaceInfo;
|
||||
}
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define STILL_IMAGE_CLASS 0x06
|
||||
#define STILL_IMAGE_SUBCLASS 0x01
|
||||
#define STILL_IMAGE_PROTOCOL 0x01
|
||||
|
||||
#define SI_FOUND_EVENTS_IN (1 << 0)
|
||||
#define SI_FOUND_DATAPIPE_IN (1 << 1)
|
||||
#define SI_FOUND_DATAPIPE_OUT (1 << 2)
|
||||
|
||||
#define COMMAND_DATA_TIMEOUT_MS 10000
|
||||
|
||||
/* Function Prototypes: */
|
||||
#if defined(__INCLUDE_FROM_SI_CLASS_HOST_C)
|
||||
static uint8_t DComp_SI_Host_NextSIInterface(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
static uint8_t DComp_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor) ATTR_NON_NULL_PTR_ARG(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue