?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /********************************************************************
2 File Information:
3 FileName: usb_device.c
4 Dependencies: See INCLUDES section
5 Processor: PIC18 or PIC24 USB Microcontrollers
6 Hardware: The code is natively intended to be used on the following
7 hardware platforms: PICDEM™ FS USB Demo Board,
8 PIC18F87J50 FS USB Plug-In Module, or
9 Explorer 16 + PIC24 USB PIM. The firmware may be
10 modified for use on other USB platforms by editing the
11 HardwareProfile.h file.
12 Complier: Microchip C18 (for PIC18) or C30 (for PIC24)
13 Company: Microchip Technology, Inc.
14  
15 Software License Agreement:
16  
17 The software supplied herewith by Microchip Technology Incorporated
18 (the “Company”) for its PIC® Microcontroller is intended and
19 supplied to you, the Company’s customer, for use solely and
20 exclusively on Microchip PIC Microcontroller products. The
21 software is owned by the Company and/or its supplier, and is
22 protected under applicable copyright laws. All rights are reserved.
23 Any use in violation of the foregoing restrictions may subject the
24 user to criminal sanctions under applicable laws, as well as to
25 civil liability for the breach of the terms and conditions of this
26 license.
27  
28 THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
29 WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
30 TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31 PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
32 IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
33 CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
34  
35 Summary:
36 This file contains functions, macros, definitions, variables,
37 datatypes, etc. that are required for usage with the MCHPFSUSB device
38 stack. This file should be included in projects that use the device stack.
39  
40 This file is located in the "\<Install Directory\>\\Microchip\\USB"
41 directory.
42  
43 Description:
44 USB Device Stack File
45  
46 This file contains functions, macros, definitions, variables,
47 datatypes, etc. that are required for usage with the MCHPFSUSB device
48 stack. This file should be included in projects that use the device stack.
49  
50 This file is located in the "\<Install Directory\>\\Microchip\\USB"
51 directory.
52  
53 When including this file in a new project, this file can either be
54 referenced from the directory in which it was installed or copied
55 directly into the user application folder. If the first method is
56 chosen to keep the file located in the folder in which it is installed
57 then include paths need to be added so that the library and the
58 application both know where to reference each others files. If the
59 application folder is located in the same folder as the Microchip
60 folder (like the current demo folders), then the following include
61 paths need to be added to the application's project:
62  
63 .
64 ..\\..\\MicrochipInclude
65  
66 If a different directory structure is used, modify the paths as
67 required. An example using absolute paths instead of relative paths
68 would be the following:
69  
70 C:\\Microchip Solutions\\Microchip\\Include
71  
72 C:\\Microchip Solutions\\My Demo Application
73  
74 ********************************************************************
75 File Description:
76  
77 Change History:
78 Rev Description
79 ---- -----------
80 2.6 Added USBCancelIO() function. Moved and some stack
81 defintions to be more consistant with the host stack.
82  
83 2.6a Fixed issue where a SET_CONFIGURATION received could cause
84 inability to transmit on an endpoint if using ping-pong
85 and an odd number of packets had been sent on that endpoint
86  
87 2.7 Fixed error where the USB error interrupt flag was not getting
88 cleared properly for PIC32 resulting in lots of extra error interrupts.
89 http://www.microchip.com/forums/tm.aspx?m=479085
90  
91 Fixed issue with dual role mode when device run in polling
92 mode. Interrupts were remaining enabled after the host mode
93 operation was complete. This was incompatible with polling
94 mode operation.
95  
96 Changed how the bus sensing works. In previous revisions it
97 was impossible to use the USBDeviceDetach to detach from the
98 bus if the bus voltage was still present. This is now
99 possible. It was also possible to move the device to the
100 ATTACHED state in interrupt mode even if the bus voltage
101 wasn't available. This is now prohibited unless VBUS is
102 present.
103  
104 Improved error case handling when the host sends more OUT
105 bytes in a control transfer than the firmware was expecting
106 to receive (based on the size parameter when calling USBEP0Receive()).
107  
108 In the USBStdSetCfgHandler(), modified the code so the USBDeviceState
109 variable only gets updated to the CONFIGURED_STATE at the end of the
110 function.
111  
112 2.7a Update to support the PIC18F47J53 A1 and later revision
113 devices.
114  
115 Fixed an error on 16-bit and 32-bit processors where a word access
116 could be performed on a byte pointer resulting in possible address
117 errors with odd aligned pointers.
118 ********************************************************************/
119  
120 /** INCLUDES *******************************************************/
121 #include "GenericTypeDefs.h"
122 #include "Compiler.h"
123 #include "./USB/USB.h"
124 #include "HardwareProfile.h"
125  
126  
127 #if defined(USB_USE_MSD)
128 #include "./USB/usb_function_msd.h"
129 #endif
130  
131 #if defined(__C32__)
132 #if (USB_PING_PONG_MODE != USB_PING_PONG__FULL_PING_PONG)
133 #error "PIC32 only supports full ping pong mode. A different mode other than full ping pong is selected in the usb_config.h file."
134 #endif
135 #endif
136  
137 //#define DEBUG_MODE
138  
139 #ifdef DEBUG_MODE
140 #include "uart2.h"
141 #endif
142  
143 #if !defined(USE_USB_BUS_SENSE_IO)
144 #undef USB_BUS_SENSE
145 #define USB_BUS_SENSE 1
146 #endif
147  
148 /** Definitions ****************************************************/
149 /* v2.1 fix - Short Packet States - Used by Control Transfer Read - CTRL_TRF_TX */
150 #define SHORT_PKT_NOT_USED 0
151 #define SHORT_PKT_PENDING 1
152 #define SHORT_PKT_SENT 2
153  
154 /* Control Transfer States */
155 #define WAIT_SETUP 0
156 #define CTRL_TRF_TX 1
157 #define CTRL_TRF_RX 2
158  
159 #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG)
160 #define USB_NEXT_EP0_OUT_PING_PONG 0x0000 // Used in USB Device Mode only
161 #define USB_NEXT_EP0_IN_PING_PONG 0x0000 // Used in USB Device Mode only
162 #define USB_NEXT_PING_PONG 0x0000 // Used in USB Device Mode only
163 #define EP0_OUT_EVEN 0 // Used in USB Device Mode only
164 #define EP0_OUT_ODD 0 // Used in USB Device Mode only
165 #define EP0_IN_EVEN 1 // Used in USB Device Mode only
166 #define EP0_IN_ODD 1 // Used in USB Device Mode only
167 #define EP1_OUT_EVEN 2 // Used in USB Device Mode only
168 #define EP1_OUT_ODD 2 // Used in USB Device Mode only
169 #define EP1_IN_EVEN 3 // Used in USB Device Mode only
170 #define EP1_IN_ODD 3 // Used in USB Device Mode only
171 #define EP2_OUT_EVEN 4 // Used in USB Device Mode only
172 #define EP2_OUT_ODD 4 // Used in USB Device Mode only
173 #define EP2_IN_EVEN 5 // Used in USB Device Mode only
174 #define EP2_IN_ODD 5 // Used in USB Device Mode only
175 #define EP3_OUT_EVEN 6 // Used in USB Device Mode only
176 #define EP3_OUT_ODD 6 // Used in USB Device Mode only
177 #define EP3_IN_EVEN 7 // Used in USB Device Mode only
178 #define EP3_IN_ODD 7 // Used in USB Device Mode only
179 #define EP4_OUT_EVEN 8 // Used in USB Device Mode only
180 #define EP4_OUT_ODD 8 // Used in USB Device Mode only
181 #define EP4_IN_EVEN 9 // Used in USB Device Mode only
182 #define EP4_IN_ODD 9 // Used in USB Device Mode only
183 #define EP5_OUT_EVEN 10 // Used in USB Device Mode only
184 #define EP5_OUT_ODD 10 // Used in USB Device Mode only
185 #define EP5_IN_EVEN 11 // Used in USB Device Mode only
186 #define EP5_IN_ODD 11 // Used in USB Device Mode only
187 #define EP6_OUT_EVEN 12 // Used in USB Device Mode only
188 #define EP6_OUT_ODD 12 // Used in USB Device Mode only
189 #define EP6_IN_EVEN 13 // Used in USB Device Mode only
190 #define EP6_IN_ODD 13 // Used in USB Device Mode only
191 #define EP7_OUT_EVEN 14 // Used in USB Device Mode only
192 #define EP7_OUT_ODD 14 // Used in USB Device Mode only
193 #define EP7_IN_EVEN 15 // Used in USB Device Mode only
194 #define EP7_IN_ODD 15 // Used in USB Device Mode only
195 #define EP8_OUT_EVEN 16 // Used in USB Device Mode only
196 #define EP8_OUT_ODD 16 // Used in USB Device Mode only
197 #define EP8_IN_EVEN 17 // Used in USB Device Mode only
198 #define EP8_IN_ODD 17 // Used in USB Device Mode only
199 #define EP9_OUT_EVEN 18 // Used in USB Device Mode only
200 #define EP9_OUT_ODD 18 // Used in USB Device Mode only
201 #define EP9_IN_EVEN 19 // Used in USB Device Mode only
202 #define EP9_IN_ODD 19 // Used in USB Device Mode only
203 #define EP10_OUT_EVEN 20 // Used in USB Device Mode only
204 #define EP10_OUT_ODD 20 // Used in USB Device Mode only
205 #define EP10_IN_EVEN 21 // Used in USB Device Mode only
206 #define EP10_IN_ODD 21 // Used in USB Device Mode only
207 #define EP11_OUT_EVEN 22 // Used in USB Device Mode only
208 #define EP11_OUT_ODD 22 // Used in USB Device Mode only
209 #define EP11_IN_EVEN 23 // Used in USB Device Mode only
210 #define EP11_IN_ODD 23 // Used in USB Device Mode only
211 #define EP12_OUT_EVEN 24 // Used in USB Device Mode only
212 #define EP12_OUT_ODD 24 // Used in USB Device Mode only
213 #define EP12_IN_EVEN 25 // Used in USB Device Mode only
214 #define EP12_IN_ODD 25 // Used in USB Device Mode only
215 #define EP13_OUT_EVEN 26 // Used in USB Device Mode only
216 #define EP13_OUT_ODD 26 // Used in USB Device Mode only
217 #define EP13_IN_EVEN 27 // Used in USB Device Mode only
218 #define EP13_IN_ODD 27 // Used in USB Device Mode only
219 #define EP14_OUT_EVEN 28 // Used in USB Device Mode only
220 #define EP14_OUT_ODD 28 // Used in USB Device Mode only
221 #define EP14_IN_EVEN 29 // Used in USB Device Mode only
222 #define EP14_IN_ODD 29 // Used in USB Device Mode only
223 #define EP15_OUT_EVEN 30 // Used in USB Device Mode only
224 #define EP15_OUT_ODD 30 // Used in USB Device Mode only
225 #define EP15_IN_EVEN 31 // Used in USB Device Mode only
226 #define EP15_IN_ODD 31 // Used in USB Device Mode only
227  
228 #define EP(ep,dir,pp) (2*ep+dir) // Used in USB Device Mode only
229  
230 #define BD(ep,dir,pp) ((8 * ep) + (4 * dir)) // Used in USB Device Mode only
231  
232 #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY)
233 #define USB_NEXT_EP0_OUT_PING_PONG 0x0004
234 #define USB_NEXT_EP0_IN_PING_PONG 0x0000
235 #define USB_NEXT_PING_PONG 0x0000
236 #define EP0_OUT_EVEN 0
237 #define EP0_OUT_ODD 1
238 #define EP0_IN_EVEN 2
239 #define EP0_IN_ODD 2
240 #define EP1_OUT_EVEN 3
241 #define EP1_OUT_ODD 3
242 #define EP1_IN_EVEN 4
243 #define EP1_IN_ODD 4
244 #define EP2_OUT_EVEN 5
245 #define EP2_OUT_ODD 5
246 #define EP2_IN_EVEN 6
247 #define EP2_IN_ODD 6
248 #define EP3_OUT_EVEN 7
249 #define EP3_OUT_ODD 7
250 #define EP3_IN_EVEN 8
251 #define EP3_IN_ODD 8
252 #define EP4_OUT_EVEN 9
253 #define EP4_OUT_ODD 9
254 #define EP4_IN_EVEN 10
255 #define EP4_IN_ODD 10
256 #define EP5_OUT_EVEN 11
257 #define EP5_OUT_ODD 11
258 #define EP5_IN_EVEN 12
259 #define EP5_IN_ODD 12
260 #define EP6_OUT_EVEN 13
261 #define EP6_OUT_ODD 13
262 #define EP6_IN_EVEN 14
263 #define EP6_IN_ODD 14
264 #define EP7_OUT_EVEN 15
265 #define EP7_OUT_ODD 15
266 #define EP7_IN_EVEN 16
267 #define EP7_IN_ODD 16
268 #define EP8_OUT_EVEN 17
269 #define EP8_OUT_ODD 17
270 #define EP8_IN_EVEN 18
271 #define EP8_IN_ODD 18
272 #define EP9_OUT_EVEN 19
273 #define EP9_OUT_ODD 19
274 #define EP9_IN_EVEN 20
275 #define EP9_IN_ODD 20
276 #define EP10_OUT_EVEN 21
277 #define EP10_OUT_ODD 21
278 #define EP10_IN_EVEN 22
279 #define EP10_IN_ODD 22
280 #define EP11_OUT_EVEN 23
281 #define EP11_OUT_ODD 23
282 #define EP11_IN_EVEN 24
283 #define EP11_IN_ODD 24
284 #define EP12_OUT_EVEN 25
285 #define EP12_OUT_ODD 25
286 #define EP12_IN_EVEN 26
287 #define EP12_IN_ODD 26
288 #define EP13_OUT_EVEN 27
289 #define EP13_OUT_ODD 27
290 #define EP13_IN_EVEN 28
291 #define EP13_IN_ODD 28
292 #define EP14_OUT_EVEN 29
293 #define EP14_OUT_ODD 29
294 #define EP14_IN_EVEN 30
295 #define EP14_IN_ODD 30
296 #define EP15_OUT_EVEN 31
297 #define EP15_OUT_ODD 31
298 #define EP15_IN_EVEN 32
299 #define EP15_IN_ODD 32
300  
301 #define EP(ep,dir,pp) (2*ep+dir+(((ep==0)&&(dir==0))?pp:2))
302 #define BD(ep,dir,pp) (4*(ep+dir+(((ep==0)&&(dir==0))?pp:2)))
303  
304 #elif (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG)
305 #if defined (__18CXX) || defined(__C30__)
306 #define USB_NEXT_EP0_OUT_PING_PONG 0x0004
307 #define USB_NEXT_EP0_IN_PING_PONG 0x0004
308 #define USB_NEXT_PING_PONG 0x0004
309 #elif defined(__C32__)
310 #define USB_NEXT_EP0_OUT_PING_PONG 0x0008
311 #define USB_NEXT_EP0_IN_PING_PONG 0x0008
312 #define USB_NEXT_PING_PONG 0x0008
313 #else
314 #error "Not defined for this compiler"
315 #endif
316 #define EP0_OUT_EVEN 0
317 #define EP0_OUT_ODD 1
318 #define EP0_IN_EVEN 2
319 #define EP0_IN_ODD 3
320 #define EP1_OUT_EVEN 4
321 #define EP1_OUT_ODD 5
322 #define EP1_IN_EVEN 6
323 #define EP1_IN_ODD 7
324 #define EP2_OUT_EVEN 8
325 #define EP2_OUT_ODD 9
326 #define EP2_IN_EVEN 10
327 #define EP2_IN_ODD 11
328 #define EP3_OUT_EVEN 12
329 #define EP3_OUT_ODD 13
330 #define EP3_IN_EVEN 14
331 #define EP3_IN_ODD 15
332 #define EP4_OUT_EVEN 16
333 #define EP4_OUT_ODD 17
334 #define EP4_IN_EVEN 18
335 #define EP4_IN_ODD 19
336 #define EP5_OUT_EVEN 20
337 #define EP5_OUT_ODD 21
338 #define EP5_IN_EVEN 22
339 #define EP5_IN_ODD 23
340 #define EP6_OUT_EVEN 24
341 #define EP6_OUT_ODD 25
342 #define EP6_IN_EVEN 26
343 #define EP6_IN_ODD 27
344 #define EP7_OUT_EVEN 28
345 #define EP7_OUT_ODD 29
346 #define EP7_IN_EVEN 30
347 #define EP7_IN_ODD 31
348 #define EP8_OUT_EVEN 32
349 #define EP8_OUT_ODD 33
350 #define EP8_IN_EVEN 34
351 #define EP8_IN_ODD 35
352 #define EP9_OUT_EVEN 36
353 #define EP9_OUT_ODD 37
354 #define EP9_IN_EVEN 38
355 #define EP9_IN_ODD 39
356 #define EP10_OUT_EVEN 40
357 #define EP10_OUT_ODD 41
358 #define EP10_IN_EVEN 42
359 #define EP10_IN_ODD 43
360 #define EP11_OUT_EVEN 44
361 #define EP11_OUT_ODD 45
362 #define EP11_IN_EVEN 46
363 #define EP11_IN_ODD 47
364 #define EP12_OUT_EVEN 48
365 #define EP12_OUT_ODD 49
366 #define EP12_IN_EVEN 50
367 #define EP12_IN_ODD 51
368 #define EP13_OUT_EVEN 52
369 #define EP13_OUT_ODD 53
370 #define EP13_IN_EVEN 54
371 #define EP13_IN_ODD 55
372 #define EP14_OUT_EVEN 56
373 #define EP14_OUT_ODD 57
374 #define EP14_IN_EVEN 58
375 #define EP14_IN_ODD 59
376 #define EP15_OUT_EVEN 60
377 #define EP15_OUT_ODD 61
378 #define EP15_IN_EVEN 62
379 #define EP15_IN_ODD 63
380  
381 #define EP(ep,dir,pp) (4*ep+2*dir+pp)
382  
383 #if defined (__18CXX) || defined(__C30__)
384 #define BD(ep,dir,pp) (4*(4*ep+2*dir+pp))
385 #elif defined(__C32__)
386 #define BD(ep,dir,pp) (8*(4*ep+2*dir+pp))
387 #else
388 #error "Not defined for this compiler"
389 #endif
390  
391 #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0)
392 #define USB_NEXT_EP0_OUT_PING_PONG 0x0000
393 #define USB_NEXT_EP0_IN_PING_PONG 0x0000
394 #define USB_NEXT_PING_PONG 0x0004
395 #define EP0_OUT_EVEN 0
396 #define EP0_OUT_ODD 0
397 #define EP0_IN_EVEN 1
398 #define EP0_IN_ODD 1
399 #define EP1_OUT_EVEN 2
400 #define EP1_OUT_ODD 3
401 #define EP1_IN_EVEN 4
402 #define EP1_IN_ODD 5
403 #define EP2_OUT_EVEN 6
404 #define EP2_OUT_ODD 7
405 #define EP2_IN_EVEN 8
406 #define EP2_IN_ODD 9
407 #define EP3_OUT_EVEN 10
408 #define EP3_OUT_ODD 11
409 #define EP3_IN_EVEN 12
410 #define EP3_IN_ODD 13
411 #define EP4_OUT_EVEN 14
412 #define EP4_OUT_ODD 15
413 #define EP4_IN_EVEN 16
414 #define EP4_IN_ODD 17
415 #define EP5_OUT_EVEN 18
416 #define EP5_OUT_ODD 19
417 #define EP5_IN_EVEN 20
418 #define EP5_IN_ODD 21
419 #define EP6_OUT_EVEN 22
420 #define EP6_OUT_ODD 23
421 #define EP6_IN_EVEN 24
422 #define EP6_IN_ODD 25
423 #define EP7_OUT_EVEN 26
424 #define EP7_OUT_ODD 27
425 #define EP7_IN_EVEN 28
426 #define EP7_IN_ODD 29
427 #define EP8_OUT_EVEN 30
428 #define EP8_OUT_ODD 31
429 #define EP8_IN_EVEN 32
430 #define EP8_IN_ODD 33
431 #define EP9_OUT_EVEN 34
432 #define EP9_OUT_ODD 35
433 #define EP9_IN_EVEN 36
434 #define EP9_IN_ODD 37
435 #define EP10_OUT_EVEN 38
436 #define EP10_OUT_ODD 39
437 #define EP10_IN_EVEN 40
438 #define EP10_IN_ODD 41
439 #define EP11_OUT_EVEN 42
440 #define EP11_OUT_ODD 43
441 #define EP11_IN_EVEN 44
442 #define EP11_IN_ODD 45
443 #define EP12_OUT_EVEN 46
444 #define EP12_OUT_ODD 47
445 #define EP12_IN_EVEN 48
446 #define EP12_IN_ODD 49
447 #define EP13_OUT_EVEN 50
448 #define EP13_OUT_ODD 51
449 #define EP13_IN_EVEN 52
450 #define EP13_IN_ODD 53
451 #define EP14_OUT_EVEN 54
452 #define EP14_OUT_ODD 55
453 #define EP14_IN_EVEN 56
454 #define EP14_IN_ODD 57
455 #define EP15_OUT_EVEN 58
456 #define EP15_OUT_ODD 59
457 #define EP15_IN_EVEN 60
458 #define EP15_IN_ODD 61
459  
460 #define EP(ep,dir,pp) (4*ep+2*dir+((ep==0)?0:(pp-2)))
461 #define BD(ep,dir,pp) (4*(4*ep+2*dir+((ep==0)?0:(pp-2))))
462  
463 #else
464 #error "No ping pong mode defined."
465 #endif
466  
467 /** VARIABLES ******************************************************/
468 #pragma udata
469  
470 USB_VOLATILE USB_DEVICE_STATE USBDeviceState;
471 USB_VOLATILE BYTE USBActiveConfiguration;
472 USB_VOLATILE BYTE USBAlternateInterface[USB_MAX_NUM_INT];
473 volatile BDT_ENTRY *pBDTEntryEP0OutCurrent;
474 volatile BDT_ENTRY *pBDTEntryEP0OutNext;
475 volatile BDT_ENTRY *pBDTEntryOut[USB_MAX_EP_NUMBER+1];
476 volatile BDT_ENTRY *pBDTEntryIn[USB_MAX_EP_NUMBER+1];
477 USB_VOLATILE BYTE shortPacketStatus;
478 USB_VOLATILE BYTE controlTransferState;
479 USB_VOLATILE IN_PIPE inPipes[1];
480 USB_VOLATILE OUT_PIPE outPipes[1];
481 USB_VOLATILE BYTE *pDst;
482 USB_VOLATILE BOOL RemoteWakeup;
483 USB_VOLATILE BYTE USTATcopy;
484 USB_VOLATILE BOOL BothEP0OutUOWNsSet;
485 USB_VOLATILE WORD USBInMaxPacketSize[USB_MAX_EP_NUMBER];
486 USB_VOLATILE BYTE *USBInData[USB_MAX_EP_NUMBER];
487  
488 /** USB FIXED LOCATION VARIABLES ***********************************/
489 #if defined(__18CXX)
490 #if defined(__18F14K50) || defined(__18F13K50) || defined(__18LF14K50) || defined(__18LF13K50)
491 #pragma udata USB_BDT=0x200 //See Linker Script, BDT in bank 2 on these devices - usb2:0x200-0x2FF(256-byte)
492 #elif defined(__18F47J53) || defined(__18F46J53) || defined(__18F27J53) || defined(__18F26J53) || defined(__18LF47J53) || defined(__18LF46J53) || defined(__18LF27J53) || defined(__18LF26J53)
493 #pragma udata USB_BDT=0xD00 //BDT in Bank 13 on these devices
494 #else
495 #pragma udata USB_BDT=0x400 //All other PIC18 devices place the BDT in usb4:0x400-0x4FF(256-byte)
496 #endif
497 #endif
498  
499 /********************************************************************
500 * Section A: Buffer Descriptor Table
501 * - 256 bytes max. Actual size depends on number of endpoints enabled and
502 * the ping pong buffering mode.
503 * - USB_MAX_EP_NUMBER is defined in usb_config.h
504 *******************************************************************/
505 #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG)
506 volatile BDT_ENTRY BDT[(USB_MAX_EP_NUMBER + 1) * 2] __attribute__ ((aligned (512)));
507 #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY)
508 volatile BDT_ENTRY BDT[((USB_MAX_EP_NUMBER + 1) * 2)+1] __attribute__ ((aligned (512)));
509 #elif (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG)
510 volatile BDT_ENTRY BDT[(USB_MAX_EP_NUMBER + 1) * 4] __attribute__ ((aligned (512)));
511 #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0)
512 volatile BDT_ENTRY BDT[((USB_MAX_EP_NUMBER + 1) * 4)-2] __attribute__ ((aligned (512)));
513 #else
514 #error "No ping pong mode defined."
515 #endif
516  
517 /********************************************************************
518 * Section B: EP0 Buffer Space
519 *******************************************************************/
520 volatile CTRL_TRF_SETUP SetupPkt; // 8-byte only
521 volatile BYTE CtrlTrfData[USB_EP0_BUFF_SIZE];
522  
523 /********************************************************************
524 * Section C: non-EP0 Buffer Space
525 *******************************************************************/
526 // Can provide compile time option to do software pingpong
527 #if defined(USB_USE_HID)
528 volatile unsigned char hid_report_out[HID_INT_OUT_EP_SIZE];
529 volatile unsigned char hid_report_in[HID_INT_IN_EP_SIZE];
530 #endif
531  
532 #if defined(USB_USE_MSD)
533 //volatile far USB_MSD_CBW_CSW msd_cbw_csw;
534 volatile USB_MSD_CBW msd_cbw;
535 volatile USB_MSD_CSW msd_csw;
536 //#pragma udata
537  
538 #if defined(__18CXX)
539 #pragma udata myMSD=MSD_BUFFER_ADDRESS
540 #endif
541 volatile char msd_buffer[512];
542 #endif
543  
544 #if defined(__18CXX)
545 #pragma udata
546 #endif
547  
548 //Depricated in v2.2 - will be removed in a future revision
549 #if !defined(USB_USER_DEVICE_DESCRIPTOR)
550 //Device descriptor
551 extern ROM USB_DEVICE_DESCRIPTOR device_dsc;
552 #else
553 USB_USER_DEVICE_DESCRIPTOR_INCLUDE;
554 #endif
555  
556 #if !defined(USB_USER_CONFIG_DESCRIPTOR)
557 //Array of configuration descriptors
558 extern ROM BYTE *ROM USB_CD_Ptr[];
559 #else
560 USB_USER_CONFIG_DESCRIPTOR_INCLUDE;
561 #endif
562  
563 extern ROM BYTE *ROM USB_SD_Ptr[];
564  
565 /** DECLARATIONS ***************************************************/
566 #pragma code
567  
568 /** Macros *********************************************************/
569  
570 /****** Event callback enabling/disabling macros ********************
571 This section of code is used to disable specific USB events that may not be
572 desired by the user. This can save code size and increase throughput and
573 decrease CPU utiliazation.
574 ********************************************************************/
575 #if defined USB_DISABLE_SUSPEND_HANDLER
576 #define USB_SUSPEND_HANDLER(event,pointer,size)
577  
578 #warning "Disabling the suspend handler is not recommended. Proper suspend handling is required to create a compliant USB device."
579 #else
580 #define USB_SUSPEND_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
581 #endif
582  
583 #if defined USB_DISABLE_WAKEUP_FROM_SUSPEND_HANDLER
584 #define USB_WAKEUP_FROM_SUSPEND_HANDLER(event,pointer,size)
585  
586 #warning "Disabling the wake from suspend handler is not recommended. Proper suspend handling is required to create a compliant USB device."
587 #else
588 #define USB_WAKEUP_FROM_SUSPEND_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
589 #endif
590  
591 #if defined USB_DISABLE_SOF_HANDLER
592 #define USB_SOF_HANDLER(event,pointer,size)
593 #else
594 #define USB_SOF_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
595 #endif
596  
597 #if defined USB_DISABLE_ERROR_HANDLER
598 #define USB_ERROR_HANDLER(event,pointer,size)
599 #else
600 #define USB_ERROR_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
601 #endif
602  
603 #if defined USB_DISABLE_NONSTANDARD_EP0_REQUEST_HANDLER
604 #define USB_DISABLE_NONSTANDARD_EP0_REQUEST_HANDLER(event,pointer,size)
605 #else
606 #define USB_DISABLE_NONSTANDARD_EP0_REQUEST_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
607 #endif
608  
609 #if defined USB_DISABLE_SET_DESCRIPTOR_HANDLER
610 #define USB_SET_DESCRIPTOR_HANDLER(event,pointer,size)
611 #else
612 #define USB_SET_DESCRIPTOR_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
613 #endif
614  
615 #if defined USB_DISABLE_SET_CONFIGURATION_HANDLER
616 #define USB_SET_CONFIGURATION_HANDLER(event,pointer,size)
617 #else
618 #define USB_SET_CONFIGURATION_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
619 #endif
620  
621 #if defined USB_DISABLE_TRANSFER_COMPLETE_HANDLER
622 #define USB_TRASFER_COMPLETE_HANDLER(event,pointer,size)
623 #else
624 #define USB_TRASFER_COMPLETE_HANDLER(event,pointer,size) USER_USB_CALLBACK_EVENT_HANDLER(event,pointer,size)
625 #endif
626  
627 /** Function Prototypes ********************************************/
628 //External
629 //This is the prototype for the required user event handler
630 BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size);
631  
632 //Internal
633 void USBCtrlEPService(void);
634 void USBCtrlTrfSetupHandler(void);
635 void USBCtrlTrfInHandler(void);
636 void USBCheckStdRequest(void);
637 void USBStdGetDscHandler(void);
638 void USBCtrlEPServiceComplete(void);
639 void USBCtrlTrfTxService(void);
640 void USBPrepareForNextSetupTrf(void);
641 void USBCtrlTrfRxService(void);
642 void USBStdSetCfgHandler(void);
643 void USBStdGetStatusHandler(void);
644 void USBStdFeatureReqHandler(void);
645 void USBCtrlTrfOutHandler(void);
646 BOOL USBIsTxBusy(BYTE EPNumber);
647 void USBPut(BYTE EPNum, BYTE Data);
648 void USBEPService(void);
649 void USBConfigureEndpoint(BYTE EPNum, BYTE direction);
650  
651 void USBProtocolResetHandler(void);
652 void USBWakeFromSuspend(void);
653 void USBSuspend(void);
654 void USBStallHandler(void);
655 USB_HANDLE USBTransferOnePacket(BYTE ep, BYTE dir, BYTE* data, BYTE len);
656 void USBEnableEndpoint(BYTE ep,BYTE options);
657  
658 //DOM-IGNORE-BEGIN
659 /****************************************************************************
660 Function:
661 void USBDeviceInit(void)
662  
663 Description:
664 This function initializes the device stack
665 it in the default state
666  
667 Precondition:
668 None
669  
670 Parameters:
671 None
672  
673 Return Values:
674 None
675  
676 Remarks:
677 The USB module will be completely reset including
678 all of the internal variables, registers, and
679 interrupt flags.
680 ***************************************************************************/
681 //DOM-IGNORE-END
682 void USBDeviceInit(void)
683 {
684 BYTE i;
685  
686 USBDisableInterrupts();
687  
688 // Clear all USB error flags
689 USBClearInterruptRegister(U1EIR);
690  
691 // Clears all USB interrupts
692 USBClearInterruptRegister(U1IR);
693  
694 SetConfigurationOptions();
695  
696 //power up the module
697 USBPowerModule();
698  
699 //set the address of the BDT (if applicable)
700 USBSetBDTAddress(BDT);
701  
702 // Assert reset request to all of the Ping Pong buffer pointers
703 USBPingPongBufferReset = 1;
704  
705 // Reset to default address
706 U1ADDR = 0x00;
707  
708 //Clear all of the endpoint control registers
709 DisableNonZeroEndpoints(USB_MAX_EP_NUMBER);
710  
711 //Stop trying to reset ping pong buffer pointers
712 USBPingPongBufferReset = 0;
713  
714 //Clear all of the BDT entries
715 for(i=0;i<(sizeof(BDT)/sizeof(BDT_ENTRY));i++)
716 {
717 BDT[i].Val = 0x00;
718 }
719  
720 // Initialize EP0 as a Ctrl EP
721 U1EP0 = EP_CTRL|USB_HANDSHAKE_ENABLED;
722  
723 // Flush any pending transactions
724 while(USBTransactionCompleteIF == 1)
725 {
726 USBClearInterruptFlag(USBTransactionCompleteIFReg,USBTransactionCompleteIFBitNum);
727 }
728  
729 //clear all of the internal pipe information
730 inPipes[0].info.Val = 0;
731 outPipes[0].info.Val = 0;
732 outPipes[0].wCount.Val = 0;
733  
734 // Make sure packet processing is enabled
735 USBPacketDisable = 0;
736  
737 //Initialize all pBDTEntryIn[] and pBDTEntryOut[]
738 //pointers to NULL, so they don't get used inadvertently.
739 for(i = 0; i < (BYTE)(USB_MAX_EP_NUMBER+1u); i++)
740 {
741 pBDTEntryIn[i] = 0u;
742 pBDTEntryOut[i] = 0u;
743 }
744  
745 //Get ready for the first packet
746 pBDTEntryIn[0] = (volatile BDT_ENTRY*)&BDT[EP0_IN_EVEN];
747  
748 // Clear active configuration
749 USBActiveConfiguration = 0;
750  
751 //Indicate that we are now in the detached state
752 USBDeviceState = DETACHED_STATE;
753 }
754  
755 //DOM-IGNORE-BEGIN
756 /****************************************************************************
757 Function:
758 void USBDeviceTasks(void)
759  
760 Description:
761 This function is the main state machine of the
762 USB device side stack. This function should be
763 called periodically to receive and transmit
764 packets through the stack. This function should
765 be called preferably once every 100us
766 during the enumeration process. After the
767 enumeration process this function still needs to
768 be called periodically to respond to various
769 situations on the bus but is more relaxed in its
770 time requirements. This function should also
771 be called at least as fast as the OUT data
772 expected from the PC.
773  
774 Precondition:
775 None
776  
777 Parameters:
778 None
779  
780 Return Values:
781 None
782  
783 Remarks:
784 None
785 ***************************************************************************/
786 //DOM-IGNORE-END
787 #if defined(USB_INTERRUPT)
788 #if defined(__18CXX)
789 void USBDeviceTasks(void)
790 #elif defined(__C30__)
791 //void __attribute__((interrupt,auto_psv,address(0xA800))) _USB1Interrupt()
792 void __attribute__((interrupt,auto_psv)) _USB1Interrupt()
793 #elif defined(__PIC32MX__)
794 #pragma interrupt _USB1Interrupt ipl4 vector 45
795 void _USB1Interrupt( void )
796 #endif
797 #else
798 void USBDeviceTasks(void)
799 #endif
800 {
801 BYTE i;
802  
803 #ifdef USB_SUPPORT_OTG
804 //SRP Time Out Check
805 if (USBOTGSRPIsReady())
806 {
807 if (USBT1MSECIF && USBT1MSECIE)
808 {
809 if (USBOTGGetSRPTimeOutFlag())
810 {
811 if (USBOTGIsSRPTimeOutExpired())
812 {
813 USB_OTGEventHandler(0,OTG_EVENT_SRP_FAILED,0,0);
814 }
815 }
816  
817 //Clear Interrupt Flag
818 USBClearInterruptFlag(USBT1MSECIFReg,USBT1MSECIFBitNum);
819 }
820 }
821 #endif
822  
823 #if defined(USB_POLLING)
824 //If the interrupt option is selected then the customer is required
825 // to notify the stack when the device is attached or removed from the
826 // bus by calling the USBDeviceAttach() and USBDeviceDetach() functions.
827 if (USB_BUS_SENSE != 1)
828 {
829 // Disable module & detach from bus
830 U1CON = 0;
831  
832 // Mask all USB interrupts
833 U1IE = 0;
834  
835 //Move to the detached state
836 USBDeviceState = DETACHED_STATE;
837  
838 #ifdef USB_SUPPORT_OTG
839 //Disable D+ Pullup
840 U1OTGCONbits.DPPULUP = 0;
841  
842 //Disable HNP
843 USBOTGDisableHnp();
844  
845 //Deactivate HNP
846 USBOTGDeactivateHnp();
847  
848 //If ID Pin Changed State
849 if (USBIDIF && USBIDIE)
850 {
851 //Re-detect & Initialize
852 USBOTGInitialize();
853  
854 //Clear ID Interrupt Flag
855 USBClearInterruptFlag(USBIDIFReg,USBIDIFBitNum);
856 }
857 #endif
858  
859 #ifdef __C30__
860 //USBClearInterruptFlag(U1OTGIR, 3);
861 #endif
862 //return so that we don't go through the rest of
863 //the state machine
864 USBClearUSBInterrupt();
865 return;
866 }
867  
868 #ifdef USB_SUPPORT_OTG
869 //If Session Is Started Then
870 else
871 {
872 //If SRP Is Ready
873 if (USBOTGSRPIsReady())
874 {
875 //Clear SRPReady
876 USBOTGClearSRPReady();
877  
878 //Clear SRP Timeout Flag
879 USBOTGClearSRPTimeOutFlag();
880  
881 //Indicate Session Started
882 UART2PrintString( "\r\n***** USB OTG B Event - Session Started *****\r\n" );
883 }
884 }
885 #endif //#ifdef USB_SUPPORT_OTG
886  
887 //if we are in the detached state
888 if(USBDeviceState == DETACHED_STATE)
889 {
890 //Initialize register to known value
891 U1CON = 0;
892  
893 // Mask all USB interrupts
894 U1IE = 0;
895  
896 //Enable/set things like: pull ups, full/low-speed mode,
897 //set the ping pong mode, and set internal transceiver
898 SetConfigurationOptions();
899  
900 // Enable module & attach to bus
901 while(!U1CONbits.USBEN){U1CONbits.USBEN = 1;}
902  
903 //moved to the attached state
904 USBDeviceState = ATTACHED_STATE;
905  
906 #ifdef USB_SUPPORT_OTG
907 U1OTGCON |= USB_OTG_DPLUS_ENABLE | USB_OTG_ENABLE;
908 #endif
909 }
910 #endif //#if defined(USB_POLLING)
911  
912 if(USBDeviceState == ATTACHED_STATE)
913 {
914 /*
915 * After enabling the USB module, it takes some time for the
916 * voltage on the D+ or D- line to rise high enough to get out
917 * of the SE0 condition. The USB Reset interrupt should not be
918 * unmasked until the SE0 condition is cleared. This helps
919 * prevent the firmware from misinterpreting this unique event
920 * as a USB bus reset from the USB host.
921 */
922  
923 if(!USBSE0Event)
924 {
925 USBClearInterruptRegister(U1IR);// Clear all USB interrupts
926 #if defined(USB_POLLING)
927 U1IE=0; // Mask all USB interrupts
928 #endif
929 USBResetIE = 1; // Unmask RESET interrupt
930 USBIdleIE = 1; // Unmask IDLE interrupt
931 USBDeviceState = POWERED_STATE;
932 }
933 }
934  
935 #ifdef USB_SUPPORT_OTG
936 //If ID Pin Changed State
937 if (USBIDIF && USBIDIE)
938 {
939 //Re-detect & Initialize
940 USBOTGInitialize();
941  
942 USBClearInterruptFlag(USBIDIFReg,USBIDIFBitNum);
943 }
944 #endif
945  
946 /*
947 * Task A: Service USB Activity Interrupt
948 */
949 if(USBActivityIF && USBActivityIE)
950 {
951 USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum);
952 #if defined(USB_SUPPORT_OTG)
953 U1OTGIR = 0x10;
954 #else
955 USBWakeFromSuspend();
956 #endif
957 }
958  
959 /*
960 * Pointless to continue servicing if the device is in suspend mode.
961 */
962 if(USBSuspendControl==1)
963 {
964 USBClearUSBInterrupt();
965 return;
966 }
967  
968 /*
969 * Task B: Service USB Bus Reset Interrupt.
970 * When bus reset is received during suspend, ACTVIF will be set first,
971 * once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted.
972 * This is why URSTIF is checked after ACTVIF.
973 *
974 * The USB reset flag is masked when the USB state is in
975 * DETACHED_STATE or ATTACHED_STATE, and therefore cannot
976 * cause a USB reset event during these two states.
977 */
978 if(USBResetIF && USBResetIE)
979 {
980 USBDeviceInit();
981  
982 //Re-enable the interrupts since the USBDeviceInit() function will
983 // disable them. This will do nothing in a polling setup
984 USBEnableInterrupts();
985  
986 USBDeviceState = DEFAULT_STATE;
987  
988 /********************************************************************
989 Bug Fix: Feb 26, 2007 v2.1 (#F1)
990 *********************************************************************
991 In the original firmware, if an OUT token is sent by the host
992 before a SETUP token is sent, the firmware would respond with an ACK.
993 This is not a correct response, the firmware should have sent a STALL.
994 This is a minor non-compliance since a compliant host should not
995 send an OUT before sending a SETUP token. The fix allows a SETUP
996 transaction to be accepted while stalling OUT transactions.
997 ********************************************************************/
998 BDT[EP0_OUT_EVEN].ADR = ConvertToPhysicalAddress(&SetupPkt);
999 BDT[EP0_OUT_EVEN].CNT = USB_EP0_BUFF_SIZE;
1000 BDT[EP0_OUT_EVEN].STAT.Val &= ~_STAT_MASK;
1001 BDT[EP0_OUT_EVEN].STAT.Val |= _USIE|_DAT0|_DTSEN|_BSTALL;
1002  
1003 #ifdef USB_SUPPORT_OTG
1004 //Disable HNP
1005 USBOTGDisableHnp();
1006  
1007 //Deactivate HNP
1008 USBOTGDeactivateHnp();
1009 #endif
1010  
1011 USBClearInterruptFlag(USBResetIFReg,USBResetIFBitNum);
1012 }
1013  
1014 /*
1015 * Task C: Service other USB interrupts
1016 */
1017 if(USBIdleIF && USBIdleIE)
1018 {
1019 #ifdef USB_SUPPORT_OTG
1020 //If Suspended, Try to switch to Host
1021 USBOTGSelectRole(ROLE_HOST);
1022 #else
1023 USBSuspend();
1024 #endif
1025  
1026 USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum);
1027 }
1028  
1029 if(USBSOFIF && USBSOFIE)
1030 {
1031 USB_SOF_HANDLER(EVENT_SOF,0,1);
1032 USBClearInterruptFlag(USBSOFIFReg,USBSOFIFBitNum);
1033 }
1034  
1035 if(USBStallIF && USBStallIE)
1036 {
1037 USBStallHandler();
1038 }
1039  
1040 if(USBErrorIF && USBErrorIE)
1041 {
1042 USB_ERROR_HANDLER(EVENT_BUS_ERROR,0,1);
1043 USBClearInterruptRegister(U1EIR); // This clears UERRIF
1044  
1045 //On PIC18 or PIC24F, clearing the source of the error will automatically
1046 // clear the interrupt flag. On PIC32 the interrut flag must be manually
1047 // cleared.
1048 #if defined(__C32__)
1049 USBClearInterruptFlag( USBErrorIFReg, USBErrorIFBitNum );
1050 #endif
1051 }
1052  
1053 /*
1054 * Pointless to continue servicing if the host has not sent a bus reset.
1055 * Once bus reset is received, the device transitions into the DEFAULT
1056 * state and is ready for communication.
1057 */
1058 if(USBDeviceState < DEFAULT_STATE)
1059 {
1060 USBClearUSBInterrupt();
1061 return;
1062 }
1063  
1064 /*
1065 * Task D: Servicing USB Transaction Complete Interrupt
1066 */
1067 if(USBTransactionCompleteIE)
1068 {
1069 for(i = 0; i < 4; i++) //Drain or deplete the USAT FIFO entries. If the USB FIFO ever gets full, USB bandwidth
1070 { //utilization can be compromised, and the device won't be able to receive SETUP packets.
1071 if(USBTransactionCompleteIF)
1072 {
1073 USTATcopy = U1STAT;
1074  
1075 USBClearInterruptFlag(USBTransactionCompleteIFReg,USBTransactionCompleteIFBitNum);
1076  
1077 /*
1078 * USBCtrlEPService only services transactions over EP0.
1079 * It ignores all other EP transactions.
1080 */
1081  
1082 if((USTATcopy & ENDPOINT_MASK) == 0)
1083 {
1084 USBCtrlEPService();
1085 }
1086 else
1087 {
1088 USB_TRASFER_COMPLETE_HANDLER(
1089 EVENT_TRANSFER,
1090 (BYTE*)&USTATcopy,
1091 0);
1092 }
1093 }//end if(USBTransactionCompleteIF)
1094 else
1095 break; //USTAT FIFO must be empty.
1096 }//end for()
1097 }//end if(USBTransactionCompleteIE)
1098  
1099 USBClearUSBInterrupt();
1100 }//end of USBDeviceTasks()
1101  
1102 /********************************************************************
1103 * Function: void USBStallHandler(void)
1104 *
1105 * PreCondition: None
1106 *
1107 * Input: None
1108 *
1109 * Output: None
1110 *
1111 * Side Effects:
1112 *
1113 * Overview: This function handles the event of a STALL
1114 * occuring on the bus
1115 *
1116 * Note: None
1117 *******************************************************************/
1118 void USBStallHandler(void)
1119 {
1120 /*
1121 * Does not really have to do anything here,
1122 * even for the control endpoint.
1123 * All BDs of Endpoint 0 are owned by SIE right now,
1124 * but once a Setup Transaction is received, the ownership
1125 * for EP0_OUT will be returned to CPU.
1126 * When the Setup Transaction is serviced, the ownership
1127 * for EP0_IN will then be forced back to CPU by firmware.
1128 */
1129  
1130 /* v2b fix */
1131 if(U1EP0bits.EPSTALL == 1)
1132 {
1133 // UOWN - if 0, owned by CPU, if 1, owned by SIE
1134 if((pBDTEntryEP0OutCurrent->STAT.Val == _USIE) && (pBDTEntryIn[0]->STAT.Val == (_USIE|_BSTALL)))
1135 {
1136 // Set ep0Bo to stall also
1137 pBDTEntryEP0OutCurrent->STAT.Val = _USIE|_DAT0|_DTSEN|_BSTALL;
1138 }//end if
1139 U1EP0bits.EPSTALL = 0; // Clear stall status
1140 }//end if
1141  
1142 USBClearInterruptFlag(USBStallIFReg,USBStallIFBitNum);
1143 }
1144  
1145 /********************************************************************
1146 * Function: void USBSuspend(void)
1147 *
1148 * PreCondition: None
1149 *
1150 * Input: None
1151 *
1152 * Output: None
1153 *
1154 * Side Effects:
1155 *
1156 * Overview: This function handles if the host tries to
1157 * suspend the device
1158 *
1159 * Note: None
1160 *******************************************************************/
1161 void USBSuspend(void)
1162 {
1163 /*
1164 * NOTE: Do not clear UIRbits.ACTVIF here!
1165 * Reason:
1166 * ACTVIF is only generated once an IDLEIF has been generated.
1167 * This is a 1:1 ratio interrupt generation.
1168 * For every IDLEIF, there will be only one ACTVIF regardless of
1169 * the number of subsequent bus transitions.
1170 *
1171 * If the ACTIF is cleared here, a problem could occur when:
1172 * [ IDLE ][bus activity ->
1173 * <--- 3 ms -----> ^
1174 * ^ ACTVIF=1
1175 * IDLEIF=1
1176 * # # # # (#=Program polling flags)
1177 * ^
1178 * This polling loop will see both
1179 * IDLEIF=1 and ACTVIF=1.
1180 * However, the program services IDLEIF first
1181 * because ACTIVIE=0.
1182 * If this routine clears the only ACTIVIF,
1183 * then it can never get out of the suspend
1184 * mode.
1185 */
1186 USBActivityIE = 1; // Enable bus activity interrupt
1187 USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum);
1188  
1189 #if defined(__18CXX)
1190 U1CONbits.SUSPND = 1; // Put USB module in power conserve
1191 // mode, SIE clock inactive
1192 #endif
1193  
1194  
1195 /*
1196 * At this point the PIC can go into sleep,idle, or
1197 * switch to a slower clock, etc. This should be done in the
1198 * USBCBSuspend() if necessary.
1199 */
1200 USB_SUSPEND_HANDLER(EVENT_SUSPEND,0,0);
1201 }
1202  
1203 /********************************************************************
1204 * Function: void USBWakeFromSuspend(void)
1205 *
1206 * PreCondition: None
1207 *
1208 * Input: None
1209 *
1210 * Output: None
1211 *
1212 * Side Effects: None
1213 *
1214 * Overview:
1215 *
1216 * Note: None
1217 *******************************************************************/
1218 void USBWakeFromSuspend(void)
1219 {
1220 /*
1221 * If using clock switching, the place to restore the original
1222 * microcontroller core clock frequency is in the USBCBWakeFromSuspend() callback
1223 */
1224 USB_WAKEUP_FROM_SUSPEND_HANDLER(EVENT_RESUME,0,0);
1225  
1226 #if defined(__18CXX)
1227 //To avoid improperly clocking the USB module, make sure the oscillator
1228 //settings are consistant with USB operation before clearing the SUSPND bit.
1229 //Make sure the correct oscillator settings are selected in the
1230 //"USB_WAKEUP_FROM_SUSPEND_HANDLER(EVENT_RESUME,0,0)" handler.
1231 U1CONbits.SUSPND = 0; // Bring USB module out of power conserve
1232 // mode.
1233 #endif
1234  
1235  
1236 USBActivityIE = 0;
1237  
1238 /********************************************************************
1239 Bug Fix: Feb 26, 2007 v2.1
1240 *********************************************************************
1241 The ACTVIF bit cannot be cleared immediately after the USB module wakes
1242 up from Suspend or while the USB module is suspended. A few clock cycles
1243 are required to synchronize the internal hardware state machine before
1244 the ACTIVIF bit can be cleared by firmware. Clearing the ACTVIF bit
1245 before the internal hardware is synchronized may not have an effect on
1246 the value of ACTVIF. Additonally, if the USB module uses the clock from
1247 the 96 MHz PLL source, then after clearing the SUSPND bit, the USB
1248 module may not be immediately operational while waiting for the 96 MHz
1249 PLL to lock.
1250 ********************************************************************/
1251  
1252 // UIRbits.ACTVIF = 0; // Removed
1253 #if defined(__18CXX)
1254 while(USBActivityIF)
1255 #endif
1256 {
1257 USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum);
1258 } // Added
1259  
1260 }//end USBWakeFromSuspend
1261  
1262 /********************************************************************
1263 * Function: void USBCtrlEPService(void)
1264 *
1265 * PreCondition: USTAT is loaded with a valid endpoint address.
1266 *
1267 * Input: None
1268 *
1269 * Output: None
1270 *
1271 * Side Effects: None
1272 *
1273 * Overview: USBCtrlEPService checks for three transaction
1274 * types that it knows how to service and services
1275 * them:
1276 * 1. EP0 SETUP
1277 * 2. EP0 OUT
1278 * 3. EP0 IN
1279 * It ignores all other types (i.e. EP1, EP2, etc.)
1280 *
1281 * Note: None
1282 *******************************************************************/
1283 void USBCtrlEPService(void)
1284 {
1285 //Check if the last transaction was on EP0 OUT endpoint (of any kind, to either the even or odd buffer if ping pong buffers used)
1286 if((USTATcopy & USTAT_EP0_PP_MASK) == USTAT_EP0_OUT_EVEN)
1287 {
1288 //Point to the EP0 OUT buffer of the buffer that arrived
1289 #if defined(__18CXX)
1290 pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[(USTATcopy & USTAT_EP_MASK)>>1];
1291 #elif defined(__C30__) || defined(__C32__)
1292 pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[(USTATcopy & USTAT_EP_MASK)>>2];
1293 #else
1294 #error "unimplemented"
1295 #endif
1296  
1297 //Set the next out to the current out packet
1298 pBDTEntryEP0OutNext = pBDTEntryEP0OutCurrent;
1299 //Toggle it to the next ping pong buffer (if applicable)
1300 ((BYTE_VAL*)&pBDTEntryEP0OutNext)->Val ^= USB_NEXT_EP0_OUT_PING_PONG;
1301  
1302 //If the current EP0 OUT buffer has a SETUP packet
1303 if(pBDTEntryEP0OutCurrent->STAT.PID == PID_SETUP)
1304 {
1305 //Check if the SETUP transaction data went into the CtrlTrfData buffer.
1306 //If so, need to copy it to the SetupPkt buffer so that it can be
1307 //processed correctly by USBCtrlTrfSetupHandler().
1308 if(pBDTEntryEP0OutCurrent->ADR == ConvertToPhysicalAddress(&CtrlTrfData))
1309 {
1310 unsigned char setup_cnt;
1311  
1312 pBDTEntryEP0OutCurrent->ADR = ConvertToPhysicalAddress(&SetupPkt);
1313 for(setup_cnt = 0; setup_cnt < sizeof(CTRL_TRF_SETUP); setup_cnt++)
1314 {
1315 *(((BYTE*)&SetupPkt)+setup_cnt) = *(((BYTE*)&CtrlTrfData)+setup_cnt);
1316 }//end for
1317 }
1318  
1319 //Handle the control transfer (parse the 8-byte SETUP command and figure out what to do)
1320 USBCtrlTrfSetupHandler();
1321 }
1322 else
1323 {
1324 //Handle the DATA transfer
1325 USBCtrlTrfOutHandler();
1326 }
1327 }
1328 else if((USTATcopy & USTAT_EP0_PP_MASK) == USTAT_EP0_IN)
1329 {
1330 //Otherwise the transmission was and EP0 IN
1331 // so take care of the IN transfer
1332 USBCtrlTrfInHandler();
1333 }
1334  
1335 }//end USBCtrlEPService
1336  
1337 /********************************************************************
1338 * Function: void USBCtrlTrfSetupHandler(void)
1339 *
1340 * PreCondition: SetupPkt buffer is loaded with valid USB Setup Data
1341 *
1342 * Input: None
1343 *
1344 * Output: None
1345 *
1346 * Side Effects: None
1347 *
1348 * Overview: This routine is a task dispatcher and has 3 stages.
1349 * 1. It initializes the control transfer state machine.
1350 * 2. It calls on each of the module that may know how to
1351 * service the Setup Request from the host.
1352 * Module Example: USBD, HID, CDC, MSD, ...
1353 * A callback function, USBCBCheckOtherReq(),
1354 * is required to call other module handlers.
1355 * 3. Once each of the modules has had a chance to check if
1356 * it is responsible for servicing the request, stage 3
1357 * then checks direction of the transfer to determine how
1358 * to prepare EP0 for the control transfer.
1359 * Refer to USBCtrlEPServiceComplete() for more details.
1360 *
1361 * Note: Microchip USB Firmware has three different states for
1362 * the control transfer state machine:
1363 * 1. WAIT_SETUP
1364 * 2. CTRL_TRF_TX (device sends data to host through IN transactions)
1365 * 3. CTRL_TRF_RX (device receives data from host through OUT transactions)
1366 * Refer to firmware manual to find out how one state
1367 * is transitioned to another.
1368 *
1369 * A Control Transfer is composed of many USB transactions.
1370 * When transferring data over multiple transactions,
1371 * it is important to keep track of data source, data
1372 * destination, and data count. These three parameters are
1373 * stored in pSrc,pDst, and wCount. A flag is used to
1374 * note if the data source is from ROM or RAM.
1375 *
1376 *******************************************************************/
1377 void USBCtrlTrfSetupHandler(void)
1378 {
1379 //if the SIE currently owns the buffer
1380 if(pBDTEntryIn[0]->STAT.UOWN != 0)
1381 {
1382 //give control back to the CPU
1383 // Compensate for after a STALL
1384 pBDTEntryIn[0]->STAT.Val = _UCPU;
1385 }
1386  
1387 //Keep track of if a short packet has been sent yet or not
1388 shortPacketStatus = SHORT_PKT_NOT_USED;
1389  
1390 /* Stage 1 */
1391 controlTransferState = WAIT_SETUP;
1392  
1393 inPipes[0].wCount.Val = 0;
1394 inPipes[0].info.Val = 0;
1395  
1396 /* Stage 2 */
1397 USBCheckStdRequest();
1398 USB_DISABLE_NONSTANDARD_EP0_REQUEST_HANDLER(EVENT_EP0_REQUEST,0,0);
1399  
1400 /* Stage 3 */
1401 USBCtrlEPServiceComplete();
1402  
1403 }//end USBCtrlTrfSetupHandler
1404 /******************************************************************************
1405 * Function: void USBCtrlTrfOutHandler(void)
1406 *
1407 * PreCondition: None
1408 *
1409 * Input: None
1410 *
1411 * Output: None
1412 *
1413 * Side Effects: None
1414 *
1415 * Overview: This routine handles an OUT transaction according to
1416 * which control transfer state is currently active.
1417 *
1418 * Note: Note that if the the control transfer was from
1419 * host to device, the session owner should be notified
1420 * at the end of each OUT transaction to service the
1421 * received data.
1422 *
1423 *****************************************************************************/
1424 void USBCtrlTrfOutHandler(void)
1425 {
1426 if(controlTransferState == CTRL_TRF_RX)
1427 {
1428 USBCtrlTrfRxService(); //Copies the newly received data into the appropriate buffer and configures EP0 OUT for next transaction.
1429 }
1430 else //In this case the last OUT transaction must have been a status stage of a CTRL_TRF_TX
1431 {
1432 //Prepare EP0 OUT for the next SETUP transaction, however, it may have
1433 //already been prepared if ping-pong buffering was enabled on EP0 OUT,
1434 //and the last control transfer was of direction: device to host, see
1435 //USBCtrlEPServiceComplete(). If it was already prepared, do not want
1436 //to do anything to the BDT.
1437 USBPrepareForNextSetupTrf();
1438 if(BothEP0OutUOWNsSet == FALSE)
1439 {
1440 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
1441 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt);
1442 pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|_DTSEN|_BSTALL;
1443 }
1444 else
1445 {
1446 BothEP0OutUOWNsSet = FALSE;
1447 }
1448 }
1449 }
1450  
1451 /******************************************************************************
1452 * Function: void USBCtrlTrfInHandler(void)
1453 *
1454 * PreCondition: None
1455 *
1456 * Input: None
1457 *
1458 * Output: None
1459 *
1460 * Side Effects: None
1461 *
1462 * Overview: This routine handles an IN transaction according to
1463 * which control transfer state is currently active.
1464 *
1465 * Note: A Set Address Request must not change the acutal address
1466 * of the device until the completion of the control
1467 * transfer. The end of the control transfer for Set Address
1468 * Request is an IN transaction. Therefore it is necessary
1469 * to service this unique situation when the condition is
1470 * right. Macro mUSBCheckAdrPendingState is defined in
1471 * usb9.h and its function is to specifically service this
1472 * event.
1473 *****************************************************************************/
1474 void USBCtrlTrfInHandler(void)
1475 {
1476 BYTE lastDTS;
1477  
1478 lastDTS = pBDTEntryIn[0]->STAT.DTS;
1479  
1480 //switch to the next ping pong buffer
1481 ((BYTE_VAL*)&pBDTEntryIn[0])->Val ^= USB_NEXT_EP0_IN_PING_PONG;
1482  
1483 //mUSBCheckAdrPendingState(); // Must check if in ADR_PENDING_STATE
1484 if(USBDeviceState == ADR_PENDING_STATE)
1485 {
1486 U1ADDR = SetupPkt.bDevADR.Val;
1487 if(U1ADDR > 0)
1488 {
1489 USBDeviceState=ADDRESS_STATE;
1490 }
1491 else
1492 {
1493 USBDeviceState=DEFAULT_STATE;
1494 }
1495 }//end if
1496  
1497  
1498 if(controlTransferState == CTRL_TRF_TX)
1499 {
1500 pBDTEntryIn[0]->ADR = ConvertToPhysicalAddress(CtrlTrfData);
1501 USBCtrlTrfTxService();
1502  
1503 /* v2b fix */
1504 if(shortPacketStatus == SHORT_PKT_SENT)
1505 {
1506 // If a short packet has been sent, don't want to send any more,
1507 // stall next time if host is still trying to read.
1508 pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL;
1509 }
1510 else
1511 {
1512 if(lastDTS == 0)
1513 {
1514 pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|_DTSEN;
1515 }
1516 else
1517 {
1518 pBDTEntryIn[0]->STAT.Val = _USIE|_DAT0|_DTSEN;
1519 }
1520 }//end if(...)else
1521 }
1522 else // must have been a CTRL_TRF_RX status stage IN packet
1523 {
1524 USBPrepareForNextSetupTrf();
1525 }
1526  
1527 }
1528  
1529 /********************************************************************
1530 * Function: void USBPrepareForNextSetupTrf(void)
1531 *
1532 * PreCondition: None
1533 *
1534 * Input: None
1535 *
1536 * Output: None
1537 *
1538 * Side Effects: None
1539 *
1540 * Overview: The routine forces EP0 OUT to be ready for a new
1541 * Setup transaction, and forces EP0 IN to be owned
1542 * by CPU.
1543 *
1544 * Note: None
1545 *******************************************************************/
1546 void USBPrepareForNextSetupTrf(void)
1547 {
1548 controlTransferState = WAIT_SETUP;
1549  
1550 //Don't need to do anything to EP0 OUT BDT here, as EP0 OUT next is
1551 //already configured and ready to receive a SETUP transaction. This is
1552 //done in the USBCtrlTrfOutHandler() or USBCtrlEPServiceComplete() function,
1553 //depending upon the type of the last control transfer.
1554  
1555 pBDTEntryIn[0]->STAT.Val = _UCPU;
1556 {
1557 BDT_ENTRY* p;
1558  
1559 p = (BDT_ENTRY*)(((unsigned int)pBDTEntryIn[0])^USB_NEXT_EP0_IN_PING_PONG);
1560 p->STAT.Val = _UCPU;
1561 }
1562  
1563 //if someone is still expecting data from the control transfer
1564 // then make sure to terminate that request and let them know that
1565 // they are done
1566 if(outPipes[0].info.bits.busy == 1)
1567 {
1568 if(outPipes[0].pFunc != NULL)
1569 {
1570 outPipes[0].pFunc();
1571 }
1572 outPipes[0].info.bits.busy = 0;
1573 }
1574 }//end USBPrepareForNextSetupTrf
1575  
1576 /********************************************************************
1577 * Function: void USBCheckStdRequest(void)
1578 *
1579 * PreCondition: None
1580 *
1581 * Input: None
1582 *
1583 * Output: None
1584 *
1585 * Side Effects: None
1586 *
1587 * Overview: This routine checks the setup data packet to see
1588 * if it knows how to handle it
1589 *
1590 * Note: None
1591 *******************************************************************/
1592 void USBCheckStdRequest(void)
1593 {
1594 if(SetupPkt.RequestType != USB_SETUP_TYPE_STANDARD_BITFIELD) return;
1595  
1596 switch(SetupPkt.bRequest)
1597 {
1598 case USB_REQUEST_SET_ADDRESS:
1599 inPipes[0].info.bits.busy = 1; // This will generate a zero length packet
1600 USBDeviceState = ADR_PENDING_STATE; // Update state only
1601 /* See USBCtrlTrfInHandler() for the next step */
1602 break;
1603 case USB_REQUEST_GET_DESCRIPTOR:
1604 USBStdGetDscHandler();
1605 break;
1606 case USB_REQUEST_SET_CONFIGURATION:
1607 USBStdSetCfgHandler();
1608 break;
1609 case USB_REQUEST_GET_CONFIGURATION:
1610 inPipes[0].pSrc.bRam = (BYTE*)&USBActiveConfiguration; // Set Source
1611 inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
1612 inPipes[0].wCount.v[0] = 1; // Set data count
1613 inPipes[0].info.bits.busy = 1;
1614 break;
1615 case USB_REQUEST_GET_STATUS:
1616 USBStdGetStatusHandler();
1617 break;
1618 case USB_REQUEST_CLEAR_FEATURE:
1619 case USB_REQUEST_SET_FEATURE:
1620 USBStdFeatureReqHandler();
1621 break;
1622 case USB_REQUEST_GET_INTERFACE:
1623 inPipes[0].pSrc.bRam = (BYTE*)&USBAlternateInterface[SetupPkt.bIntfID]; // Set source
1624 inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
1625 inPipes[0].wCount.v[0] = 1; // Set data count
1626 inPipes[0].info.bits.busy = 1;
1627 break;
1628 case USB_REQUEST_SET_INTERFACE:
1629 inPipes[0].info.bits.busy = 1;
1630 USBAlternateInterface[SetupPkt.bIntfID] = SetupPkt.bAltID;
1631 break;
1632 case USB_REQUEST_SET_DESCRIPTOR:
1633 USB_SET_DESCRIPTOR_HANDLER(EVENT_SET_DESCRIPTOR,0,0);
1634 break;
1635 case USB_REQUEST_SYNCH_FRAME:
1636 default:
1637 break;
1638 }//end switch
1639 }//end USBCheckStdRequest
1640  
1641 /********************************************************************
1642 * Function: void USBStdFeatureReqHandler(void)
1643 *
1644 * PreCondition: None
1645 *
1646 * Input: None
1647 *
1648 * Output: None
1649 *
1650 * Side Effects: None
1651 *
1652 * Overview: This routine handles the standard SET & CLEAR
1653 * FEATURES requests
1654 *
1655 * Note: None
1656 *******************************************************************/
1657 void USBStdFeatureReqHandler(void)
1658 {
1659 BDT_ENTRY *p;
1660 #if defined(__C32__)
1661 DWORD* pUEP;
1662 #else
1663 unsigned char* pUEP;
1664 #endif
1665 #ifdef USB_SUPPORT_OTG
1666 if ((SetupPkt.bFeature == OTG_FEATURE_B_HNP_ENABLE)&&
1667 (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD))
1668 {
1669 inPipes[0].info.bits.busy = 1;
1670 if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE)
1671 USBOTGEnableHnp();
1672 else
1673 USBOTGDisableHnp();
1674 }
1675  
1676 if ((SetupPkt.bFeature == OTG_FEATURE_A_HNP_SUPPORT)&&
1677 (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD))
1678 {
1679 inPipes[0].info.bits.busy = 1;
1680 if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE)
1681 USBOTGEnableSupportHnp();
1682 else
1683 USBOTGDisableSupportHnp();
1684 }
1685  
1686  
1687 if ((SetupPkt.bFeature == OTG_FEATURE_A_ALT_HNP_SUPPORT)&&
1688 (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD))
1689 {
1690 inPipes[0].info.bits.busy = 1;
1691 if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE)
1692 USBOTGEnableAltHnp();
1693 else
1694 USBOTGDisableAltHnp();
1695 }
1696 #endif
1697 if((SetupPkt.bFeature == USB_FEATURE_DEVICE_REMOTE_WAKEUP)&&
1698 (SetupPkt.Recipient == USB_SETUP_RECIPIENT_DEVICE_BITFIELD))
1699 {
1700 inPipes[0].info.bits.busy = 1;
1701 if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE)
1702 RemoteWakeup = TRUE;
1703 else
1704 RemoteWakeup = FALSE;
1705 }//end if
1706  
1707 if((SetupPkt.bFeature == USB_FEATURE_ENDPOINT_HALT)&&
1708 (SetupPkt.Recipient == USB_SETUP_RECIPIENT_ENDPOINT_BITFIELD)&&
1709 (SetupPkt.EPNum != 0))
1710 {
1711 inPipes[0].info.bits.busy = 1;
1712 /* Must do address calculation here */
1713  
1714 if(SetupPkt.EPDir == 0)
1715 {
1716 p = (BDT_ENTRY*)pBDTEntryOut[SetupPkt.EPNum];
1717 }
1718 else
1719 {
1720 p = (BDT_ENTRY*)pBDTEntryIn[SetupPkt.EPNum];
1721 }
1722  
1723 //if it was a SET_FEATURE request
1724 if(SetupPkt.bRequest == USB_REQUEST_SET_FEATURE)
1725 {
1726 //Then STALL the endpoint
1727 p->STAT.Val = _USIE|_BSTALL;
1728 }
1729 else
1730 {
1731 //If it was not a SET_FEATURE
1732 //point to the appropriate UEP register
1733 #if defined(__C32__)
1734 pUEP = (DWORD*)(&U1EP0);
1735 pUEP += (SetupPkt.EPNum*4);
1736 #else
1737 pUEP = (unsigned char*)(&U1EP0+SetupPkt.EPNum);
1738 #endif
1739  
1740 //Clear the STALL bit in the UEP register
1741 *pUEP &= ~UEP_STALL;
1742  
1743 if(SetupPkt.EPDir == 1) // IN
1744 {
1745 //If the endpoint is an IN endpoint then we
1746 // need to return it to the CPU and reset the
1747 // DTS bit so that the next transfer is correct
1748 #if (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG)
1749 p->STAT.Val = _UCPU|_DAT0;
1750 //toggle over the to the next buffer
1751 ((BYTE_VAL*)&p)->Val ^= USB_NEXT_PING_PONG;
1752 p->STAT.Val = _UCPU|_DAT1;
1753 #else
1754 p->STAT.Val = _UCPU|_DAT1;
1755 #endif
1756 }
1757 else
1758 {
1759 //If the endpoint was an OUT endpoint then we
1760 // need to give control of the endpoint back to
1761 // the SIE so that the function driver can
1762 // receive the data as they expected. Also need
1763 // to set the DTS bit so the next packet will be
1764 // correct
1765 #if (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG)
1766 p->STAT.Val = _USIE|_DAT0|_DTSEN;
1767 //toggle over the to the next buffer
1768 ((BYTE_VAL*)&p)->Val ^= USB_NEXT_PING_PONG;
1769 p->STAT.Val = _USIE|_DAT1|_DTSEN;
1770 #else
1771 p->STAT.Val = _USIE|_DAT1|_DTSEN;
1772 #endif
1773  
1774 }
1775 }//end if
1776  
1777 }//end if
1778 }//end USBStdFeatureReqHandler
1779  
1780 /********************************************************************
1781 * Function: void USBStdGetDscHandler(void)
1782 *
1783 * PreCondition: None
1784 *
1785 * Input: None
1786 *
1787 * Output: None
1788 *
1789 * Side Effects: None
1790 *
1791 * Overview: This routine handles the standard GET_DESCRIPTOR
1792 * request.
1793 *
1794 * Note: None
1795 *******************************************************************/
1796 void USBStdGetDscHandler(void)
1797 {
1798 if(SetupPkt.bmRequestType == 0x80)
1799 {
1800 inPipes[0].info.Val = USB_EP0_ROM | USB_EP0_BUSY | USB_EP0_INCLUDE_ZERO;
1801  
1802 switch(SetupPkt.bDescriptorType)
1803 {
1804 case USB_DESCRIPTOR_DEVICE:
1805 #if !defined(USB_USER_DEVICE_DESCRIPTOR)
1806 inPipes[0].pSrc.bRom = (ROM BYTE*)&device_dsc;
1807 #else
1808 inPipes[0].pSrc.bRom = (ROM BYTE*)USB_USER_DEVICE_DESCRIPTOR;
1809 #endif
1810 inPipes[0].wCount.Val = sizeof(device_dsc);
1811 break;
1812 case USB_DESCRIPTOR_CONFIGURATION:
1813 #if !defined(USB_USER_CONFIG_DESCRIPTOR)
1814 inPipes[0].pSrc.bRom = *(USB_CD_Ptr+SetupPkt.bDscIndex);
1815 #else
1816 inPipes[0].pSrc.bRom = *(USB_USER_CONFIG_DESCRIPTOR+SetupPkt.bDscIndex);
1817 #endif
1818  
1819 //This must be loaded using byte addressing. The source pointer
1820 // may not be word aligned for the 16 or 32 bit machines resulting
1821 // in an address error on the dereference.
1822 inPipes[0].wCount.byte.LB = *(inPipes[0].pSrc.bRom+2);
1823 inPipes[0].wCount.byte.HB = *(inPipes[0].pSrc.bRom+3);
1824 break;
1825 case USB_DESCRIPTOR_STRING:
1826 //USB_NUM_STRING_DESCRIPTORS was introduced as optional in release v2.3. In v2.4 and
1827 // later it is now manditory. This should be defined in usb_config.h and should
1828 // indicate the number of string descriptors.
1829 if(SetupPkt.bDscIndex<USB_NUM_STRING_DESCRIPTORS)
1830 {
1831 //Get a pointer to the String descriptor requested
1832 inPipes[0].pSrc.bRom = *(USB_SD_Ptr+SetupPkt.bDscIndex);
1833 // Set data count
1834 inPipes[0].wCount.Val = *inPipes[0].pSrc.bRom;
1835 }
1836 else
1837 {
1838 inPipes[0].info.Val = 0;
1839 }
1840 break;
1841 default:
1842 inPipes[0].info.Val = 0;
1843 break;
1844 }//end switch
1845 }//end if
1846 }//end USBStdGetDscHandler
1847  
1848 /********************************************************************
1849 * Function: void USBStdGetStatusHandler(void)
1850 *
1851 * PreCondition: None
1852 *
1853 * Input: None
1854 *
1855 * Output: None
1856 *
1857 * Side Effects: None
1858 *
1859 * Overview: This routine handles the standard GET_STATUS request
1860 *
1861 * Note: None
1862 *******************************************************************/
1863 void USBStdGetStatusHandler(void)
1864 {
1865 CtrlTrfData[0] = 0; // Initialize content
1866 CtrlTrfData[1] = 0;
1867  
1868 switch(SetupPkt.Recipient)
1869 {
1870 case USB_SETUP_RECIPIENT_DEVICE_BITFIELD:
1871 inPipes[0].info.bits.busy = 1;
1872 /*
1873 * [0]: bit0: Self-Powered Status [0] Bus-Powered [1] Self-Powered
1874 * bit1: RemoteWakeup [0] Disabled [1] Enabled
1875 */
1876 if(self_power == 1) // self_power is defined in HardwareProfile.h
1877 {
1878 CtrlTrfData[0]|=0x01;
1879 }
1880  
1881 if(RemoteWakeup == TRUE)
1882 {
1883 CtrlTrfData[0]|=0x02;
1884 }
1885 break;
1886 case USB_SETUP_RECIPIENT_INTERFACE_BITFIELD:
1887 inPipes[0].info.bits.busy = 1; // No data to update
1888 break;
1889 case USB_SETUP_RECIPIENT_ENDPOINT_BITFIELD:
1890 inPipes[0].info.bits.busy = 1;
1891 /*
1892 * [0]: bit0: Halt Status [0] Not Halted [1] Halted
1893 */
1894 {
1895 BDT_ENTRY *p;
1896  
1897 if(SetupPkt.EPDir == 0)
1898 {
1899 p = (BDT_ENTRY*)pBDTEntryOut[SetupPkt.EPNum];
1900 }
1901 else
1902 {
1903 p = (BDT_ENTRY*)pBDTEntryIn[SetupPkt.EPNum];
1904 }
1905  
1906 if(p->STAT.Val & _BSTALL) // Use _BSTALL as a bit mask
1907 CtrlTrfData[0]=0x01; // Set bit0
1908 break;
1909 }
1910 }//end switch
1911  
1912 if(inPipes[0].info.bits.busy == 1)
1913 {
1914 inPipes[0].pSrc.bRam = (BYTE*)&CtrlTrfData; // Set Source
1915 inPipes[0].info.bits.ctrl_trf_mem = USB_EP0_RAM; // Set memory type
1916 inPipes[0].wCount.v[0] = 2; // Set data count
1917 }//end if(...)
1918 }//end USBStdGetStatusHandler
1919  
1920 /******************************************************************************
1921 * Function: void USBCtrlEPServiceComplete(void)
1922 *
1923 * PreCondition: None
1924 *
1925 * Input: None
1926 *
1927 * Output: None
1928 *
1929 * Side Effects: None
1930 *
1931 * Overview: This routine wrap up the remaining tasks in servicing
1932 * a Setup Request. Its main task is to set the endpoint
1933 * controls appropriately for a given situation. See code
1934 * below.
1935 * There are three main scenarios:
1936 * a) There was no handler for the Request, in this case
1937 * a STALL should be sent out.
1938 * b) The host has requested a read control transfer,
1939 * endpoints are required to be setup in a specific way.
1940 * c) The host has requested a write control transfer, or
1941 * a control data stage is not required, endpoints are
1942 * required to be setup in a specific way.
1943 *
1944 * Packet processing is resumed by clearing PKTDIS bit.
1945 *
1946 * Note: None
1947 *****************************************************************************/
1948 void USBCtrlEPServiceComplete(void)
1949 {
1950 /*
1951 * PKTDIS bit is set when a Setup Transaction is received.
1952 * Clear to resume packet processing.
1953 */
1954 USBPacketDisable = 0;
1955  
1956 if(inPipes[0].info.bits.busy == 0)
1957 {
1958 if(outPipes[0].info.bits.busy == 1)
1959 {
1960 controlTransferState = CTRL_TRF_RX;
1961 /*
1962 * Control Write:
1963 * <SETUP[0]><OUT[1]><OUT[0]>...<IN[1]> | <SETUP[0]>
1964 *
1965 * 1. Prepare IN EP to respond to early termination
1966 *
1967 * This is the same as a Zero Length Packet Response
1968 * for control transfer without a data stage
1969 */
1970 pBDTEntryIn[0]->CNT = 0;
1971 pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|_DTSEN;
1972  
1973 /*
1974 * 2. Prepare OUT EP to receive data.
1975 */
1976 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
1977 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&CtrlTrfData);
1978 pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT1|_DTSEN;
1979 }
1980 else
1981 {
1982 /*
1983 * If no one knows how to service this request then stall.
1984 * Must also prepare EP0 to receive the next SETUP transaction.
1985 */
1986 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
1987 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt);
1988 pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|_DTSEN|_BSTALL;
1989 pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL;
1990 }
1991 }
1992 else // A module has claimed ownership of the control transfer session.
1993 {
1994 if(outPipes[0].info.bits.busy == 0)
1995 {
1996 if(SetupPkt.DataDir == USB_SETUP_DEVICE_TO_HOST_BITFIELD)
1997 {
1998 if(SetupPkt.wLength < inPipes[0].wCount.Val)
1999 {
2000 inPipes[0].wCount.Val = SetupPkt.wLength;
2001 }
2002 USBCtrlTrfTxService();
2003 controlTransferState = CTRL_TRF_TX;
2004 /*
2005 * Control Read:
2006 * <SETUP[0]><IN[1]><IN[0]>...<OUT[1]> | <SETUP[0]>
2007 * 1. Prepare OUT EP to respond to early termination
2008 *
2009 * NOTE:
2010 * If something went wrong during the control transfer,
2011 * the last status stage may not be sent by the host.
2012 * When this happens, two different things could happen
2013 * depending on the host.
2014 * a) The host could send out a RESET.
2015 * b) The host could send out a new SETUP transaction
2016 * without sending a RESET first.
2017 * To properly handle case (b), the OUT EP must be setup
2018 * to receive either a zero length OUT transaction, or a
2019 * new SETUP transaction.
2020 *
2021 * Furthermore, the Cnt byte should be set to prepare for
2022 * the SETUP data (8-byte or more), and the buffer address
2023 * should be pointed to SetupPkt.
2024 */
2025 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
2026 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt);
2027 pBDTEntryEP0OutNext->STAT.Val = _USIE; // Note: DTSEN is 0
2028 BothEP0OutUOWNsSet = FALSE; //Indicator flag used in USBCtrlTrfOutHandler()
2029  
2030 #if (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY) || (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG)
2031 pBDTEntryEP0OutCurrent->CNT = USB_EP0_BUFF_SIZE;
2032 pBDTEntryEP0OutCurrent->ADR = ConvertToPhysicalAddress(&SetupPkt);
2033 pBDTEntryEP0OutCurrent->STAT.Val = _USIE|_BSTALL; //Prepare endpoint to accept a SETUP transaction
2034 BothEP0OutUOWNsSet = TRUE; //Indicator flag used in USBCtrlTrfOutHandler()
2035 #endif
2036  
2037 /*
2038 * 2. Prepare IN EP to transfer data, Cnt should have
2039 * been initialized by responsible request owner.
2040 */
2041 pBDTEntryIn[0]->ADR = ConvertToPhysicalAddress(&CtrlTrfData);
2042 pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|_DTSEN;
2043 }
2044 else // (SetupPkt.DataDir == USB_SETUP_DIRECTION_HOST_TO_DEVICE)
2045 {
2046 controlTransferState = CTRL_TRF_RX;
2047 /*
2048 * Control Write:
2049 * <SETUP[0]><OUT[1]><OUT[0]>...<IN[1]> | <SETUP[0]>
2050 *
2051 * 1. Prepare IN EP to respond to early termination
2052 *
2053 * This is the same as a Zero Length Packet Response
2054 * for control transfer without a data stage
2055 */
2056 pBDTEntryIn[0]->CNT = 0;
2057 pBDTEntryIn[0]->STAT.Val = _USIE|_DAT1|_DTSEN;
2058  
2059 /*
2060 * 2. Prepare OUT EP to receive data.
2061 */
2062 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
2063 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&CtrlTrfData);
2064 pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT1|_DTSEN;
2065 }
2066 }
2067 }//end if(ctrl_trf_session_owner == MUID_NULL)
2068  
2069 }//end USBCtrlEPServiceComplete
2070  
2071  
2072 /******************************************************************************
2073 * Function: void USBCtrlTrfTxService(void)
2074 *
2075 * PreCondition: pSrc, wCount, and usb_stat.ctrl_trf_mem are setup properly.
2076 *
2077 * Input: None
2078 *
2079 * Output: None
2080 *
2081 * Side Effects: None
2082 *
2083 * Overview: This routine is used for device to host control transfers
2084 * (IN transactions). This function takes care of managing a
2085 * transfer over multiple USB transactions.
2086 * This routine should be called from only two places.
2087 * One from USBCtrlEPServiceComplete() and one from
2088 * USBCtrlTrfInHandler().
2089 *
2090 * Note: This routine works with isochronous endpoint larger than
2091 * 256 bytes and is shown here as an example of how to deal
2092 * with BC9 and BC8. In reality, a control endpoint can never
2093 * be larger than 64 bytes.
2094 *****************************************************************************/
2095 void USBCtrlTrfTxService(void)
2096 {
2097 WORD_VAL byteToSend;
2098  
2099 /*
2100 * First, have to figure out how many byte of data to send.
2101 */
2102 if(inPipes[0].wCount.Val < USB_EP0_BUFF_SIZE)
2103 {
2104 byteToSend.Val = inPipes[0].wCount.Val;
2105  
2106 /* v2b fix */
2107 if(shortPacketStatus == SHORT_PKT_NOT_USED)
2108 {
2109 shortPacketStatus = SHORT_PKT_PENDING;
2110 }
2111 else if(shortPacketStatus == SHORT_PKT_PENDING)
2112 {
2113 shortPacketStatus = SHORT_PKT_SENT;
2114 }//end if
2115 /* end v2b fix for this section */
2116 }
2117 else
2118 {
2119 byteToSend.Val = USB_EP0_BUFF_SIZE;
2120 }
2121  
2122 /*
2123 * Next, load the number of bytes to send to BC9..0 in buffer descriptor
2124 */
2125 #if defined(__18CXX)
2126 pBDTEntryIn[0]->STAT.BC9 = 0;
2127 pBDTEntryIn[0]->STAT.BC8 = 0;
2128 #endif
2129  
2130 #if defined(__18CXX) || defined(__C30__)
2131 pBDTEntryIn[0]->STAT.Val |= byteToSend.byte.HB;
2132 pBDTEntryIn[0]->CNT = byteToSend.byte.LB;
2133 #elif defined(__C32__)
2134 pBDTEntryIn[0]->CNT = byteToSend.Val;
2135 #else
2136 #error "Not defined for this compiler"
2137 #endif
2138  
2139 /*
2140 * Subtract the number of bytes just about to be sent from the total.
2141 */
2142 inPipes[0].wCount.Val = inPipes[0].wCount.Val - byteToSend.Val;
2143  
2144 pDst = (USB_VOLATILE BYTE*)CtrlTrfData; // Set destination pointer
2145  
2146 if(inPipes[0].info.bits.ctrl_trf_mem == USB_EP0_ROM) // Determine type of memory source
2147 {
2148 while(byteToSend.Val)
2149 {
2150 *pDst++ = *inPipes[0].pSrc.bRom++;
2151 byteToSend.Val--;
2152 }//end while(byte_to_send.Val)
2153 }
2154 else // RAM
2155 {
2156 while(byteToSend.Val)
2157 {
2158 *pDst++ = *inPipes[0].pSrc.bRam++;
2159 byteToSend.Val--;
2160 }//end while(byte_to_send.Val)
2161 }//end if(usb_stat.ctrl_trf_mem == _ROM)
2162  
2163 }//end USBCtrlTrfTxService
2164  
2165 /******************************************************************************
2166 * Function: void USBCtrlTrfRxService(void)
2167 *
2168 * PreCondition: pDst and wCount are setup properly.
2169 * pSrc is always &CtrlTrfData
2170 * usb_stat.ctrl_trf_mem is always USB_EP0_RAM.
2171 * wCount should be set to 0 at the start of each control
2172 * transfer.
2173 *
2174 * Input: None
2175 *
2176 * Output: None
2177 *
2178 * Side Effects: None
2179 *
2180 * Overview: This routine is used for host to device control transfers
2181 * (uses OUT transactions). This function receives the data that arrives
2182 * on EP0 OUT, and copies it into the appropriate outPipes[0].pDst.bRam
2183 * buffer. Once the host has sent all the data it was intending
2184 * to send, this function will call the appropriate outPipes[0].pFunc()
2185 * handler (unless it is NULL), so that it can be used by the
2186 * intended target firmware.
2187 *
2188 * Note: None
2189 *****************************************************************************/
2190 void USBCtrlTrfRxService(void)
2191 {
2192 BYTE byteToRead;
2193 BYTE i;
2194  
2195 byteToRead = pBDTEntryEP0OutCurrent->CNT;
2196  
2197 /*
2198 * Accumulate total number of bytes read
2199 */
2200 if(byteToRead > outPipes[0].wCount.Val)
2201 {
2202 byteToRead = outPipes[0].wCount.Val;
2203 }
2204  
2205 outPipes[0].wCount.Val = outPipes[0].wCount.Val - byteToRead;
2206  
2207 for(i=0;i<byteToRead;i++)
2208 {
2209 *outPipes[0].pDst.bRam++ = CtrlTrfData[i];
2210 }//end while(byteToRead.Val)
2211  
2212 //If there is more data to read
2213 if(outPipes[0].wCount.Val > 0)
2214 {
2215 /*
2216 * Don't have to worry about overwriting _KEEP bit
2217 * because if _KEEP was set, TRNIF would not have been
2218 * generated in the first place.
2219 */
2220 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
2221 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&CtrlTrfData);
2222 if(pBDTEntryEP0OutCurrent->STAT.DTS == 0)
2223 {
2224 pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT1|_DTSEN;
2225 }
2226 else
2227 {
2228 pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|_DTSEN;
2229 }
2230 }
2231 else
2232 {
2233 //We have received all OUT packets that we were expecting to
2234 //receive for the control transfer.
2235 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
2236 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt);
2237 //Configure EP0 OUT to receive the next SETUP transaction for any future
2238 //control transfers. However, set BSTALL in case the host tries to send
2239 //more data than it claims it was going to send.
2240 pBDTEntryEP0OutNext->STAT.Val = _USIE|_BSTALL;
2241  
2242 //All data bytes for the host to device control write have now been
2243 //received successfully.
2244 //Go ahead and call the user specified callback function, to use/consume
2245 //the control transfer data (ex: if the "void (*function)" parameter
2246 //was non-NULL when USBEP0Receive() was called).
2247 if(outPipes[0].pFunc != NULL)
2248 {
2249 outPipes[0].pFunc();
2250 }
2251 outPipes[0].info.bits.busy = 0;
2252 }
2253 }//end USBCtrlTrfRxService
2254  
2255 /********************************************************************
2256 * Function: void USBStdSetCfgHandler(void)
2257 *
2258 * PreCondition: None
2259 *
2260 * Input: None
2261 *
2262 * Output: None
2263 *
2264 * Side Effects: None
2265 *
2266 * Overview: This routine first disables all endpoints by
2267 * clearing UEP registers. It then configures
2268 * (initializes) endpoints by calling the callback
2269 * function USBCBInitEP().
2270 *
2271 * Note: None
2272 *******************************************************************/
2273 void USBStdSetCfgHandler(void)
2274 {
2275 BYTE i;
2276  
2277 // This will generate a zero length packet
2278 inPipes[0].info.bits.busy = 1;
2279  
2280 //Clear all of the endpoint control registers
2281 DisableNonZeroEndpoints(USB_MAX_EP_NUMBER);
2282  
2283 //Clear all of the BDT entries
2284 for(i=0;i<(sizeof(BDT)/sizeof(BDT_ENTRY));i++)
2285 {
2286 BDT[i].Val = 0x00;
2287 }
2288  
2289 // Assert reset request to all of the Ping Pong buffer pointers
2290 USBPingPongBufferReset = 1;
2291  
2292 //clear the alternate interface settings
2293 memset((void*)&USBAlternateInterface,0x00,USB_MAX_NUM_INT);
2294  
2295 //Stop trying to reset ping pong buffer pointers
2296 USBPingPongBufferReset = 0;
2297  
2298 pBDTEntryIn[0] = (volatile BDT_ENTRY*)&BDT[EP0_IN_EVEN];
2299  
2300 //Set the next out to the current out packet
2301 pBDTEntryEP0OutCurrent = (volatile BDT_ENTRY*)&BDT[EP0_OUT_EVEN];
2302 pBDTEntryEP0OutNext = pBDTEntryEP0OutCurrent;
2303  
2304 //set the current configuration
2305 USBActiveConfiguration = SetupPkt.bConfigurationValue;
2306  
2307 //if the configuration value == 0
2308 if(USBActiveConfiguration == 0)
2309 {
2310 //Go back to the addressed state
2311 USBDeviceState = ADDRESS_STATE;
2312 }
2313 else
2314 {
2315 //initialize the required endpoints
2316 USB_SET_CONFIGURATION_HANDLER(EVENT_CONFIGURED,(void*)&USBActiveConfiguration,1);
2317  
2318 //Otherwise go to the configured state. Update the state variable last,
2319 //after performing all of the set configuration related initialization
2320 //tasks.
2321 USBDeviceState = CONFIGURED_STATE;
2322 }//end if(SetupPkt.bConfigurationValue == 0)
2323 }//end USBStdSetCfgHandler
2324  
2325 /********************************************************************
2326 * Function: void USBConfigureEndpoint(BYTE EPNum, BYTE direction)
2327 *
2328 * PreCondition: None
2329 *
2330 * Input: BYTE EPNum - the endpoint to be configured
2331 * BYTE direction - the direction to be configured
2332 *
2333 * Output: None
2334 *
2335 * Side Effects: None
2336 *
2337 * Overview: This function will configure the specified
2338 * endpoint
2339 *
2340 * Note: None
2341 *******************************************************************/
2342 void USBConfigureEndpoint(BYTE EPNum, BYTE direction)
2343 {
2344 volatile BDT_ENTRY* handle;
2345  
2346 handle = (volatile BDT_ENTRY*)&BDT[EP0_OUT_EVEN];
2347 handle += BD(EPNum,direction,0)/sizeof(BDT_ENTRY);
2348  
2349 handle->STAT.UOWN = 0;
2350  
2351 if(direction == 0)
2352 {
2353 pBDTEntryOut[EPNum] = handle;
2354 }
2355 else
2356 {
2357 pBDTEntryIn[EPNum] = handle;
2358 }
2359  
2360 #if (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG)
2361 handle->STAT.DTS = 0;
2362 (handle+1)->STAT.DTS = 1;
2363 #elif (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG)
2364 //Set DTS to one because the first thing we will do
2365 //when transmitting is toggle the bit
2366 handle->STAT.DTS = 1;
2367 #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY)
2368 if(EPNum != 0)
2369 {
2370 handle->STAT.DTS = 1;
2371 }
2372 #elif (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0)
2373 if(EPNum != 0)
2374 {
2375 handle->STAT.DTS = 0;
2376 (handle+1)->STAT.DTS = 1;
2377 }
2378 #endif
2379 }
2380  
2381 /*****************************************************************************************************************
2382 Function:
2383 void USBEnableEndpoint(BYTE ep, BYTE options)
2384  
2385 Summary:
2386 This function will enable the specified endpoint with the specified
2387 options
2388 Description:
2389 This function will enable the specified endpoint with the specified
2390 options.
2391  
2392 Typical Usage:
2393 <code>
2394 void USBCBInitEP(void)
2395 {
2396 USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
2397 USBMSDInit();
2398 }
2399 </code>
2400  
2401 In the above example endpoint number MSD_DATA_IN_EP is being configured
2402 for both IN and OUT traffic with handshaking enabled. Also since
2403 MSD_DATA_IN_EP is not endpoint 0 (MSD does not allow this), then we can
2404 explicitly disable SETUP packets on this endpoint.
2405 Conditions:
2406 None
2407 Input:
2408 BYTE ep - the endpoint to be configured
2409 BYTE options - optional settings for the endpoint. The options should
2410 be ORed together to form a single options string. The
2411 available optional settings for the endpoint. The
2412 options should be ORed together to form a single options
2413 string. The available options are the following\:
2414 * USB_HANDSHAKE_ENABLED enables USB handshaking (ACK,
2415 NAK)
2416 * USB_HANDSHAKE_DISABLED disables USB handshaking (ACK,
2417 NAK)
2418 * USB_OUT_ENABLED enables the out direction
2419 * USB_OUT_DISABLED disables the out direction
2420 * USB_IN_ENABLED enables the in direction
2421 * USB_IN_DISABLED disables the in direction
2422 * USB_ALLOW_SETUP enables control transfers
2423 * USB_DISALLOW_SETUP disables control transfers
2424 * USB_STALL_ENDPOINT STALLs this endpoint
2425 Return:
2426 None
2427 Remarks:
2428 None
2429 *****************************************************************************************************************/
2430 void USBEnableEndpoint(BYTE ep, BYTE options)
2431 {
2432 //Set the options to the appropriate endpoint control register
2433 //*((unsigned char*)(&U1EP0+ep)) = options;
2434 {
2435 unsigned char* p;
2436  
2437 #if defined(__C32__)
2438 p = (unsigned char*)(&U1EP0+(4*ep));
2439 #else
2440 p = (unsigned char*)(&U1EP0+ep);
2441 #endif
2442 *p = options;
2443 }
2444  
2445 if(options & USB_OUT_ENABLED)
2446 {
2447 USBConfigureEndpoint(ep,0);
2448 }
2449 if(options & USB_IN_ENABLED)
2450 {
2451 USBConfigureEndpoint(ep,1);
2452 }
2453 }
2454  
2455 /********************************************************************
2456 * Function: void USBStallEndpoint(BYTE ep, BYTE dir)
2457 *
2458 * PreCondition: None
2459 *
2460 * Input:
2461 * BYTE ep - the endpoint the data will be transmitted on
2462 * BYTE dir - the direction of the transfer
2463 *
2464 * Output: None
2465 *
2466 * Side Effects: Endpoint is STALLed
2467 *
2468 * Overview: STALLs the specified endpoint
2469 *
2470 * Note: None
2471 *******************************************************************/
2472 void USBStallEndpoint(BYTE ep, BYTE dir)
2473 {
2474 BDT_ENTRY *p;
2475  
2476 if(ep == 0)
2477 {
2478 /*
2479 * If no one knows how to service this request then stall.
2480 * Must also prepare EP0 to receive the next SETUP transaction.
2481 */
2482 pBDTEntryEP0OutNext->CNT = USB_EP0_BUFF_SIZE;
2483 pBDTEntryEP0OutNext->ADR = ConvertToPhysicalAddress(&SetupPkt);
2484  
2485 /* v2b fix */
2486 pBDTEntryEP0OutNext->STAT.Val = _USIE|_DAT0|_DTSEN|_BSTALL;
2487 pBDTEntryIn[0]->STAT.Val = _USIE|_BSTALL;
2488 }
2489 else
2490 {
2491 p = (BDT_ENTRY*)(&BDT[EP(ep,dir,0)]);
2492 p->STAT.Val |= _BSTALL | _USIE;
2493  
2494 //If the device is in FULL or ALL_BUT_EP0 ping pong modes
2495 //then stall that entry as well
2496 #if (USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) || \
2497 (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0)
2498  
2499 p = (BDT_ENTRY*)(&BDT[EP(ep,dir,1)]);
2500 p->STAT.Val |= _BSTALL | _USIE;
2501 #endif
2502 }
2503 }
2504  
2505 /********************************************************************
2506 * Function: USB_HANDLE USBTransferOnePacket(
2507 * BYTE ep,
2508 * BYTE dir,
2509 * BYTE* data,
2510 * BYTE len)
2511 *
2512 * PreCondition: The pBDTEntryIn[] or pBDTEntryOut[] pointer to
2513 * the endpoint that will be used must have been
2514 * initialized, prior to calling USBTransferOnePacket().
2515 * Therefore, the application firmware should not call
2516 * USBTransferOnePacket() until after the USB stack has been
2517 initialized (by USBDeviceInit()), and the host has sent a
2518 * set configuration request. This can be checked by
2519 * verifying that the USBGetDeviceState() == CONFIGURED_STATE,
2520 * prior to calling USBTransferOnePacket().
2521 *
2522 * Note: If calling the USBTransferOnePacket()
2523 * function from within the USBCBInitEP() callback function,
2524 * the set configuration is still being processed and the
2525 * USBDeviceState may not be == CONFIGURED_STATE yet. In this
2526 * special case, the USBTransferOnePacket() may still be
2527 * called, but make sure that the endpoint has been enabled
2528 * and initialized by the USBEnableEndpoint() function first.
2529 *
2530 * Input:
2531 * BYTE ep - the endpoint number that the data will be transmitted or
2532 * received on
2533 * BYTE dir - the direction of the transfer
2534 * This value is either OUT_FROM_HOST or IN_TO_HOST
2535 * BYTE* data - For IN transactions: pointer to the RAM buffer containing
2536 * the data to be sent to the host.
2537 * For OUT transactions: pointer to the RAM buffer that the
2538 * received data should get written to.
2539 * BYTE len - length of the data needing to be sent (for IN transactions).
2540 * For OUT transactions, the len parameter should normally be set
2541 * to the endpoint size specified in the endpoint descriptor.
2542 *
2543 * Output:
2544 * USB_HANDLE - handle to the transfer. The handle is a pointer to
2545 * the BDT entry associated with this transaction. The
2546 * status of the transaction (ex: if it is complete or still
2547 * pending) can be checked using the USBHandleBusy() macro
2548 * and supplying the USB_HANDLE provided by
2549 * USBTransferOnePacket().
2550 *
2551 *
2552 * Side Effects: None
2553 *
2554 * Overview: The USBTransferOnePacket() function prepares a USB endpoint
2555 * so that it may send data to the host (an IN transaction),
2556 * or receive data from the host (an OUT transaction). The
2557 * USBTransferOnePacket() function can be used both to receive
2558 * and send data to the host. The USBTransferOnePacket()
2559 * function is the primary API function provided by the USB
2560 * stack firmware for sending or receiving application data
2561 * over the USB port. The USBTransferOnePacket() is intended
2562 * for use with all application endpoints. It is not used for
2563 * sending or receiving applicaiton data through endpoint 0
2564 * by using control transfers. Separate API functions,
2565 * such as USBEP0Receive(), USBEP0SendRAMPtr(), and
2566 * USBEP0SendROMPtr() are provided for this purpose.
2567 *
2568 * The USBTransferOnePacket() writes to the Buffer Descriptor
2569 * Table (BDT) entry associated with an endpoint buffer, and
2570 * sets the UOWN bit, which prepares the USB hardware to
2571 * allow the transaction to complete. The application firmware
2572 * can use the USBHandleBusy() macro to check the status of the
2573 * transaction, to see if the data has been successfully
2574 * transmitted yet.
2575 *
2576 * Note: None
2577 *******************************************************************/
2578 USB_HANDLE USBTransferOnePacket(BYTE ep,BYTE dir,BYTE* data,BYTE len)
2579 {
2580 volatile BDT_ENTRY* handle;
2581  
2582 //If the direction is IN
2583 if(dir != 0)
2584 {
2585 //point to the IN BDT of the specified endpoint
2586 handle = pBDTEntryIn[ep];
2587 }
2588 else
2589 {
2590 //else point to the OUT BDT of the specified endpoint
2591 handle = pBDTEntryOut[ep];
2592 }
2593  
2594 //Error checking code. Make sure the handle (pBDTEntryIn[ep] or
2595 //pBDTEntryOut[ep]) is initialized before using it.
2596 if(handle == 0)
2597 {
2598 return 0;
2599 }
2600  
2601 //Toggle the DTS bit if required
2602 #if (USB_PING_PONG_MODE == USB_PING_PONG__NO_PING_PONG)
2603 handle->STAT.Val ^= _DTSMASK;
2604 #elif (USB_PING_PONG_MODE == USB_PING_PONG__EP0_OUT_ONLY)
2605 if(ep != 0)
2606 {
2607 handle->STAT.Val ^= _DTSMASK;
2608 }
2609 #endif
2610  
2611 //Set the data pointer, data length, and enable the endpoint
2612 handle->ADR = ConvertToPhysicalAddress(data);
2613 handle->CNT = len;
2614 handle->STAT.Val &= _DTSMASK;
2615 handle->STAT.Val |= _USIE | _DTSEN;
2616  
2617 //Point to the next buffer for ping pong purposes.
2618 if(dir != 0)
2619 {
2620 //toggle over the to the next buffer for an IN endpoint
2621 ((BYTE_VAL*)&pBDTEntryIn[ep])->Val ^= USB_NEXT_PING_PONG;
2622 }
2623 else
2624 {
2625 //toggle over the to the next buffer for an OUT endpoint
2626 ((BYTE_VAL*)&pBDTEntryOut[ep])->Val ^= USB_NEXT_PING_PONG;
2627 }
2628 return (USB_HANDLE)handle;
2629 }
2630  
2631 /**************************************************************************
2632 Function:
2633 void USBCancelIO(BYTE endpoint)
2634  
2635 Description:
2636 This function cancels the transfers pending on the specified endpoint.
2637 This function can only be used after a SETUP packet is received and
2638 before that setup packet is handled. This is the time period in which
2639 the EVENT_EP0_REQUEST is thrown, before the event handler function
2640 returns to the stack.
2641  
2642 Precondition:
2643  
2644 Parameters:
2645 BYTE endpoint - the endpoint number you wish to cancel the transfers for
2646  
2647 Return Values:
2648 None
2649  
2650 Remarks:
2651 None
2652  
2653 **************************************************************************/
2654 void USBCancelIO(BYTE endpoint)
2655 {
2656 if(USBPacketDisable == 1)
2657 {
2658 //The PKTDIS bit is currently set right now. It is therefore "safe"
2659 //to mess with the BDT right now.
2660 pBDTEntryIn[endpoint]->Val &= _DTSMASK; //Makes UOWN = 0 (_UCPU mode). Deactivates endpoint. Only sends NAKs.
2661 pBDTEntryIn[endpoint]->Val ^= _DTSMASK; //Toggle the DTS bit. This packet didn't get sent yet, and the next call to USBTransferOnePacket() will re-toggle the DTS bit back to the original (correct) value.
2662  
2663 //Need to do additional handling if ping-pong buffering is being used
2664 #if ((USB_PING_PONG_MODE == USB_PING_PONG__FULL_PING_PONG) || (USB_PING_PONG_MODE == USB_PING_PONG__ALL_BUT_EP0))
2665 //Point to the next buffer for ping pong purposes. UOWN getting cleared
2666 //(either due to SIE clearing it after a transaction, or the firmware
2667 //clearing it) makes hardware ping pong pointer advance.
2668 ((BYTE_VAL*)&pBDTEntryIn[endpoint])->Val ^= USB_NEXT_PING_PONG;
2669  
2670 pBDTEntryIn[endpoint]->STAT.Val &= _DTSMASK;
2671 pBDTEntryIn[endpoint]->STAT.Val ^= _DTSMASK;
2672 #endif
2673 }
2674 }
2675  
2676 /**************************************************************************
2677 Function:
2678 void USBDeviceDetach(void)
2679  
2680 Description:
2681  
2682 Precondition:
2683  
2684 Parameters:
2685 None
2686  
2687 Return Values:
2688 None
2689  
2690 Remarks:
2691 None
2692  
2693 **************************************************************************/
2694 #if defined(USB_INTERRUPT)
2695 void USBDeviceDetach(void)
2696 {
2697 //If the interrupt option is selected then the customer is required
2698 // to notify the stack when the device is attached or removed from the
2699 // bus by calling the USBDeviceAttach() and USBDeviceDetach() functions.
2700 #ifdef USB_SUPPORT_OTG
2701 if (USB_BUS_SENSE != 1)
2702 #endif
2703 {
2704 // Disable module & detach from bus
2705 U1CON = 0;
2706  
2707 // Mask all USB interrupts
2708 U1IE = 0;
2709  
2710 //Move to the detached state
2711 USBDeviceState = DETACHED_STATE;
2712  
2713 #ifdef USB_SUPPORT_OTG
2714 //Disable D+ Pullup
2715 U1OTGCONbits.DPPULUP = 0;
2716  
2717 //Disable HNP
2718 USBOTGDisableHnp();
2719  
2720 //Deactivate HNP
2721 USBOTGDeactivateHnp();
2722  
2723 //If ID Pin Changed State
2724 if (USBIDIF && USBIDIE)
2725 {
2726 //Re-detect & Initialize
2727 USBOTGInitialize();
2728  
2729 //Clear ID Interrupt Flag
2730 USBClearInterruptFlag(USBIDIFReg,USBIDIFBitNum);
2731 }
2732 #endif
2733  
2734 #ifdef __C30__
2735 //USBClearInterruptFlag(U1OTGIR, 3);
2736 #endif
2737 //return so that we don't go through the rest of
2738 //the state machine
2739 return;
2740 }
2741  
2742 #ifdef USB_SUPPORT_OTG
2743 //If Session Is Started Then
2744 else
2745 {
2746 //If SRP Is Ready
2747 if (USBOTGSRPIsReady())
2748 {
2749 //Clear SRPReady
2750 USBOTGClearSRPReady();
2751  
2752 //Clear SRP Timeout Flag
2753 USBOTGClearSRPTimeOutFlag();
2754  
2755 //Indicate Session Started
2756 UART2PrintString( "\r\n***** USB OTG B Event - Session Started *****\r\n" );
2757 }
2758 }
2759 #endif
2760 }
2761 #endif //#if defined(USB_INTERRUPT)
2762 /**************************************************************************
2763 Function:
2764 void USBDeviceAttach(void)
2765  
2766 Description:
2767  
2768 Precondition:
2769 For normal USB devices:
2770 Make sure that if the module was previously on, that it has been turned off
2771 for a long time (ex: 100ms+) before calling this function to re-enable the module.
2772 If the device turns off the D+ (for full speed) or D- (for low speed) ~1.5k ohm
2773 pull up resistor, and then turns it back on very quickly, common hosts will sometimes
2774 reject this event, since no human could ever unplug and reattach a USB device in a
2775 microseconds (or nanoseconds) timescale. The host could simply treat this as some kind
2776 of glitch and ignore the event altogether.
2777 Parameters:
2778 None
2779  
2780 Return Values:
2781 None
2782  
2783 Remarks:
2784 None
2785  
2786 **************************************************************************/
2787 #if defined(USB_INTERRUPT)
2788 void USBDeviceAttach(void)
2789 {
2790 //if we are in the detached state
2791 if(USBDeviceState == DETACHED_STATE)
2792 {
2793 if(USB_BUS_SENSE == 1)
2794 {
2795 //Initialize registers to known states.
2796 U1CON = 0;
2797  
2798 // Mask all USB interrupts
2799 U1IE = 0;
2800  
2801 //Configure things like: pull ups, full/low-speed mode,
2802 //set the ping pong mode, and set internal transceiver
2803 SetConfigurationOptions();
2804  
2805 USBEnableInterrupts();
2806  
2807 // Enable module & attach to bus
2808 while(!U1CONbits.USBEN){U1CONbits.USBEN = 1;}
2809  
2810 //moved to the attached state
2811 USBDeviceState = ATTACHED_STATE;
2812  
2813 #ifdef USB_SUPPORT_OTG
2814 U1OTGCON = USB_OTG_DPLUS_ENABLE | USB_OTG_ENABLE;
2815 #endif
2816 }
2817 }
2818 }
2819 #endif //#if defined(USB_INTERRUPT)
2820 /** EOF USBDevice.c *****************************************************/
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3