⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial_dl.cpp

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//------------------------------------------------------------------------------
//
//  File:  serial_dl.c
//
//  This is a hardware-independent USB Serial Client driver. It will interpret 
//  and respond to standard USB Host requests, as well as serial-specific
//  Host requests during initialization. 
//
//  This code is meant to provide the minimal set of routines necessary for USB
//  transfers, and is targeted for the boot-loader and small code size.

#include <windows.h>
#include <usbfntypes.h>
#include <usbfn.h>
#include <oal.h>
#include <oal_blserial.h>


//------------------------------------------------------------------------------
//
//  Entry points for calling application
//
extern "C" BOOL USBSerialInit();

static BOOL g_USBSerialInitialized = FALSE;


//------------------------------------------------------------------------------
//
//  Exit points to USB Function driver. Using the UFN MDD/PDD interfaces, reused
//  from OS driver. PDD Interface receives transfer information in 'STransfer's
//
UFN_MDD_INTERFACE_INFO g_mddInterface;
UFN_PDD_INTERFACE_INFO g_pddInterface;

STransfer g_EP0Transfer; // EP0
STransfer g_EP1Transfer; // Bulk out
STransfer g_EP2Transfer; // Bulk in


//------------------------------------------------------------------------------
//
//  Type:  DEVICE_STATE, g_DeviceState
//
//  Keep track of the USB state - Cable detatched, attached, initialized, etc.
//
enum DEVICE_STATE {
    DS_DETACHED = 0,
    DS_ATTACHED,
    DS_POWERED,
    DS_DEFAULT,
    DS_ADDRESSED,
    DS_CONFIGURED,
    DS_SUSPENDED,
};
enum DEVICE_STATE g_DeviceState = DS_DETACHED;


//------------------------------------------------------------------------------
//
//  Type:  TRANSFER_STATE
//
//  USB Serial defines 3 endpoints, hold the current state of each endpoint
//    0: Control
//    1: Receive Packets
//    2: Send Packets
//  
//
enum TRANSFER_STATE {
    TS_IDLE=0,
    TS_RECEIVING_MESSAGE,
    TS_SENDING_MESSAGE,
    TS_RECEIVING_PACKET,
    TS_SENDING_PACKET,
    TS_SENDING_PACKET_TERMINATOR
};
enum TRANSFER_STATE g_EP0State = TS_IDLE;
enum TRANSFER_STATE g_EP1State = TS_IDLE;
enum TRANSFER_STATE g_EP2State = TS_IDLE;

//------------------------------------------------------------------------------
//
//  Endpoint 0 Transfer types
//
//  Necessary for constructing Host responses and issuing them to hardware
typedef enum {
    EP0Setup = 0,
    EP0Out,
    EP0In
} EP0_DIR;

typedef struct _EP0_REQUEST EP0_REQUEST, *PEP0_REQUEST;
struct _EP0_REQUEST
{
    EP0_DIR eDir;
    UCHAR *pucData;
    DWORD dwExpectedSize;
    DWORD dwActualSize;
    VOID (*pfnNotification)(EP0_REQUEST *pRequest, PVOID pvUser);
    PVOID pvUser;

    DWORD dwProcessed;
    BOOL fCompleted;
};


//------------------------------------------------------------------------------
//
//  Receive buffer managment routines
//
//  This wrapper will buffer data coming from the hardware line, and provide
//  it to the application on request.
//
#define RECV_BUFFER_SIZE 1750  // Must be at least KITL_MTU + 1
#define SPACE_IN_BUFFER(head,tail) \
     (tail >= head ? tail-head : RECV_BUFFER_SIZE - head + tail)
#define SPACE_UNTIL_WRAP(tail) (RECV_BUFFER_SIZE - tail)

BYTE g_RecvBuffer[RECV_BUFFER_SIZE];
USHORT g_RecvBufferHead = 0;
USHORT g_RecvBufferTail = 0;


//------------------------------------------------------------------------------
//
//  USB Serial session descriptors
//
//  Data needed by the USB Host to initialize a USB Serial session
//
#define EP0MaxSize 16
#define EPMaxSize  64
#define CFGLEN     32    // Length of configuration descriptor
#define iCONF      18    // Index in gs_pucUSBDescriptors for Configuration Descriptors
#define iINF       27    // Index in gs_pucUsBDescriptors for Interface Descriptors

