testing n-Bed with a Logitech C270 camera

Dependencies:   USBHost mbed

Fork of USBHostC270_example by Norimasa Okamoto

USBHostC270/BaseUvc.h

Committer:
va009039
Date:
2013-03-18
Revision:
11:6a8eef89eb22
Parent:
10:387c49b2fc7e
Child:
12:ea4badc78215

File content as of revision 11:6a8eef89eb22:

// BaseUvc.h

#pragma once

// --- UVC --------------------------------------------------
#define _30FPS  333333
#define _25FPS  400000
#define _20FPS  500000
#define _15FPS  666666
#define _10FPS 1000000
#define _5FPS  2000000
#define _1FPS 10000000

#define SET_CUR  0x01
#define GET_CUR  0x81
#define GET_MIN  0x82
#define GET_MAX  0x83
#define GET_RES  0x84
#define GET_LEN  0x85
#define GET_INFO 0x86
#define GET_DEF  0x87

#define VS_PROBE_CONTROL  0x01
#define VS_COMMIT_CONTROL 0x02

class BaseEp;
struct HCITD {    // HostController Isochronous Transfer Descriptor
    __IO uint32_t Control;      // +0 Transfer descriptor control
    uint8_t*  BufferPage0;      // +4 Buffer Page 0
    HCITD* Next;                // +8 Physical pointer to next Isochronous Transfer Descriptor
    uint8_t*  BufferEnd;        // +12 buffer End
    __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW
    BaseEp* ep;                 // +32 endpoint object
    __IO uint8_t buf[0];        // +36 buffer
                                // +36
    HCITD(BaseEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize);
    inline void* operator new(size_t size, int buf_size) {
        void* p;
        if (posix_memalign(&p, 32, size+buf_size) == 0) {
            return p;
        }
        return NULL;
    }

    inline void operator delete(void* p) {
        free(p);
    }

    inline uint16_t StartingFrame() {
        return Control & 0xffff;
    }

    inline uint8_t FrameCount() {
        return ((Control>>24)&7)+1;
    }    

    inline uint8_t ConditionCode() {
        return Control>>28;
    }
};

struct _HCED {    // HostController EndPoint Descriptor
    __IO uint32_t Control; // +0 Endpoint descriptor control
    HCTD* TailTd;          // +4 Physical address of tail in Transfer descriptor list
    __IO HCTD* HeadTd;     // +8 Physcial address of head in Transfer descriptor list
    _HCED* Next;           // +12 Physical address of next Endpoint descriptor
                           // +16
    _HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed) {
        Control =  addr            | /* USB address */
        ((ep & 0x7F) << 7)         | /* Endpoint address */
        (ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
        ((lowSpeed?1:0) << 13)     | /* speed full=0 low=1 */
        (size << 16);                /* MaxPkt Size */
        Next = NULL;
    }

    inline void* operator new(size_t size) {
        void* p;
        if (posix_memalign(&p, 16, size) == 0) {
            return p;
        }
        return NULL;
    }

    inline void operator delete(void* p) {
        free(p);
    }

    inline uint8_t FunctionAddress() {
        return Control & 0x7f;
    }

    inline int Speed() {
        return (Control>>13)&1;
    }

    inline void setFunctionAddress(int addr) {
        Control &= ~0x7f;
        Control |= addr;
    }

    inline void setMaxPacketSize(uint16_t size) {
        Control &= ~0xffff0000;
        Control |= size<<16;
    }

    int Skip() {
        return (Control>>14) & 1;
    }

    void setSkip() {
        Control |= (1<<14);
    }

    void setFormat() {
        Control |= (1<<15);
    }

    template<typename T>
    inline bool enqueue(T* td) {
        if (td) {
            T* tail = reinterpret_cast<T*>(TailTd);
            if (tail) {
                tail->Next = td;
                TailTd = reinterpret_cast<HCTD*>(td);
                return true;
            }
        }
        return false;
    }

    template<typename T>
    inline T* dequeue() {
        T* head = reinterpret_cast<T*>(reinterpret_cast<uint32_t>(HeadTd)&~3); // delete Halted and Toggle Carry bit
        T* tail = reinterpret_cast<T*>(TailTd);
        if (head == NULL || tail == NULL || head == tail) {
            return NULL;
        }
        HeadTd = reinterpret_cast<HCTD*>(head->Next);
        return head;
    }
    template<typename T>
    void init_queue(T* td) {
        TailTd = reinterpret_cast<HCTD*>(td);
        HeadTd = reinterpret_cast<HCTD*>(td); 
    }
};

