📄 lib_desc.c
字号:
//*----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : lib_desc.c
//* Object : USB peripheral library.
//*
//* 1.0 07/23/01 ODi : Creation
//*----------------------------------------------------------------------------
#include "periph/usb/lib_desc.h"
typedef enum {
SETUP,
DATA_IN,
DATA_OUT,
STATUS_IN,
STATUS_OUT,
UNKNOWN
} USB_CTL_STAGE;
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
// //////////////////////////////////////////////////////////////////////////
void usbDescInHandler(
SPipe *pPipe) /* IN pipe handler */
{
register u_int uisr;
uisr = at91_usb_ep_uisr(USB_ENDPOINT_REF(pPipe));
// Previous packet has been sent successfully an ACK has been received
if (uisr & USB_TXCOMPLETE) {
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), USB_TXCOMPLETE);
// Send the next data payload
if ( !(pPipe->pBuffer->IsEmpty(pPipe->pBuffer)) )
pPipe->pPeriph->Send(pPipe->pPeriph);
}
else
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), uisr);
}
// //////////////////////////////////////////////////////////////////////////
void usbDescOutHandler(
SPipe *pPipe) /* OUT pipe handler */
{
register u_int uisr;
uisr = at91_usb_ep_uisr(USB_ENDPOINT_REF(pPipe));
// Previous packet has been sent successfully an ACK has been received
if (uisr & (USB_RCV_DATA_BANK0 | USB_RCV_DATA_BANK1)) {
// Receive the next data payload
if ( !(pPipe->pBuffer->IsFull(pPipe->pBuffer)) )
pPipe->pPeriph->Receive(pPipe->pPeriph);
else
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), uisr);
}
else
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), uisr);
}
// //////////////////////////////////////////////////////////////////////////
int cpt;
void usbDescCtlHandler(
USBDesc const *pDesc, /* Application request handlers */
SPipe *pPipe, /* Control pipe handler */
USBSetupData *pSetup, /* Pointer to a setup structure as defined in USB spec */
char *dataOut, /* Buffer used in DATA OUT transactions */
unsigned int dataOutMax , /* Buffer size */
unsigned int *dataOutSize) /* Number of bytes received */
{
register u_int uisr;
uisr = at91_usb_ep_uisr(USB_ENDPOINT_REF(pPipe));
// A setup packet has been received and automatically acknowledged by the macro
if (uisr & USB_RXSETUP) {
/* Clear stall, this is not done by the macro */
//at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), (USB_TXCOMPLETE | USB_STALLSENT | USB_FORCESTALL));
/* Read the setup packet */
at91_usb_ep_read( USB_ENDPOINT_REF(pPipe),
(char *) pSetup,
sizeof(USBSetupData));
// **** DEVICE -> HOST transfer, init a Data IN stage
if (pSetup->bmRequestType & (1 << 7)) {
/* Enable the READ on control endpoint */
at91_usb_ep_ctrl_read(USB_ENDPOINT_REF(pPipe));
/* Clear all RXSETUP interrupts */
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), USB_RXSETUP);
/* Handle the request */
usbDescDispatchRequest(pDesc, pPipe, pSetup);
}
// **** HOST -> DEVICE transfer, init a Data OUT stage
else {
/* Clear the RXSETUP interrupt */
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), USB_RXSETUP);
/* If no Data stage, handle the request */
if (pSetup->wLength == 0) {
usbDescDispatchRequest(pDesc, pPipe, pSetup);
}
else {
if (cpt == 2)
pPipe->Read(pPipe, dataOut, MIN(dataOutMax, pSetup->wLength));
else
pPipe->Read(pPipe, dataOut, MIN(dataOutMax, pSetup->wLength));
++cpt;
}
}
}
// A Data OUT trqnsfer has been received and acknowledge. Macro is waiting for
// the uC to read data in the DPR => USR_RCV_DATA_BANK0 is set
else if (uisr & USB_RCV_DATA_BANK0) {
// **** DEVICE -> HOST (End of Status OUT Stage)
if (pSetup->bmRequestType & (1 << 7))
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), USB_RCV_DATA_BANK0);
// **** HOST -> DEVICE (Data OUT Stage)
else {
// This check is just to prevent from extra DATA OUT (not specified in USB spec)
if ( (pPipe->pBuffer->IsFull(pPipe->pBuffer)) ) {
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), USB_RCV_DATA_BANK0);
usbDescRequestError(pPipe);
}
else {
// Accept the Data OUT payload
*dataOutSize += pPipe->pPeriph->Receive(pPipe->pPeriph);
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), USB_RCV_DATA_BANK0);
// If the Data OUT stage is achieved, handle the request
if (pPipe->pBuffer->IsFull(pPipe->pBuffer)) {
if (cpt > 1)
usbDescDispatchRequest(pDesc, pPipe, pSetup);
else
usbDescDispatchRequest(pDesc, pPipe, pSetup);
}
}
}
}
// An ACK has been received after a DATA IN transfer => USB_TXCOMPLETE is set
else if (uisr & USB_TXCOMPLETE) {
// Clear USB_TXCOMPLETE
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), USB_TXCOMPLETE);
// **** DEVICE -> HOST (Data IN Stage)
if (pSetup->bmRequestType & (1 << 7))
pPipe->pPeriph->Send(pPipe->pPeriph);
// **** HOST -> DEVICE (Status IN Stage)
else {
// Test if this is a setAddress()
if ((pSetup->bmRequestType == 0) && (pSetup->bRequest == USB_SET_ADDRESS) ) {
// Valid Address: set the Device State
if (pSetup->wValue != 0) {
at91_usb_set_address(USB_PIPE_REF(pPipe), pSetup->wValue);
at91_usb_set_state(USB_PIPE_REF(pPipe), USB_FADDEN);
}
// Back to the default device State
else {
at91_usb_set_address(USB_PIPE_REF(pPipe), 0);
at91_usb_set_state(USB_PIPE_REF(pPipe), 0);
}
}
}
}
// The STALL has been acknowledged, Clear the USB_FORCESTALL to accept the next setup packet
else if (uisr & USB_STALLSENT) {
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), (USB_FORCESTALL | USB_STALLSENT));
}
/* ==== Default behavior ==== */
else if (uisr) {
/* Should not happen */
at91_usb_ep_uicr(USB_ENDPOINT_REF(pPipe), uisr);
}
}
/* ************************************ */
/* usbDescDispatchRequest */
/* */
/* Arguments: */
/* pPipe: pointer to default pipe */
/* handler */
/* pSetup: pointer to setup datas */
/* Return: */
/* Nothing */
/* Description: */
/* This request handle standard */
/* request or call */
/* usbDescDispatchClassRequest */
/* usbDescDispatchVendorRequest */
/* ************************************ */
void usbDescDispatchRequest(USBDesc const *pDesc, SPipe *pPipe, USBSetupData *pSetup)
{
switch ((pSetup->bmRequestType & (0x60)) >> 5) {
case 0: /* Standard request */
switch (pSetup->bRequest) {
case USB_CLEAR_FEATURE: usbDescClearFeature( (void (*) ()) pDesc->clearFeature, pPipe, pSetup); break;
case USB_GET_CONFIGURATION: usbDescGetConfiguration((void (*) ()) pDesc->getConfiguration, pPipe, pSetup); break;
case USB_GET_DESCRIPTOR: usbDescGetDescriptor( (void (*) ()) pDesc->getDescriptor, pPipe, pSetup); break;
case USB_GET_INTERFACE: usbDescGetInterface( (void (*) ()) pDesc->getInterface, pPipe, pSetup); break;
case USB_GET_STATUS: usbDescGetStatus( (void (*) ()) pDesc->getStatus, pPipe, pSetup); break;
case USB_SET_ADDRESS: usbDescSetAddress( (void (*) ()) pDesc->setAddress, pPipe, pSetup); break;
case USB_SET_CONFIGURATION: usbDescSetConfiguration((void (*) ()) pDesc->setConfiguration, pPipe, pSetup); break;
case USB_SET_DESCRIPTOR: usbDescSetDescriptor( (void (*) ()) pDesc->setDescriptor, pPipe, pSetup); break;
case USB_SET_FEATURE: usbDescSetFeature( (void (*) ()) pDesc->setFeature, pPipe, pSetup); break;
case USB_SET_INTERFACE: usbDescSetInterface( (void (*) ()) pDesc->setInterface, pPipe, pSetup); break;
case USB_SYNCH_FRAME: usbDescSynchFrame( (void (*) ()) pDesc->synchFrame, pPipe, pSetup); break;
default: usbDescRequestError(pPipe); break;
}
break;
case 1: /* Class request */
if (pDesc->dispatchClassRequest)
pDesc->dispatchClassRequest(pPipe, pSetup, pDesc->pPrivateClassData);
break;
case 2: /* Vendor request */
if (pDesc->dispatchVendorRequest)
pDesc->dispatchVendorRequest(pPipe, pSetup, pDesc->pPrivateVendorData);
break;
default: /* Reserved */
usbDescRequestError(pPipe);
break;
}
return;
}
/* ************************************ */
/* usbDescClearFeature */
/* */
/* Arguments: */
/* pPipe: pointer to default pipe */
/* handler */
/* pSetup: pointer to setup datas */
/* Return: */
/* Nothing */
/* Description: */
/* This request is used to clear or */
/* disable a specific feature */
/* ************************************ */
void usbDescClearFeature(
void (*clearFeature) (), /* Pointer to application request handler */
SPipe *pPipe, /* Default Pipe Handler */
USBSetupData *pSetup) /* Descriptor type */
{
u_int usbState = at91_usb_get_state(USB_PIPE_REF(pPipe));
u_int recipient = (pSetup->bmRequestType & 0x1F);
/* Check request arguments */
if (recipient > 2 || pSetup->wLength != 0)
/* Device behavior not specified */
usbDescRequestError(pPipe);
/* ================ Configured state ================= */
else if ( (usbState & USB_CONFG) ) {
/* If an application handler exists, transmit the request */
if (clearFeature)
(*clearFeature)(pPipe, recipient, pSetup->wIndex, pSetup->wValue);
else
usbDescRequestError(pPipe);
}
/* =================== Address state ================= */
else if ( (usbState & USB_FADDEN) ) {
/* This request is valid in Address State only when reference endpoint 0 */
if (recipient != 0 && pSetup->wIndex != 0)
usbDescRequestError(pPipe);
else {
/* If an application handler exists, transmit the request */
if (clearFeature )
(*clearFeature)(pPipe, recipient, pSetup->wIndex, pSetup->wValue);
else
usbDescRequestError(pPipe);
}
}
/* =================== Default state ================= */
else
/* Device behavior not specified */
usbDescRequestError(pPipe);
}
/* ************************************ */
/* usbDescGetConfiguration */
/* */
/* Arguments: */
/* pPipe: pointer to default pipe */
/* handler */
/* pSetup: pointer to setup datas */
/* Return: */
/* Nothing */
/* Description: */
/* This request returns the current */
/* device configuration value */
/* ************************************ */
void usbDescGetConfiguration(
void (*getConfiguration) (), /* Pointer to application request handler */
SPipe *pPipe, /* Default Pipe Handler */
USBSetupData *pSetup) /* Descriptor type */
{
u_int usbState = at91_usb_get_state(USB_PIPE_REF(pPipe));
/* Check request arguments */
if (pSetup->wValue != 0 || pSetup->wIndex != 0 || pSetup->wLength != 1)
/* Device behavior not specified */
usbDescRequestError(pPipe);
/* ================ Configured state ================= */
else if ( (usbState & USB_CONFG) ) {
/* If an application handler exists, transmit the request */
if (getConfiguration )
(*getConfiguration)(pPipe);
else
usbDescRequestError(pPipe);
}
/* =================== Address state ================= */
else if ( (usbState & USB_FADDEN) )
/* Return a 0 value */
pPipe->Write(pPipe, "\0x00", 1);
/* =================== Default state ================= */
else
/* Device behavior not specified */
usbDescRequestError(pPipe);
}
/* ************************************ */
/* usbDescGetDescriptor */
/* */
/* Arguments: */
/* pPipe: pointer to default pipe */
/* handler */
/* pSetup: pointer to setup datas */
/* Return: */
/* Nothing */
/* Description: */
/* This request returns the */
/* specified descriptor if the */
/* descriptor exists */
/* ************************************ */
void usbDescGetDescriptor(
void (*getDescriptor) (), /* Pointer to application request handler */
SPipe *pPipe, /* Default Pipe Handler */
USBSetupData *pSetup) /* Descriptor type */
{
/* This request is valid in all states */
if (getDescriptor)
(*getDescriptor)(
pPipe,
((pSetup->wValue) >> 8), /* Descriptor type */
((pSetup->wValue) & 0xFF), /* Descriptor Index */
pSetup->wIndex, /* Language ID */
pSetup->wLength); /* Descripotr Length */
else
usbDescRequestError(pPipe);
}
/* ************************************ */
/* usbDescGetInterface */
/* */
/* Arguments: */
/* pPipe: pointer to default pipe */
/* handler */
/* pSetup: pointer to setup datas */
/* Return: */
/* Nothing */
/* Description: */
/* This request returns the */
/* selected alternate setting for */
/* the specified interface */
/* ************************************ */
void usbDescGetInterface(
void (*getInterface) (), /* Pointer to application request handler */
SPipe *pPipe, /* Default Pipe Handler */
USBSetupData *pSetup) /* Descriptor type */
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -