UsbHost.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/>.
    
        I have written this lib for two reasons, 1 so that I have code that I know works and 2 because I wanted to learn USB.
    The first release is unfinished due to the lack of time to test all the transfer types. As and when I find time
    to implement the other parts I will update the lib. I hope this should be finished by June 2012. I 'hope' ;)
    
    Some of the comments and enums / structs taken from the libusb project.    libusb.org
    
    Also borrowed some bits from http://www.beyondlogic.org/usbnutshell    A very good read.
    
    Another good read. http://www.usbmadesimple.co.uk/ums_4.htm (took some comments from here too)
    
    I also used the code in USBHost as a reference although it is a little unstructured and has some bad coding habbits in to so I would recommend advoiding that code.
*/


#ifndef __USBHOST_H__
#define __USBHOST_H__

#include "UsbHostController.h"
#include "UsbEnums.h"
#include "UsbStructures.h"

namespace USB
{



#define MAX_DEVICES 4
#define DEFAULT_TIMEOUT 500

//Some forward definitions of types. Done so we don't have to include all the headers. Helps to stop include spaghetti.
struct HostController;
struct Device;
struct DeviceDescriptor;
struct TransferCallback;

struct Host : HostControllerMessages
{
    
    Host();
    ~Host();

    /**
     * Polls the driver so it can get some if it's non interupt work done.
     */
    virtual void Update();
    
    /**
     * Fetches the device description, this is the basic structure returned by the device.
     */
    int getDeviceDescriptor(int deviceID,DeviceDescription &description);
    
    /**
     * The memory pointer returned is a block of memory for the configurtaion and it's interfaces and their endpoints as one block.
     */
    const uint8_t* getConfigurationDescriptor(int deviceID,int index);
    
    /**
     * Fetches the string at the passed index.
     */
    const char* getStringDescriptor(int deviceID,int index);
    
    /**
     * Sets the configuration to be used.
     */
    int setConfiguration(int deviceID,int configuration);
    
    /**
     * Perform a USB control transfer.
     * The direction of the transfer is inferred from the requestType field of the setup packet.
     * Function is blocking, will return with result or fail on error or timeout.
     * 
     * TODO: Code needs error codes and error checking such as is the data size larger than the EP allows (ok don't need to check as the device will respond with multiple packets)
     *
     * @param device          a handle for the device to communicate with
     * @param requestType     the request type field for the setup packet
     * @param bRequest        the request field for the setup packet
     * @param value           the value field for the setup packet
     * @param index           the index field for the setup packet
     * @param data            a suitably-sized data buffer for either input or output (depending on direction bits within requestType)
     * @param length          the length field for the setup packet. The data buffer should be at least this size.
     * @param timeout         timeout (in millseconds) that this function should wait before giving up due to no response being received. For an unlimited timeout, use value 0. (currently does nothing)
     */
    int ControlTransfer(int deviceID,uint8_t requestType, uint8_t request, uint16_t value, uint16_t index,const uint8_t *data, uint16_t length, uint32_t timeout);

    /**
     * Perform a USB bulk transfer.
     * The direction of the transfer is inferred from the direction bits of the endpoint address.
     * For bulk reads, the length field indicates the maximum length of data you are expecting to receive. If less data arrives than expected, this function will return that data, so be sure to check the transferred output parameter.
     * You should also check the transferred parameter for bulk writes. Not all of the data may have been written.
     * Also check transferred when dealing with a timeout error code. libusb may have to split your transfer into a number of chunks to satisfy underlying O/S requirements, meaning that the timeout may expire after the first few chunks have completed. libusb is careful not to lose any data that may have been transferred; do not assume that timeout conditions indicate a complete lack of I/O.
     *
     * @param device        A handle for the device to communicate with
     * @param endpoint      The address of a valid endpoint to communicate with
     * @param data          A suitably-sized data buffer for either input or output (depending on endpoint)
     * @param length        For bulk writes, the number of bytes from data to be sent. for bulk reads, the maximum number of bytes to receive into the data buffer.
     * @param callbackID    If set then when the transfer is complete the callback will be called with this ID and the information about the transfer.
     */
    int BulkTransfer(int device,uint8_t endpoint,const uint8_t* data,int length,TransferCallback* callback = NULL);
    
    /**
     * When a usb device is connected this is called.
     */
    virtual void onConnected(int deviceID,const DeviceDescription& description) = 0;
    
    /**
     * Called when a device disconnects from the system.
     */
    virtual void onDisconnected(int deviceID) = 0;

protected:

    virtual void AddDevice(int hub,int port,int hubPortStatus);
    virtual void TransferDone(TransferDescriptor *transfer);

private:
    HostController* driver;
    Device *devices[MAX_DEVICES];
    
    /**
     * The way the hardware and the spec is designed there is only one device in setup mode.
     * This device will be the only one to respond to requests.
     * To keep the code simple, that is not having a different code path for device zero
     * I use this struct for the init phase.
     */
    Device* deviceZero;
    
    /**
     * Allocates the device from the memory pool on the driver and put it in our array.
     * Because the array size is fixed (for speed and memory) this function may return NULL
     * when more than MAX_DEVICES is connected.
     */
    Device* AllocateDevice(int endpointZeroMaxPacketSize,int hubPortStatus);
    
    void SendControlTransferData(Device* device,int dataToggle);
    void SendControlTransferAcknowledge(Device* device,int dataToggle);
    
    /**
     * ID is one based, array is zero based. Device zero is the host controller and a reserved ID as per the host controller spec.
     * Returns the device or NULL if the ID is invalid or device is now disconnected. (device pointer will be NULL when disconnected)
     * If deviceID is zero then a pointer to the 'deviceZero' object is returned.
     */
    Device* getDevice(int deviceID);

    
};//class Controller

};//namespace USB

#endif