struct _HCCA {    // Host Controller Communication Area
    _HCED* InterruptTable[32]; // +0 Interrupt Table
    __IO uint16_t FrameNumber;// +128 Frame Number
    __IO uint16_t Pad1;       // +130
    __IO HCTD* DoneHead;      // +132 Done Head
    uint8_t Reserved[116];    // +136 Reserved for future use
    uint8_t Unknown[4];       // +252 Unused
                              // +256
    inline void* operator new(size_t size) {
        void* p;
        if (posix_memalign(&p, 256, size) == 0) {
            return p;
        }
        return NULL;
    }

    inline void operator delete(void* p) {
        free(p);
    }
    
    inline void enqueue(_HCED* ed) {
        for(int i = 0; i < 32; i++) {
            if (InterruptTable[i] == NULL) {
                InterruptTable[i] = ed;
            } else {
                _HCED* nextEd = InterruptTable[i];
                while(nextEd->Next && nextEd->Next != ed) {
                    nextEd = nextEd->Next;
                }
                nextEd->Next = ed;
            }
        }
    }
    
    inline void dequeue(_HCED* ed) {
         for(int i = 0; i < 32; i++) {
            if (InterruptTable[i] == ed) {
                InterruptTable[i] = ed->Next;
            } else if (InterruptTable[i]) {
                _HCED* nextEd = InterruptTable[i];
                while(nextEd) {
                    if (nextEd->Next == ed) {
                        nextEd->Next = ed->Next;
                        break;
                    }
                    nextEd = nextEd->Next;
                }
            }
         }
    }
};

#define HCTD_QUEUE_SIZE 3

class BaseEp { // endpoint
public:
    void init(int addr, uint8_t ep = 0, uint16_t size = 8, int lowSpeed = 0);
    int GetAddr();
    int GetLowSpeed();
    void update_FunctionAddress(int addr);
    void update_MaxPacketSize(uint16_t size);
    int transfer(uint8_t* buf, int len);
    int status(uint32_t millisec=osWaitForever);
    //
    virtual void enable() = 0;
    virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} // WDH
    int wait_queue_HCTD(HCTD* wait_td, uint32_t millisec=osWaitForever);
    // report
    uint8_t m_ConditionCode;
    int m_report_queue_error;
protected:
    int send_receive(uint8_t* buf, int len, int millisec);
    HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever);
    _HCED* m_pED;
    Queue<HCTD, HCTD_QUEUE_SIZE> m_queue; // TD done queue
    int m_td_queue_count;
};

class IsochronousEp : public BaseEp {
public:
    void init(int addr, uint8_t ep, uint16_t size);
    void reset(int delay_ms = 100);
    HCITD* isochronousReceive(int millisec=osWaitForever);
    int isochronousSend(uint8_t* buf, int len, int millisec=osWaitForever);
    HCITD* get_queue_HCITD(int millisec);
    uint16_t m_PacketSize;
    void disconnect();
private:
    HCITD* new_HCITD(BaseEp* obj);
    int m_itd_queue_count;
    uint16_t m_FrameNumber;
    int m_FrameCount; // 1-8
    virtual void enable();
};

class BaseUvc {
public:
    void poll(int millisec=osWaitForever);
    USB_TYPE Control(int req, int cs, int index, uint8_t* buf, int size);
    USB_TYPE setInterfaceAlternate(uint8_t intf, uint8_t alt);
    //ControlEp* m_ctlEp;
    IsochronousEp* m_isoEp;
    uint32_t report_cc_count[16];  // ConditionCode
    uint32_t report_ps_cc_count[16]; // Packt Status ConditionCode
    // callback
    void onResult(uint16_t frame, uint8_t* buf, int len);
    void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) );
    class CDummy;
    template<class T> 
    void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) )
    {
        m_pCb = NULL;
        m_pCbItem = (CDummy*) pItem;
        m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod;
    }
    void clearOnResult();
    CDummy* m_pCbItem;
    void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int);
    void (*m_pCb)(uint16_t, uint8_t*, int);
protected:
    USBHost * host;
    USBDeviceConnected * dev;
};