static USB_DEVICE_DESCRIPTOR deviceDescriptor;
static UFN_ENDPOINT rgEndPoints[3];
static UFN_INTERFACE Interface;
static UFN_CONFIGURATION deviceConfiguration;
static UFN_BUS_SPEED busSpeed;

///////////////////////////////
// Serial USB Descriptor Set //
///////////////////////////////

static UCHAR gs_pucUSBDescriptors[]=  {

/////////////////////////////////////////////
// Standard Device Descriptor (One Device) //
/////////////////////////////////////////////

/* 0  */    18,                 // bLength
/* 1  */    USB_DEVICE_DESCRIPTOR_TYPE, 
/* 2  */    0, 1,               // bcdUSB
/* 4  */    0xff,               // bDeviceClass (0xFF = Vendor Specific)
/* 5  */    0xff,               // bDeviceSubClass
/* 6  */    0xff,               // bDeviceProtocol
/* 7  */    EP0MaxSize,         // bMaxPacketSize0
/* 8  */    0x5E, 0x04,         // idVendor (Microsoft Vendor ID)
#if USING_USBSER
/* 10 */    0x79, 0x00,         // idProduct
/* 12 */    0x90, 0,            // bcdDevice
#else
/* 10 */    0xCE, 0x00,         // idProduct
/* 12 */    0, 0,               // bcdDevice
#endif
/* 14 */    0,                  // iManufacturer - index of Manf String Descriptor
/* 15 */    0,                  // iProduct - index of Product String Descriptor
/* 16 */    0,                  // iSerialNumber - Index of Serial Number String
/* 17 */    1,                  // bNumConfigurations

///////////////////////////////////////////////////////////
// Standard Configuration Descriptor (One Configuration) //
///////////////////////////////////////////////////////////

/* 18 */    9,                  // bLength
/* 19 */    USB_CONFIGURATION_DESCRIPTOR_TYPE, 
/* 20 */    CFGLEN%256,CFGLEN/256,  // wTotalLength
/* 22 */    1,                  // bNumInterfaces
/* 23 */    1,                  // bConfigurationValue
/* 24 */    0,                  // iConfiguration
/* 25 */    0x40,               // bmAttributes (self powered)
/* 26 */    1,                  // MaxPower (x2 mA)

///////////////////////////////////////////////////
// Standard Interface Descriptor (One Interface) //
///////////////////////////////////////////////////

/* 27 */    9,                  // bLength
/* 28 */    USB_INTERFACE_DESCRIPTOR_TYPE, 
/* 29 */    0,                  // bInterfaceNumber
/* 30 */    0,                  // bAlternateSetting
/* 31 */    2,                  // bNumEndpoints (number endpoints used, excluding EP0)
/* 32 */    0xff,               // bInterfaceClass
/* 33 */    0xff,               // bInterfaceSubClass
/* 34 */    0xff,               // bInterfaceProtocol
/* 35 */    0,                  // ilInterface  (Index of this interface string desc.)

///////////////////////////////////////////////////
// Standard Endpoint Descriptor (EP1 - BULK OUT) //
///////////////////////////////////////////////////

/* 36 */    7,                  // bLength
/* 37 */    USB_ENDPOINT_DESCRIPTOR_TYPE,
/* 38 */    0x01,               // bEndpointAddress (EP 1, OUT)
/* 39 */    2,                  // bmAttributes  (0010 = Bulk)
/* 40 */    EPMaxSize, 0,       // wMaxPacketSize
/* 42 */    0,                  // bInterval (ignored for Bulk)

//////////////////////////////////////////////////
// Standard Endpoint Descriptor (EP2 - BULK IN) //
//////////////////////////////////////////////////

/* 43 */    7,                  // bLength
/* 44 */    USB_ENDPOINT_DESCRIPTOR_TYPE,   
/* 45 */    0x82,               // bEndpointAddress (EP 2, IN)
/* 46 */    2,                  // bmAttributes  (0010 = Bulk)
/* 47 */    EPMaxSize, 0,       // wMaxPacketSize
/* 49 */    0                   // bInterval (ignored for Bulk)
};

