![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
LogitechC270 webcam class driver alpha version
Fork of USBHostMSD_HelloWorld by
USBHostC270/USBisochronous/USBIsochronous.cpp@12:ea4badc78215, 2013-03-20 (annotated)
- Committer:
- va009039
- Date:
- Wed Mar 20 14:28:39 2013 +0000
- Revision:
- 12:ea4badc78215
support detach
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 12:ea4badc78215 | 1 | // USBIsochronous.cpp |
va009039 | 12:ea4badc78215 | 2 | #include "USBHostConf.h" |
va009039 | 12:ea4badc78215 | 3 | #include "USBHost.h" |
va009039 | 12:ea4badc78215 | 4 | #include "USBIsochronous.h" |
va009039 | 12:ea4badc78215 | 5 | |
va009039 | 12:ea4badc78215 | 6 | //#define ISO_DEBUG 1 |
va009039 | 12:ea4badc78215 | 7 | #ifdef ISO_DEBUG |
va009039 | 12:ea4badc78215 | 8 | #define ISO_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); |
va009039 | 12:ea4badc78215 | 9 | #else |
va009039 | 12:ea4badc78215 | 10 | #define ISO_DBG(...) while(0); |
va009039 | 12:ea4badc78215 | 11 | #endif |
va009039 | 12:ea4badc78215 | 12 | |
va009039 | 12:ea4badc78215 | 13 | #define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; |
va009039 | 12:ea4badc78215 | 14 | |
va009039 | 12:ea4badc78215 | 15 | HCITD::HCITD(IsochronousEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) { |
va009039 | 12:ea4badc78215 | 16 | Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED |
va009039 | 12:ea4badc78215 | 17 | ((FrameCount-1) << 24)| // FC FrameCount |
va009039 | 12:ea4badc78215 | 18 | TD_DELAY_INT(0) | // DI DelayInterrupt |
va009039 | 12:ea4badc78215 | 19 | FrameNumber; // SF StartingFrame |
va009039 | 12:ea4badc78215 | 20 | BufferPage0 = const_cast<uint8_t*>(buf); |
va009039 | 12:ea4badc78215 | 21 | BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1; |
va009039 | 12:ea4badc78215 | 22 | Next = NULL; |
va009039 | 12:ea4badc78215 | 23 | ep = obj; |
va009039 | 12:ea4badc78215 | 24 | uint32_t addr = reinterpret_cast<uint32_t>(buf); |
va009039 | 12:ea4badc78215 | 25 | for(int i = 0; i < FrameCount; i++) { |
va009039 | 12:ea4badc78215 | 26 | uint16_t offset = addr & 0x0fff; |
va009039 | 12:ea4badc78215 | 27 | if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) { |
va009039 | 12:ea4badc78215 | 28 | offset |= 0x1000; |
va009039 | 12:ea4badc78215 | 29 | } |
va009039 | 12:ea4badc78215 | 30 | OffsetPSW[i] = 0xe000|offset; |
va009039 | 12:ea4badc78215 | 31 | addr += PacketSize; |
va009039 | 12:ea4badc78215 | 32 | } |
va009039 | 12:ea4badc78215 | 33 | } |
va009039 | 12:ea4badc78215 | 34 | |
va009039 | 12:ea4badc78215 | 35 | void IsochronousEp::init(int addr, uint8_t ep, uint16_t size, uint8_t frameCount, uint8_t queueLimit) |
va009039 | 12:ea4badc78215 | 36 | { |
va009039 | 12:ea4badc78215 | 37 | //ISO_DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size); |
va009039 | 12:ea4badc78215 | 38 | TEST_ASSERT(addr >= 1); |
va009039 | 12:ea4badc78215 | 39 | TEST_ASSERT(size >= 8 && size <= 1023); |
va009039 | 12:ea4badc78215 | 40 | m_pED = new _HCED(addr, ep, size); |
va009039 | 12:ea4badc78215 | 41 | TEST_ASSERT(m_pED); |
va009039 | 12:ea4badc78215 | 42 | |
va009039 | 12:ea4badc78215 | 43 | m_pED->setFormat(); // F Format ITD |
va009039 | 12:ea4badc78215 | 44 | |
va009039 | 12:ea4badc78215 | 45 | TEST_ASSERT(size >= 128 && size <= 1023); |
va009039 | 12:ea4badc78215 | 46 | m_PacketSize = size; |
va009039 | 12:ea4badc78215 | 47 | TEST_ASSERT(frameCount >= 1 && frameCount <= 8); |
va009039 | 12:ea4badc78215 | 48 | m_FrameCount = frameCount; |
va009039 | 12:ea4badc78215 | 49 | TEST_ASSERT(queueLimit >= 1 && queueLimit <= HCITD_QUEUE_SIZE); |
va009039 | 12:ea4badc78215 | 50 | m_itd_queue_limit = queueLimit; |
va009039 | 12:ea4badc78215 | 51 | |
va009039 | 12:ea4badc78215 | 52 | m_itd_queue_count = 0; |
va009039 | 12:ea4badc78215 | 53 | reset(); |
va009039 | 12:ea4badc78215 | 54 | HCITD* itd = new_HCITD(this); |
va009039 | 12:ea4badc78215 | 55 | m_pED->init_queue<HCITD>(itd); |
va009039 | 12:ea4badc78215 | 56 | TEST_ASSERT(itd); |
va009039 | 12:ea4badc78215 | 57 | if (itd == NULL) { |
va009039 | 12:ea4badc78215 | 58 | return; |
va009039 | 12:ea4badc78215 | 59 | } |
va009039 | 12:ea4badc78215 | 60 | _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA); |
va009039 | 12:ea4badc78215 | 61 | TEST_ASSERT(hcca); |
va009039 | 12:ea4badc78215 | 62 | if (hcca == NULL) { |
va009039 | 12:ea4badc78215 | 63 | return; |
va009039 | 12:ea4badc78215 | 64 | } |
va009039 | 12:ea4badc78215 | 65 | hcca->enqueue(m_pED); |
va009039 | 12:ea4badc78215 | 66 | } |
va009039 | 12:ea4badc78215 | 67 | |
va009039 | 12:ea4badc78215 | 68 | void IsochronousEp::reset(int delay_ms) |
va009039 | 12:ea4badc78215 | 69 | { |
va009039 | 12:ea4badc78215 | 70 | m_FrameNumber = LPC_USB->HcFmNumber + delay_ms; |
va009039 | 12:ea4badc78215 | 71 | } |
va009039 | 12:ea4badc78215 | 72 | |
va009039 | 12:ea4badc78215 | 73 | HCITD* IsochronousEp::new_HCITD(IsochronousEp* obj) |
va009039 | 12:ea4badc78215 | 74 | { |
va009039 | 12:ea4badc78215 | 75 | HCITD* itd = new(m_PacketSize*m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, m_PacketSize); |
va009039 | 12:ea4badc78215 | 76 | if (itd == NULL) { |
va009039 | 12:ea4badc78215 | 77 | return NULL; |
va009039 | 12:ea4badc78215 | 78 | } |
va009039 | 12:ea4badc78215 | 79 | m_FrameNumber += m_FrameCount; |
va009039 | 12:ea4badc78215 | 80 | return itd; |
va009039 | 12:ea4badc78215 | 81 | } |
va009039 | 12:ea4badc78215 | 82 | |
va009039 | 12:ea4badc78215 | 83 | HCITD* IsochronousEp::isochronousReceive(int timeout_ms) |
va009039 | 12:ea4badc78215 | 84 | { |
va009039 | 12:ea4badc78215 | 85 | TEST_ASSERT(m_itd_queue_count >= 0); |
va009039 | 12:ea4badc78215 | 86 | while(m_itd_queue_count < m_itd_queue_limit) { |
va009039 | 12:ea4badc78215 | 87 | if (m_pED == NULL) { |
va009039 | 12:ea4badc78215 | 88 | ISO_DBG("m_pED is NULL"); |
va009039 | 12:ea4badc78215 | 89 | break; |
va009039 | 12:ea4badc78215 | 90 | } |
va009039 | 12:ea4badc78215 | 91 | if (m_pED->Skip()) { |
va009039 | 12:ea4badc78215 | 92 | break; |
va009039 | 12:ea4badc78215 | 93 | } |
va009039 | 12:ea4badc78215 | 94 | HCITD* blank_itd = new_HCITD(this); |
va009039 | 12:ea4badc78215 | 95 | TEST_ASSERT(blank_itd); |
va009039 | 12:ea4badc78215 | 96 | if (m_pED->enqueue<HCITD>(blank_itd)) { |
va009039 | 12:ea4badc78215 | 97 | m_itd_queue_count++; |
va009039 | 12:ea4badc78215 | 98 | } |
va009039 | 12:ea4badc78215 | 99 | enable(); // Enable Periodic |
va009039 | 12:ea4badc78215 | 100 | } |
va009039 | 12:ea4badc78215 | 101 | |
va009039 | 12:ea4badc78215 | 102 | HCITD* itd = get_queue_HCITD(timeout_ms); |
va009039 | 12:ea4badc78215 | 103 | if (itd) { |
va009039 | 12:ea4badc78215 | 104 | m_itd_queue_count--; |
va009039 | 12:ea4badc78215 | 105 | } |
va009039 | 12:ea4badc78215 | 106 | return itd; |
va009039 | 12:ea4badc78215 | 107 | } |
va009039 | 12:ea4badc78215 | 108 | |
va009039 | 12:ea4badc78215 | 109 | int IsochronousEp::isochronousSend(uint8_t* buf, int len, int timeout_ms) |
va009039 | 12:ea4badc78215 | 110 | { |
va009039 | 12:ea4badc78215 | 111 | //ISO_DBG("buf: %p, len: %d", buf, len); |
va009039 | 12:ea4badc78215 | 112 | HCITD* itd = get_queue_HCITD(timeout_ms); |
va009039 | 12:ea4badc78215 | 113 | if (itd) { |
va009039 | 12:ea4badc78215 | 114 | delete itd; |
va009039 | 12:ea4badc78215 | 115 | m_itd_queue_count--; |
va009039 | 12:ea4badc78215 | 116 | TEST_ASSERT(m_itd_queue_count >= 0); |
va009039 | 12:ea4badc78215 | 117 | } |
va009039 | 12:ea4badc78215 | 118 | TEST_ASSERT(m_itd_queue_count >= 0); |
va009039 | 12:ea4badc78215 | 119 | if(m_itd_queue_count < m_itd_queue_limit) { |
va009039 | 12:ea4badc78215 | 120 | if (m_pED == NULL) { |
va009039 | 12:ea4badc78215 | 121 | ISO_DBG("m_pED is NULL"); |
va009039 | 12:ea4badc78215 | 122 | return 0; |
va009039 | 12:ea4badc78215 | 123 | } |
va009039 | 12:ea4badc78215 | 124 | if (m_pED->Skip()) { |
va009039 | 12:ea4badc78215 | 125 | return 0; |
va009039 | 12:ea4badc78215 | 126 | } |
va009039 | 12:ea4badc78215 | 127 | itd = new_HCITD(this); |
va009039 | 12:ea4badc78215 | 128 | TEST_ASSERT(itd); |
va009039 | 12:ea4badc78215 | 129 | //ISO_DBG("m_pED: %p itd: %p", m_pED, itd); |
va009039 | 12:ea4badc78215 | 130 | memcpy(const_cast<uint8_t*>(itd->buf), buf, len); |
va009039 | 12:ea4badc78215 | 131 | if (m_pED->enqueue<HCITD>(itd)) { |
va009039 | 12:ea4badc78215 | 132 | m_itd_queue_count++; |
va009039 | 12:ea4badc78215 | 133 | } |
va009039 | 12:ea4badc78215 | 134 | enable(); // Enable Periodic |
va009039 | 12:ea4badc78215 | 135 | //ISO_DBG("m_itd_queue_count: %d", m_itd_queue_count); |
va009039 | 12:ea4badc78215 | 136 | return len; |
va009039 | 12:ea4badc78215 | 137 | } |
va009039 | 12:ea4badc78215 | 138 | return 0; |
va009039 | 12:ea4badc78215 | 139 | } |
va009039 | 12:ea4badc78215 | 140 | |
va009039 | 12:ea4badc78215 | 141 | HCITD* IsochronousEp::get_queue_HCITD(int timeout_ms) |
va009039 | 12:ea4badc78215 | 142 | { |
va009039 | 12:ea4badc78215 | 143 | Timer t; |
va009039 | 12:ea4badc78215 | 144 | t.reset(); |
va009039 | 12:ea4badc78215 | 145 | t.start(); |
va009039 | 12:ea4badc78215 | 146 | do { |
va009039 | 12:ea4badc78215 | 147 | osEvent evt = m_queue.get(0); |
va009039 | 12:ea4badc78215 | 148 | if (evt.status == osEventMessage) { |
va009039 | 12:ea4badc78215 | 149 | HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p); |
va009039 | 12:ea4badc78215 | 150 | TEST_ASSERT(itd); |
va009039 | 12:ea4badc78215 | 151 | return itd; |
va009039 | 12:ea4badc78215 | 152 | } else if (evt.status == osOK) { |
va009039 | 12:ea4badc78215 | 153 | ; |
va009039 | 12:ea4badc78215 | 154 | } else if (evt.status == osEventTimeout) { |
va009039 | 12:ea4badc78215 | 155 | break; |
va009039 | 12:ea4badc78215 | 156 | } else { |
va009039 | 12:ea4badc78215 | 157 | ISO_DBG("evt.status: %02x\n", evt.status); |
va009039 | 12:ea4badc78215 | 158 | TEST_ASSERT(evt.status == osEventMessage); |
va009039 | 12:ea4badc78215 | 159 | break; |
va009039 | 12:ea4badc78215 | 160 | } |
va009039 | 12:ea4badc78215 | 161 | } while(t.read_ms() < timeout_ms); |
va009039 | 12:ea4badc78215 | 162 | return NULL; |
va009039 | 12:ea4badc78215 | 163 | } |
va009039 | 12:ea4badc78215 | 164 | |
va009039 | 12:ea4badc78215 | 165 | void IsochronousEp::enable() |
va009039 | 12:ea4badc78215 | 166 | { |
va009039 | 12:ea4badc78215 | 167 | LPC_USB->HcControl |= OR_CONTROL_PLE; |
va009039 | 12:ea4badc78215 | 168 | } |
va009039 | 12:ea4badc78215 | 169 | |
va009039 | 12:ea4badc78215 | 170 | void IsochronousEp::disconnect() |
va009039 | 12:ea4badc78215 | 171 | { |
va009039 | 12:ea4badc78215 | 172 | m_pED->setSkip(); // skip bit on |
va009039 | 12:ea4badc78215 | 173 | ISO_DBG("rtos-queue: %d", m_itd_queue_count); |
va009039 | 12:ea4badc78215 | 174 | int queue_count = m_itd_queue_count; |
va009039 | 12:ea4badc78215 | 175 | Timer t; |
va009039 | 12:ea4badc78215 | 176 | t.reset(); |
va009039 | 12:ea4badc78215 | 177 | t.start(); |
va009039 | 12:ea4badc78215 | 178 | do { |
va009039 | 12:ea4badc78215 | 179 | HCITD* itd = get_queue_HCITD(10); |
va009039 | 12:ea4badc78215 | 180 | if (itd) { |
va009039 | 12:ea4badc78215 | 181 | ISO_DBG("delete ITD:%p from rtos-queue %d ms", itd, t.read_ms()); |
va009039 | 12:ea4badc78215 | 182 | delete itd; |
va009039 | 12:ea4badc78215 | 183 | queue_count--; |
va009039 | 12:ea4badc78215 | 184 | t.reset(); |
va009039 | 12:ea4badc78215 | 185 | } |
va009039 | 12:ea4badc78215 | 186 | } while(t.read_ms() < 50); |
va009039 | 12:ea4badc78215 | 187 | ISO_DBG("rtos-queue: %d, %d ms", queue_count, t.read_ms()); |
va009039 | 12:ea4badc78215 | 188 | TEST_ASSERT(queue_count >= 0); |
va009039 | 12:ea4badc78215 | 189 | while(1) { |
va009039 | 12:ea4badc78215 | 190 | HCITD* itd = m_pED->dequeue<HCITD>(); |
va009039 | 12:ea4badc78215 | 191 | if (itd == NULL) { |
va009039 | 12:ea4badc78215 | 192 | break; |
va009039 | 12:ea4badc78215 | 193 | } |
va009039 | 12:ea4badc78215 | 194 | ISO_DBG("delete ITD:%p from ED(%p)-queue", itd, m_pED); |
va009039 | 12:ea4badc78215 | 195 | delete itd; |
va009039 | 12:ea4badc78215 | 196 | TEST_ASSERT(queue_count > 0); |
va009039 | 12:ea4badc78215 | 197 | queue_count--; |
va009039 | 12:ea4badc78215 | 198 | } |
va009039 | 12:ea4badc78215 | 199 | TEST_ASSERT(queue_count == 0); |
va009039 | 12:ea4badc78215 | 200 | HCITD* tail = reinterpret_cast<HCITD*>(m_pED->TailTd); |
va009039 | 12:ea4badc78215 | 201 | ISO_DBG("delete ITD:%p from ED(%p)-tail", tail, m_pED); |
va009039 | 12:ea4badc78215 | 202 | TEST_ASSERT(tail); |
va009039 | 12:ea4badc78215 | 203 | delete tail; |
va009039 | 12:ea4badc78215 | 204 | m_pED->init_queue<HCITD>(NULL); |
va009039 | 12:ea4badc78215 | 205 | |
va009039 | 12:ea4badc78215 | 206 | _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA); |
va009039 | 12:ea4badc78215 | 207 | TEST_ASSERT(hcca); |
va009039 | 12:ea4badc78215 | 208 | hcca->dequeue(m_pED); |
va009039 | 12:ea4badc78215 | 209 | ISO_DBG("delete ED:%p", m_pED); |
va009039 | 12:ea4badc78215 | 210 | delete m_pED; |
va009039 | 12:ea4badc78215 | 211 | m_pED = NULL; |
va009039 | 12:ea4badc78215 | 212 | } |