UsbHostController.h

Committer:
RichardUK
Date:
2012-09-19
Revision:
2:33e7ce63dd6d
Parent:
1:4461071ed964

File content as of revision 2:33e7ce63dd6d:

/**
    A host controller driver from the mBed device.
    Copyright (C) 2012  Richard e Collins - richard.collins@linux.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.    
*/

#ifndef __USB_HOST_CONTROLLER_H__
#define __USB_HOST_CONTROLLER_H__

#include <stdint.h>

namespace USB
{

struct HostControllerCommunicationsArea;
struct LinkedListItem;
struct EndpointDescriptor;
struct TransferDescriptor;
struct Device;
struct TransferCallback;

struct HostControllerMessages
{
    /**
     * Called when a device has been connected to a hub, be it the root controller hub or a usb hub.
     */
    virtual void AddDevice(int hub,int port,int hubPortStatus) = 0;
    
    /**
     * Called when a transfer has been done. Depending on the transfer type it may be called a few times for one high level action.
     * For example a ControlTransfer can cause 3 replies, one for the setup packet, one for the data and one for the ack knollage msg.
     */
     virtual void TransferDone(TransferDescriptor *transfer) = 0;
};

struct HostController
{
    struct
    {
        unsigned newDeviceConnected:1;
        unsigned unrecoverableError:1;
    }flags;
    
    /*
     * The number of the pool items currently allocated by the system.
     */
    int numAllocatedPoolItems;
    
    uint32_t USBInterupt();

    
protected:
    friend class Host;

    /**
     * Returns the singleton used for interacting with the root hub controller.
     */
    static HostController *get();
    
    /**
     * Once started never stopped, as the memory is in reserved space there is nothing gained in stopping it.
     */
    void Init(HostControllerMessages *messageCallback,Device*& deviceZero);
    
    /**
     * Handles state changes from interupts and calls functions from results interupt transfers.
     * Has to be done on main thread as I have no control of the callbacks execute time. Don't want to kill the interupt handlers.
     */
    void Update();
    
    /**
     * The memory returned is 16 bytes in size.
     */
    void *AllocateMemoryPoolItem();
    
    /**
     * An item that had preveslly been allocated from a call to 'AllocateMemoryPoolItem'.
     */
    void FreeMemoryPoolItem(void *item);
    
    /*
     * Allocates an endpoint to use in a USB data transfer.
     */
    EndpointDescriptor *GetEndpointDescriptor(EndpointDescriptor** headED,uint32_t functionAddress,int endpointNumber,int maximumPacketSize,int lowspeed);
    
    /*
     * Allocates a transfer descriptor to use in a USB data transfer.
     * direction == 0 for SETUP, == 1 for OUT (to device) and == 2 for IN (from device)
     * dataToggle == 0 for DATA0 and == 1 for DATA1
     */
    TransferDescriptor *AllocateTransferDescriptor(int deviceID,int direction,const uint8_t* data,int dataLength);
    
    /**
     * Adds the endpoint to the host controller so that the next frame it will be processed for control transfers.
     */
    void QueueControlTransfer(int deviceID,int direction,int endpointNumber,int maximumPacketSize,int lowspeed,int dataToggle,const uint8_t* data,int dataLength);
    
    /**
     * Adds the endpoint to the host controller so that the next frame it will be processed for bulk transfers.
     */
    void QueueBulkTransfer(int deviceID,int direction,int endpointNumber,int maximumPacketSize,int lowspeed,TransferCallback* callback,const uint8_t* data,int dataLength);
    
    /**
     * Temp work buffer, not used in this code, the driver, but is used in the host code that calls it.
     */
    uint8_t* getScratchRam();
    
    /**
     * Return how many of the pool items are being used.
     */
    int getNumAllocatedPoolItems()
    {
        return numAllocatedPoolItems;
    }
    
    /*
     * Removes all the endpoints associated with this device from the host controller.
     */
    void DetachDevice(int deviceID);
    
private:
        /*
     * Will be useing the first block of extra SRAM. There are two extra 16k blocks.
     * These blocks have their own DMA and so don't interupt the CPU.
     * Also as they are seperated from the main 32k of SRAM we are not
     * stealing from the heap or the stack.
     *
     *  The LPC1768 contains 64 kB of on-chip static RAM memory. Up to 32 kB of SRAM,
     * accessible by the CPU and all three DMA controllers are on a higher-speed bus. Devices
     * containing more than 32 kB SRAM have two additional 16 kB SRAM blocks, each situated
     * on separate slave ports on the AHB multilayer matrix.
     * This architecture allows the possibility for CPU and DMA accesses to be separated in
     * such a way that there are few or no delays for the bus masters.
     */
    HostControllerCommunicationsArea *commsArea;
 
    /**
     * The object that recivies messages from the host controller.
     */
    HostControllerMessages *messageCallback;
    
    
    /**
     * This is the linked list object for the memory pool.
     */
    LinkedListItem *memoryPoolHead;

        
    /**
     * Because of noise on the lines we can get spammed in the usb interupt. (could because I am missing some resisters)
     * So what I do is reset this timeout each time we get told the status has changed.
     * When it has settled down the timeout will nolonger get reset on so will fire.
     * At that point i'll tell the Update function that it needs update the root hub object.
     */
    Timeout delayedRootHubStatusChangeTimeout;
    
    /**
     * The state of the last status change interupt.
     */
    uint32_t hubPortStatus;
    
    /**
     * Removes all the endpoints for a given device from the passed list.
     */
    void RemoveEndpointsForDevice(int deviceID,EndpointDescriptor **list);
    
    /**
     * Adds the endpoint to the host controller so that the next frame it will be processed for transfers.
     */
    TransferDescriptor* QueueTransfer(EndpointDescriptor** headED,int deviceID,int direction,int endpointNumber,int maximumPacketSize,int lowspeed,const uint8_t* data,int dataLength);

    
};//class Controller

};//namespace USB

#endif //#ifndef __USB_HOST_CONTROLLER_H__