// Device specific request
#define SET_CONTROL_LINE_STATE  0x22


//------------------------------------------------------------------------------
//
//  Function:  Interrupt Thread
//
//  Entry to PDD interrupt thread. This will be called repeatedly (bootloader uses polling)
//
extern "C" DWORD InterruptThread(VOID *pPddContext);
extern "C" BOOL InitializeHardware(); // Hook for board-specific init (GPIO's, clocks, etc)
extern "C" void msWait(UINT32 msVal);

//------------------------------------------------------------------------------
//
//  Function:  HandleUSBDeviceRegistration
//
//  Negotiate for physical bulk endpoints for send/receive. Negotiate hardware's
//  maxPacketSizes and update our descriptors to reflect hardware capabilities.
//
static void HandleUSBDeviceRegistration()
{
    DWORD dwRet;
    DWORD logicalEndPoint;
    DWORD physicalEndPoint;
    BOOL logEndPointTaken[4] = {FALSE, FALSE, FALSE, FALSE};
    BOOL physEndPointTaken[16] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
                                  FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE };

    USB_CONFIGURATION_DESCRIPTOR *pUsbConfDesc = (USB_CONFIGURATION_DESCRIPTOR*)&gs_pucUSBDescriptors[iCONF];
    USB_INTERFACE_DESCRIPTOR *pUsbInfDesc = (USB_INTERFACE_DESCRIPTOR*)&gs_pucUSBDescriptors[iINF];

    // Fill descriptors that the PDD will use to register configuration and interface
    deviceConfiguration.pInterfaces = &Interface;
    deviceConfiguration.Descriptor.bNumInterfaces = 1;
    Interface.pEndpoints = rgEndPoints;
    Interface.Descriptor.bNumEndpoints = 2;
    deviceDescriptor.bMaxPacketSize0 = EP0MaxSize;
    busSpeed = BS_FULL_SPEED;

    // Fill endpoint descriptors with some initial values, and negotiate them with PDD
    // Logical EP0
    rgEndPoints[0].Descriptor.bEndpointAddress = 0x00;
    rgEndPoints[0].Descriptor.wMaxPacketSize = EP0MaxSize;
    rgEndPoints[0].Descriptor.bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
    // Logical EP1
    rgEndPoints[1].Descriptor.bEndpointAddress = 0x01; // EP1, OUT (BULK) 
    rgEndPoints[1].Descriptor.wMaxPacketSize = EPMaxSize;
    rgEndPoints[1].Descriptor.bmAttributes = USB_ENDPOINT_TYPE_BULK;
    // Logical EP2	
    rgEndPoints[2].Descriptor.bEndpointAddress = 0x82; // EP2, IN (BULK) 
    rgEndPoints[2].Descriptor.wMaxPacketSize = EPMaxSize;
    rgEndPoints[2].Descriptor.bmAttributes = USB_ENDPOINT_TYPE_BULK;

    // Ensure that the specified endpoint 0 can be supported
    dwRet = g_pddInterface.pfnIsEndpointSupportable(
        g_pddInterface.pvPddContext, 0, busSpeed, &rgEndPoints[0].Descriptor, 0,0,0);
    if( dwRet != ERROR_SUCCESS )
        {
        OALMSG(OAL_ETHER&&OAL_FUNC, (L"ERROR: PDD cannot support endpoint 0\r\n"));
        }

    // Setup remaining endpoints (Logical endpoints 1 and 2 for Serial) 
    for( logicalEndPoint = 1; logicalEndPoint <=2; logicalEndPoint++)
        {
        for( physicalEndPoint=1; physicalEndPoint<16; physicalEndPoint++ )
            {

            if( !physEndPointTaken[physicalEndPoint] )
                {

               rgEndPoints[logicalEndPoint].Descriptor.bEndpointAddress &= ~0x7F;
               rgEndPoints[logicalEndPoint].Descriptor.bEndpointAddress |= physicalEndPoint;

               dwRet = g_pddInterface.pfnIsEndpointSupportable(
	            g_pddInterface.pvPddContext, 
	            physicalEndPoint, busSpeed, &rgEndPoints[logicalEndPoint].Descriptor, 
	            pUsbConfDesc->bConfigurationValue,
	            pUsbInfDesc->bInterfaceNumber, pUsbInfDesc->bAlternateSetting);

	        if( dwRet == ERROR_SUCCESS )
                   {
                   OALMSG(OAL_ETHER&&OAL_FUNC, (L"Mapping %d to %d\r\n", logicalEndPoint, physicalEndPoint));
                   physEndPointTaken[physicalEndPoint] = TRUE;
		     logEndPointTaken[logicalEndPoint] = TRUE;
                   break;
	            }
               }
    	    }

        if( !logEndPointTaken[logicalEndPoint])
            {
	     OALMSG(OAL_ETHER&&OAL_FUNC, (L"ERROR: PDD cannot support logical endpoint %d\r\n", logicalEndPoint));
	     break;
	     }
    	}

    // Update master descriptor with negotiated values. 
    // Logical EP1
    gs_pucUSBDescriptors[38] = rgEndPoints[1].Descriptor.bEndpointAddress;
    gs_pucUSBDescriptors[40] = (UCHAR)((rgEndPoints[1].Descriptor.wMaxPacketSize >> 0) & 0xFF);
    gs_pucUSBDescriptors[41] = (UCHAR)((rgEndPoints[1].Descriptor.wMaxPacketSize >> 8) & 0xFF);
    // Logical EP2
    gs_pucUSBDescriptors[45] = rgEndPoints[2].Descriptor.bEndpointAddress;
    gs_pucUSBDescriptors[47] = (UCHAR)((rgEndPoints[2].Descriptor.wMaxPacketSize >> 0) & 0xFF);
    gs_pucUSBDescriptors[48] = (UCHAR)((rgEndPoints[2].Descriptor.wMaxPacketSize >> 8) & 0xFF);

    // We assume knowledge of the RegisterDevice function implementation and pass very simplified arguments
    g_pddInterface.pfnRegisterDevice( g_pddInterface.pvPddContext, 
                                        NULL, NULL, NULL,
                                        &deviceDescriptor, &deviceConfiguration, NULL,
                                        NULL, 0 );

}

