Remove the PIO config from the clkout_on() function.
[dtplug] / drivers / usbcore.c
1 /****************************************************************************
2  *   drivers/usbcore.c
3  *
4  * Copyright 2012 Nathael Pajani <nathael.pajani@ed3l.fr>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *************************************************************************** */
21 /*
22  * This file holds all the hardware related functions for the USB subsystem
23  */
25 #include <stdint.h>
27 #include "core/lpc_regs_17xx.h"
28 #include "core/lpc_core_cm3.h"
29 #include "core/system.h"
31 //extern char* UARTBUFFER;
32 //extern volatile int UARTPTR;
33 //static char* HEXA = "0123456789ABCDEF";
35 /***************************************************************************** */
36 /*          USB configuration                                                  */
37 /***************************************************************************** */
38 /* Turn on USB Clock
39  * USB Clock is generated using PPL1, allowing easier setting of system clock
40  *   to any desired value. This will consume some more power, but the LPC1764
41  *   used on the DTPlug board has only device USB, thus we are certainly
42  *   connected to a big computer using tens or hundreds of Watts - don't care.
43  *
44  * M and P values determinatinn :
45  *    M = (48MHz / Fosc) and Fosc is 12MHz
46  *      ==> M = 4
47  *    P = FCCO / (2 × M × Fosc) and FCCO must be between 156 and 320MHz
48  *    P must be even  ... if P is 2 we have FCCO = 2 * 2 * 4 * 12MHz = 192MHz
49  *      ==> P = 2
50  */
51 static void usb_clk_on(void)
52 {
53         struct lpc_sys_control* sys_ctrl = LPC_SYS_CONTROL;
54         uint32_t M = 4; /* M = (48MHz / Fosc) and Fosc is 12MHz */
55         uint32_t P = 2; /* P = FCCO / (2 × M × Fosc) and FCCO must be between 156 and 320MHz */
57         /* Configure PLL 1 for USB */
58         /* Note :  ALL STEPS ARE REQUIRED ! */
59         /* First of all, turn off interrupts, nothing should happen between the two writes of the
60            feed sequence (writting of 0xAA and 0x55 to pll1_feed) */
61         lpc_disable_irq();
62         /* Disable PLL if requiered */
63         if ((sys_ctrl->pll1_status & (0x03 << 8)) != 0) {
64                 /* Disconnect PLL first */
65                 sys_ctrl->pll1_control &= ~(LPC_PLL_CTRL_PLL_CONNECT);
66                 sys_ctrl->pll1_feed = 0xAA;
67                 sys_ctrl->pll1_feed = 0x55;
68                 /* Then disable PLL */
69                 sys_ctrl->pll1_control = 0;
70                 sys_ctrl->pll1_feed = 0xAA;
71                 sys_ctrl->pll1_feed = 0x55;
72         }
73         /* PLL now off. Set clock div to 1 to get max freq */
74         /* Make sure that external crystal is enabled and ready */
75         if (!(sys_ctrl->sys_osc_ctrl_and_status & (0x01 << 6))) {
76                 sys_ctrl->sys_osc_ctrl_and_status |= (1 << 5);
77                 while ( ! (sys_ctrl->sys_osc_ctrl_and_status & (0x01 << 6)) );
78         }
79         /* Setup PLL */
80         sys_ctrl->pll1_config = (((M - 1) & 0x1F) | ((P >> 1) & 0x3) << 5);
81         sys_ctrl->pll1_feed = 0xAA;
82         sys_ctrl->pll1_feed = 0x55;
83         /* Enable PLL */
84         sys_ctrl->pll1_control = LPC_PLL_CTRL_PLL_ENABLE;
85         sys_ctrl->pll1_feed = 0xAA;
86         sys_ctrl->pll1_feed = 0x55;
87         /* Wait for PLL lock (note : interrupts are disabled) */
88         while ( ! (sys_ctrl->pll1_status & (0x01 << 10)) );
89         /* Connect PLL */
90         sys_ctrl->pll1_control = (LPC_PLL_CTRL_PLL_ENABLE | LPC_PLL_CTRL_PLL_CONNECT);
91         sys_ctrl->pll1_feed = 0xAA;
92         sys_ctrl->pll1_feed = 0x55;
93         /* Turn interrupts on once again*/
94         lpc_enable_irq();
95 }
97 void usb_clk_off(void)
98 {
99         /* FIXME */
102 #if 0
103 /* Setup all USB pins according to their function for the DTPlug */
104 void set_usb_pins(void)
106         /* D+ and D- */
107         lpc_set_pin_func(0, 29, LPC_IO_FUNC_ALT1, LPC_IO_MODE_NO_PULL, LPC_IO_STD);
108         lpc_set_pin_func(0, 30, LPC_IO_FUNC_ALT1, LPC_IO_MODE_NO_PULL, LPC_IO_STD);
109         /* Link */
110         lpc_set_pin_func(1, 18, LPC_IO_FUNC_ALT1, LPC_IO_MODE_PULL_UP, LPC_IO_STD);
111         /* VBUS */
112         lpc_set_pin_func(1, 30, LPC_IO_FUNC_ALT2, LPC_IO_MODE_NO_PULL, LPC_IO_STD);
113         /* Soft Connect */
114         lpc_set_pin_func(2,  9, LPC_IO_FUNC_ALT1, LPC_IO_MODE_PULL_UP, LPC_IO_STD);
116 #endif
118 /* Enable clocks to USB block and AHB master */
119 void usb_up(void)
121         struct lpc_usb_clock* usb_clk = LPC_USB_CLOCK;
122         /* Enable USB Device and AHB clock */
123         usb_clk->control = LPC_USB_CLK_ON; /* Set DEV_CLK_EN and AHB_CLK_EN in the USBClkCtrl register */
124         /* and wait for them (DEV_CLK_ON in USBClkSt) */
125         while ((usb_clk->status & LPC_USB_CLK_ON) != LPC_USB_CLK_ON);
128 /* Setup USB
129  *  calls usb_clk_on to configure PLL1 and turn on USB Clock
130  *  enable the clocks to the USB block and AHB master
131  */
132 void usb_on(void)
134         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
136         NVIC_DisableIRQ(USB_IRQ);
138         /* Provide power to USB Block */
139         subsystem_power(LPC_USB_POWER_ON, 1);
140         /* Turn on USB Clock (PLL 1) */
141         usb_clk_on();
142         /* Enable clocks to USB block and AHB master */
143         usb_up();
145         /* Disable all DMA */
146         usb_dev->ep_dma_disable = ~(0x0UL);
147         usb_dev->dma_int_enable = 0;
148         /* Enable USB interrupt */
149         usb_dev->dev_int_enable = 0;
150         usb_dev->dev_int_clear = ~(0x0UL);
151         usb_dev->ep_int_enable = 0;
152         usb_dev->ep_int_clear  = ~(0x0UL);
153         NVIC_EnableIRQ(USB_IRQ);
156 /***************************************************************************** */
157 /*         USB subsystem functions                                             */
158 /***************************************************************************** */
159 /* Activate and configure an endpoint
160  *    ep_num is the logical endpoint number
161  *    dir is either USB_DIR_IN or USB_DIR_OUT
162  */
163 void usb_endpoint_realize(uint32_t ep_num, uint32_t max_packet_size, int dir)
165         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
166 //      uint32_t inf_flags = usb_dev->dev_int_enable;
167         uint32_t physical_ep = ((ep_num * 2) + (dir ? 1 : 0));
169         /* Remove USB_EP_RLZED_INT from usb interrupts (if it was in) */
170 //      usb_dev->dev_int_enable &= ~USB_EP_RLZED_INT;
171         /* Clear the EP_realized bit in int status */
172         usb_dev->dev_int_clear = USB_EP_RLZED_INT;
173         /* Set up enpoint */
174         usb_dev->realize_ep |= (1 << physical_ep);
175         usb_dev->ep_index = physical_ep;
176         usb_dev->max_packet_size = max_packet_size;
177         usb_dev->ep_int_enable |= (USB_EP_Rx_INT(ep_num) | USB_EP_Tx_INT(ep_num));
178         /* Wait for endpoint realized */
179         while ((usb_dev->dev_int_status & USB_EP_RLZED_INT) == 0);
180         /* Clear the EP_realized bit in int status */
181         usb_dev->dev_int_clear = USB_EP_RLZED_INT;
182         /* Restore interrupt flags */
183 //      usb_dev->dev_int_enable = inf_flags;
185 /* Deactivate an endpoint, see usb_endpoint_realize() for comments */
186 void usb_endpoint_remove(uint32_t ep_num, int dir)
188         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
189         uint32_t physical_ep = ((ep_num * 2) + (dir ? 1 : 0));
190 //      uint32_t inf_flags = usb_dev->dev_int_enable;
192 //      usb_dev->dev_int_enable &= ~USB_EP_RLZED_INT;
193         usb_dev->dev_int_clear = USB_EP_RLZED_INT;
194         usb_dev->ep_int_enable &= ~(USB_EP_Rx_INT(ep_num) | USB_EP_Tx_INT(ep_num));
195         usb_dev->realize_ep &= ~(1 << physical_ep);
196         while ((usb_dev->dev_int_status & USB_EP_RLZED_INT) == 0);
197         usb_dev->dev_int_clear = USB_EP_RLZED_INT;
198 //      usb_dev->dev_int_enable = inf_flags;
201 /* Reset USB sub-system */
202 /* Called on USB Reset by the user USB interrupt handler */
203 void usb_reset(uint32_t usb_ctrl_endpoint_max_pkt_size)
205         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
207         NVIC_DisableIRQ(USB_IRQ);
208         /* Set-up control endpoints */
209         usb_endpoint_realize(0, usb_ctrl_endpoint_max_pkt_size, USB_DIR_OUT);
210         usb_endpoint_realize(0, usb_ctrl_endpoint_max_pkt_size, USB_DIR_IN);
212         /* Disable all DMA */
213         usb_dev->ep_dma_disable = ~(0x0UL);
214         usb_dev->dma_int_enable = 0;
215         /* Setup USB interrupt */
216         usb_dev->ep_int_clear  = ~(0x0UL);
217         usb_dev->dev_int_clear = ~(0x0UL);
218         /* control endpoints interrupts */
219         usb_dev->ep_int_enable = (USB_EP_Rx_INT(0) | USB_EP_Tx_INT(0));
220         usb_dev->ep_int_priority = 0; /* FIXME */
221         /* Device interrupts */
222         /* FIXME */
223         usb_dev->dev_int_enable = (USB_DEV_STAT_INT | USB_EP_SLOW_INT);
224         /* usb_dev->dev_int_enable |= (USB_ERR_INT); */
225         /* usb_dev->dev_int_enable |= (USB_FRAME_INT); *//* Used only for isochronous transfers */
226         NVIC_EnableIRQ(USB_IRQ);
229 /***************************************************************************** */
230 /*        Serial Interface Engine (SIE)                                        */
231 /***************************************************************************** */
232 /* Perform SIE Command */
233 void usb_cmd(uint8_t cmd)
235         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
236 #if 0
237         uint32_t inf_flags = usb_dev->dev_int_enable;
238         /* Clear CCEMPTY and CDFULL interrupts and mask them */
239         usb_dev->dev_int_enable &= ~(USB_CMD_CODE_EMPTY_INT | USB_CMD_DATA_FULL_INT);
240         usb_dev->dev_int_clear = (USB_CMD_CODE_EMPTY_INT | USB_CMD_DATA_FULL_INT);
241 #endif
242         usb_dev->dev_int_clear = USB_CMD_CODE_EMPTY_INT;
243         /* SIE Command */
244         usb_dev->command_code = USB_CMD_COMMAND(cmd);
245         while ((usb_dev->dev_int_status & USB_CMD_CODE_EMPTY_INT) == 0);
246 #if 0
247         usb_dev->dev_int_clear = USB_CMD_CODE_EMPTY_INT;
248         /* Restore interrupts */
249         usb_dev->dev_int_enable = inf_flags;
250 #endif
252 /* Perform SIE Command + SIE Write */
253 void usb_cmd_write(uint8_t cmd, uint8_t val)
255         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
256 #if 0
257         uint32_t inf_flags = usb_dev->dev_int_enable;
258         /* Clear CCEMPTY and CDFULL interrupts and mask them */
259         usb_dev->dev_int_enable &= ~(USB_CMD_CODE_EMPTY_INT | USB_CMD_DATA_FULL_INT);
260         usb_dev->dev_int_clear = (USB_CMD_CODE_EMPTY_INT | USB_CMD_DATA_FULL_INT);
261 #endif
262         /* SIE Command */
263         usb_dev->dev_int_clear = USB_CMD_CODE_EMPTY_INT;
264         usb_dev->command_code = USB_CMD_COMMAND(cmd);
265         while ((usb_dev->dev_int_status & USB_CMD_CODE_EMPTY_INT) == 0);
266         /* SIE Write */
267         usb_dev->dev_int_clear = USB_CMD_CODE_EMPTY_INT;
268         usb_dev->command_code = USB_CMD_WRITE(val);
269         while ((usb_dev->dev_int_status & USB_CMD_CODE_EMPTY_INT) == 0);
270 #if 0
271         usb_dev->dev_int_clear = USB_CMD_CODE_EMPTY_INT;
272         /* Restore interrupts */
273         usb_dev->dev_int_enable = inf_flags;
274 #endif
276 /* Perform SIE Command + SIE Read
277  * If width is two, the perform a second SIE Read to get MSB byte
278  */
279 uint32_t usb_cmd_read(uint8_t cmd, uint8_t width)
281         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
282         uint32_t result = 0;
283 #if 0
284         uint32_t inf_flags = usb_dev->dev_int_enable;
285         /* Clear CCEMPTY and CDFULL interrupts and mask them */
286         usb_dev->dev_int_enable &= ~(USB_CMD_CODE_EMPTY_INT | USB_CMD_DATA_FULL_INT);
287         usb_dev->dev_int_clear = (USB_CMD_CODE_EMPTY_INT | USB_CMD_DATA_FULL_INT);
288 #endif
289         /* SIE Command */
290         usb_dev->dev_int_clear = USB_CMD_CODE_EMPTY_INT;
291         usb_dev->command_code = USB_CMD_COMMAND(cmd);
292         while ((usb_dev->dev_int_status & USB_CMD_CODE_EMPTY_INT) == 0);
293         /* SIE Read */
294         usb_dev->dev_int_clear = USB_CMD_DATA_FULL_INT;
295         usb_dev->command_code = USB_CMD_READ(cmd);
296         while ((usb_dev->dev_int_status & USB_CMD_DATA_FULL_INT) == 0);
297         result = usb_dev->command_data;
298         /* Second SIE Read to get MSB byte */
299         if (width == 2) {
300                 usb_dev->dev_int_clear = USB_CMD_DATA_FULL_INT;
301                 usb_dev->command_code = USB_CMD_READ(cmd);
302                 while ((usb_dev->dev_int_status & USB_CMD_DATA_FULL_INT) == 0);
303                 result |= (usb_dev->command_data << 8);
304         }
305 #if 0
306         /* Restore interrupts */
307         usb_dev->dev_int_enable = inf_flags;
308 #endif
309         return result;
312 /* Set device address */
313 void usb_set_address(uint8_t addr)
315         /* The LPC1764 user manual says that "The address set in the device will take
316          *   effect after the status stage of the control transaction."
317          * The UM10139 for LPC214x says also : "(Alternately, issuing the Set Address
318          *   command twice will set the address in the device)"
319          * Issue the USB_SIE_SET_ADDRESS command twice to set it right now
320          * Another way would be to force the status stage to happen ? */
321         usb_cmd_write(USB_SIE_SET_ADDRESS, (addr | USB_DEVICE_ENABLE));
323 /* Disable USB device */
324 void usb_disable(void)
326         usb_cmd_write(USB_SIE_SET_ADDRESS, 0x00);
328 /* Read current frame number */
329 uint16_t usb_read_current_frame_number(void)
331         uint16_t cfn = (uint16_t)usb_cmd_read(USB_SIE_READ_CFN, 2);
332         return cfn;
334 /* This will activate the Good link (UP_LED signal) indicator */
335 void usb_dev_set_configured(void)
337         usb_cmd_write(USB_SIE_CONFIGURE_DEV, USB_DEVICE_CONFIGURED);
339 /* Test USB clocks 
340  * Read the Test register, read should return 0xA50F if the USB clocks
341  *  (usbclk and AHB slave clock) are running
342  * returns 1 if OK, 0 if not running */
343 #define USB_CLOCKS_RUNNING 0xA50F
344 uint32_t usb_clocks_running(void)
346         uint16_t result = (uint16_t)usb_cmd_read(USB_SIE_READ_TEST_REG, 2);
347         if (result == USB_CLOCKS_RUNNING);
348                 return 1;
349         return 0;
351 /* USB soft connect
352  * Connect / disconnect can be done by software by setting the CON Bit
353  *   using the SIE Set Device Status command
354  */
355 void usb_connect(void)
357         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
358         /* FIXME : do I need to mask device status change interrupt and wait for
359          *    status change notification ?
360          */
361         usb_dev->dev_int_clear = USB_DEV_STAT_INT; /* Clear the device status change interrupt */
362         usb_cmd_write(USB_SIE_DEV_STATUS, USB_DEVSTAT_CONNECT); /* all other bits have no effet on write ? */
366 /* Read endpoint status
367  * ep_num is logical endpoint number
368  * returns the value read using SIE command ored with the endpoint status in bit 7.
369  */
370 uint8_t usb_read_endpoint_status(uint32_t ep_num, int dir)
372         uint32_t physical_ep = ((ep_num * 2) + (dir ? 1 : 0));
373         uint8_t result = (uint8_t)usb_cmd_read(USB_SIE_SELECT_EP(physical_ep), 1);
374         return (result & USB_EPSTAT_MASK);
377 static uint32_t endpoints_halted = ~(0); /* Default is to have all endpoints disabled */
378 uint8_t usb_endpoint_halted(uint32_t ep_num, int dir)
380         uint32_t physical_ep = ((ep_num * 2) + (dir ? 1 : 0));
381         return ((endpoints_halted >> physical_ep) & 0x01);
383 /* Reset endpoint / Enable USB endpoint / Un-Stall endpoint
384  * ep_num is logical endpoint number
385  */
386 void usb_endpoint_reset(uint32_t ep_num, int dir)
388         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
389         uint32_t physical_ep = ((ep_num * 2) + (dir ? 1 : 0));
390         /* reset only for realized endpoints */
391         if (usb_dev->realize_ep & (1 << physical_ep)) {
392                 usb_cmd_write(USB_SIE_SET_EP_STAT(physical_ep), 0x00);
393                 /* Store endpoint status */
394                 endpoints_halted &= ~(1 << physical_ep);
395         }
397 /* Disable USB endpoint
398  * ep_num is logical endpoint number
399  */
400 void usb_endpoint_disable(uint32_t ep_num, int dir)
402         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
403         uint32_t physical_ep = ((ep_num * 2) + (dir ? 1 : 0));
404         /* only for realized endpoints */
405         if (usb_dev->realize_ep & (1 << physical_ep)) {
406                 usb_cmd_write(USB_SIE_SET_EP_STAT(physical_ep), USB_EP_SET_STAT_DISABLED);
407                 /* Store endpoint status */
408                 endpoints_halted |= (1 << physical_ep);
409         }
411 /* Stall  USB endpoint
412  * ep_num is logical endpoint number
413  */
414 void usb_endpoint_stall(uint32_t ep_num, int dir)
416         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
417         uint32_t physical_ep = ((ep_num * 2) + (dir ? 1 : 0));
418         /* reset only for realized endpoints */
419         if (usb_dev->realize_ep & (1 << physical_ep)) {
420                 usb_cmd_write(USB_SIE_SET_EP_STAT(physical_ep), USB_EP_SET_STAT_STALLED);
421         }
425 /* Clear the endpoint (OUT) buffer (received data) so new data can be received.
426  * ep_num is the logical endpoint number (0-15)
427  * If the endpoint is the control endpoint, returns 1 if the previously received packet
428  *    was over-written by a later SETUP packet.
429  * returns 0 in all other cases
430  */
431 uint8_t usb_clear_buffer(uint32_t ep_num)
433         uint32_t physical_ep = (ep_num * 2);
434         usb_cmd(USB_SIE_SELECT_EP(physical_ep));
435         if (ep_num == 0) {
436                 return (usb_cmd_read(USB_SIE_EP_CLEAR_BUF, 1) & 0x01);
437         }
438         usb_cmd(USB_SIE_EP_CLEAR_BUF);
439         return 0;
441 /* Validate the endpoint (IN) buffer for sending
442  * ep_num is the logical endpoint number (0-15)
443  */
444 void usb_validate_buffer(uint32_t ep_num)
446         uint32_t physical_ep = ((ep_num * 2) + 1);
447         usb_cmd(USB_SIE_SELECT_EP(physical_ep));
448         usb_cmd(USB_SIE_EP_VALIDATE_BUF);
451 /* FIXME : Implement error code handling ? (get error code and read error status)
452  * Error code handling must actually be done by user code.
453  */
454 /* Get device status */
455 uint8_t usb_get_dev_status(void)
457         return (uint8_t)usb_cmd_read(USB_SIE_DEV_STATUS, 1);
459 /* Get device error status */
460 uint8_t usb_get_dev_error_status(void)
462         return (uint8_t)usb_cmd_read(USB_SIE_READ_ERROR_STATUS, 1);
464 /* Get device error code */
465 uint8_t usb_get_dev_error_code(void)
467         return (uint8_t)usb_cmd_read(USB_SIE_GET_ERROR_CODE, 1);
471 /***************************************************************************** */
472 /*        Endpoint read and write                                              */
473 /***************************************************************************** */
474 /* Note that this code does NOT support interleaved read and write operations, which is
475  permited on the same endpoint. */
477 /* Read data from an endpoint
478  * ep_num is the logical endpoint number
479  * buf is a data buffer big enougth for this endpoint's max packet size, and MUST be word
480  *    aligned
481  * isochronous can be set for isochronous endpoints to skip the clear buffer.
482  */
483 uint32_t usb_ep_read(uint8_t ep_num, char* buf, uint8_t isochronous)
485         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
486         uint32_t* bufp = (uint32_t*)((uint32_t)buf & ~(0x03));
487         uint32_t length = 0, nb = 0;
488         uint32_t packet;
490         /* Did we already read an overwritten setup packet ? */
491         if (length != 0 ) {
492                 usb_dev->ep_int_clear = (1 << (ep_num * 2));
493         }
494         /* Programm the USBCtrl register : set RD_EN and LOG_ENDPOINT and wait
495          * data to be ready */
496         usb_dev->control = (USB_READ_ENABLE | USB_CTRL_LOG_EP(ep_num));
498         do {
499                 packet = usb_dev->rx_pkt_length;
500         } while (!(packet & USB_PKT_READY));
502         /* Grab the data */
503         length = (packet & USB_PKT_REMAIN_LENGTH_MASK);
504         nb = ((length + 3) / 4);
505         while (nb--) {
506                 *bufp++ = usb_dev->rx_data;
507         }
509         usb_dev->control = 0;
510         usb_clear_buffer(ep_num);
512         return length;
514 /* Write data to an endpoint
515  * ep_num is the logical endpoint number
516  */
517 uint32_t usb_ep_write(uint8_t ep_num, char* buf, uint32_t length)
519         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
520         uint32_t* bufp = (uint32_t*)((uint32_t)buf & ~(0x03));
521         uint32_t nb = ((length + 3) / 4);
522         /* Programm the USBCtrl register : set WR_EN and LOG_ENDPOINT */
523         usb_dev->control = (USB_WRITE_ENABLE | USB_CTRL_LOG_EP(ep_num));
524         /* Programm the number of bytes to be written and put the data in the internal buffer */
525         usb_dev->tx_pkt_length = (length & USB_PKT_REMAIN_LENGTH_MASK);
526 //      usb_dev->dev_int_enable &= ~(USB_DEV_STAT_INT); /* Do not get interrupt on TxENDPKT */
527         while (nb--) {
528                 usb_dev->tx_data = *bufp++;
529         }
530         /* Do not wait for end of output if we wrote nothing */
531 //      if (length & USB_PKT_REMAIN_LENGTH_MASK) {
532 //              while (!(usb_dev->dev_int_status & USB_TxENDPKT_INT));
533 //      }
534         usb_dev->control = 0;
535 //      usb_dev->dev_int_enable |= USB_DEV_STAT_INT; /* Restore Device status interrupt */
536         /* Validate the buffer for sending */
537         usb_validate_buffer(ep_num);
538         return 0;
543 /* These dummy handlers should be overwritten by any user code using USB */
544 void Dummy_USB_Handler(uint32_t event) {
545         do { } while (0);
547 /* usb_status_handler receives the device status. */
548 void usb_status_handler(uint32_t event) __attribute__ ((weak, alias ("Dummy_USB_Handler")));
549 /* Called when USB_FRAME_INT happens, with value 0 */
550 void usb_sof_handler(uint32_t event) __attribute__ ((weak, alias ("Dummy_USB_Handler")));
551 /* Called upon error, with (error_status | (error_code << 8)) as parameter */
552 void usb_error_handler(uint32_t event) __attribute__ ((weak, alias ("Dummy_USB_Handler")));
553 /* Called upon endpoint interrupt, once for each endpoint having an interrup pending
554  *    with (endpoint_logical_num | USB_DIR_* | (endpoint_status << 8)) as parameter */
555 void usb_ep_handler(uint32_t event) __attribute__ ((weak, alias ("Dummy_USB_Handler")));
558 /* USB Interrupts Handler */
559 void USB_Handler(void)
561         struct lpc_usb_device* usb_dev = LPC_USB_DEVICE;
562         uint32_t dev_intr = usb_dev->dev_int_status; /* Store Device Interrupt Status */
564         /* Clear interrupt */
565         usb_dev->dev_int_clear = ~(0x0UL);
567         if (dev_intr & USB_DEV_STAT_INT) {
568                 uint8_t dev_status = usb_get_dev_status();
569                 /* Call the user handler ?
570                  * Note for OS : This should trigger an event for userspace rather than give
571                  *   the hand to some "user code" within an interrupt handler ! */
572                 usb_status_handler((uint32_t)dev_status);
573                 return;
574         }
575         if (dev_intr & (USB_EP_FAST_INT | USB_EP_RLZED_INT)) {
576                 struct lpc_uart* uart = LPC_UART_1;
577                 uart->func.buffer = '/';
578         }
579         if (dev_intr & USB_EP_SLOW_INT) {
580                 uint32_t ep_intr = usb_dev->ep_int_status;
581                 uint32_t mask = 0x01; /* Mask for first physical endpoint */
582                 int i = 0;
583                 //UARTBUFFER[UARTPTR++] = '+';
584                 /* Call endpoint handler for each set endpoint */
585                 while ((i < USB_PHY_ENDPOINTS) && ep_intr) {
586                         if (ep_intr & mask) {
587                                 /* Get endpoint_logical_num | USB_DIR_* in info */
588                                 uint32_t info = ((i >> 1) | ((i & 0x01) << USB_DIR_SHIFT));
590                                 //UARTBUFFER[UARTPTR++] = HEXA[i%16];
591                                 /* Clear this interrupt to get the status */
592                                 usb_dev->ep_int_clear = mask;
593                                 ep_intr &= ~mask;
594                                 while ((usb_dev->dev_int_status & USB_CMD_DATA_FULL_INT) == 0);
595                                 /* Add the status to the endpoint and direction information in info */
596                                 info |= ((usb_dev->command_data & 0xff) << 8);
597                                 /* And call the handler */
598                                 usb_ep_handler(info);
599                         }
600                         mask = mask << 1;
601                         i++;
602                 }
603         }
604 #if 0
605         if (dev_intr & USB_FRAME_INT) {
606                 UARTBUFFER[UARTPTR++] = '-';
607                 /* Call the user handler ?
608                  * Note for OS : This should trigger an event for userspace rather than give
609                  *   the hand to some "user code" within an interrupt handler ! */
610                 usb_sof_handler(0);
611         }
612 #endif
613         if (dev_intr & USB_ERR_INT) {
614                 uint32_t err = (usb_get_dev_error_status() & 0xFF);
615                 err |= ((usb_get_dev_error_code() & 0xFF) << 8);
616                 /* Call the user handler ?
617                  * Note for OS : This should trigger an event for userspace rather than give
618                  *   the hand to some "user code" within an interrupt handler ! */
619                 usb_error_handler(err);
620         }
622 /* This one is not handled and should not be enabled ! */
623 void USB_Act_Handler(void)
625         NVIC_DisableIRQ(USB_ACT_IRQ);
629 /* Start USB sub-system
630  *  usb_on() MUST have been called, or the USB subsystem is not powered and PLL is not set
631  */
632 void usb_start(uint32_t usb_ctrl_endpoint_max_pkt_size)
634         usb_up();
635         usb_reset(usb_ctrl_endpoint_max_pkt_size);
636         usb_set_address(0);
637         /* Enable endpoints 0 and 1 */
638         usb_endpoint_reset(0, 0);
639         usb_endpoint_reset(0, 1);
640         usb_connect();