1 /*******************************************************************
2 Copyright (C) 2008 FreakLabs
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 Please post support questions to the FreakLabs forum.
19 *******************************************************************/
24 /*******************************************************************/
26 #include <avr/interrupt.h>
30 /**************************************************************************/
32 Select the endpoint number so that we can see the endpoint's associated
35 /**************************************************************************/
36 void ep_select(U8 ep_num
)
41 /**************************************************************************/
43 Get the max packet size of the endpoint.
45 /**************************************************************************/
48 U8 tmp
= (UECFG1X
&= (7<<EPSIZE0
));
50 return (U8
)(1 << (tmp
+ 3));
53 /**************************************************************************/
55 Get the direction of the endpoint.
57 /**************************************************************************/
60 return (UECFG0X
& 0x1);
63 /**************************************************************************/
65 Get the endpoint type: BULK, CONTROL, INTERRUPT, ISOCHRONOUS
67 /**************************************************************************/
70 return ((UECFG0X
& (0x3 << EPTYPE0
)) >> EPTYPE0
);
73 /**************************************************************************/
75 Clear the endpoint configuration registers
77 /**************************************************************************/
84 /**************************************************************************/
86 Clear the specified endpoint's enable bit.
88 /**************************************************************************/
91 UECONX
&= ~(1 << EPEN
);
94 /**************************************************************************/
96 Configure the endpoint with the specified parameters.
98 /**************************************************************************/
99 void ep_config(U8 ep_num
, U8 type
, U8 dir
, U8 size
)
101 // init the direction the fifo
102 usb_buf_init(ep_num
, dir
);
104 // select the endpoint and reset it
106 UECONX
&= ~(1 << EPEN
);
107 UECONX
|= (1 << EPEN
);
109 // set the type, direction, and size
110 UECFG0X
|= (type
& 0x3) << EPTYPE0
;
112 UECFG1X
|= (size
& 0x7) << EPSIZE0
;
114 // we're only using single banks for now. double banks can be used on certain EPs only.
115 UECFG1X
|= (SINGLE
& 0x3) << EPBK0
;
117 // alloc memory for the endpoint
118 UECFG1X
|= (1 << ALLOC
);
120 // spin here until the config is okay
121 while (!(UESTA0X
& (1<<CFGOK
)));
123 UERST
|= (1<<ep_num
);
124 UERST
&= ~(1<<ep_num
);
126 if (ep_num
== EP_CTRL
)
131 else if (dir
== DIR_OUT
)
137 /**************************************************************************/
139 Write into the endpoint's FIFOs. These will be used to transfer data out
140 of that particular endpoint to the host.
142 /**************************************************************************/
143 void ep_write(U8 ep_num
)
146 usb_pcb_t
*pcb
= usb_pcb_get();
149 ep_size
= ep_size_get();
150 len
= pcb
->fifo
[ep_num
].len
;
152 // make sure that the tx fifo is ready to receive the out data
153 if (ep_num
== EP_CTRL
)
155 while (!TX_FIFO_READY
);
162 for (i
=0; i
<len
; i
++)
164 // check if we've reached the max packet size for the endpoint
167 // we've filled the max packet size so break and send the data
171 UEDATX
= usb_buf_read(ep_num
);
174 if (ep_num
== EP_CTRL
)
176 while (!TX_FIFO_READY
);
179 // clearing these two will send the data out
184 /**************************************************************************/
186 Read data from the endpoint's FIFO. This is where data coming into the
187 device from the host is stored.
189 /**************************************************************************/
190 void ep_read(U8 ep_num
)
193 usb_pcb_t
*pcb
= usb_pcb_get();
197 for (i
=0; i
<len
; i
++)
199 usb_buf_write(ep_num
, UEDATX
);
204 pcb
->flags
|= (ep_num
== 0) ? (1<<SETUP_DATA_AVAIL
) : (1<<RX_DATA_AVAIL
);
208 /**************************************************************************/
210 Send a zero length packet on the specified endpoint. This is usually used
211 to terminate a transfer.
213 /**************************************************************************/
214 void ep_send_zlp(U8 ep_num
)
218 while (!TX_FIFO_READY
);
220 while (!TX_FIFO_READY
);
224 /**************************************************************************/
226 Stall the endpoint due to some problem. This function will also set the
227 stall flag in the protocol control block.
229 /**************************************************************************/
230 void ep_set_stall(U8 ep_num
)
232 usb_pcb_t
*pcb
= usb_pcb_get();
234 pcb
->ep_stall
|= (1 << ep_num
);
236 UECONX
|= (1 << STALLRQ
);
239 /**************************************************************************/
241 This function will clear the stall on an endpoint.
243 /**************************************************************************/
244 void ep_clear_stall(U8 ep_num
)
246 usb_pcb_t
*pcb
= usb_pcb_get();
248 pcb
->ep_stall
&= ~(1 << ep_num
);
250 UECONX
|= (1<<STALLRQC
);
253 /**************************************************************************/
255 Reset the data toggle on the specified endpoint.
257 /**************************************************************************/
258 void ep_reset_toggle(U8 ep_num
)
261 UECONX
|= (1<<RSTDT
);
264 /**************************************************************************/
266 Clear all endpoints and initialize ep0 for control transfers.
268 /**************************************************************************/
273 // disable and clear all endpoints
274 for (i
=0; i
<MAX_EPS
; i
++)
281 // reset all the endpoints
285 // configure the control endpoint first since that one is needed for enumeration
286 ep_config(EP_CTRL
, CONTROL
, DIR_OUT
, PKTSZ_32
);
288 // set the rx setup interrupt to received the enumeration interrupts
292 /**************************************************************************/
294 Set the address for the device. This will be called when a SET_ADDR request
295 is sent by the host. We can only set the address after we send a ZLP to the host
296 informing it that we successfully received the request. Otherwise, we will
297 be on a different address when the host ACKs us back on the original address (0).
299 /**************************************************************************/
300 void ep_set_addr(U8 addr
)
302 // send out a zlp to ack the set address request
303 ep_send_zlp(EP_CTRL
);
305 // only write the top 7 bits of the address. the 8th bit is for enable
306 UDADDR
= addr
& 0x7F;
308 // enable the address after the host acknowledges the frame was sent
309 UDADDR
|= (1 << ADDEN
);
313 /**************************************************************************/
315 Return the ep where an intp occurred. If no intp occurred, then return 0xff.
317 /**************************************************************************/
322 for (i
=0; i
<MAX_EPS
; i
++)
332 /**************************************************************************/
334 Get the endpoint number that the interrupt occurred on. If no interrupt
335 is found, return 0xFF.
337 /**************************************************************************/
345 if ((UEINTX
& (1<<i
)) && (UEIENX
& (1<<i
)))