LogitechC270 webcam class driver alpha version

Dependencies:   USBHost mbed

Fork of USBHostMSD_HelloWorld by Samuel Mokrani

Committer:
va009039
Date:
Sun Mar 17 13:22:13 2013 +0000
Revision:
10:387c49b2fc7e
Parent:
9:fecabade834a
Child:
11:6a8eef89eb22
add readJPEG(), detach does not support.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 10:387c49b2fc7e 1 // BaseUvc.cpp
va009039 10:387c49b2fc7e 2
va009039 9:fecabade834a 3 #include "USBHostConf.h"
va009039 9:fecabade834a 4 #include "USBHost.h"
va009039 9:fecabade834a 5
va009039 9:fecabade834a 6 #include "BaseUvc.h"
va009039 9:fecabade834a 7
va009039 10:387c49b2fc7e 8 //#define ISO_DEBUG 1
va009039 10:387c49b2fc7e 9 #ifdef ISO_DEBUG
va009039 10:387c49b2fc7e 10 #define ISO_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
va009039 10:387c49b2fc7e 11 #else
va009039 10:387c49b2fc7e 12 #define ISO_DBG(...) while(0);
va009039 10:387c49b2fc7e 13 #endif
va009039 10:387c49b2fc7e 14
va009039 9:fecabade834a 15 #define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
va009039 9:fecabade834a 16
va009039 9:fecabade834a 17 void BaseUvc::poll(int millisec)
va009039 9:fecabade834a 18 {
va009039 10:387c49b2fc7e 19 HCITD* itd = m_isoEp->isochronousReceive(millisec);
va009039 9:fecabade834a 20 if (itd) {
va009039 9:fecabade834a 21 uint8_t cc = itd->ConditionCode();
va009039 9:fecabade834a 22 report_cc_count[cc]++;
va009039 9:fecabade834a 23 if (cc == 0) {
va009039 9:fecabade834a 24 uint16_t frame = itd->StartingFrame();
va009039 9:fecabade834a 25 int fc = itd->FrameCount();
va009039 9:fecabade834a 26 uint8_t* buf = const_cast<uint8_t*>(itd->buf);
va009039 9:fecabade834a 27 int mps = m_isoEp->m_PacketSize;
va009039 9:fecabade834a 28 for(int i = 0; i < fc; i++) {
va009039 9:fecabade834a 29 uint16_t psw = itd->OffsetPSW[i];
va009039 9:fecabade834a 30 cc = psw>>12;
va009039 9:fecabade834a 31 if (cc == 0 || cc == 9) {
va009039 9:fecabade834a 32 int len = psw & 0x7ff;
va009039 9:fecabade834a 33 onResult(frame, buf, len);
va009039 9:fecabade834a 34 }
va009039 9:fecabade834a 35 report_ps_cc_count[cc]++;
va009039 9:fecabade834a 36 buf += mps;
va009039 9:fecabade834a 37 frame++;
va009039 9:fecabade834a 38 }
va009039 9:fecabade834a 39 }
va009039 9:fecabade834a 40 delete itd;
va009039 9:fecabade834a 41 }
va009039 9:fecabade834a 42 }
va009039 9:fecabade834a 43
va009039 10:387c49b2fc7e 44 USB_TYPE BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size)
va009039 10:387c49b2fc7e 45 {
va009039 10:387c49b2fc7e 46 if (req == SET_CUR) {
va009039 10:387c49b2fc7e 47 return host->controlWrite(dev,
va009039 10:387c49b2fc7e 48 USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE,
va009039 10:387c49b2fc7e 49 req, cs<<8, index, buf, size);
va009039 10:387c49b2fc7e 50 }
va009039 10:387c49b2fc7e 51 return host->controlRead(dev,
va009039 10:387c49b2fc7e 52 USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE,
va009039 10:387c49b2fc7e 53 req, cs<<8, index, buf, size);
va009039 10:387c49b2fc7e 54 }
va009039 10:387c49b2fc7e 55
va009039 10:387c49b2fc7e 56 USB_TYPE BaseUvc::setInterfaceAlternate(uint8_t intf, uint8_t alt)
va009039 10:387c49b2fc7e 57 {
va009039 10:387c49b2fc7e 58 return host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE,
va009039 10:387c49b2fc7e 59 SET_INTERFACE, alt, intf, NULL, 0);
va009039 10:387c49b2fc7e 60 }
va009039 10:387c49b2fc7e 61
va009039 9:fecabade834a 62 void BaseUvc::onResult(uint16_t frame, uint8_t* buf, int len)
va009039 9:fecabade834a 63 {
va009039 9:fecabade834a 64 if(m_pCbItem && m_pCbMeth)
va009039 9:fecabade834a 65 (m_pCbItem->*m_pCbMeth)(frame, buf, len);
va009039 9:fecabade834a 66 else if(m_pCb)
va009039 9:fecabade834a 67 m_pCb(frame, buf, len);
va009039 9:fecabade834a 68 }
va009039 9:fecabade834a 69
va009039 9:fecabade834a 70 void BaseUvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
va009039 9:fecabade834a 71 {
va009039 9:fecabade834a 72 m_pCb = pMethod;
va009039 9:fecabade834a 73 m_pCbItem = NULL;
va009039 9:fecabade834a 74 m_pCbMeth = NULL;
va009039 9:fecabade834a 75 }
va009039 9:fecabade834a 76
va009039 9:fecabade834a 77 void BaseUvc::clearOnResult()
va009039 9:fecabade834a 78 {
va009039 9:fecabade834a 79 m_pCb = NULL;
va009039 9:fecabade834a 80 m_pCbItem = NULL;
va009039 9:fecabade834a 81 m_pCbMeth = NULL;
va009039 9:fecabade834a 82 }
va009039 9:fecabade834a 83
va009039 9:fecabade834a 84
va009039 9:fecabade834a 85 HCITD::HCITD(BaseEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
va009039 9:fecabade834a 86 Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED
va009039 9:fecabade834a 87 ((FrameCount-1) << 24)| // FC FrameCount
va009039 9:fecabade834a 88 TD_DELAY_INT(0) | // DI DelayInterrupt
va009039 9:fecabade834a 89 FrameNumber; // SF StartingFrame
va009039 9:fecabade834a 90 BufferPage0 = const_cast<uint8_t*>(buf);
va009039 9:fecabade834a 91 BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
va009039 9:fecabade834a 92 Next = NULL;
va009039 9:fecabade834a 93 ep = obj;
va009039 9:fecabade834a 94 uint32_t addr = reinterpret_cast<uint32_t>(buf);
va009039 9:fecabade834a 95 for(int i = 0; i < FrameCount; i++) {
va009039 9:fecabade834a 96 uint16_t offset = addr & 0x0fff;
va009039 9:fecabade834a 97 if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
va009039 9:fecabade834a 98 offset |= 0x1000;
va009039 9:fecabade834a 99 }
va009039 9:fecabade834a 100 OffsetPSW[i] = 0xe000|offset;
va009039 9:fecabade834a 101 addr += PacketSize;
va009039 9:fecabade834a 102 }
va009039 9:fecabade834a 103 }
va009039 9:fecabade834a 104
va009039 9:fecabade834a 105 IsochronousEp::IsochronousEp(int addr, uint8_t ep, uint16_t size):BaseEp(addr, ep, size)
va009039 9:fecabade834a 106 {
va009039 10:387c49b2fc7e 107 ISO_DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size);
va009039 9:fecabade834a 108 TEST_ASSERT(m_pED);
va009039 9:fecabade834a 109
va009039 9:fecabade834a 110 m_pED->Control |= (1 << 15); // F Format ITD
va009039 9:fecabade834a 111
va009039 9:fecabade834a 112 TEST_ASSERT(size >= 128 && size <= 1023);
va009039 9:fecabade834a 113 m_PacketSize = size;
va009039 9:fecabade834a 114 m_FrameCount = 4; // 1-8
va009039 9:fecabade834a 115 TEST_ASSERT(m_FrameCount >= 1 && m_FrameCount <= 8);
va009039 9:fecabade834a 116 m_itd_queue_count = 0;
va009039 9:fecabade834a 117 reset();
va009039 9:fecabade834a 118 HCITD* itd = new_HCITD(this);
va009039 9:fecabade834a 119 m_pED->TailTd = reinterpret_cast<HCTD*>(itd);
va009039 9:fecabade834a 120 m_pED->HeadTd = reinterpret_cast<HCTD*>(itd);
va009039 9:fecabade834a 121 TEST_ASSERT(itd);
va009039 9:fecabade834a 122 if (itd == NULL) {
va009039 9:fecabade834a 123 return;
va009039 9:fecabade834a 124 }
va009039 9:fecabade834a 125 _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
va009039 9:fecabade834a 126 TEST_ASSERT(hcca);
va009039 9:fecabade834a 127 if (hcca == NULL) {
va009039 9:fecabade834a 128 return;
va009039 9:fecabade834a 129 }
va009039 10:387c49b2fc7e 130 hcca->enqueue(m_pED);
va009039 9:fecabade834a 131 }
va009039 9:fecabade834a 132
va009039 9:fecabade834a 133 void IsochronousEp::reset(int delay_ms)
va009039 9:fecabade834a 134 {
va009039 9:fecabade834a 135 m_FrameNumber = LPC_USB->HcFmNumber + delay_ms;
va009039 9:fecabade834a 136 }
va009039 9:fecabade834a 137
va009039 9:fecabade834a 138 HCITD* IsochronousEp::new_HCITD(BaseEp* obj)
va009039 9:fecabade834a 139 {
va009039 9:fecabade834a 140 HCITD* itd = new(m_PacketSize*m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, m_PacketSize);
va009039 9:fecabade834a 141 if (itd == NULL) {
va009039 9:fecabade834a 142 return NULL;
va009039 9:fecabade834a 143 }
va009039 9:fecabade834a 144 m_FrameNumber += m_FrameCount;
va009039 9:fecabade834a 145 return itd;
va009039 9:fecabade834a 146 }
va009039 9:fecabade834a 147
va009039 10:387c49b2fc7e 148 HCITD* IsochronousEp::isochronousReceive(int millisec)
va009039 9:fecabade834a 149 {
va009039 9:fecabade834a 150 TEST_ASSERT(m_itd_queue_count >= 0);
va009039 9:fecabade834a 151 while(m_itd_queue_count < 3 && m_itd_queue_count < HCTD_QUEUE_SIZE) {
va009039 9:fecabade834a 152 HCITD* itd = reinterpret_cast<HCITD*>(m_pED->TailTd);
va009039 9:fecabade834a 153 TEST_ASSERT(itd);
va009039 9:fecabade834a 154 if (itd == NULL) {
va009039 9:fecabade834a 155 return NULL;
va009039 9:fecabade834a 156 }
va009039 9:fecabade834a 157 HCITD* blank_itd = new_HCITD(this);
va009039 9:fecabade834a 158 TEST_ASSERT(blank_itd);
va009039 9:fecabade834a 159 if (blank_itd == NULL) {
va009039 9:fecabade834a 160 return NULL;
va009039 9:fecabade834a 161 }
va009039 9:fecabade834a 162 itd->Next = blank_itd;
va009039 9:fecabade834a 163 m_pED->TailTd = reinterpret_cast<HCTD*>(blank_itd);
va009039 9:fecabade834a 164 m_itd_queue_count++;
va009039 9:fecabade834a 165 //DBG_IED(m_pED);
va009039 9:fecabade834a 166 enable(); // Enable Periodic
va009039 9:fecabade834a 167 }
va009039 9:fecabade834a 168
va009039 9:fecabade834a 169 HCITD* itd = get_queue_HCITD(millisec);
va009039 9:fecabade834a 170 if (itd) {
va009039 9:fecabade834a 171 m_itd_queue_count--;
va009039 9:fecabade834a 172 }
va009039 9:fecabade834a 173 return itd;
va009039 9:fecabade834a 174 }
va009039 9:fecabade834a 175
va009039 9:fecabade834a 176 HCITD* IsochronousEp::get_queue_HCITD(int millisec)
va009039 9:fecabade834a 177 {
va009039 9:fecabade834a 178 for(int i = 0; i < 16; i++) {
va009039 9:fecabade834a 179 osEvent evt = m_queue.get(millisec);
va009039 9:fecabade834a 180 if (evt.status == osEventMessage) {
va009039 9:fecabade834a 181 HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
va009039 9:fecabade834a 182 TEST_ASSERT(itd);
va009039 9:fecabade834a 183 return itd;
va009039 9:fecabade834a 184 } else if (evt.status == osOK) {
va009039 9:fecabade834a 185 continue;
va009039 9:fecabade834a 186 } else if (evt.status == osEventTimeout) {
va009039 9:fecabade834a 187 return NULL;
va009039 9:fecabade834a 188 } else {
va009039 10:387c49b2fc7e 189 ISO_DBG("evt.status: %02x\n", evt.status);
va009039 9:fecabade834a 190 TEST_ASSERT(evt.status == osEventMessage);
va009039 9:fecabade834a 191 return NULL;
va009039 9:fecabade834a 192 }
va009039 9:fecabade834a 193 }
va009039 9:fecabade834a 194 return NULL;
va009039 9:fecabade834a 195 }
va009039 9:fecabade834a 196
va009039 9:fecabade834a 197 void IsochronousEp::enable()
va009039 9:fecabade834a 198 {
va009039 9:fecabade834a 199 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 9:fecabade834a 200 }
va009039 9:fecabade834a 201
va009039 10:387c49b2fc7e 202 void IsochronousEp::disconnect()
va009039 10:387c49b2fc7e 203 {
va009039 10:387c49b2fc7e 204 m_pED->setSkip();
va009039 10:387c49b2fc7e 205 ISO_DBG("m_itd_queue_count: %d", m_itd_queue_count);
va009039 10:387c49b2fc7e 206 Timer t;
va009039 10:387c49b2fc7e 207 t.reset();
va009039 10:387c49b2fc7e 208 t.start();
va009039 10:387c49b2fc7e 209 while(m_itd_queue_count > 0 && t.read_ms() <= (8*3)) {
va009039 10:387c49b2fc7e 210 HCITD* itd = get_queue_HCITD(0);
va009039 10:387c49b2fc7e 211 if (itd) {
va009039 10:387c49b2fc7e 212 ISO_DBG("ITD: %p", itd);
va009039 10:387c49b2fc7e 213 delete itd;
va009039 10:387c49b2fc7e 214 m_itd_queue_count--;
va009039 10:387c49b2fc7e 215 t.reset();
va009039 10:387c49b2fc7e 216 }
va009039 10:387c49b2fc7e 217 }
va009039 10:387c49b2fc7e 218 ISO_DBG("m_itd_queue_count: %d, t_ms: %d", m_itd_queue_count, t.read_ms());
va009039 10:387c49b2fc7e 219 HCITD* head = reinterpret_cast<HCITD*>(reinterpret_cast<uint32_t>(m_pED->HeadTd)&~3); // delete Halted and Toggle Carry bit
va009039 10:387c49b2fc7e 220 TEST_ASSERT(head);
va009039 10:387c49b2fc7e 221 HCITD* tail = reinterpret_cast<HCITD*>(m_pED->TailTd);
va009039 10:387c49b2fc7e 222 TEST_ASSERT(tail);
va009039 10:387c49b2fc7e 223 while(head != tail) {
va009039 10:387c49b2fc7e 224 HCITD* next = head->Next;
va009039 10:387c49b2fc7e 225 TEST_ASSERT(next);
va009039 10:387c49b2fc7e 226 ISO_DBG("ED ITD:%p next:%p", head, next);
va009039 10:387c49b2fc7e 227 delete head;
va009039 10:387c49b2fc7e 228 TEST_ASSERT(m_itd_queue_count > 0);
va009039 10:387c49b2fc7e 229 m_itd_queue_count--;
va009039 10:387c49b2fc7e 230 head = next;
va009039 10:387c49b2fc7e 231 }
va009039 10:387c49b2fc7e 232 TEST_ASSERT(m_itd_queue_count == 0);
va009039 10:387c49b2fc7e 233 delete head;
va009039 10:387c49b2fc7e 234
va009039 10:387c49b2fc7e 235 _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
va009039 10:387c49b2fc7e 236 TEST_ASSERT(hcca);
va009039 10:387c49b2fc7e 237 hcca->dequeue(m_pED);
va009039 10:387c49b2fc7e 238 delete m_pED;
va009039 10:387c49b2fc7e 239 }
va009039 10:387c49b2fc7e 240
va009039 9:fecabade834a 241 BaseEp::BaseEp(int addr, uint8_t ep, uint16_t size, int lowSpeed):m_td_queue_count(0)
va009039 9:fecabade834a 242 {
va009039 10:387c49b2fc7e 243 ISO_DBG("%p FA=%d EN=%02x MPS=%d S=%d\n", this, addr, ep, size, lowSpeed);
va009039 9:fecabade834a 244 TEST_ASSERT(size >= 8 && size <= 1023);
va009039 9:fecabade834a 245 TEST_ASSERT(lowSpeed == 0 || lowSpeed == 1);
va009039 9:fecabade834a 246 m_pED = new _HCED(addr, ep, size, lowSpeed);
va009039 9:fecabade834a 247 TEST_ASSERT(m_pED);
va009039 9:fecabade834a 248 }