//------------------------------------------------------------------------------
//
//  Function:  HandleClassRequest
//
//  Called by HandleSetupPkt when type is USB_REQUEST_CLASS.
//  This is serial-function specific stuff that updates modem status
//
void HandleClassRequest(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
    if (pUdr->bmRequestType == (USB_REQUEST_CLASS | USB_REQUEST_FOR_INTERFACE | USB_REQUEST_HOST_TO_DEVICE) ) 
    {
        if( pUdr->bRequest == SET_CONTROL_LINE_STATE ) 
        {
            // Fill out pRequest structure such that a handshake is sent
            // and ignore any line status data
            pRequest->eDir = EP0Setup;
            pRequest->pucData = NULL;
            pRequest->dwExpectedSize = 0;
            pRequest->dwActualSize = 0;
            pRequest->pfnNotification = NULL;
            pRequest->pvUser = NULL;
        }
        else ASSERT(!"Host indicated an unsupported SET Class Request");
    }
    else
    {
        ASSERT(!"Host sent unhandled request type!");
    }
}


//------------------------------------------------------------------------------
//
//  Function:  HandleGetDescriptor
//
//  Called by HandleSetupPkt when type is USB_REQUEST_GET_DESCRIPTOR.
//  Will manage transmission of descriptors, strings, etc.
//
void HandleGetDescriptor(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
    UCHAR *pucData;
    WORD wLength;

    switch(HIBYTE(pUdr->wValue))
    {
    case USB_DEVICE_DESCRIPTOR_TYPE:
        pucData = (UCHAR *)gs_pucUSBDescriptors;
        wLength = gs_pucUSBDescriptors[0];
        break;
    case USB_CONFIGURATION_DESCRIPTOR_TYPE:
        pucData = (UCHAR *)&gs_pucUSBDescriptors[iCONF];
        wLength = CFGLEN;
        break;
    case USB_STRING_DESCRIPTOR_TYPE:
        pucData = NULL;
        wLength = 0;
        break;
    default:
        ASSERT(!"Unhandled Get DESCRIPTOR_TYPE!");
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -