testing n-Bed with a Logitech C270 camera

Dependencies:   USBHost mbed

Fork of USBHostC270_example by Norimasa Okamoto

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?

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 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 }