several changes..
1 /*********************************************************************
3 * Microchip USB C18 Firmware Version 1.0
5 *********************************************************************
6 * FileName: usbctrltrf.c
7 * Dependencies: See INCLUDES section below
9 * Compiler: C18 2.30.01+
10 * Company: Microchip Technology, Inc.
12 * Software License Agreement
14 * The software supplied herewith by Microchip Technology Incorporated
15 * (the “Company”) for its PICmicro® Microcontroller is intended and
16 * supplied to you, the Company’s customer, for use solely and
17 * exclusively on Microchip PICmicro Microcontroller products. The
18 * software is owned by the Company and/or its supplier, and is
19 * protected under applicable copyright laws. All rights are reserved.
20 * Any use in violation of the foregoing restrictions may subject the
21 * user to criminal sanctions under applicable laws, as well as to
22 * civil liability for the breach of the terms and conditions of this
25 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
26 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
27 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
29 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
30 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
33 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34 * Rawin Rojvanit 11/19/04 Original.
35 ********************************************************************/
37 /** I N C L U D E S **********************************************************/
42 /** V A R I A B L E S ********************************************************/
44 byte ctrl_trf_state; // Control Transfer State
45 byte ctrl_trf_session_owner; // Current transfer session owner
47 POINTER pSrc; // Data source pointer
48 POINTER pDst; // Data destination pointer
49 WORD wCount; // Data counter
51 /** P R I V A T E P R O T O T Y P E S ***************************************/
52 void USBCtrlTrfSetupHandler(void);
53 void USBCtrlTrfOutHandler(void);
54 void USBCtrlTrfInHandler(void);
56 /** D E C L A R A T I O N S **************************************************/
58 /******************************************************************************
59 * Function: void USBCtrlEPService(void)
61 * PreCondition: USTAT is loaded with a valid endpoint address.
69 * Overview: USBCtrlEPService checks for three transaction types that
70 * it knows how to service and services them:
74 * It ignores all other types (i.e. EP1, EP2, etc.)
77 *****************************************************************************/
78 void USBCtrlEPService(void)
82 if(ep0Bo.Stat.PID == SETUP_TOKEN) // EP0 SETUP
83 USBCtrlTrfSetupHandler();
85 USBCtrlTrfOutHandler();
87 else if(USTAT == EP00_IN) // EP0 IN
88 USBCtrlTrfInHandler();
90 }//end USBCtrlEPService
92 /******************************************************************************
93 * Function: void USBCtrlTrfSetupHandler(void)
95 * PreCondition: SetupPkt buffer is loaded with valid USB Setup Data
103 * Overview: This routine is a task dispatcher and has 3 stages.
104 * 1. It initializes the control transfer state machine.
105 * 2. It calls on each of the module that may know how to
106 * service the Setup Request from the host.
107 * Module Example: USB9, HID, CDC, MSD, ...
108 * As new classes are added, ClassReqHandler table in
109 * usbdsc.c should be updated to call all available
111 * 3. Once each of the modules has had a chance to check if
112 * it is responsible for servicing the request, stage 3
113 * then checks direction of the transfer to determine how
114 * to prepare EP0 for the control transfer.
115 * Refer to USBCtrlEPServiceComplete() for more details.
117 * Note: Microchip USB Firmware has three different states for
118 * the control transfer state machine:
122 * Refer to firmware manual to find out how one state
123 * is transitioned to another.
125 * A Control Transfer is composed of many USB transactions.
126 * When transferring data over multiple transactions,
127 * it is important to keep track of data source, data
128 * destination, and data count. These three parameters are
129 * stored in pSrc,pDst, and wCount. A flag is used to
130 * note if the data source is from ROM or RAM.
132 *****************************************************************************/
133 void USBCtrlTrfSetupHandler(void)
138 ctrl_trf_state = WAIT_SETUP;
139 ctrl_trf_session_owner = MUID_NULL; // Set owner to NULL
143 USBCheckStdRequest(); // See system\usb9\usb9.c
145 for(i=0;i < (sizeof(ClassReqHandler)/sizeof(pFunc));i++)
147 if(ctrl_trf_session_owner != MUID_NULL)break;
148 ClassReqHandler[i](); // See autofiles\usbdsc.c
152 USBCtrlEPServiceComplete();
154 }//end USBCtrlTrfSetupHandler
156 /******************************************************************************
157 * Function: void USBCtrlTrfOutHandler(void)
167 * Overview: This routine handles an OUT transaction according to
168 * which control transfer state is currently active.
170 * Note: Note that if the the control transfer was from
171 * host to device, the session owner should be notified
172 * at the end of each OUT transaction to service the
175 *****************************************************************************/
176 void USBCtrlTrfOutHandler(void)
178 if(ctrl_trf_state == CTRL_TRF_RX)
180 USBCtrlTrfRxService();
183 * Don't have to worry about overwriting _KEEP bit
184 * because if _KEEP was set, TRNIF would not have been
185 * generated in the first place.
187 if(ep0Bo.Stat.DTS == 0)
188 ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN;
190 ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN;
193 USBPrepareForNextSetupTrf();
195 }//end USBCtrlTrfOutHandler
197 /******************************************************************************
198 * Function: void USBCtrlTrfInHandler(void)
208 * Overview: This routine handles an IN transaction according to
209 * which control transfer state is currently active.
212 * Note: A Set Address Request must not change the acutal address
213 * of the device until the completion of the control
214 * transfer. The end of the control transfer for Set Address
215 * Request is an IN transaction. Therefore it is necessary
216 * to service this unique situation when the condition is
217 * right. Macro mUSBCheckAdrPendingState is defined in
218 * usb9.h and its function is to specifically service this
220 *****************************************************************************/
221 void USBCtrlTrfInHandler(void)
223 mUSBCheckAdrPendingState(); // Must check if in ADR_PENDING_STATE
225 if(ctrl_trf_state == CTRL_TRF_TX)
227 USBCtrlTrfTxService();
229 if(ep0Bi.Stat.DTS == 0)
230 ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN;
232 ep0Bi.Stat._byte = _USIE|_DAT0|_DTSEN;
235 USBPrepareForNextSetupTrf();
237 }//end USBCtrlTrfInHandler
239 /******************************************************************************
240 * Function: void USBCtrlTrfTxService(void)
242 * PreCondition: pSrc, wCount, and usb_stat.ctrl_trf_mem are setup properly.
250 * Overview: This routine should be called from only two places.
251 * One from USBCtrlEPServiceComplete() and one from
252 * USBCtrlTrfInHandler(). It takes care of managing a
253 * transfer over multiple USB transactions.
255 * Note: This routine works with isochronous endpoint larger than
256 * 256 bytes and is shown here as an example of how to deal
257 * with BC9 and BC8. In reality, a control endpoint can never
258 * be larger than 64 bytes.
259 *****************************************************************************/
260 void USBCtrlTrfTxService(void)
265 * First, have to figure out how many byte of data to send.
267 if(wCount._word < EP0_BUFF_SIZE)
268 byte_to_send._word = wCount._word;
270 byte_to_send._word = EP0_BUFF_SIZE;
273 * Next, load the number of bytes to send to BC9..0 in buffer descriptor
277 ep0Bi.Stat._byte |= MSB(byte_to_send);
278 ep0Bi.Cnt = LSB(byte_to_send);
281 * Subtract the number of bytes just about to be sent from the total.
283 wCount._word = wCount._word - byte_to_send._word;
285 pDst.bRam = (byte*)&CtrlTrfData; // Set destination pointer
287 if(usb_stat.ctrl_trf_mem == _ROM) // Determine type of memory source
289 while(byte_to_send._word)
291 *pDst.bRam = *pSrc.bRom;
294 byte_to_send._word--;
295 }//end while(byte_to_send._word)
299 while(byte_to_send._word)
301 *pDst.bRam = *pSrc.bRam;
304 byte_to_send._word--;
305 }//end while(byte_to_send._word)
306 }//end if(usb_stat.ctrl_trf_mem == _ROM)
308 }//end USBCtrlTrfTxService
310 /******************************************************************************
311 * Function: void USBCtrlTrfRxService(void)
313 * PreCondition: pDst and wCount are setup properly.
314 * pSrc is always &CtrlTrfData
315 * usb_stat.ctrl_trf_mem is always _RAM.
316 * wCount should be set to 0 at the start of each control
325 * Overview: *** This routine is only partially complete. Check for
326 * new version of the firmware.
329 *****************************************************************************/
330 void USBCtrlTrfRxService(void)
334 MSB(byte_to_read) = 0x03 & ep0Bo.Stat._byte; // Filter out last 2 bits
335 LSB(byte_to_read) = ep0Bo.Cnt;
338 * Accumulate total number of bytes read
340 wCount._word = wCount._word + byte_to_read._word;
342 pSrc.bRam = (byte*)&CtrlTrfData;
344 while(byte_to_read._word)
346 *pDst.bRam = *pSrc.bRam;
349 byte_to_read._word--;
350 }//end while(byte_to_read._word)
352 }//end USBCtrlTrfRxService
354 /******************************************************************************
355 * Function: void USBCtrlEPServiceComplete(void)
365 * Overview: This routine wrap up the ramaining tasks in servicing
366 * a Setup Request. Its main task is to set the endpoint
367 * controls appropriately for a given situation. See code
369 * There are three main scenarios:
370 * a) There was no handler for the Request, in this case
371 * a STALL should be sent out.
372 * b) The host has requested a read control transfer,
373 * endpoints are required to be setup in a specific way.
374 * c) The host has requested a write control transfer, or
375 * a control data stage is not required, endpoints are
376 * required to be setup in a specific way.
378 * Packet processing is resumed by clearing PKTDIS bit.
381 *****************************************************************************/
382 void USBCtrlEPServiceComplete(void)
384 if(ctrl_trf_session_owner == MUID_NULL)
387 * If no one knows how to service this request then stall.
388 * Must also prepare EP0 to receive the next SETUP transaction.
390 ep0Bo.Cnt = EP0_BUFF_SIZE;
391 ep0Bo.ADR = (byte*)&SetupPkt;
393 ep0Bo.Stat._byte = _USIE|_BSTALL;
394 ep0Bi.Stat._byte = _USIE|_BSTALL;
396 else // A module has claimed ownership of the control transfer session.
398 if(SetupPkt.DataDir == DEV_TO_HOST)
400 if(SetupPkt.wLength < wCount._word)
401 wCount._word = SetupPkt.wLength;
402 USBCtrlTrfTxService();
403 ctrl_trf_state = CTRL_TRF_TX;
406 * <SETUP[0]><IN[1]><IN[0]>...<OUT[1]> | <SETUP[0]>
407 * 1. Prepare OUT EP to respond to early termination
410 * If something went wrong during the control transfer,
411 * the last status stage may not be sent by the host.
412 * When this happens, two different things could happen
413 * depending on the host.
414 * a) The host could send out a RESET.
415 * b) The host could send out a new SETUP transaction
416 * without sending a RESET first.
417 * To properly handle case (b), the OUT EP must be setup
418 * to receive either a zero length OUT transaction, or a
419 * new SETUP transaction.
421 * Since the SETUP transaction requires the DTS bit to be
422 * DAT0 while the zero length OUT status requires the DTS
423 * bit to be DAT1, the DTS bit check by the hardware should
424 * be disabled. This way the SIE could accept either of
425 * the two transactions.
427 * Furthermore, the Cnt byte should be set to prepare for
428 * the SETUP data (8-byte or more), and the buffer address
429 * should be pointed to SetupPkt.
431 ep0Bo.Cnt = EP0_BUFF_SIZE;
432 ep0Bo.ADR = (byte*)&SetupPkt;
433 ep0Bo.Stat._byte = _USIE; // Note: DTSEN is 0!
436 * 2. Prepare IN EP to transfer data, Cnt should have
437 * been initialized by responsible request owner.
439 ep0Bi.ADR = (byte*)&CtrlTrfData;
440 ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN;
442 else // (SetupPkt.DataDir == HOST_TO_DEV)
444 ctrl_trf_state = CTRL_TRF_RX;
447 * <SETUP[0]><OUT[1]><OUT[0]>...<IN[1]> | <SETUP[0]>
449 * 1. Prepare IN EP to respond to early termination
451 * This is the same as a Zero Length Packet Response
452 * for control transfer without a data stage
455 ep0Bi.Stat._byte = _USIE|_DAT1|_DTSEN;
458 * 2. Prepare OUT EP to receive data.
460 ep0Bo.Cnt = EP0_BUFF_SIZE;
461 ep0Bo.ADR = (byte*)&CtrlTrfData;
462 ep0Bo.Stat._byte = _USIE|_DAT1|_DTSEN;
463 }//end if(SetupPkt.DataDir == DEV_TO_HOST)
464 }//end if(ctrl_trf_session_owner == MUID_NULL)
467 * PKTDIS bit is set when a Setup Transaction is received.
468 * Clear to resume packet processing.
472 }//end USBCtrlEPServiceComplete
474 /******************************************************************************
475 * Function: void USBPrepareForNextSetupTrf(void)
485 * Overview: The routine forces EP0 OUT to be ready for a new Setup
486 * transaction, and forces EP0 IN to be owned by CPU.
489 *****************************************************************************/
490 void USBPrepareForNextSetupTrf(void)
492 ctrl_trf_state = WAIT_SETUP; // See usbctrltrf.h
493 ep0Bo.Cnt = EP0_BUFF_SIZE; // Defined in usbcfg.h
494 ep0Bo.ADR = (byte*)&SetupPkt;
495 ep0Bo.Stat._byte = _USIE|_DAT0|_DTSEN; // EP0 buff dsc init, see usbmmap.h
496 ep0Bi.Stat._byte = _UCPU; // EP0 IN buffer initialization
497 }//end USBPrepareForNextSetupTrf
499 /** EOF usbctrltrf.c *********************************************************/