LogitechC270 webcam class driver alpha version
Fork of USBHostMSD_HelloWorld by
USBHostC270/BaseUvc.cpp@11:6a8eef89eb22, 2013-03-18 (annotated)
- Committer:
- va009039
- Date:
- Mon Mar 18 12:34:47 2013 +0000
- Revision:
- 11:6a8eef89eb22
- Parent:
- 10:387c49b2fc7e
- Child:
- 12:ea4badc78215
started detach implementation
Who changed what in which revision?
User | Revision | Line number | New 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 | 11:6a8eef89eb22 | 105 | void IsochronousEp::init(int addr, uint8_t ep, uint16_t size) |
va009039 | 9:fecabade834a | 106 | { |
va009039 | 11:6a8eef89eb22 | 107 | //ISO_DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size); |
va009039 | 11:6a8eef89eb22 | 108 | BaseEp::init(addr, ep, size); |
va009039 | 9:fecabade834a | 109 | TEST_ASSERT(m_pED); |
va009039 | 9:fecabade834a | 110 | |
va009039 | 11:6a8eef89eb22 | 111 | m_pED->setFormat(); // F Format ITD |
va009039 | 9:fecabade834a | 112 | |
va009039 | 9:fecabade834a | 113 | TEST_ASSERT(size >= 128 && size <= 1023); |
va009039 | 9:fecabade834a | 114 | m_PacketSize = size; |
va009039 | 9:fecabade834a | 115 | m_FrameCount = 4; // 1-8 |
va009039 | 9:fecabade834a | 116 | TEST_ASSERT(m_FrameCount >= 1 && m_FrameCount <= 8); |
va009039 | 9:fecabade834a | 117 | m_itd_queue_count = 0; |
va009039 | 9:fecabade834a | 118 | reset(); |
va009039 | 9:fecabade834a | 119 | HCITD* itd = new_HCITD(this); |
va009039 | 11:6a8eef89eb22 | 120 | m_pED->init_queue<HCITD>(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 | 11:6a8eef89eb22 | 152 | TEST_ASSERT(m_pED); |
va009039 | 11:6a8eef89eb22 | 153 | if (m_pED->Skip()) { |
va009039 | 11:6a8eef89eb22 | 154 | break; |
va009039 | 9:fecabade834a | 155 | } |
va009039 | 9:fecabade834a | 156 | HCITD* blank_itd = new_HCITD(this); |
va009039 | 9:fecabade834a | 157 | TEST_ASSERT(blank_itd); |
va009039 | 11:6a8eef89eb22 | 158 | if (m_pED->enqueue<HCITD>(blank_itd)) { |
va009039 | 11:6a8eef89eb22 | 159 | m_itd_queue_count++; |
va009039 | 9:fecabade834a | 160 | } |
va009039 | 9:fecabade834a | 161 | enable(); // Enable Periodic |
va009039 | 9:fecabade834a | 162 | } |
va009039 | 9:fecabade834a | 163 | |
va009039 | 9:fecabade834a | 164 | HCITD* itd = get_queue_HCITD(millisec); |
va009039 | 9:fecabade834a | 165 | if (itd) { |
va009039 | 9:fecabade834a | 166 | m_itd_queue_count--; |
va009039 | 9:fecabade834a | 167 | } |
va009039 | 9:fecabade834a | 168 | return itd; |
va009039 | 9:fecabade834a | 169 | } |
va009039 | 9:fecabade834a | 170 | |
va009039 | 9:fecabade834a | 171 | HCITD* IsochronousEp::get_queue_HCITD(int millisec) |
va009039 | 9:fecabade834a | 172 | { |
va009039 | 9:fecabade834a | 173 | for(int i = 0; i < 16; i++) { |
va009039 | 9:fecabade834a | 174 | osEvent evt = m_queue.get(millisec); |
va009039 | 9:fecabade834a | 175 | if (evt.status == osEventMessage) { |
va009039 | 9:fecabade834a | 176 | HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p); |
va009039 | 9:fecabade834a | 177 | TEST_ASSERT(itd); |
va009039 | 9:fecabade834a | 178 | return itd; |
va009039 | 9:fecabade834a | 179 | } else if (evt.status == osOK) { |
va009039 | 9:fecabade834a | 180 | continue; |
va009039 | 9:fecabade834a | 181 | } else if (evt.status == osEventTimeout) { |
va009039 | 9:fecabade834a | 182 | return NULL; |
va009039 | 9:fecabade834a | 183 | } else { |
va009039 | 10:387c49b2fc7e | 184 | ISO_DBG("evt.status: %02x\n", evt.status); |
va009039 | 9:fecabade834a | 185 | TEST_ASSERT(evt.status == osEventMessage); |
va009039 | 9:fecabade834a | 186 | return NULL; |
va009039 | 9:fecabade834a | 187 | } |
va009039 | 9:fecabade834a | 188 | } |
va009039 | 9:fecabade834a | 189 | return NULL; |
va009039 | 9:fecabade834a | 190 | } |
va009039 | 9:fecabade834a | 191 | |
va009039 | 9:fecabade834a | 192 | void IsochronousEp::enable() |
va009039 | 9:fecabade834a | 193 | { |
va009039 | 9:fecabade834a | 194 | LPC_USB->HcControl |= OR_CONTROL_PLE; |
va009039 | 9:fecabade834a | 195 | } |
va009039 | 9:fecabade834a | 196 | |
va009039 | 10:387c49b2fc7e | 197 | void IsochronousEp::disconnect() |
va009039 | 10:387c49b2fc7e | 198 | { |
va009039 | 10:387c49b2fc7e | 199 | m_pED->setSkip(); |
va009039 | 11:6a8eef89eb22 | 200 | Thread::wait(50); |
va009039 | 11:6a8eef89eb22 | 201 | ISO_DBG("rtos-queue: %d", m_itd_queue_count); |
va009039 | 11:6a8eef89eb22 | 202 | int queue_count = m_itd_queue_count; |
va009039 | 10:387c49b2fc7e | 203 | Timer t; |
va009039 | 10:387c49b2fc7e | 204 | t.reset(); |
va009039 | 10:387c49b2fc7e | 205 | t.start(); |
va009039 | 11:6a8eef89eb22 | 206 | while(queue_count > 0 && t.read_ms() < 50) { |
va009039 | 11:6a8eef89eb22 | 207 | HCITD* itd = get_queue_HCITD(10); |
va009039 | 10:387c49b2fc7e | 208 | if (itd) { |
va009039 | 11:6a8eef89eb22 | 209 | ISO_DBG("delete ITD:%p from rtos-queue %d ms", itd, t.read_ms()); |
va009039 | 10:387c49b2fc7e | 210 | delete itd; |
va009039 | 11:6a8eef89eb22 | 211 | queue_count--; |
va009039 | 10:387c49b2fc7e | 212 | t.reset(); |
va009039 | 10:387c49b2fc7e | 213 | } |
va009039 | 10:387c49b2fc7e | 214 | } |
va009039 | 11:6a8eef89eb22 | 215 | ISO_DBG("rtos-queue: %d, %d ms", queue_count, t.read_ms()); |
va009039 | 11:6a8eef89eb22 | 216 | while(1) { |
va009039 | 11:6a8eef89eb22 | 217 | HCITD* itd = m_pED->dequeue<HCITD>(); |
va009039 | 11:6a8eef89eb22 | 218 | if (itd == NULL) { |
va009039 | 11:6a8eef89eb22 | 219 | break; |
va009039 | 11:6a8eef89eb22 | 220 | } |
va009039 | 11:6a8eef89eb22 | 221 | ISO_DBG("delete ITD:%p from ED(%p)-queue", itd, m_pED); |
va009039 | 11:6a8eef89eb22 | 222 | delete itd; |
va009039 | 11:6a8eef89eb22 | 223 | TEST_ASSERT(queue_count > 0); |
va009039 | 11:6a8eef89eb22 | 224 | queue_count--; |
va009039 | 11:6a8eef89eb22 | 225 | } |
va009039 | 11:6a8eef89eb22 | 226 | TEST_ASSERT(queue_count == 0); |
va009039 | 10:387c49b2fc7e | 227 | HCITD* tail = reinterpret_cast<HCITD*>(m_pED->TailTd); |
va009039 | 11:6a8eef89eb22 | 228 | ISO_DBG("delete ITD:%p from ED(%p)-tail", tail, m_pED); |
va009039 | 10:387c49b2fc7e | 229 | TEST_ASSERT(tail); |
va009039 | 11:6a8eef89eb22 | 230 | delete tail; |
va009039 | 11:6a8eef89eb22 | 231 | m_pED->init_queue<HCITD>(NULL); |
va009039 | 10:387c49b2fc7e | 232 | |
va009039 | 10:387c49b2fc7e | 233 | _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA); |
va009039 | 10:387c49b2fc7e | 234 | TEST_ASSERT(hcca); |
va009039 | 10:387c49b2fc7e | 235 | hcca->dequeue(m_pED); |
va009039 | 11:6a8eef89eb22 | 236 | ISO_DBG("delete ED:%p", m_pED); |
va009039 | 10:387c49b2fc7e | 237 | delete m_pED; |
va009039 | 11:6a8eef89eb22 | 238 | m_pED = NULL; |
va009039 | 10:387c49b2fc7e | 239 | } |
va009039 | 10:387c49b2fc7e | 240 | |
va009039 | 11:6a8eef89eb22 | 241 | void BaseEp::init(int addr, uint8_t ep, uint16_t size, int lowSpeed) |
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 | 11:6a8eef89eb22 | 248 | m_td_queue_count = 0; |
va009039 | 9:fecabade834a | 249 | } |