User | Revision | Line number | New contents of line |
nhiro3303 |
0:42b8e1bc6235
|
1
|
/* mbed USBHost Library
|
nhiro3303 |
0:42b8e1bc6235
|
2
|
* Copyright (c) 2006-2013 ARM Limited
|
nhiro3303 |
0:42b8e1bc6235
|
3
|
*
|
nhiro3303 |
0:42b8e1bc6235
|
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
nhiro3303 |
0:42b8e1bc6235
|
5
|
* you may not use this file except in compliance with the License.
|
nhiro3303 |
0:42b8e1bc6235
|
6
|
* You may obtain a copy of the License at
|
nhiro3303 |
0:42b8e1bc6235
|
7
|
*
|
nhiro3303 |
0:42b8e1bc6235
|
8
|
* http://www.apache.org/licenses/LICENSE-2.0
|
nhiro3303 |
0:42b8e1bc6235
|
9
|
*
|
nhiro3303 |
0:42b8e1bc6235
|
10
|
* Unless required by applicable law or agreed to in writing, software
|
nhiro3303 |
0:42b8e1bc6235
|
11
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
nhiro3303 |
0:42b8e1bc6235
|
12
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nhiro3303 |
0:42b8e1bc6235
|
13
|
* See the License for the specific language governing permissions and
|
nhiro3303 |
0:42b8e1bc6235
|
14
|
* limitations under the License.
|
nhiro3303 |
0:42b8e1bc6235
|
15
|
*/
|
nhiro3303 |
0:42b8e1bc6235
|
16
|
|
nhiro3303 |
0:42b8e1bc6235
|
17
|
#if defined(TARGET_LPC4088)||defined(TARGET_LPC1768)
|
nhiro3303 |
0:42b8e1bc6235
|
18
|
#include "USBHALHost.h"
|
nhiro3303 |
0:42b8e1bc6235
|
19
|
|
nhiro3303 |
0:42b8e1bc6235
|
20
|
#ifndef CTASSERT
|
nhiro3303 |
0:42b8e1bc6235
|
21
|
template <bool>struct CtAssert;
|
nhiro3303 |
0:42b8e1bc6235
|
22
|
template <>struct CtAssert<true> {};
|
nhiro3303 |
0:42b8e1bc6235
|
23
|
#define CTASSERT(A) CtAssert<A>();
|
nhiro3303 |
0:42b8e1bc6235
|
24
|
#endif
|
nhiro3303 |
0:42b8e1bc6235
|
25
|
|
nhiro3303 |
0:42b8e1bc6235
|
26
|
#ifdef _USB_DBG
|
nhiro3303 |
0:42b8e1bc6235
|
27
|
#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
|
nhiro3303 |
0:42b8e1bc6235
|
28
|
#define USB_DBG_HEX(A,B) debug_hex(A,B)
|
nhiro3303 |
0:42b8e1bc6235
|
29
|
#define USB_DBG_ED(A) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
30
|
#define USB_DBG_TD(A) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
31
|
#define USB_DBG_ED_IF(A,B) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
32
|
void debug_hex(uint8_t* buf, int size);
|
nhiro3303 |
0:42b8e1bc6235
|
33
|
#else
|
nhiro3303 |
0:42b8e1bc6235
|
34
|
#define USB_DBG(...) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
35
|
#define USB_DBG_ED(A) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
36
|
#define USB_DBG_TD(A) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
37
|
#define USB_DBG_ED_IF(A,B) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
38
|
#define USB_DBG_HEX(A,B) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
39
|
#endif
|
nhiro3303 |
0:42b8e1bc6235
|
40
|
|
nhiro3303 |
0:42b8e1bc6235
|
41
|
#define USB_TRACE1(A) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
42
|
|
nhiro3303 |
0:42b8e1bc6235
|
43
|
#ifdef _USB_TEST
|
nhiro3303 |
0:42b8e1bc6235
|
44
|
#undef USB_TEST_ASSERT
|
nhiro3303 |
0:42b8e1bc6235
|
45
|
void usb_test_assert_internal(const char *expr, const char *file, int line);
|
nhiro3303 |
0:42b8e1bc6235
|
46
|
#define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
|
nhiro3303 |
0:42b8e1bc6235
|
47
|
#else
|
nhiro3303 |
0:42b8e1bc6235
|
48
|
#define USB_TEST_ASSERT(EXPR) while(0)
|
nhiro3303 |
0:42b8e1bc6235
|
49
|
#endif
|
nhiro3303 |
0:42b8e1bc6235
|
50
|
|
nhiro3303 |
0:42b8e1bc6235
|
51
|
#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
|
nhiro3303 |
0:42b8e1bc6235
|
52
|
|
nhiro3303 |
0:42b8e1bc6235
|
53
|
// bits of the USB/OTG clock control register
|
nhiro3303 |
0:42b8e1bc6235
|
54
|
#define HOST_CLK_EN (1<<0)
|
nhiro3303 |
0:42b8e1bc6235
|
55
|
#define DEV_CLK_EN (1<<1)
|
nhiro3303 |
0:42b8e1bc6235
|
56
|
#define PORTSEL_CLK_EN (1<<3)
|
nhiro3303 |
0:42b8e1bc6235
|
57
|
#define AHB_CLK_EN (1<<4)
|
nhiro3303 |
0:42b8e1bc6235
|
58
|
|
nhiro3303 |
0:42b8e1bc6235
|
59
|
// bits of the USB/OTG clock status register
|
nhiro3303 |
0:42b8e1bc6235
|
60
|
#define HOST_CLK_ON (1<<0)
|
nhiro3303 |
0:42b8e1bc6235
|
61
|
#define DEV_CLK_ON (1<<1)
|
nhiro3303 |
0:42b8e1bc6235
|
62
|
#define PORTSEL_CLK_ON (1<<3)
|
nhiro3303 |
0:42b8e1bc6235
|
63
|
#define AHB_CLK_ON (1<<4)
|
nhiro3303 |
0:42b8e1bc6235
|
64
|
|
nhiro3303 |
0:42b8e1bc6235
|
65
|
// we need host clock, OTG/portsel clock and AHB clock
|
nhiro3303 |
0:42b8e1bc6235
|
66
|
#define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
|
nhiro3303 |
0:42b8e1bc6235
|
67
|
#define FI 0x2EDF /* 12000 bits per frame (-1) */
|
nhiro3303 |
0:42b8e1bc6235
|
68
|
#define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
|
nhiro3303 |
0:42b8e1bc6235
|
69
|
|
nhiro3303 |
0:42b8e1bc6235
|
70
|
USBHALHost* USBHALHost::instHost;
|
nhiro3303 |
0:42b8e1bc6235
|
71
|
|
nhiro3303 |
0:42b8e1bc6235
|
72
|
USBHALHost::USBHALHost() {
|
nhiro3303 |
0:42b8e1bc6235
|
73
|
instHost = this;
|
nhiro3303 |
0:42b8e1bc6235
|
74
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
75
|
|
nhiro3303 |
0:42b8e1bc6235
|
76
|
void USBHALHost::init() {
|
nhiro3303 |
0:42b8e1bc6235
|
77
|
NVIC_DisableIRQ(USB_IRQn);
|
nhiro3303 |
0:42b8e1bc6235
|
78
|
m_pHcca = new HCCA();
|
nhiro3303 |
0:42b8e1bc6235
|
79
|
init_hw_ohci(m_pHcca);
|
nhiro3303 |
0:42b8e1bc6235
|
80
|
ResetRootHub();
|
nhiro3303 |
0:42b8e1bc6235
|
81
|
NVIC_SetVector(USB_IRQn, (uint32_t)_usbisr);
|
nhiro3303 |
0:42b8e1bc6235
|
82
|
NVIC_SetPriority(USB_IRQn, 0);
|
nhiro3303 |
0:42b8e1bc6235
|
83
|
NVIC_EnableIRQ(USB_IRQn);
|
nhiro3303 |
0:42b8e1bc6235
|
84
|
|
nhiro3303 |
0:42b8e1bc6235
|
85
|
USB_INFO("Simple USBHost Library for LPC4088/LPC1768");
|
nhiro3303 |
0:42b8e1bc6235
|
86
|
bool lowSpeed = wait_attach();
|
nhiro3303 |
0:42b8e1bc6235
|
87
|
addDevice(NULL, 0, lowSpeed);
|
nhiro3303 |
0:42b8e1bc6235
|
88
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
89
|
|
nhiro3303 |
0:42b8e1bc6235
|
90
|
void USBHALHost::init_hw_ohci(HCCA* pHcca) {
|
nhiro3303 |
0:42b8e1bc6235
|
91
|
LPC_SC->PCONP &= ~(1UL<<31); //Cut power
|
nhiro3303 |
0:42b8e1bc6235
|
92
|
wait_ms(1000);
|
nhiro3303 |
0:42b8e1bc6235
|
93
|
LPC_SC->PCONP |= (1UL<<31); // turn on power for USB
|
nhiro3303 |
0:42b8e1bc6235
|
94
|
LPC_USB->USBClkCtrl |= CLOCK_MASK; // Enable USB host clock, port selection and AHB clock
|
nhiro3303 |
0:42b8e1bc6235
|
95
|
// Wait for clocks to become available
|
nhiro3303 |
0:42b8e1bc6235
|
96
|
while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
|
nhiro3303 |
0:42b8e1bc6235
|
97
|
;
|
nhiro3303 |
0:42b8e1bc6235
|
98
|
LPC_USB->OTGStCtrl |= 1;
|
nhiro3303 |
0:42b8e1bc6235
|
99
|
LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
|
nhiro3303 |
0:42b8e1bc6235
|
100
|
|
nhiro3303 |
0:42b8e1bc6235
|
101
|
#if defined(TARGET_LPC1768)
|
nhiro3303 |
0:42b8e1bc6235
|
102
|
LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
|
nhiro3303 |
0:42b8e1bc6235
|
103
|
LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
|
nhiro3303 |
0:42b8e1bc6235
|
104
|
#elif defined(TARGET_LPC4088)
|
nhiro3303 |
0:42b8e1bc6235
|
105
|
LPC_IOCON->P0_29 = 0x01; // USB_D+1
|
nhiro3303 |
0:42b8e1bc6235
|
106
|
LPC_IOCON->P0_30 = 0x01; // USB_D-1
|
nhiro3303 |
0:42b8e1bc6235
|
107
|
// DO NOT CHANGE P1_19.
|
nhiro3303 |
0:42b8e1bc6235
|
108
|
#else
|
nhiro3303 |
0:42b8e1bc6235
|
109
|
#error "target error"
|
nhiro3303 |
0:42b8e1bc6235
|
110
|
#endif
|
nhiro3303 |
0:42b8e1bc6235
|
111
|
USB_DBG("initialize OHCI\n");
|
nhiro3303 |
0:42b8e1bc6235
|
112
|
wait_ms(100); /* Wait 50 ms before apply reset */
|
nhiro3303 |
0:42b8e1bc6235
|
113
|
USB_TEST_ASSERT((LPC_USB->HcRevision&0xff) == 0x10); // check revision
|
nhiro3303 |
0:42b8e1bc6235
|
114
|
LPC_USB->HcControl = 0; /* HARDWARE RESET */
|
nhiro3303 |
0:42b8e1bc6235
|
115
|
LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */
|
nhiro3303 |
0:42b8e1bc6235
|
116
|
LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */
|
nhiro3303 |
0:42b8e1bc6235
|
117
|
/* SOFTWARE RESET */
|
nhiro3303 |
0:42b8e1bc6235
|
118
|
LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
|
nhiro3303 |
0:42b8e1bc6235
|
119
|
LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */
|
nhiro3303 |
0:42b8e1bc6235
|
120
|
LPC_USB->HcPeriodicStart = FI*90/100;
|
nhiro3303 |
0:42b8e1bc6235
|
121
|
/* Put HC in operational state */
|
nhiro3303 |
0:42b8e1bc6235
|
122
|
LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
|
nhiro3303 |
0:42b8e1bc6235
|
123
|
LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */
|
nhiro3303 |
0:42b8e1bc6235
|
124
|
USB_TEST_ASSERT(pHcca);
|
nhiro3303 |
0:42b8e1bc6235
|
125
|
for (int i = 0; i < 32; i++) {
|
nhiro3303 |
0:42b8e1bc6235
|
126
|
pHcca->InterruptTable[i] = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
127
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
128
|
LPC_USB->HcHCCA = reinterpret_cast<uint32_t>(pHcca);
|
nhiro3303 |
0:42b8e1bc6235
|
129
|
LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
|
nhiro3303 |
0:42b8e1bc6235
|
130
|
LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
|
nhiro3303 |
0:42b8e1bc6235
|
131
|
|
nhiro3303 |
0:42b8e1bc6235
|
132
|
LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
|
nhiro3303 |
0:42b8e1bc6235
|
133
|
LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
|
nhiro3303 |
0:42b8e1bc6235
|
134
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
135
|
|
nhiro3303 |
0:42b8e1bc6235
|
136
|
void USBHALHost::ResetRootHub() {
|
nhiro3303 |
0:42b8e1bc6235
|
137
|
wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */
|
nhiro3303 |
0:42b8e1bc6235
|
138
|
LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
|
nhiro3303 |
0:42b8e1bc6235
|
139
|
USB_DBG("Before loop\n");
|
nhiro3303 |
0:42b8e1bc6235
|
140
|
while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
|
nhiro3303 |
0:42b8e1bc6235
|
141
|
;
|
nhiro3303 |
0:42b8e1bc6235
|
142
|
LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
|
nhiro3303 |
0:42b8e1bc6235
|
143
|
USB_DBG("After loop\n");
|
nhiro3303 |
0:42b8e1bc6235
|
144
|
wait_ms(200); /* Wait for 100 MS after port reset */
|
nhiro3303 |
0:42b8e1bc6235
|
145
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
146
|
|
nhiro3303 |
0:42b8e1bc6235
|
147
|
bool USBHALHost::wait_attach() {
|
nhiro3303 |
0:42b8e1bc6235
|
148
|
bool lowSpeed = false;
|
nhiro3303 |
0:42b8e1bc6235
|
149
|
uint32_t status = LPC_USB->HcRhPortStatus1;
|
nhiro3303 |
0:42b8e1bc6235
|
150
|
if (status & OR_RH_PORT_LSDA) { // lowSpeedDeviceAttached
|
nhiro3303 |
0:42b8e1bc6235
|
151
|
lowSpeed = true;
|
nhiro3303 |
0:42b8e1bc6235
|
152
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
153
|
return lowSpeed;
|
nhiro3303 |
0:42b8e1bc6235
|
154
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
155
|
|
nhiro3303 |
0:42b8e1bc6235
|
156
|
void enable(ENDPOINT_TYPE type) {
|
nhiro3303 |
0:42b8e1bc6235
|
157
|
switch(type) {
|
nhiro3303 |
0:42b8e1bc6235
|
158
|
case CONTROL_ENDPOINT:
|
nhiro3303 |
0:42b8e1bc6235
|
159
|
LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
|
nhiro3303 |
0:42b8e1bc6235
|
160
|
LPC_USB->HcControl |= OR_CONTROL_CLE;
|
nhiro3303 |
0:42b8e1bc6235
|
161
|
break;
|
nhiro3303 |
0:42b8e1bc6235
|
162
|
case ISOCHRONOUS_ENDPOINT:
|
nhiro3303 |
0:42b8e1bc6235
|
163
|
LPC_USB->HcControl |= OR_CONTROL_PLE;
|
nhiro3303 |
0:42b8e1bc6235
|
164
|
break;
|
nhiro3303 |
0:42b8e1bc6235
|
165
|
case BULK_ENDPOINT:
|
nhiro3303 |
0:42b8e1bc6235
|
166
|
LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
|
nhiro3303 |
0:42b8e1bc6235
|
167
|
LPC_USB->HcControl |= OR_CONTROL_BLE;
|
nhiro3303 |
0:42b8e1bc6235
|
168
|
break;
|
nhiro3303 |
0:42b8e1bc6235
|
169
|
case INTERRUPT_ENDPOINT:
|
nhiro3303 |
0:42b8e1bc6235
|
170
|
LPC_USB->HcControl |= OR_CONTROL_PLE;
|
nhiro3303 |
0:42b8e1bc6235
|
171
|
break;
|
nhiro3303 |
0:42b8e1bc6235
|
172
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
173
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
174
|
|
nhiro3303 |
0:42b8e1bc6235
|
175
|
void USBHALHost::token_init(USBEndpoint* ep) {
|
nhiro3303 |
0:42b8e1bc6235
|
176
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
177
|
if (ed == NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
178
|
ed = new HCED(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
179
|
ep->setHALData<HCED*>(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
180
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
181
|
USBDeviceConnected* dev = ep->getDevice();
|
nhiro3303 |
0:42b8e1bc6235
|
182
|
USB_TEST_ASSERT(dev);
|
nhiro3303 |
0:42b8e1bc6235
|
183
|
if (dev) {
|
nhiro3303 |
0:42b8e1bc6235
|
184
|
uint8_t devAddr = dev->getAddress();
|
nhiro3303 |
0:42b8e1bc6235
|
185
|
USB_DBG("devAddr=%02x", devAddr);
|
nhiro3303 |
0:42b8e1bc6235
|
186
|
ed->setFunctionAddress(devAddr);
|
nhiro3303 |
0:42b8e1bc6235
|
187
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
188
|
uint16_t size = ep->getSize();
|
nhiro3303 |
0:42b8e1bc6235
|
189
|
USB_DBG("MaxPacketSize=%d", size);
|
nhiro3303 |
0:42b8e1bc6235
|
190
|
ed->setMaxPacketSize(size);
|
nhiro3303 |
0:42b8e1bc6235
|
191
|
if (ed->HeadTd == NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
192
|
HCTD* td = new HCTD(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
193
|
ed->TailTd = td;
|
nhiro3303 |
0:42b8e1bc6235
|
194
|
ed->HeadTd = td;
|
nhiro3303 |
0:42b8e1bc6235
|
195
|
switch(ep->getType()) {
|
nhiro3303 |
0:42b8e1bc6235
|
196
|
case CONTROL_ENDPOINT:
|
nhiro3303 |
0:42b8e1bc6235
|
197
|
ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
|
nhiro3303 |
0:42b8e1bc6235
|
198
|
LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
199
|
break;
|
nhiro3303 |
0:42b8e1bc6235
|
200
|
case BULK_ENDPOINT:
|
nhiro3303 |
0:42b8e1bc6235
|
201
|
ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcBulkHeadED);
|
nhiro3303 |
0:42b8e1bc6235
|
202
|
LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
203
|
break;
|
nhiro3303 |
0:42b8e1bc6235
|
204
|
case INTERRUPT_ENDPOINT:
|
nhiro3303 |
0:42b8e1bc6235
|
205
|
HCCA* pHcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
|
nhiro3303 |
0:42b8e1bc6235
|
206
|
ed->Next = pHcca->InterruptTable[0];
|
nhiro3303 |
0:42b8e1bc6235
|
207
|
pHcca->InterruptTable[0] = ed;
|
nhiro3303 |
0:42b8e1bc6235
|
208
|
break;
|
nhiro3303 |
0:42b8e1bc6235
|
209
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
210
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
211
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
212
|
|
nhiro3303 |
0:42b8e1bc6235
|
213
|
int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
|
nhiro3303 |
0:42b8e1bc6235
|
214
|
token_init(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
215
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
216
|
HCTD* td = ed->TailTd;
|
nhiro3303 |
0:42b8e1bc6235
|
217
|
setup->wLength = wLength;
|
nhiro3303 |
0:42b8e1bc6235
|
218
|
TBUF* tbuf = new(sizeof(SETUP_PACKET))TBUF(setup, sizeof(SETUP_PACKET));
|
nhiro3303 |
0:42b8e1bc6235
|
219
|
td->transfer(tbuf, sizeof(SETUP_PACKET));
|
nhiro3303 |
0:42b8e1bc6235
|
220
|
td->Control |= TD_TOGGLE_0|TD_SETUP; // DATA0
|
nhiro3303 |
0:42b8e1bc6235
|
221
|
HCTD* blank = new HCTD(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
222
|
ed->enqueue(blank);
|
nhiro3303 |
0:42b8e1bc6235
|
223
|
//DBG_ED(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
224
|
enable(ep->getType());
|
nhiro3303 |
0:42b8e1bc6235
|
225
|
|
nhiro3303 |
0:42b8e1bc6235
|
226
|
td = ed->get_queue_HCTD();
|
nhiro3303 |
0:42b8e1bc6235
|
227
|
USB_TEST_ASSERT(td);
|
nhiro3303 |
0:42b8e1bc6235
|
228
|
int result = td->getLengthTransferred();
|
nhiro3303 |
0:42b8e1bc6235
|
229
|
USB_DBG_TD(td);
|
nhiro3303 |
0:42b8e1bc6235
|
230
|
delete tbuf;
|
nhiro3303 |
0:42b8e1bc6235
|
231
|
delete td;
|
nhiro3303 |
0:42b8e1bc6235
|
232
|
return result;
|
nhiro3303 |
0:42b8e1bc6235
|
233
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
234
|
|
nhiro3303 |
0:42b8e1bc6235
|
235
|
static HCED* getHCED_iso(USBEndpoint* ep) {
|
nhiro3303 |
0:42b8e1bc6235
|
236
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
237
|
if (ed != NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
238
|
return ed;
|
nhiro3303 |
0:42b8e1bc6235
|
239
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
240
|
ed = new HCED(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
241
|
ep->setHALData<HCED*>(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
242
|
ed->setFormat(); // F Format ITD
|
nhiro3303 |
0:42b8e1bc6235
|
243
|
ed->iso.FrameCount = ep->ohci.frameCount;
|
nhiro3303 |
0:42b8e1bc6235
|
244
|
ed->iso.queue_limit = ep->ohci.queueLimit;
|
nhiro3303 |
0:42b8e1bc6235
|
245
|
ed->iso.queue_count = 0;
|
nhiro3303 |
0:42b8e1bc6235
|
246
|
ed->iso.Current_FrameCount = 0;
|
nhiro3303 |
0:42b8e1bc6235
|
247
|
ed->iso.Current_itd = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
248
|
ed->iso.FrameNumber = LPC_USB->HcFmNumber + 10; // after 10msec
|
nhiro3303 |
0:42b8e1bc6235
|
249
|
HCITD* itd = ed->new_HCITD();
|
nhiro3303 |
0:42b8e1bc6235
|
250
|
ed->init_queue(reinterpret_cast<HCTD*>(itd));
|
nhiro3303 |
0:42b8e1bc6235
|
251
|
HCCA* hcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
|
nhiro3303 |
0:42b8e1bc6235
|
252
|
hcca->enqueue(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
253
|
LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable
|
nhiro3303 |
0:42b8e1bc6235
|
254
|
LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable
|
nhiro3303 |
0:42b8e1bc6235
|
255
|
return ed;
|
nhiro3303 |
0:42b8e1bc6235
|
256
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
257
|
|
nhiro3303 |
0:42b8e1bc6235
|
258
|
static void enablePeriodic() {
|
nhiro3303 |
0:42b8e1bc6235
|
259
|
LPC_USB->HcControl |= OR_CONTROL_PLE;
|
nhiro3303 |
0:42b8e1bc6235
|
260
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
261
|
|
nhiro3303 |
0:42b8e1bc6235
|
262
|
HCITD* isochronousReceive(USBEndpoint* ep) {
|
nhiro3303 |
0:42b8e1bc6235
|
263
|
HCED* ed = getHCED_iso(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
264
|
USB_TEST_ASSERT(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
265
|
while(ed->iso.queue_count < ed->iso.queue_limit) {
|
nhiro3303 |
0:42b8e1bc6235
|
266
|
HCITD* blank_itd = ed->new_HCITD();
|
nhiro3303 |
0:42b8e1bc6235
|
267
|
if (ed->enqueue(reinterpret_cast<HCTD*>(blank_itd))) {
|
nhiro3303 |
0:42b8e1bc6235
|
268
|
ed->iso.queue_count++;
|
nhiro3303 |
0:42b8e1bc6235
|
269
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
270
|
enablePeriodic();
|
nhiro3303 |
0:42b8e1bc6235
|
271
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
272
|
|
nhiro3303 |
0:42b8e1bc6235
|
273
|
HCITD* itd = ed->get_queue_HCITD();
|
nhiro3303 |
0:42b8e1bc6235
|
274
|
if (itd) {
|
nhiro3303 |
0:42b8e1bc6235
|
275
|
ed->iso.queue_count--;
|
nhiro3303 |
0:42b8e1bc6235
|
276
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
277
|
return itd;
|
nhiro3303 |
0:42b8e1bc6235
|
278
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
279
|
|
nhiro3303 |
0:42b8e1bc6235
|
280
|
int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
|
nhiro3303 |
0:42b8e1bc6235
|
281
|
HCED* ed = getHCED_iso(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
282
|
if (ed->iso.Current_FrameCount == 0) {
|
nhiro3303 |
0:42b8e1bc6235
|
283
|
HCITD* itd = isochronousReceive(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
284
|
if (itd == NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
285
|
return -1;
|
nhiro3303 |
0:42b8e1bc6235
|
286
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
287
|
if (itd->ConditionCode() != 0) {
|
nhiro3303 |
0:42b8e1bc6235
|
288
|
delete itd;
|
nhiro3303 |
0:42b8e1bc6235
|
289
|
return -1;
|
nhiro3303 |
0:42b8e1bc6235
|
290
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
291
|
ed->iso.Current_itd = itd;
|
nhiro3303 |
0:42b8e1bc6235
|
292
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
293
|
|
nhiro3303 |
0:42b8e1bc6235
|
294
|
HCITD* itd = ed->iso.Current_itd;
|
nhiro3303 |
0:42b8e1bc6235
|
295
|
int fc = ed->iso.Current_FrameCount;
|
nhiro3303 |
0:42b8e1bc6235
|
296
|
int result = -1;
|
nhiro3303 |
0:42b8e1bc6235
|
297
|
uint8_t cc = itd->ConditionCode(fc);
|
nhiro3303 |
0:42b8e1bc6235
|
298
|
if (cc == 0 || cc == 9) {
|
nhiro3303 |
0:42b8e1bc6235
|
299
|
result = itd->Length(fc);
|
nhiro3303 |
0:42b8e1bc6235
|
300
|
memcpy(data, itd->Buffer(fc), result);
|
nhiro3303 |
0:42b8e1bc6235
|
301
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
302
|
|
nhiro3303 |
0:42b8e1bc6235
|
303
|
if (++ed->iso.Current_FrameCount >= itd->FrameCount()) {
|
nhiro3303 |
0:42b8e1bc6235
|
304
|
ed->iso.Current_FrameCount = 0;
|
nhiro3303 |
0:42b8e1bc6235
|
305
|
delete ed->iso.Current_itd;
|
nhiro3303 |
0:42b8e1bc6235
|
306
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
307
|
return result;
|
nhiro3303 |
0:42b8e1bc6235
|
308
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
309
|
|
nhiro3303 |
0:42b8e1bc6235
|
310
|
int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, int size) {
|
nhiro3303 |
0:42b8e1bc6235
|
311
|
token_init(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
312
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
313
|
HCTD* td = ed->TailTd;
|
nhiro3303 |
0:42b8e1bc6235
|
314
|
TBUF* tbuf = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
315
|
if (data != NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
316
|
tbuf = new(size)TBUF();
|
nhiro3303 |
0:42b8e1bc6235
|
317
|
td->transfer(tbuf, size);
|
nhiro3303 |
0:42b8e1bc6235
|
318
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
319
|
td->Control |= TD_IN;
|
nhiro3303 |
0:42b8e1bc6235
|
320
|
HCTD* blank = new HCTD(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
321
|
ed->enqueue(blank);
|
nhiro3303 |
0:42b8e1bc6235
|
322
|
USB_DBG_ED_IF(ed->EndpointNumber()==0, ed); // control transfer
|
nhiro3303 |
0:42b8e1bc6235
|
323
|
enable(ep->getType());
|
nhiro3303 |
0:42b8e1bc6235
|
324
|
|
nhiro3303 |
0:42b8e1bc6235
|
325
|
td = ed->get_queue_HCTD();
|
nhiro3303 |
0:42b8e1bc6235
|
326
|
USB_TEST_ASSERT(td);
|
nhiro3303 |
0:42b8e1bc6235
|
327
|
if (data != NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
328
|
memcpy(data, tbuf->buf, size);
|
nhiro3303 |
0:42b8e1bc6235
|
329
|
delete tbuf;
|
nhiro3303 |
0:42b8e1bc6235
|
330
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
331
|
int result = td->getLengthTransferred();
|
nhiro3303 |
0:42b8e1bc6235
|
332
|
delete td;
|
nhiro3303 |
0:42b8e1bc6235
|
333
|
return result;
|
nhiro3303 |
0:42b8e1bc6235
|
334
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
335
|
|
nhiro3303 |
0:42b8e1bc6235
|
336
|
int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, int size) {
|
nhiro3303 |
0:42b8e1bc6235
|
337
|
token_init(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
338
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
339
|
HCTD* td = ed->TailTd;
|
nhiro3303 |
0:42b8e1bc6235
|
340
|
TBUF* tbuf = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
341
|
if (data != NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
342
|
tbuf = new(size)TBUF(data, size);
|
nhiro3303 |
0:42b8e1bc6235
|
343
|
td->transfer(tbuf, size);
|
nhiro3303 |
0:42b8e1bc6235
|
344
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
345
|
td->Control |= TD_OUT;
|
nhiro3303 |
0:42b8e1bc6235
|
346
|
HCTD* blank = new HCTD(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
347
|
ed->enqueue(blank);
|
nhiro3303 |
0:42b8e1bc6235
|
348
|
USB_DBG_ED(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
349
|
enable(ep->getType());
|
nhiro3303 |
0:42b8e1bc6235
|
350
|
|
nhiro3303 |
0:42b8e1bc6235
|
351
|
td = ed->get_queue_HCTD();
|
nhiro3303 |
0:42b8e1bc6235
|
352
|
USB_TEST_ASSERT(td);
|
nhiro3303 |
0:42b8e1bc6235
|
353
|
if (data != NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
354
|
delete tbuf;
|
nhiro3303 |
0:42b8e1bc6235
|
355
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
356
|
int result = td->getLengthTransferred();
|
nhiro3303 |
0:42b8e1bc6235
|
357
|
delete td;
|
nhiro3303 |
0:42b8e1bc6235
|
358
|
return result;
|
nhiro3303 |
0:42b8e1bc6235
|
359
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
360
|
|
nhiro3303 |
0:42b8e1bc6235
|
361
|
void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
|
nhiro3303 |
0:42b8e1bc6235
|
362
|
token_init(ep);
|
nhiro3303 |
0:42b8e1bc6235
|
363
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
364
|
HCTD* td = ed->TailTd;
|
nhiro3303 |
0:42b8e1bc6235
|
365
|
TBUF* tbuf = new(size)TBUF();
|
nhiro3303 |
0:42b8e1bc6235
|
366
|
td->transfer(tbuf, size);
|
nhiro3303 |
0:42b8e1bc6235
|
367
|
td->Control |= TD_IN;
|
nhiro3303 |
0:42b8e1bc6235
|
368
|
HCTD* blank = new HCTD(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
369
|
ed->enqueue(blank);
|
nhiro3303 |
0:42b8e1bc6235
|
370
|
enable(ep->getType());
|
nhiro3303 |
0:42b8e1bc6235
|
371
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
372
|
|
nhiro3303 |
0:42b8e1bc6235
|
373
|
USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) {
|
nhiro3303 |
0:42b8e1bc6235
|
374
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
375
|
if (ed == NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
376
|
return USB_TYPE_ERROR;
|
nhiro3303 |
0:42b8e1bc6235
|
377
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
378
|
HCTD* td = ed->get_queue_HCTD(0);
|
nhiro3303 |
0:42b8e1bc6235
|
379
|
if (td) {
|
nhiro3303 |
0:42b8e1bc6235
|
380
|
int len = td->getLengthTransferred();
|
nhiro3303 |
0:42b8e1bc6235
|
381
|
TBUF* tbuf = (TBUF*)td->buf_top;
|
nhiro3303 |
0:42b8e1bc6235
|
382
|
memcpy(ep->getBufStart(), tbuf->buf, len);
|
nhiro3303 |
0:42b8e1bc6235
|
383
|
ep->setLengthTransferred(len);
|
nhiro3303 |
0:42b8e1bc6235
|
384
|
ep->setState((USB_TYPE)td->ConditionCode());
|
nhiro3303 |
0:42b8e1bc6235
|
385
|
delete td;
|
nhiro3303 |
0:42b8e1bc6235
|
386
|
delete tbuf;
|
nhiro3303 |
0:42b8e1bc6235
|
387
|
return USB_TYPE_OK;
|
nhiro3303 |
0:42b8e1bc6235
|
388
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
389
|
return USB_TYPE_PROCESSING;
|
nhiro3303 |
0:42b8e1bc6235
|
390
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
391
|
|
nhiro3303 |
0:42b8e1bc6235
|
392
|
void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) {
|
nhiro3303 |
0:42b8e1bc6235
|
393
|
USB_TEST_ASSERT(toggle == 1);
|
nhiro3303 |
0:42b8e1bc6235
|
394
|
HCED* ed = ep->getHALData<HCED*>();
|
nhiro3303 |
0:42b8e1bc6235
|
395
|
ed->setToggle(toggle);
|
nhiro3303 |
0:42b8e1bc6235
|
396
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
397
|
|
nhiro3303 |
0:42b8e1bc6235
|
398
|
void USBHALHost::_usbisr(void) {
|
nhiro3303 |
0:42b8e1bc6235
|
399
|
if (instHost) {
|
nhiro3303 |
0:42b8e1bc6235
|
400
|
instHost->UsbIrqhandler();
|
nhiro3303 |
0:42b8e1bc6235
|
401
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
402
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
403
|
|
nhiro3303 |
0:42b8e1bc6235
|
404
|
HCTD* td_reverse(HCTD* td)
|
nhiro3303 |
0:42b8e1bc6235
|
405
|
{
|
nhiro3303 |
0:42b8e1bc6235
|
406
|
HCTD* result = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
407
|
HCTD* next;
|
nhiro3303 |
0:42b8e1bc6235
|
408
|
while(td) {
|
nhiro3303 |
0:42b8e1bc6235
|
409
|
next = const_cast<HCTD*>(td->Next);
|
nhiro3303 |
0:42b8e1bc6235
|
410
|
td->Next = result;
|
nhiro3303 |
0:42b8e1bc6235
|
411
|
result = td;
|
nhiro3303 |
0:42b8e1bc6235
|
412
|
td = next;
|
nhiro3303 |
0:42b8e1bc6235
|
413
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
414
|
return result;
|
nhiro3303 |
0:42b8e1bc6235
|
415
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
416
|
|
nhiro3303 |
0:42b8e1bc6235
|
417
|
void USBHALHost::UsbIrqhandler() {
|
nhiro3303 |
0:42b8e1bc6235
|
418
|
if (!(LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable)) {
|
nhiro3303 |
0:42b8e1bc6235
|
419
|
return;
|
nhiro3303 |
0:42b8e1bc6235
|
420
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
421
|
m_report_irq++;
|
nhiro3303 |
0:42b8e1bc6235
|
422
|
uint32_t status = LPC_USB->HcInterruptStatus;
|
nhiro3303 |
0:42b8e1bc6235
|
423
|
if (status & OR_INTR_STATUS_FNO) {
|
nhiro3303 |
0:42b8e1bc6235
|
424
|
m_report_FNO++;
|
nhiro3303 |
0:42b8e1bc6235
|
425
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
426
|
if (status & OR_INTR_STATUS_WDH) {
|
nhiro3303 |
0:42b8e1bc6235
|
427
|
union {
|
nhiro3303 |
0:42b8e1bc6235
|
428
|
HCTD* done_td;
|
nhiro3303 |
0:42b8e1bc6235
|
429
|
uint32_t lsb;
|
nhiro3303 |
0:42b8e1bc6235
|
430
|
};
|
nhiro3303 |
0:42b8e1bc6235
|
431
|
done_td = const_cast<HCTD*>(m_pHcca->DoneHead);
|
nhiro3303 |
0:42b8e1bc6235
|
432
|
USB_TEST_ASSERT(done_td);
|
nhiro3303 |
0:42b8e1bc6235
|
433
|
m_pHcca->DoneHead = NULL; // reset
|
nhiro3303 |
0:42b8e1bc6235
|
434
|
if (lsb & 1) { // error ?
|
nhiro3303 |
0:42b8e1bc6235
|
435
|
lsb &= ~1;
|
nhiro3303 |
0:42b8e1bc6235
|
436
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
437
|
HCTD* td = td_reverse(done_td);
|
nhiro3303 |
0:42b8e1bc6235
|
438
|
while(td) {
|
nhiro3303 |
0:42b8e1bc6235
|
439
|
HCED* ed = td->parent;
|
nhiro3303 |
0:42b8e1bc6235
|
440
|
USB_TEST_ASSERT(ed);
|
nhiro3303 |
0:42b8e1bc6235
|
441
|
if (ed) {
|
nhiro3303 |
0:42b8e1bc6235
|
442
|
ed->irqWdhHandler(td);
|
nhiro3303 |
0:42b8e1bc6235
|
443
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
444
|
td = td->Next;
|
nhiro3303 |
0:42b8e1bc6235
|
445
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
446
|
m_report_WDH++;
|
nhiro3303 |
0:42b8e1bc6235
|
447
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
448
|
LPC_USB->HcInterruptStatus = status; // Clear Interrrupt Status
|
nhiro3303 |
0:42b8e1bc6235
|
449
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
450
|
|
nhiro3303 |
0:42b8e1bc6235
|
451
|
TBUF::TBUF(const void* data, int size) {
|
nhiro3303 |
0:42b8e1bc6235
|
452
|
if (size > 0) {
|
nhiro3303 |
0:42b8e1bc6235
|
453
|
memcpy(buf, data, size);
|
nhiro3303 |
0:42b8e1bc6235
|
454
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
455
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
456
|
|
nhiro3303 |
0:42b8e1bc6235
|
457
|
HCTD::HCTD(HCED* obj) {
|
nhiro3303 |
0:42b8e1bc6235
|
458
|
CTASSERT(sizeof(HCTD) == 36);
|
nhiro3303 |
0:42b8e1bc6235
|
459
|
USB_TEST_ASSERT(obj);
|
nhiro3303 |
0:42b8e1bc6235
|
460
|
Control = TD_CC|TD_ROUNDING;
|
nhiro3303 |
0:42b8e1bc6235
|
461
|
CurrBufPtr = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
462
|
Next = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
463
|
BufEnd = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
464
|
buf_top = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
465
|
buf_size = 0;
|
nhiro3303 |
0:42b8e1bc6235
|
466
|
parent = obj;
|
nhiro3303 |
0:42b8e1bc6235
|
467
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
468
|
|
nhiro3303 |
0:42b8e1bc6235
|
469
|
HCITD::HCITD(HCED* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
|
nhiro3303 |
0:42b8e1bc6235
|
470
|
Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED
|
nhiro3303 |
0:42b8e1bc6235
|
471
|
((FrameCount-1) << 24)| // FC FrameCount
|
nhiro3303 |
0:42b8e1bc6235
|
472
|
TD_DELAY_INT(0) | // DI DelayInterrupt
|
nhiro3303 |
0:42b8e1bc6235
|
473
|
FrameNumber; // SF StartingFrame
|
nhiro3303 |
0:42b8e1bc6235
|
474
|
BufferPage0 = const_cast<uint8_t*>(buf);
|
nhiro3303 |
0:42b8e1bc6235
|
475
|
BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
|
nhiro3303 |
0:42b8e1bc6235
|
476
|
Next = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
477
|
parent = obj;
|
nhiro3303 |
0:42b8e1bc6235
|
478
|
uint32_t addr = reinterpret_cast<uint32_t>(buf);
|
nhiro3303 |
0:42b8e1bc6235
|
479
|
for(int i = 0; i < FrameCount; i++) {
|
nhiro3303 |
0:42b8e1bc6235
|
480
|
uint16_t offset = addr & 0x0fff;
|
nhiro3303 |
0:42b8e1bc6235
|
481
|
if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
|
nhiro3303 |
0:42b8e1bc6235
|
482
|
offset |= 0x1000;
|
nhiro3303 |
0:42b8e1bc6235
|
483
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
484
|
OffsetPSW[i] = 0xe000|offset;
|
nhiro3303 |
0:42b8e1bc6235
|
485
|
addr += PacketSize;
|
nhiro3303 |
0:42b8e1bc6235
|
486
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
487
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
488
|
|
nhiro3303 |
0:42b8e1bc6235
|
489
|
uint8_t* HCITD::Buffer(int fc) {
|
nhiro3303 |
0:42b8e1bc6235
|
490
|
int offset = fc * parent->getMaxPacketSize();
|
nhiro3303 |
0:42b8e1bc6235
|
491
|
return const_cast<uint8_t*>(buf) + offset;
|
nhiro3303 |
0:42b8e1bc6235
|
492
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
493
|
|
nhiro3303 |
0:42b8e1bc6235
|
494
|
HCED::HCED(USBEndpoint* ep) {
|
nhiro3303 |
0:42b8e1bc6235
|
495
|
CTASSERT(sizeof(HCED) <= (64*2));
|
nhiro3303 |
0:42b8e1bc6235
|
496
|
USBDeviceConnected* dev = ep->getDevice();
|
nhiro3303 |
0:42b8e1bc6235
|
497
|
int devAddr = 0;
|
nhiro3303 |
0:42b8e1bc6235
|
498
|
bool lowSpeed = false;
|
nhiro3303 |
0:42b8e1bc6235
|
499
|
if (dev) {
|
nhiro3303 |
0:42b8e1bc6235
|
500
|
devAddr = dev->getAddress();
|
nhiro3303 |
0:42b8e1bc6235
|
501
|
lowSpeed = dev->getSpeed();
|
nhiro3303 |
0:42b8e1bc6235
|
502
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
503
|
int ep_number = ep->getAddress();
|
nhiro3303 |
0:42b8e1bc6235
|
504
|
int MaxPacketSize = ep->getSize();
|
nhiro3303 |
0:42b8e1bc6235
|
505
|
Control = devAddr | /* USB address */
|
nhiro3303 |
0:42b8e1bc6235
|
506
|
((ep_number & 0x7F) << 7) | /* Endpoint address */
|
nhiro3303 |
0:42b8e1bc6235
|
507
|
(ep_number!=0?(((ep_number&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
|
nhiro3303 |
0:42b8e1bc6235
|
508
|
((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */
|
nhiro3303 |
0:42b8e1bc6235
|
509
|
(MaxPacketSize << 16); /* MaxPkt Size */
|
nhiro3303 |
0:42b8e1bc6235
|
510
|
TailTd = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
511
|
HeadTd = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
512
|
Next = NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
513
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
514
|
|
nhiro3303 |
0:42b8e1bc6235
|
515
|
bool HCED::enqueue(HCTD* td) {
|
nhiro3303 |
0:42b8e1bc6235
|
516
|
if (td) {
|
nhiro3303 |
0:42b8e1bc6235
|
517
|
HCTD* tail = reinterpret_cast<HCTD*>(TailTd);
|
nhiro3303 |
0:42b8e1bc6235
|
518
|
if (tail) {
|
nhiro3303 |
0:42b8e1bc6235
|
519
|
tail->Next = td;
|
nhiro3303 |
0:42b8e1bc6235
|
520
|
TailTd = reinterpret_cast<HCTD*>(td);
|
nhiro3303 |
0:42b8e1bc6235
|
521
|
return true;
|
nhiro3303 |
0:42b8e1bc6235
|
522
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
523
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
524
|
return false;
|
nhiro3303 |
0:42b8e1bc6235
|
525
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
526
|
|
nhiro3303 |
0:42b8e1bc6235
|
527
|
void HCED::init_queue(HCTD* td) {
|
nhiro3303 |
0:42b8e1bc6235
|
528
|
TailTd = reinterpret_cast<HCTD*>(td);
|
nhiro3303 |
0:42b8e1bc6235
|
529
|
HeadTd = reinterpret_cast<HCTD*>(td);
|
nhiro3303 |
0:42b8e1bc6235
|
530
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
531
|
|
nhiro3303 |
0:42b8e1bc6235
|
532
|
void HCED::setToggle(uint8_t toggle) {
|
nhiro3303 |
0:42b8e1bc6235
|
533
|
uint32_t c = reinterpret_cast<uint32_t>(HeadTd);
|
nhiro3303 |
0:42b8e1bc6235
|
534
|
if (toggle == 0) { // DATA0
|
nhiro3303 |
0:42b8e1bc6235
|
535
|
c &= ~0x02;
|
nhiro3303 |
0:42b8e1bc6235
|
536
|
} else { // DATA1
|
nhiro3303 |
0:42b8e1bc6235
|
537
|
c |= 0x02;
|
nhiro3303 |
0:42b8e1bc6235
|
538
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
539
|
HeadTd = reinterpret_cast<HCTD*>(c);
|
nhiro3303 |
0:42b8e1bc6235
|
540
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
541
|
|
nhiro3303 |
0:42b8e1bc6235
|
542
|
uint8_t HCED::getToggle() {
|
nhiro3303 |
0:42b8e1bc6235
|
543
|
uint32_t c = reinterpret_cast<uint32_t>(HeadTd);
|
nhiro3303 |
0:42b8e1bc6235
|
544
|
return (c&0x02) ? 1 : 0;
|
nhiro3303 |
0:42b8e1bc6235
|
545
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
546
|
|
nhiro3303 |
0:42b8e1bc6235
|
547
|
HCTD* HCED::get_queue_HCTD(uint32_t millisec)
|
nhiro3303 |
0:42b8e1bc6235
|
548
|
{
|
nhiro3303 |
0:42b8e1bc6235
|
549
|
for(int i = 0; i < 16; i++) {
|
nhiro3303 |
0:42b8e1bc6235
|
550
|
osEvent evt = done_queue_get(millisec);
|
nhiro3303 |
0:42b8e1bc6235
|
551
|
if (evt.status == osEventMessage) {
|
nhiro3303 |
0:42b8e1bc6235
|
552
|
HCTD* td = reinterpret_cast<HCTD*>(evt.value.p);
|
nhiro3303 |
0:42b8e1bc6235
|
553
|
USB_TEST_ASSERT(td);
|
nhiro3303 |
0:42b8e1bc6235
|
554
|
uint8_t cc = td->ConditionCode();
|
nhiro3303 |
0:42b8e1bc6235
|
555
|
if (cc != 0) {
|
nhiro3303 |
0:42b8e1bc6235
|
556
|
m_ConditionCode = cc;
|
nhiro3303 |
0:42b8e1bc6235
|
557
|
USB_DBG_TD(td);
|
nhiro3303 |
0:42b8e1bc6235
|
558
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
559
|
return td;
|
nhiro3303 |
0:42b8e1bc6235
|
560
|
} else if (evt.status == osOK) {
|
nhiro3303 |
0:42b8e1bc6235
|
561
|
continue;
|
nhiro3303 |
0:42b8e1bc6235
|
562
|
} else if (evt.status == osEventTimeout) {
|
nhiro3303 |
0:42b8e1bc6235
|
563
|
return NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
564
|
} else {
|
nhiro3303 |
0:42b8e1bc6235
|
565
|
USB_DBG("evt.status: %02x\n", evt.status);
|
nhiro3303 |
0:42b8e1bc6235
|
566
|
USB_TEST_ASSERT(evt.status == osEventMessage);
|
nhiro3303 |
0:42b8e1bc6235
|
567
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
568
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
569
|
return NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
570
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
571
|
|
nhiro3303 |
0:42b8e1bc6235
|
572
|
HCITD* HCED::get_queue_HCITD() {
|
nhiro3303 |
0:42b8e1bc6235
|
573
|
osEvent evt = done_queue_get(0);
|
nhiro3303 |
0:42b8e1bc6235
|
574
|
if (evt.status == osEventMessage) {
|
nhiro3303 |
0:42b8e1bc6235
|
575
|
HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
|
nhiro3303 |
0:42b8e1bc6235
|
576
|
USB_TEST_ASSERT(itd);
|
nhiro3303 |
0:42b8e1bc6235
|
577
|
return itd;
|
nhiro3303 |
0:42b8e1bc6235
|
578
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
579
|
return NULL;
|
nhiro3303 |
0:42b8e1bc6235
|
580
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
581
|
HCITD* HCED::new_HCITD() {
|
nhiro3303 |
0:42b8e1bc6235
|
582
|
uint16_t mps = getMaxPacketSize();
|
nhiro3303 |
0:42b8e1bc6235
|
583
|
int total_size = mps * iso.FrameCount;
|
nhiro3303 |
0:42b8e1bc6235
|
584
|
HCITD* itd = new(total_size)HCITD(this, iso.FrameNumber, iso.FrameCount, mps);
|
nhiro3303 |
0:42b8e1bc6235
|
585
|
iso.FrameNumber += iso.FrameCount;
|
nhiro3303 |
0:42b8e1bc6235
|
586
|
return itd;
|
nhiro3303 |
0:42b8e1bc6235
|
587
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
588
|
|
nhiro3303 |
0:42b8e1bc6235
|
589
|
void HCCA::enqueue(HCED* ed) {
|
nhiro3303 |
0:42b8e1bc6235
|
590
|
for(int i = 0; i < 32; i++) {
|
nhiro3303 |
0:42b8e1bc6235
|
591
|
if (InterruptTable[i] == NULL) {
|
nhiro3303 |
0:42b8e1bc6235
|
592
|
InterruptTable[i] = ed;
|
nhiro3303 |
0:42b8e1bc6235
|
593
|
} else {
|
nhiro3303 |
0:42b8e1bc6235
|
594
|
HCED* nextEd = InterruptTable[i];
|
nhiro3303 |
0:42b8e1bc6235
|
595
|
while(nextEd->Next && nextEd->Next != ed) {
|
nhiro3303 |
0:42b8e1bc6235
|
596
|
nextEd = nextEd->Next;
|
nhiro3303 |
0:42b8e1bc6235
|
597
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
598
|
nextEd->Next = ed;
|
nhiro3303 |
0:42b8e1bc6235
|
599
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
600
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
601
|
}
|
nhiro3303 |
0:42b8e1bc6235
|
602
|
|
nhiro3303 |
0:42b8e1bc6235
|
603
|
#endif // defined(TARGET_LPC4088)||defined(TARGET_LPC1768)
|
nhiro3303 |
0:42b8e1bc6235
|
604
|
|