slime@2
|
1 |
/*********************************************************************
|
slime@2
|
2 |
*
|
slime@2
|
3 |
* Microchip USB C18 Firmware Version 1.0
|
slime@2
|
4 |
*
|
slime@2
|
5 |
*********************************************************************
|
slime@2
|
6 |
* FileName: usbctrltrf.c
|
slime@2
|
7 |
* Dependencies: See INCLUDES section below
|
slime@2
|
8 |
* Processor: PIC18
|
slime@2
|
9 |
* Compiler: C18 2.30.01+
|
slime@2
|
10 |
* Company: Microchip Technology, Inc.
|
slime@2
|
11 |
*
|
slime@2
|
12 |
* Software License Agreement
|
slime@2
|
13 |
*
|
slime@2
|
14 |
* The software supplied herewith by Microchip Technology Incorporated
|
slime@2
|
15 |
* (the “Company”) for its PICmicro® Microcontroller is intended and
|
slime@2
|
16 |
* supplied to you, the Company’s customer, for use solely and
|
slime@2
|
17 |
* exclusively on Microchip PICmicro Microcontroller products. The
|
slime@2
|
18 |
* software is owned by the Company and/or its supplier, and is
|
slime@2
|
19 |
* protected under applicable copyright laws. All rights are reserved.
|
slime@2
|
20 |
* Any use in violation of the foregoing restrictions may subject the
|
slime@2
|
21 |
* user to criminal sanctions under applicable laws, as well as to
|
slime@2
|
22 |
* civil liability for the breach of the terms and conditions of this
|
slime@2
|
23 |
* license.
|
slime@2
|
24 |
*
|
slime@2
|
25 |
* THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
|
slime@2
|
26 |
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
|
slime@2
|
27 |
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
slime@2
|
28 |
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
|
slime@2
|
29 |
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
|
slime@2
|
30 |
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
slime@2
|
31 |
*
|
slime@2
|
32 |
* Author Date Comment
|
slime@2
|
33 |
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
slime@2
|
34 |
* Rawin Rojvanit 11/19/04 Original.
|
slime@2
|
35 |
********************************************************************/
|
slime@2
|
36 |
|
slime@2
|
37 |
/** I N C L U D E S **********************************************************/
|
slime@2
|
38 |
#include <p18cxxx.h>
|
slime@2
|
39 |
#include "typedefs.h"
|
slime@2
|
40 |
#include "usb.h"
|
slime@2
|
41 |
|
slime@2
|
42 |
/** V A R I A B L E S ********************************************************/
|
slime@2
|
43 |
#pragma udata
|
slime@2
|
44 |
byte ctrl_trf_state; // Control Transfer State
|
slime@2
|
45 |
byte ctrl_trf_session_owner; // Current transfer session owner
|
slime@2
|
46 |
|
slime@2
|
47 |
POINTER pSrc; // Data source pointer
|
slime@2
|
48 |
POINTER pDst; // Data destination pointer
|
slime@2
|
49 |
WORD wCount; // Data counter
|
slime@2
|
50 |
|
slime@2
|
51 |
/** P R I V A T E P R O T O T Y P E S ***************************************/
|
slime@2
|
52 |
void USBCtrlTrfSetupHandler(void);
|
slime@2
|
53 |
void USBCtrlTrfOutHandler(void);
|
slime@2
|
54 |
void USBCtrlTrfInHandler(void);
|
slime@2
|
55 |
|
slime@2
|
56 |
/** D E C L A R A T I O N S **************************************************/
|
slime@2
|
57 |
#pragma code
|
slime@2
|
58 |
/******************************************************************************
|
slime@2
|
59 |
* Function: void USBCtrlEPService(void)
|
slime@2
|
60 |
*
|
slime@2
|
61 |
* PreCondition: USTAT is loaded with a valid endpoint address.
|
slime@2
|
62 |
*
|
slime@2
|
63 |
* Input: None
|
slime@2
|
64 |
*
|
slime@2
|
65 |
* Output: None
|
slime@2
|
66 |
*
|
slime@2
|
67 |
* Side Effects: None
|
slime@2
|
68 |
*
|
slime@2
|
69 |
* Overview: USBCtrlEPService checks for three transaction types that
|
slime@2
|
70 |
* it knows how to service and services them:
|
slime@2
|
71 |
* 1. EP0 SETUP
|
slime@2
|
72 |
* 2. EP0 OUT
|
slime@2
|
73 |
* 3. EP0 IN
|
slime@2
|
74 |
* It ignores all other types (i.e. EP1, EP2, etc.)
|
slime@2
|
75 |
*
|
slime@2
|
76 |
* Note: None
|
slime@2
|
77 |
*****************************************************************************/
|
slime@2
|
78 |
void USBCtrlEPService(void)
|
slime@2
|
79 |
{
|
slime@2
|
80 |
if(USTAT == EP00_OUT)
|
slime@2
|
81 |
{
|
slime@2
|
82 |
if(ep0Bo.Stat.PID == SETUP_TOKEN) // EP0 SETUP
|
slime@2
|
83 |
USBCtrlTrfSetupHandler();
|
slime@2
|
84 |
else // EP0 OUT
|
slime@2
|
85 |
USBCtrlTrfOutHandler();
|
slime@2
|
86 |
}
|
slime@2
|
87 |
else if(USTAT == EP00_IN) // EP0 IN
|
slime@2
|
88 |
USBCtrlTrfInHandler();
|
slime@2
|
89 |
|
slime@2
|
90 |
}//end USBCtrlEPService
|
slime@2
|
91 |
|
slime@2
|
92 |
/******************************************************************************
|
slime@2
|
93 |
* Function: void USBCtrlTrfSetupHandler(void)
|
slime@2
|
94 |
*
|
slime@2
|
95 |
* PreCondition: SetupPkt buffer is loaded with valid USB Setup Data
|
slime@2
|
96 |
*
|
slime@2
|
97 |
* Input: None
|
slime@2
|
98 |
*
|
slime@2
|
99 |
* Output: None
|
slime@2
|
100 |
*
|
slime@2
|
101 |
* Side Effects: None
|
slime@2
|
102 |
*
|
slime@2
|
103 |
* Overview: This routine is a task dispatcher and has 3 stages.
|
slime@2
|
104 |
* 1. It initializes the control transfer state machine.
|
slime@2
|
105 |
* 2. It calls on each of the module that may know how to
|
slime@2
|
106 |
* service the Setup Request from the host.
|
slime@2
|
107 |
* Module Example: USB9, HID, CDC, MSD, ...
|
slime@2
|
108 |
* As new classes are added, ClassReqHandler table in
|
slime@2
|
109 |
* usbdsc.c should be updated to call all available
|
slime@2
|
110 |
* class handlers.
|
slime@2
|
111 |
* 3. Once each of the modules has had a chance to check if
|
slime@2
|
112 |
* it is responsible for servicing the request, stage 3
|
slime@2
|
113 |
* then checks direction of the transfer to determine how
|
slime@2
|
114 |
* to prepare EP0 for the control transfer.
|
slime@2
|
115 |
* Refer to USBCtrlEPServiceComplete() for more details.
|
slime@2
|
116 |
*
|
slime@2
|
117 |
* Note: Microchip USB Firmware has three different states for
|
slime@2
|
118 |
* the control transfer state machine:
|
slime@2
|
119 |
* 1. WAIT_SETUP
|
slime@2
|
120 |
* 2. CTRL_TRF_TX
|
slime@2
|
121 |
* 3. CTRL_TRF_RX
|
slime@2
|
122 |
* Refer to firmware manual to find out how one state
|
slime@2
|
123 |
* is transitioned to another.
|
slime@2
|
124 |
*
|
slime@2
|
125 |
* A Control Transfer is composed of many USB transactions.
|
slime@2
|
126 |
* When transferring data over multiple transactions,
|
slime@2
|
127 |
* it is important to keep track of data source, data
|
slime@2
|
128 |
* destination, and data count. These three parameters are
|
slime@2
|
129 |
* stored in pSrc,pDst, and wCount. A flag is used to
|
slime@2
|
130 |
* note if the data source is from ROM or RAM.
|
slime@2
|
131 |
*
|
slime@2
|
132 |
*****************************************************************************/
|
slime@2
|
133 |
void USBCtrlTrfSetupHandler(void)
|
slime@2
|
134 |
{
|
slime@2
|
135 |
byte i;
|
slime@2
|
136 |
|
slime@2
|
137 |
/* Stage 1 */
|
slime@2
|
138 |
ctrl_trf_state = WAIT_SETUP;
|
slime@2
|
139 |
ctrl_trf_session_owner = MUID_NULL; // Set owner to NULL
|
slime@2
|
140 |
wCount._word = 0;
|
slime@2
|
141 |
|
slime@2
|
142 |
/* Stage 2 */
|
slime@2
|
143 |
USBCheckStdRequest(); // See system\usb9\usb9.c
|
slime@2
|
144 |
|
slime@2
|
145 |
for(i=0;i < (sizeof(ClassReqHandler)/sizeof(pFunc));i++)
|
slime@2
|
146 |
{
|
slime@2
|
147 |
if(ctrl_trf_session_owner != MUID_NULL)break;
|
slime@2
|
148 |
ClassReqHandler[i](); // See autofiles\usbdsc.c
|
slime@2
|
149 |
}//end while
|
slime@2
|
150 |
|
slime@2
|
151 |
/* Stage 3 */
|
slime@2
|
152 |
USBCtrlEPServiceComplete();
|
slime@2
|
153 |
|
slime@2
|
154 |
}//end USBCtrlTrfSetupHandler
|
slime@2
|
155 |
|
slime@2
|
156 |
/******************************************************************************
|
slime@2
|
157 |
* Function: void USBCtrlTrfOutHandler(void)
|
slime@2
|
158 |
*
|
slime@2
|
159 |
* PreCondition: None
|
slime@2
|
160 |
*
|
slime@2
|
161 |
* Input: None
|
slime@2
|
162 |
*
|
slime@2
|
163 |
* Output: None
|
slime@2
|
164 |
*
|
slime@2
|
165 |
* Side Effects: None
|
slime@2
|
166 |
*
|
slime@2
|
167 |
* Overview: This routine handles an OUT transaction according to
|
slime@2
|
168 |
* which control transfer state is currently active.
|
slime@2
|
169 |
*
|
slime@2
|
170 |
* Note: Note that if the the control transfer was from
|
slime@2
|
171 |
* host to device, the session owner should be notified
|
slime@2
|
172 |
* at the end of each OUT transaction to service the
|
slime@2
|
173 |
* received data.
|
slime@2
|
174 |
*
|
slime@2
|
175 |
*****************************************************************************/
|
slime@2
|
176 |
void USBCtrlTrfOutHandler(void)
|
slime@2
|
177 |
{
|
slime@2
|
178 |
if(ctrl_trf_state == CTRL_TRF_RX)
|
slime@2
|
179 |
{
|
slime@2
|
180 |
USBCtrlTrfRxService();
|
slime@2
|
181 |
|
slime@2
|
182 |
/*
|
slime@2
|
183 |
* Don't have to worry about overwriting _KEEP bit
|
slime@2
|
184 |
* because if _KEEP was set, TRNIF would not have been
|
slime@2
|
185 |
* generated in the first place.
|
slime@2
|
186 |
*/
|
slime@2
|
187 |
if(ep0Bo.Stat.DTS == 0)
|
slime@2
|
188 |
ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN;
|
slime@2
|
189 |
else
|
slime@2
|
190 |
ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN;
|
slime@2
|
191 |
}
|
slime@2
|
192 |
else // CTRL_TRF_TX
|
slime@2
|
193 |
USBPrepareForNextSetupTrf();
|
slime@2
|
194 |
|
slime@2
|
195 |
}//end USBCtrlTrfOutHandler
|
slime@2
|
196 |
|
slime@2
|
197 |
/******************************************************************************
|
slime@2
|
198 |
* Function: void USBCtrlTrfInHandler(void)
|
slime@2
|
199 |
*
|
slime@2
|
200 |
* PreCondition: None
|
slime@2
|
201 |
*
|
slime@2
|
202 |
* Input: None
|
slime@2
|
203 |
*
|
slime@2
|
204 |
* Output: None
|
slime@2
|
205 |
*
|
slime@2
|
206 |
* Side Effects: None
|
slime@2
|
207 |
*
|
slime@2
|
208 |
* Overview: This routine handles an IN transaction according to
|
slime@2
|
209 |
* which control transfer state is currently active.
|
slime@2
|
210 |
*
|
slime@2
|
211 |
*
|
slime@2
|
212 |
* Note: A Set Address Request must not change the acutal address
|
slime@2
|
213 |
* of the device until the completion of the control
|
slime@2
|
214 |
* transfer. The end of the control transfer for Set Address
|
slime@2
|
215 |
* Request is an IN transaction. Therefore it is necessary
|
slime@2
|
216 |
* to service this unique situation when the condition is
|
slime@2
|
217 |
* right. Macro mUSBCheckAdrPendingState is defined in
|
slime@2
|
218 |
* usb9.h and its function is to specifically service this
|
slime@2
|
219 |
* event.
|
slime@2
|
220 |
*****************************************************************************/
|
slime@2
|
221 |
void USBCtrlTrfInHandler(void)
|
slime@2
|
222 |
{
|
slime@2
|
223 |
mUSBCheckAdrPendingState(); // Must check if in ADR_PENDING_STATE
|
slime@2
|
224 |
|
slime@2
|
225 |
if(ctrl_trf_state == CTRL_TRF_TX)
|
slime@2
|
226 |
{
|
slime@2
|
227 |
USBCtrlTrfTxService();
|
slime@2
|
228 |
|
slime@2
|
229 |
if(ep0Bi.Stat.DTS == 0)
|
slime@2
|
230 |
ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN;
|
slime@2
|
231 |
else
|
slime@2
|
232 |
ep0Bi.Stat._byte = _USIE|_DAT0|_DTSEN;
|
slime@2
|
233 |
}
|
slime@2
|
234 |
else // CTRL_TRF_RX
|
slime@2
|
235 |
USBPrepareForNextSetupTrf();
|
slime@2
|
236 |
|
slime@2
|
237 |
}//end USBCtrlTrfInHandler
|
slime@2
|
238 |
|
slime@2
|
239 |
/******************************************************************************
|
slime@2
|
240 |
* Function: void USBCtrlTrfTxService(void)
|
slime@2
|
241 |
*
|
slime@2
|
242 |
* PreCondition: pSrc, wCount, and usb_stat.ctrl_trf_mem are setup properly.
|
slime@2
|
243 |
*
|
slime@2
|
244 |
* Input: None
|
slime@2
|
245 |
*
|
slime@2
|
246 |
* Output: None
|
slime@2
|
247 |
*
|
slime@2
|
248 |
* Side Effects: None
|
slime@2
|
249 |
*
|
slime@2
|
250 |
* Overview: This routine should be called from only two places.
|
slime@2
|
251 |
* One from USBCtrlEPServiceComplete() and one from
|
slime@2
|
252 |
* USBCtrlTrfInHandler(). It takes care of managing a
|
slime@2
|
253 |
* transfer over multiple USB transactions.
|
slime@2
|
254 |
*
|
slime@2
|
255 |
* Note: This routine works with isochronous endpoint larger than
|
slime@2
|
256 |
* 256 bytes and is shown here as an example of how to deal
|
slime@2
|
257 |
* with BC9 and BC8. In reality, a control endpoint can never
|
slime@2
|
258 |
* be larger than 64 bytes.
|
slime@2
|
259 |
*****************************************************************************/
|
slime@2
|
260 |
void USBCtrlTrfTxService(void)
|
slime@2
|
261 |
{
|
slime@2
|
262 |
WORD byte_to_send;
|
slime@2
|
263 |
|
slime@2
|
264 |
/*
|
slime@2
|
265 |
* First, have to figure out how many byte of data to send.
|
slime@2
|
266 |
*/
|
slime@2
|
267 |
if(wCount._word < EP0_BUFF_SIZE)
|
slime@2
|
268 |
byte_to_send._word = wCount._word;
|
slime@2
|
269 |
else
|
slime@2
|
270 |
byte_to_send._word = EP0_BUFF_SIZE;
|
slime@2
|
271 |
|
slime@2
|
272 |
/*
|
slime@2
|
273 |
* Next, load the number of bytes to send to BC9..0 in buffer descriptor
|
slime@2
|
274 |
*/
|
slime@2
|
275 |
ep0Bi.Stat.BC9 = 0;
|
slime@2
|
276 |
ep0Bi.Stat.BC8 = 0;
|
slime@2
|
277 |
ep0Bi.Stat._byte |= MSB(byte_to_send);
|
slime@2
|
278 |
ep0Bi.Cnt = LSB(byte_to_send);
|
slime@2
|
279 |
|
slime@2
|
280 |
/*
|
slime@2
|
281 |
* Subtract the number of bytes just about to be sent from the total.
|
slime@2
|
282 |
*/
|
slime@2
|
283 |
wCount._word = wCount._word - byte_to_send._word;
|
slime@2
|
284 |
|
slime@2
|
285 |
pDst.bRam = (byte*)&CtrlTrfData; // Set destination pointer
|
slime@2
|
286 |
|
slime@2
|
287 |
if(usb_stat.ctrl_trf_mem == _ROM) // Determine type of memory source
|
slime@2
|
288 |
{
|
slime@2
|
289 |
while(byte_to_send._word)
|
slime@2
|
290 |
{
|
slime@2
|
291 |
*pDst.bRam = *pSrc.bRom;
|
slime@2
|
292 |
pDst.bRam++;
|
slime@2
|
293 |
pSrc.bRom++;
|
slime@2
|
294 |
byte_to_send._word--;
|
slime@2
|
295 |
}//end while(byte_to_send._word)
|
slime@2
|
296 |
}
|
slime@2
|
297 |
else // RAM
|
slime@2
|
298 |
{
|
slime@2
|
299 |
while(byte_to_send._word)
|
slime@2
|
300 |
{
|
slime@2
|
301 |
*pDst.bRam = *pSrc.bRam;
|
slime@2
|
302 |
pDst.bRam++;
|
slime@2
|
303 |
pSrc.bRam++;
|
slime@2
|
304 |
byte_to_send._word--;
|
slime@2
|
305 |
}//end while(byte_to_send._word)
|
slime@2
|
306 |
}//end if(usb_stat.ctrl_trf_mem == _ROM)
|
slime@2
|
307 |
|
slime@2
|
308 |
}//end USBCtrlTrfTxService
|
slime@2
|
309 |
|
slime@2
|
310 |
/******************************************************************************
|
slime@2
|
311 |
* Function: void USBCtrlTrfRxService(void)
|
slime@2
|
312 |
*
|
slime@2
|
313 |
* PreCondition: pDst and wCount are setup properly.
|
slime@2
|
314 |
* pSrc is always &CtrlTrfData
|
slime@2
|
315 |
* usb_stat.ctrl_trf_mem is always _RAM.
|
slime@2
|
316 |
* wCount should be set to 0 at the start of each control
|
slime@2
|
317 |
* transfer.
|
slime@2
|
318 |
*
|
slime@2
|
319 |
* Input: None
|
slime@2
|
320 |
*
|
slime@2
|
321 |
* Output: None
|
slime@2
|
322 |
*
|
slime@2
|
323 |
* Side Effects: None
|
slime@2
|
324 |
*
|
slime@2
|
325 |
* Overview: *** This routine is only partially complete. Check for
|
slime@2
|
326 |
* new version of the firmware.
|
slime@2
|
327 |
*
|
slime@2
|
328 |
* Note: None
|
slime@2
|
329 |
*****************************************************************************/
|
slime@2
|
330 |
void USBCtrlTrfRxService(void)
|
slime@2
|
331 |
{
|
slime@2
|
332 |
WORD byte_to_read;
|
slime@2
|
333 |
|
slime@2
|
334 |
MSB(byte_to_read) = 0x03 & ep0Bo.Stat._byte; // Filter out last 2 bits
|
slime@2
|
335 |
LSB(byte_to_read) = ep0Bo.Cnt;
|
slime@2
|
336 |
|
slime@2
|
337 |
/*
|
slime@2
|
338 |
* Accumulate total number of bytes read
|
slime@2
|
339 |
*/
|
slime@2
|
340 |
wCount._word = wCount._word + byte_to_read._word;
|
slime@2
|
341 |
|
slime@2
|
342 |
pSrc.bRam = (byte*)&CtrlTrfData;
|
slime@2
|
343 |
|
slime@2
|
344 |
while(byte_to_read._word)
|
slime@2
|
345 |
{
|
slime@2
|
346 |
*pDst.bRam = *pSrc.bRam;
|
slime@2
|
347 |
pDst.bRam++;
|
slime@2
|
348 |
pSrc.bRam++;
|
slime@2
|
349 |
byte_to_read._word--;
|
slime@2
|
350 |
}//end while(byte_to_read._word)
|
slime@2
|
351 |
|
slime@2
|
352 |
}//end USBCtrlTrfRxService
|
slime@2
|
353 |
|
slime@2
|
354 |
/******************************************************************************
|
slime@2
|
355 |
* Function: void USBCtrlEPServiceComplete(void)
|
slime@2
|
356 |
*
|
slime@2
|
357 |
* PreCondition: None
|
slime@2
|
358 |
*
|
slime@2
|
359 |
* Input: None
|
slime@2
|
360 |
*
|
slime@2
|
361 |
* Output: None
|
slime@2
|
362 |
*
|
slime@2
|
363 |
* Side Effects: None
|
slime@2
|
364 |
*
|
slime@2
|
365 |
* Overview: This routine wrap up the ramaining tasks in servicing
|
slime@2
|
366 |
* a Setup Request. Its main task is to set the endpoint
|
slime@2
|
367 |
* controls appropriately for a given situation. See code
|
slime@2
|
368 |
* below.
|
slime@2
|
369 |
* There are three main scenarios:
|
slime@2
|
370 |
* a) There was no handler for the Request, in this case
|
slime@2
|
371 |
* a STALL should be sent out.
|
slime@2
|
372 |
* b) The host has requested a read control transfer,
|
slime@2
|
373 |
* endpoints are required to be setup in a specific way.
|
slime@2
|
374 |
* c) The host has requested a write control transfer, or
|
slime@2
|
375 |
* a control data stage is not required, endpoints are
|
slime@2
|
376 |
* required to be setup in a specific way.
|
slime@2
|
377 |
*
|
slime@2
|
378 |
* Packet processing is resumed by clearing PKTDIS bit.
|
slime@2
|
379 |
*
|
slime@2
|
380 |
* Note: None
|
slime@2
|
381 |
*****************************************************************************/
|
slime@2
|
382 |
void USBCtrlEPServiceComplete(void)
|
slime@2
|
383 |
{
|
slime@2
|
384 |
if(ctrl_trf_session_owner == MUID_NULL)
|
slime@2
|
385 |
{
|
slime@2
|
386 |
/*
|
slime@2
|
387 |
* If no one knows how to service this request then stall.
|
slime@2
|
388 |
* Must also prepare EP0 to receive the next SETUP transaction.
|
slime@2
|
389 |
*/
|
slime@2
|
390 |
ep0Bo.Cnt = EP0_BUFF_SIZE;
|
slime@2
|
391 |
ep0Bo.ADR = (byte*)&SetupPkt;
|
slime@2
|
392 |
|
slime@2
|
393 |
ep0Bo.Stat._byte = _USIE|_BSTALL;
|
slime@2
|
394 |
ep0Bi.Stat._byte = _USIE|_BSTALL;
|
slime@2
|
395 |
}
|
slime@2
|
396 |
else // A module has claimed ownership of the control transfer session.
|
slime@2
|
397 |
{
|
slime@2
|
398 |
if(SetupPkt.DataDir == DEV_TO_HOST)
|
slime@2
|
399 |
{
|
slime@2
|
400 |
if(SetupPkt.wLength < wCount._word)
|
slime@2
|
401 |
wCount._word = SetupPkt.wLength;
|
slime@2
|
402 |
USBCtrlTrfTxService();
|
slime@2
|
403 |
ctrl_trf_state = CTRL_TRF_TX;
|
slime@2
|
404 |
/*
|
slime@2
|
405 |
* Control Read:
|
slime@2
|
406 |
* <SETUP[0]><IN[1]><IN[0]>...<OUT[1]> | <SETUP[0]>
|
slime@2
|
407 |
* 1. Prepare OUT EP to respond to early termination
|
slime@2
|
408 |
*
|
slime@2
|
409 |
* NOTE:
|
slime@2
|
410 |
* If something went wrong during the control transfer,
|
slime@2
|
411 |
* the last status stage may not be sent by the host.
|
slime@2
|
412 |
* When this happens, two different things could happen
|
slime@2
|
413 |
* depending on the host.
|
slime@2
|
414 |
* a) The host could send out a RESET.
|
slime@2
|
415 |
* b) The host could send out a new SETUP transaction
|
slime@2
|
416 |
* without sending a RESET first.
|
slime@2
|
417 |
* To properly handle case (b), the OUT EP must be setup
|
slime@2
|
418 |
* to receive either a zero length OUT transaction, or a
|
slime@2
|
419 |
* new SETUP transaction.
|
slime@2
|
420 |
*
|
slime@2
|
421 |
* Since the SETUP transaction requires the DTS bit to be
|
slime@2
|
422 |
* DAT0 while the zero length OUT status requires the DTS
|
slime@2
|
423 |
* bit to be DAT1, the DTS bit check by the hardware should
|
slime@2
|
424 |
* be disabled. This way the SIE could accept either of
|
slime@2
|
425 |
* the two transactions.
|
slime@2
|
426 |
*
|
slime@2
|
427 |
* Furthermore, the Cnt byte should be set to prepare for
|
slime@2
|
428 |
* the SETUP data (8-byte or more), and the buffer address
|
slime@2
|
429 |
* should be pointed to SetupPkt.
|
slime@2
|
430 |
*/
|
slime@2
|
431 |
ep0Bo.Cnt = EP0_BUFF_SIZE;
|
slime@2
|
432 |
ep0Bo.ADR = (byte*)&SetupPkt;
|
slime@2
|
433 |
ep0Bo.Stat._byte = _USIE; // Note: DTSEN is 0!
|
slime@2
|
434 |
|
slime@2
|
435 |
/*
|
slime@2
|
436 |
* 2. Prepare IN EP to transfer data, Cnt should have
|
slime@2
|
437 |
* been initialized by responsible request owner.
|
slime@2
|
438 |
*/
|
slime@2
|
439 |
ep0Bi.ADR = (byte*)&CtrlTrfData;
|
slime@2
|
440 |
ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN;
|
slime@2
|
441 |
}
|
slime@2
|
442 |
else // (SetupPkt.DataDir == HOST_TO_DEV)
|
slime@2
|
443 |
{
|
slime@2
|
444 |
ctrl_trf_state = CTRL_TRF_RX;
|
slime@2
|
445 |
/*
|
slime@2
|
446 |
* Control Write:
|
slime@2
|
447 |
* <SETUP[0]><OUT[1]><OUT[0]>...<IN[1]> | <SETUP[0]>
|
slime@2
|
448 |
*
|
slime@2
|
449 |
* 1. Prepare IN EP to respond to early termination
|
slime@2
|
450 |
*
|
slime@2
|
451 |
* This is the same as a Zero Length Packet Response
|
slime@2
|
452 |
* for control transfer without a data stage
|
slime@2
|
453 |
*/
|
slime@2
|
454 |
ep0Bi.Cnt = 0;
|
slime@2
|
455 |
ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN;
|
slime@2
|
456 |
|
slime@2
|
457 |
/*
|
slime@2
|
458 |
* 2. Prepare OUT EP to receive data.
|
slime@2
|
459 |
*/
|
slime@2
|
460 |
ep0Bo.Cnt = EP0_BUFF_SIZE;
|
slime@2
|
461 |
ep0Bo.ADR = (byte*)&CtrlTrfData;
|
slime@2
|
462 |
ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN;
|
slime@2
|
463 |
}//end if(SetupPkt.DataDir == DEV_TO_HOST)
|
slime@2
|
464 |
}//end if(ctrl_trf_session_owner == MUID_NULL)
|
slime@2
|
465 |
|
slime@2
|
466 |
/*
|
slime@2
|
467 |
* PKTDIS bit is set when a Setup Transaction is received.
|
slime@2
|
468 |
* Clear to resume packet processing.
|
slime@2
|
469 |
*/
|
slime@2
|
470 |
UCONbits.PKTDIS = 0;
|
slime@2
|
471 |
|
slime@2
|
472 |
}//end USBCtrlEPServiceComplete
|
slime@2
|
473 |
|
slime@2
|
474 |
/******************************************************************************
|
slime@2
|
475 |
* Function: void USBPrepareForNextSetupTrf(void)
|
slime@2
|
476 |
*
|
slime@2
|
477 |
* PreCondition: None
|
slime@2
|
478 |
*
|
slime@2
|
479 |
* Input: None
|
slime@2
|
480 |
*
|
slime@2
|
481 |
* Output: None
|
slime@2
|
482 |
*
|
slime@2
|
483 |
* Side Effects: None
|
slime@2
|
484 |
*
|
slime@2
|
485 |
* Overview: The routine forces EP0 OUT to be ready for a new Setup
|
slime@2
|
486 |
* transaction, and forces EP0 IN to be owned by CPU.
|
slime@2
|
487 |
*
|
slime@2
|
488 |
* Note: None
|
slime@2
|
489 |
*****************************************************************************/
|
slime@2
|
490 |
void USBPrepareForNextSetupTrf(void)
|
slime@2
|
491 |
{
|
slime@2
|
492 |
ctrl_trf_state = WAIT_SETUP; // See usbctrltrf.h
|
slime@2
|
493 |
ep0Bo.Cnt = EP0_BUFF_SIZE; // Defined in usbcfg.h
|
slime@2
|
494 |
ep0Bo.ADR = (byte*)&SetupPkt;
|
slime@2
|
495 |
ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN; // EP0 buff dsc init, see usbmmap.h
|
slime@2
|
496 |
ep0Bi.Stat._byte = _UCPU; // EP0 IN buffer initialization
|
slime@2
|
497 |
}//end USBPrepareForNextSetupTrf
|
slime@2
|
498 |
|
slime@2
|
499 |
/** EOF usbctrltrf.c *********************************************************/
|