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: usbdrv.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 |
#include "io_cfg.h" // Required for USBCheckBusStatus()
|
slime@2
|
42 |
|
slime@2
|
43 |
/** V A R I A B L E S ********************************************************/
|
slime@2
|
44 |
#pragma udata
|
slime@2
|
45 |
|
slime@2
|
46 |
/** P R I V A T E P R O T O T Y P E S ***************************************/
|
slime@2
|
47 |
void USBModuleEnable(void);
|
slime@2
|
48 |
void USBModuleDisable(void);
|
slime@2
|
49 |
|
slime@2
|
50 |
void USBSuspend(void);
|
slime@2
|
51 |
void USBWakeFromSuspend(void);
|
slime@2
|
52 |
|
slime@2
|
53 |
void USBProtocolResetHandler(void);
|
slime@2
|
54 |
void USB_SOF_Handler(void);
|
slime@2
|
55 |
void USBStallHandler(void);
|
slime@2
|
56 |
void USBErrorHandler(void);
|
slime@2
|
57 |
|
slime@2
|
58 |
/** D E C L A R A T I O N S **************************************************/
|
slime@2
|
59 |
#pragma code
|
slime@2
|
60 |
/******************************************************************************
|
slime@2
|
61 |
* Function: void USBCheckBusStatus(void)
|
slime@2
|
62 |
*
|
slime@2
|
63 |
* PreCondition: None
|
slime@2
|
64 |
*
|
slime@2
|
65 |
* Input: None
|
slime@2
|
66 |
*
|
slime@2
|
67 |
* Output: None
|
slime@2
|
68 |
*
|
slime@2
|
69 |
* Side Effects: None
|
slime@2
|
70 |
*
|
slime@2
|
71 |
* Overview: This routine enables/disables the USB module by monitoring
|
slime@2
|
72 |
* the USB power signal.
|
slime@2
|
73 |
*
|
slime@2
|
74 |
* Note: None
|
slime@2
|
75 |
*****************************************************************************/
|
slime@2
|
76 |
void USBCheckBusStatus(void)
|
slime@2
|
77 |
{
|
slime@2
|
78 |
/**************************************************************************
|
slime@2
|
79 |
* Bus Attachment & Detachment Detection
|
slime@2
|
80 |
* usb_bus_sense is an i/o pin defined in io_cfg.h
|
slime@2
|
81 |
*************************************************************************/
|
slime@2
|
82 |
#define USB_BUS_ATTACHED 1
|
slime@2
|
83 |
#define USB_BUS_DETACHED 0
|
slime@2
|
84 |
|
slime@2
|
85 |
if(usb_bus_sense == USB_BUS_ATTACHED) // Is USB bus attached?
|
slime@2
|
86 |
{
|
slime@2
|
87 |
if(UCONbits.USBEN == 0) // Is the module off?
|
slime@2
|
88 |
USBModuleEnable(); // Is off, enable it
|
slime@2
|
89 |
}
|
slime@2
|
90 |
else
|
slime@2
|
91 |
{
|
slime@2
|
92 |
if(UCONbits.USBEN == 1) // Is the module on?
|
slime@2
|
93 |
USBModuleDisable(); // Is on, disable it
|
slime@2
|
94 |
}//end if(usb_bus_sense...)
|
slime@2
|
95 |
|
slime@2
|
96 |
/*
|
slime@2
|
97 |
* After enabling the USB module, it takes some time for the voltage
|
slime@2
|
98 |
* on the D+ or D- line to rise high enough to get out of the SE0 condition.
|
slime@2
|
99 |
* The USB Reset interrupt should not be unmasked until the SE0 condition is
|
slime@2
|
100 |
* cleared. This helps preventing the firmware from misinterpreting this
|
slime@2
|
101 |
* unique event as a USB bus reset from the USB host.
|
slime@2
|
102 |
*/
|
slime@2
|
103 |
if(usb_device_state == ATTACHED_STATE)
|
slime@2
|
104 |
{
|
slime@2
|
105 |
if(!UCONbits.SE0)
|
slime@2
|
106 |
{
|
slime@2
|
107 |
UIR = 0; // Clear all USB interrupts
|
slime@2
|
108 |
UIE = 0; // Mask all USB interrupts
|
slime@2
|
109 |
UIEbits.URSTIE = 1; // Unmask RESET interrupt
|
slime@2
|
110 |
UIEbits.IDLEIE = 1; // Unmask IDLE interrupt
|
slime@2
|
111 |
usb_device_state = POWERED_STATE;
|
slime@2
|
112 |
}//end if // else wait until SE0 is cleared
|
slime@2
|
113 |
}//end if(usb_device_state == ATTACHED_STATE)
|
slime@2
|
114 |
|
slime@2
|
115 |
}//end USBCheckBusStatus
|
slime@2
|
116 |
|
slime@2
|
117 |
/******************************************************************************
|
slime@2
|
118 |
* Function: void USBModuleEnable(void)
|
slime@2
|
119 |
*
|
slime@2
|
120 |
* PreCondition: None
|
slime@2
|
121 |
*
|
slime@2
|
122 |
* Input: None
|
slime@2
|
123 |
*
|
slime@2
|
124 |
* Output: None
|
slime@2
|
125 |
*
|
slime@2
|
126 |
* Side Effects: None
|
slime@2
|
127 |
*
|
slime@2
|
128 |
* Overview: This routine enables the USB module.
|
slime@2
|
129 |
* An end designer should never have to call this routine
|
slime@2
|
130 |
* manually. This routine should only be called from
|
slime@2
|
131 |
* USBCheckBusStatus().
|
slime@2
|
132 |
*
|
slime@2
|
133 |
* Note: See USBCheckBusStatus() for more information.
|
slime@2
|
134 |
*****************************************************************************/
|
slime@2
|
135 |
void USBModuleEnable(void)
|
slime@2
|
136 |
{
|
slime@2
|
137 |
UCON = 0;
|
slime@2
|
138 |
UIE = 0; // Mask all USB interrupts
|
slime@2
|
139 |
UCONbits.USBEN = 1; // Enable module & attach to bus
|
slime@2
|
140 |
usb_device_state = ATTACHED_STATE; // Defined in usbmmap.c & .h
|
slime@2
|
141 |
}//end USBModuleEnable
|
slime@2
|
142 |
|
slime@2
|
143 |
/******************************************************************************
|
slime@2
|
144 |
* Function: void USBModuleDisable(void)
|
slime@2
|
145 |
*
|
slime@2
|
146 |
* PreCondition: None
|
slime@2
|
147 |
*
|
slime@2
|
148 |
* Input: None
|
slime@2
|
149 |
*
|
slime@2
|
150 |
* Output: None
|
slime@2
|
151 |
*
|
slime@2
|
152 |
* Side Effects: None
|
slime@2
|
153 |
*
|
slime@2
|
154 |
* Overview: This routine disables the USB module.
|
slime@2
|
155 |
* An end designer should never have to call this routine
|
slime@2
|
156 |
* manually. This routine should only be called from
|
slime@2
|
157 |
* USBCheckBusStatus().
|
slime@2
|
158 |
*
|
slime@2
|
159 |
* Note: See USBCheckBusStatus() for more information.
|
slime@2
|
160 |
*****************************************************************************/
|
slime@2
|
161 |
void USBModuleDisable(void)
|
slime@2
|
162 |
{
|
slime@2
|
163 |
UCON = 0; // Disable module & detach from bus
|
slime@2
|
164 |
UIE = 0; // Mask all USB interrupts
|
slime@2
|
165 |
usb_device_state = DETACHED_STATE; // Defined in usbmmap.c & .h
|
slime@2
|
166 |
}//end USBModuleDisable
|
slime@2
|
167 |
|
slime@2
|
168 |
/******************************************************************************
|
slime@2
|
169 |
* Function: void USBSoftDetach(void)
|
slime@2
|
170 |
*
|
slime@2
|
171 |
* PreCondition: None
|
slime@2
|
172 |
*
|
slime@2
|
173 |
* Input: None
|
slime@2
|
174 |
*
|
slime@2
|
175 |
* Output: None
|
slime@2
|
176 |
*
|
slime@2
|
177 |
* Side Effects: The device will have to be re-enumerated to function again.
|
slime@2
|
178 |
*
|
slime@2
|
179 |
* Overview: USBSoftDetach electrically disconnects the device from
|
slime@2
|
180 |
* the bus. This is done by stop supplying Vusb voltage to
|
slime@2
|
181 |
* pull-up resistor. The pull-down resistors on the host
|
slime@2
|
182 |
* side will pull both differential signal lines low and
|
slime@2
|
183 |
* the host registers the event as a disconnect.
|
slime@2
|
184 |
*
|
slime@2
|
185 |
* Since the USB cable is not physically disconnected, the
|
slime@2
|
186 |
* power supply through the cable can still be sensed by
|
slime@2
|
187 |
* the device. The next time USBCheckBusStatus() function
|
slime@2
|
188 |
* is called, it will reconnect the device back to the bus.
|
slime@2
|
189 |
*
|
slime@2
|
190 |
* Note: None
|
slime@2
|
191 |
*****************************************************************************/
|
slime@2
|
192 |
void USBSoftDetach(void)
|
slime@2
|
193 |
{
|
slime@2
|
194 |
USBModuleDisable();
|
slime@2
|
195 |
}//end USBSoftDetach
|
slime@2
|
196 |
|
slime@2
|
197 |
/******************************************************************************
|
slime@2
|
198 |
* Function: void USBDriverService(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 is the heart of this firmware. It manages
|
slime@2
|
209 |
* all USB interrupts.
|
slime@2
|
210 |
*
|
slime@2
|
211 |
* Note: Device state transitions through the following stages:
|
slime@2
|
212 |
* DETACHED -> ATTACHED -> POWERED -> DEFAULT ->
|
slime@2
|
213 |
* ADDRESS_PENDING -> ADDRESSED -> CONFIGURED -> READY
|
slime@2
|
214 |
*****************************************************************************/
|
slime@2
|
215 |
void USBDriverService(void)
|
slime@2
|
216 |
{
|
slime@2
|
217 |
/*
|
slime@2
|
218 |
* Pointless to continue servicing if USB cable is not even attached.
|
slime@2
|
219 |
*/
|
slime@2
|
220 |
if(usb_device_state == DETACHED_STATE) return;
|
slime@2
|
221 |
|
slime@2
|
222 |
/*
|
slime@2
|
223 |
* Task A: Service USB Activity Interrupt
|
slime@2
|
224 |
*/
|
slime@2
|
225 |
|
slime@2
|
226 |
if(UIRbits.ACTVIF && UIEbits.ACTVIE) USBWakeFromSuspend();
|
slime@2
|
227 |
|
slime@2
|
228 |
/*
|
slime@2
|
229 |
* Pointless to continue servicing if the device is in suspend mode.
|
slime@2
|
230 |
*/
|
slime@2
|
231 |
if(UCONbits.SUSPND==1) return;
|
slime@2
|
232 |
|
slime@2
|
233 |
/*
|
slime@2
|
234 |
* Task B: Service USB Bus Reset Interrupt.
|
slime@2
|
235 |
* When bus reset is received during suspend, ACTVIF will be set first,
|
slime@2
|
236 |
* once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted.
|
slime@2
|
237 |
* This is why URSTIF is checked after ACTVIF.
|
slime@2
|
238 |
*/
|
slime@2
|
239 |
if(UIRbits.URSTIF && UIEbits.URSTIE) USBProtocolResetHandler();
|
slime@2
|
240 |
|
slime@2
|
241 |
/*
|
slime@2
|
242 |
* Task C: Service other USB interrupts
|
slime@2
|
243 |
*/
|
slime@2
|
244 |
if(UIRbits.IDLEIF && UIEbits.IDLEIE) USBSuspend();
|
slime@2
|
245 |
if(UIRbits.SOFIF && UIEbits.SOFIE) USB_SOF_Handler();
|
slime@2
|
246 |
if(UIRbits.STALLIF && UIEbits.STALLIE) USBStallHandler();
|
slime@2
|
247 |
if(UIRbits.UERRIF && UIEbits.UERRIE) USBErrorHandler();
|
slime@2
|
248 |
|
slime@2
|
249 |
/*
|
slime@2
|
250 |
* Pointless to continue servicing if the host has not sent a bus reset.
|
slime@2
|
251 |
* Once bus reset is received, the device transitions into the DEFAULT
|
slime@2
|
252 |
* state and is ready for communication.
|
slime@2
|
253 |
*/
|
slime@2
|
254 |
if(usb_device_state < DEFAULT_STATE) return;
|
slime@2
|
255 |
|
slime@2
|
256 |
/*
|
slime@2
|
257 |
* Task D: Servicing USB Transaction Complete Interrupt
|
slime@2
|
258 |
*/
|
slime@2
|
259 |
if(UIRbits.TRNIF && UIEbits.TRNIE)
|
slime@2
|
260 |
{
|
slime@2
|
261 |
/*
|
slime@2
|
262 |
* USBCtrlEPService only services transactions over EP0.
|
slime@2
|
263 |
* It ignores all other EP transactions.
|
slime@2
|
264 |
*/
|
slime@2
|
265 |
USBCtrlEPService();
|
slime@2
|
266 |
|
slime@2
|
267 |
/*
|
slime@2
|
268 |
* Other EP can be serviced later by responsible device class firmware.
|
slime@2
|
269 |
* Each device driver knows when an OUT or IN transaction is ready by
|
slime@2
|
270 |
* checking the buffer ownership bit.
|
slime@2
|
271 |
* An OUT EP should always be owned by SIE until the data is ready.
|
slime@2
|
272 |
* An IN EP should always be owned by CPU until the data is ready.
|
slime@2
|
273 |
*
|
slime@2
|
274 |
* Because of this logic, it is not necessary to save the USTAT value
|
slime@2
|
275 |
* of non-EP0 transactions.
|
slime@2
|
276 |
*/
|
slime@2
|
277 |
UIRbits.TRNIF = 0;
|
slime@2
|
278 |
}//end if(UIRbits.TRNIF && UIEbits.TRNIE)
|
slime@2
|
279 |
|
slime@2
|
280 |
}//end USBDriverService
|
slime@2
|
281 |
|
slime@2
|
282 |
/******************************************************************************
|
slime@2
|
283 |
* Function: void USBSuspend(void)
|
slime@2
|
284 |
*
|
slime@2
|
285 |
* PreCondition: None
|
slime@2
|
286 |
*
|
slime@2
|
287 |
* Input: None
|
slime@2
|
288 |
*
|
slime@2
|
289 |
* Output: None
|
slime@2
|
290 |
*
|
slime@2
|
291 |
* Side Effects: None
|
slime@2
|
292 |
*
|
slime@2
|
293 |
* Overview:
|
slime@2
|
294 |
*
|
slime@2
|
295 |
* Note: None
|
slime@2
|
296 |
*****************************************************************************/
|
slime@2
|
297 |
void USBSuspend(void)
|
slime@2
|
298 |
{
|
slime@2
|
299 |
/*
|
slime@2
|
300 |
* NOTE: Do not clear UIRbits.ACTVIF here!
|
slime@2
|
301 |
* Reason:
|
slime@2
|
302 |
* ACTVIF is only generated once an IDLEIF has been generated.
|
slime@2
|
303 |
* This is a 1:1 ratio interrupt generation.
|
slime@2
|
304 |
* For every IDLEIF, there will be only one ACTVIF regardless of
|
slime@2
|
305 |
* the number of subsequent bus transitions.
|
slime@2
|
306 |
*
|
slime@2
|
307 |
* If the ACTIF is cleared here, a problem could occur when:
|
slime@2
|
308 |
* [ IDLE ][bus activity ->
|
slime@2
|
309 |
* <--- 3 ms -----> ^
|
slime@2
|
310 |
* ^ ACTVIF=1
|
slime@2
|
311 |
* IDLEIF=1
|
slime@2
|
312 |
* # # # # (#=Program polling flags)
|
slime@2
|
313 |
* ^
|
slime@2
|
314 |
* This polling loop will see both
|
slime@2
|
315 |
* IDLEIF=1 and ACTVIF=1.
|
slime@2
|
316 |
* However, the program services IDLEIF first
|
slime@2
|
317 |
* because ACTIVIE=0.
|
slime@2
|
318 |
* If this routine clears the only ACTIVIF,
|
slime@2
|
319 |
* then it can never get out of the suspend
|
slime@2
|
320 |
* mode.
|
slime@2
|
321 |
*/
|
slime@2
|
322 |
UIEbits.ACTVIE = 1; // Enable bus activity interrupt
|
slime@2
|
323 |
UIRbits.IDLEIF = 0;
|
slime@2
|
324 |
UCONbits.SUSPND = 1; // Put USB module in power conserve
|
slime@2
|
325 |
// mode, SIE clock inactive
|
slime@2
|
326 |
/*
|
slime@2
|
327 |
* At this point the PIC can go into sleep,idle, or
|
slime@2
|
328 |
* switch to a slower clock, etc.
|
slime@2
|
329 |
*/
|
slime@2
|
330 |
|
slime@2
|
331 |
/* Modifiable Section */
|
slime@2
|
332 |
PIR2bits.USBIF = 0;
|
slime@2
|
333 |
PIE2bits.USBIE = 1; // Set USB wakeup source
|
slime@2
|
334 |
Sleep(); // Goto sleep
|
slime@2
|
335 |
PIE2bits.USBIE = 0;
|
slime@2
|
336 |
/* End Modifiable Section */
|
slime@2
|
337 |
|
slime@2
|
338 |
}//end USBSuspend
|
slime@2
|
339 |
|
slime@2
|
340 |
/******************************************************************************
|
slime@2
|
341 |
* Function: void USBWakeFromSuspend(void)
|
slime@2
|
342 |
*
|
slime@2
|
343 |
* PreCondition: None
|
slime@2
|
344 |
*
|
slime@2
|
345 |
* Input: None
|
slime@2
|
346 |
*
|
slime@2
|
347 |
* Output: None
|
slime@2
|
348 |
*
|
slime@2
|
349 |
* Side Effects: None
|
slime@2
|
350 |
*
|
slime@2
|
351 |
* Overview:
|
slime@2
|
352 |
*
|
slime@2
|
353 |
* Note: None
|
slime@2
|
354 |
*****************************************************************************/
|
slime@2
|
355 |
void USBWakeFromSuspend(void)
|
slime@2
|
356 |
{
|
slime@2
|
357 |
/*
|
slime@2
|
358 |
* If using clock switching, this is the place to restore the
|
slime@2
|
359 |
* original clock frequency.
|
slime@2
|
360 |
*/
|
slime@2
|
361 |
UCONbits.SUSPND = 0;
|
slime@2
|
362 |
UIEbits.ACTVIE = 0;
|
slime@2
|
363 |
UIRbits.ACTVIF = 0;
|
slime@2
|
364 |
}//end USBWakeFromSuspend
|
slime@2
|
365 |
|
slime@2
|
366 |
/******************************************************************************
|
slime@2
|
367 |
* Function: void USBRemoteWakeup(void)
|
slime@2
|
368 |
*
|
slime@2
|
369 |
* PreCondition: None
|
slime@2
|
370 |
*
|
slime@2
|
371 |
* Input: None
|
slime@2
|
372 |
*
|
slime@2
|
373 |
* Output: None
|
slime@2
|
374 |
*
|
slime@2
|
375 |
* Side Effects: None
|
slime@2
|
376 |
*
|
slime@2
|
377 |
* Overview: This function should be called by user when the device
|
slime@2
|
378 |
* is waken up by an external stimulus other than ACTIVIF.
|
slime@2
|
379 |
* Please read the note below to understand the limitations.
|
slime@2
|
380 |
*
|
slime@2
|
381 |
* Note: The modifiable section in this routine should be changed
|
slime@2
|
382 |
* to meet the application needs. Current implementation
|
slime@2
|
383 |
* temporary blocks other functions from executing for a
|
slime@2
|
384 |
* period of 1-13 ms depending on the core frequency.
|
slime@2
|
385 |
*
|
slime@2
|
386 |
* According to USB 2.0 specification section 7.1.7.7,
|
slime@2
|
387 |
* "The remote wakeup device must hold the resume signaling
|
slime@2
|
388 |
* for at lest 1 ms but for no more than 15 ms."
|
slime@2
|
389 |
* The idea here is to use a delay counter loop, using a
|
slime@2
|
390 |
* common value that would work over a wide range of core
|
slime@2
|
391 |
* frequencies.
|
slime@2
|
392 |
* That value selected is 1800. See table below:
|
slime@2
|
393 |
* ==========================================================
|
slime@2
|
394 |
* Core Freq(MHz) MIP RESUME Signal Period (ms)
|
slime@2
|
395 |
* ==========================================================
|
slime@2
|
396 |
* 48 12 1.05
|
slime@2
|
397 |
* 4 1 12.6
|
slime@2
|
398 |
* ==========================================================
|
slime@2
|
399 |
* * These timing could be incorrect when using code
|
slime@2
|
400 |
* optimization or extended instruction mode,
|
slime@2
|
401 |
* or when having other interrupts enabled.
|
slime@2
|
402 |
* Make sure to verify using the MPLAB SIM's Stopwatch
|
slime@2
|
403 |
*****************************************************************************/
|
slime@2
|
404 |
void USBRemoteWakeup(void)
|
slime@2
|
405 |
{
|
slime@2
|
406 |
static word delay_count;
|
slime@2
|
407 |
|
slime@2
|
408 |
if(usb_stat.RemoteWakeup == 1) // Check if RemoteWakeup function
|
slime@2
|
409 |
{ // has been enabled by the host.
|
slime@2
|
410 |
USBWakeFromSuspend(); // Unsuspend USB modue
|
slime@2
|
411 |
UCONbits.RESUME = 1; // Start RESUME signaling
|
slime@2
|
412 |
|
slime@2
|
413 |
/* Modifiable Section */
|
slime@2
|
414 |
|
slime@2
|
415 |
delay_count = 1800U; // Set RESUME line for 1-13 ms
|
slime@2
|
416 |
do
|
slime@2
|
417 |
{
|
slime@2
|
418 |
delay_count--;
|
slime@2
|
419 |
}while(delay_count);
|
slime@2
|
420 |
|
slime@2
|
421 |
/* End Modifiable Section */
|
slime@2
|
422 |
|
slime@2
|
423 |
UCONbits.RESUME = 0;
|
slime@2
|
424 |
}//endif
|
slime@2
|
425 |
}//end USBRemoteWakeup
|
slime@2
|
426 |
|
slime@2
|
427 |
/******************************************************************************
|
slime@2
|
428 |
* Function: void USB_SOF_Handler(void)
|
slime@2
|
429 |
*
|
slime@2
|
430 |
* PreCondition: None
|
slime@2
|
431 |
*
|
slime@2
|
432 |
* Input: None
|
slime@2
|
433 |
*
|
slime@2
|
434 |
* Output: None
|
slime@2
|
435 |
*
|
slime@2
|
436 |
* Side Effects: None
|
slime@2
|
437 |
*
|
slime@2
|
438 |
* Overview: The USB host sends out a SOF packet to full-speed devices
|
slime@2
|
439 |
* every 1 ms. This interrupt may be useful for isochronous
|
slime@2
|
440 |
* pipes. End designers should implement callback routine
|
slime@2
|
441 |
* as necessary.
|
slime@2
|
442 |
*
|
slime@2
|
443 |
* Note: None
|
slime@2
|
444 |
*****************************************************************************/
|
slime@2
|
445 |
void USB_SOF_Handler(void)
|
slime@2
|
446 |
{
|
slime@2
|
447 |
/* Callback routine here */
|
slime@2
|
448 |
|
slime@2
|
449 |
UIRbits.SOFIF = 0;
|
slime@2
|
450 |
}//end USB_SOF_Handler
|
slime@2
|
451 |
|
slime@2
|
452 |
/******************************************************************************
|
slime@2
|
453 |
* Function: void USBStallHandler(void)
|
slime@2
|
454 |
*
|
slime@2
|
455 |
* PreCondition: A STALL packet is sent to the host by the SIE.
|
slime@2
|
456 |
*
|
slime@2
|
457 |
* Input: None
|
slime@2
|
458 |
*
|
slime@2
|
459 |
* Output: None
|
slime@2
|
460 |
*
|
slime@2
|
461 |
* Side Effects: None
|
slime@2
|
462 |
*
|
slime@2
|
463 |
* Overview: The STALLIF is set anytime the SIE sends out a STALL
|
slime@2
|
464 |
* packet regardless of which endpoint causes it.
|
slime@2
|
465 |
* A Setup transaction overrides the STALL function. A stalled
|
slime@2
|
466 |
* endpoint stops stalling once it receives a setup packet.
|
slime@2
|
467 |
* In this case, the SIE will accepts the Setup packet and
|
slime@2
|
468 |
* set the TRNIF flag to notify the firmware. STALL function
|
slime@2
|
469 |
* for that particular endpoint pipe will be automatically
|
slime@2
|
470 |
* disabled (direction specific).
|
slime@2
|
471 |
*
|
slime@2
|
472 |
* There are a few reasons for an endpoint to be stalled.
|
slime@2
|
473 |
* 1. When a non-supported USB request is received.
|
slime@2
|
474 |
* Example: GET_DESCRIPTOR(DEVICE_QUALIFIER)
|
slime@2
|
475 |
* 2. When an endpoint is currently halted.
|
slime@2
|
476 |
* 3. When the device class specifies that an endpoint must
|
slime@2
|
477 |
* stall in response to a specific event.
|
slime@2
|
478 |
* Example: Mass Storage Device Class
|
slime@2
|
479 |
* If the CBW is not valid, the device shall
|
slime@2
|
480 |
* STALL the Bulk-In pipe.
|
slime@2
|
481 |
* See USB Mass Storage Class Bulk-only Transport
|
slime@2
|
482 |
* Specification for more details.
|
slime@2
|
483 |
*
|
slime@2
|
484 |
* Note: UEPn.EPSTALL can be scanned to see which endpoint causes
|
slime@2
|
485 |
* the stall event.
|
slime@2
|
486 |
* If
|
slime@2
|
487 |
*****************************************************************************/
|
slime@2
|
488 |
void USBStallHandler(void)
|
slime@2
|
489 |
{
|
slime@2
|
490 |
/*
|
slime@2
|
491 |
* Does not really have to do anything here,
|
slime@2
|
492 |
* even for the control endpoint.
|
slime@2
|
493 |
* All BDs of Endpoint 0 are owned by SIE right now,
|
slime@2
|
494 |
* but once a Setup Transaction is received, the ownership
|
slime@2
|
495 |
* for EP0_OUT will be returned to CPU.
|
slime@2
|
496 |
* When the Setup Transaction is serviced, the ownership
|
slime@2
|
497 |
* for EP0_IN will then be forced back to CPU by firmware.
|
slime@2
|
498 |
*/
|
slime@2
|
499 |
if(UEP0bits.EPSTALL == 1)
|
slime@2
|
500 |
{
|
slime@2
|
501 |
USBPrepareForNextSetupTrf(); // Firmware work-around
|
slime@2
|
502 |
UEP0bits.EPSTALL = 0;
|
slime@2
|
503 |
}
|
slime@2
|
504 |
UIRbits.STALLIF = 0;
|
slime@2
|
505 |
}//end USBStallHandler
|
slime@2
|
506 |
|
slime@2
|
507 |
/******************************************************************************
|
slime@2
|
508 |
* Function: void USBErrorHandler(void)
|
slime@2
|
509 |
*
|
slime@2
|
510 |
* PreCondition: None
|
slime@2
|
511 |
*
|
slime@2
|
512 |
* Input: None
|
slime@2
|
513 |
*
|
slime@2
|
514 |
* Output: None
|
slime@2
|
515 |
*
|
slime@2
|
516 |
* Side Effects: None
|
slime@2
|
517 |
*
|
slime@2
|
518 |
* Overview: The purpose of this interrupt is mainly for debugging
|
slime@2
|
519 |
* during development. Check UEIR to see which error causes
|
slime@2
|
520 |
* the interrupt.
|
slime@2
|
521 |
*
|
slime@2
|
522 |
* Note: None
|
slime@2
|
523 |
*****************************************************************************/
|
slime@2
|
524 |
void USBErrorHandler(void)
|
slime@2
|
525 |
{
|
slime@2
|
526 |
UIRbits.UERRIF = 0;
|
slime@2
|
527 |
}//end USBErrorHandler
|
slime@2
|
528 |
|
slime@2
|
529 |
/******************************************************************************
|
slime@2
|
530 |
* Function: void USBProtocolResetHandler(void)
|
slime@2
|
531 |
*
|
slime@2
|
532 |
* PreCondition: A USB bus reset is received from the host.
|
slime@2
|
533 |
*
|
slime@2
|
534 |
* Input: None
|
slime@2
|
535 |
*
|
slime@2
|
536 |
* Output: None
|
slime@2
|
537 |
*
|
slime@2
|
538 |
* Side Effects: Currently, this routine flushes any pending USB
|
slime@2
|
539 |
* transactions. It empties out the USTAT FIFO. This action
|
slime@2
|
540 |
* might not be desirable in some applications.
|
slime@2
|
541 |
*
|
slime@2
|
542 |
* Overview: Once a USB bus reset is received from the host, this
|
slime@2
|
543 |
* routine should be called. It resets the device address to
|
slime@2
|
544 |
* zero, disables all non-EP0 endpoints, initializes EP0 to
|
slime@2
|
545 |
* be ready for default communication, clears all USB
|
slime@2
|
546 |
* interrupt flags, unmasks applicable USB interrupts, and
|
slime@2
|
547 |
* reinitializes internal state-machine variables.
|
slime@2
|
548 |
*
|
slime@2
|
549 |
* Note: None
|
slime@2
|
550 |
*****************************************************************************/
|
slime@2
|
551 |
void USBProtocolResetHandler(void)
|
slime@2
|
552 |
{
|
slime@2
|
553 |
UEIR = 0; // Clear all USB error flags
|
slime@2
|
554 |
UIR = 0; // Clears all USB interrupts
|
slime@2
|
555 |
UEIE = 0b10011111; // Unmask all USB error interrupts
|
slime@2
|
556 |
UIE = 0b01111011; // Enable all interrupts except ACTVIE
|
slime@2
|
557 |
|
slime@2
|
558 |
UADDR = 0x00; // Reset to default address
|
slime@2
|
559 |
mDisableEP1to15(); // Reset all non-EP0 UEPn registers
|
slime@2
|
560 |
UEP0 = EP_CTRL|HSHK_EN; // Init EP0 as a Ctrl EP, see usbdrv.h
|
slime@2
|
561 |
|
slime@2
|
562 |
while(UIRbits.TRNIF == 1) // Flush any pending transactions
|
slime@2
|
563 |
UIRbits.TRNIF = 0;
|
slime@2
|
564 |
|
slime@2
|
565 |
UCONbits.PKTDIS = 0; // Make sure packet processing is enabled
|
slime@2
|
566 |
USBPrepareForNextSetupTrf(); // Declared in usbctrltrf.c
|
slime@2
|
567 |
|
slime@2
|
568 |
usb_stat.RemoteWakeup = 0; // Default status flag to disable
|
slime@2
|
569 |
usb_active_cfg = 0; // Clear active configuration
|
slime@2
|
570 |
usb_device_state = DEFAULT_STATE;
|
slime@2
|
571 |
}//end USBProtocolResetHandler
|
slime@2
|
572 |
|
slime@2
|
573 |
|
slime@2
|
574 |
/* Auxiliary Function */
|
slime@2
|
575 |
void ClearArray(byte* startAdr,byte count)
|
slime@2
|
576 |
{
|
slime@2
|
577 |
*startAdr;
|
slime@2
|
578 |
while(count)
|
slime@2
|
579 |
{
|
slime@2
|
580 |
_asm
|
slime@2
|
581 |
clrf POSTINC0,0
|
slime@2
|
582 |
_endasm
|
slime@2
|
583 |
count--;
|
slime@2
|
584 |
}//end while
|
slime@2
|
585 |
}//end ClearArray
|
slime@2
|
586 |
|
slime@2
|
587 |
/** EOF usbdrv.c *************************************************************/
|