]> git.zerfleddert.de Git - fnordlicht-mini/blob - firmware/fnordlicht-controller/usb.c
reference firmware
[fnordlicht-mini] / firmware / fnordlicht-controller / usb.c
1 /* vim:ts=4 sts=4 et tw=80
2 *
3 * fnordlicht firmware
4 *
5 * for additional information please
6 * see http://lochraster.org/fnordlichtmini
7 *
8 * (c) by Alexander Neumann <alexander@bumpern.de>
9 *
10 * This program is free software: you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 3 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /* includes */
24 #include "globals.h"
25 #include "../common/io.h"
26
27 #include <stdint.h>
28 #include <stdbool.h>
29
30 #include "../common/common.h"
31 #include "usbdrv/usbdrv.h"
32 #include "timer.h"
33 #include "uart.h"
34 #include "ir.h"
35
36 static bool usb_status;
37
38 /* supply custom usbDeviceConnect() and usbDeviceDisconnect() macros
39 * which turn the interrupt on and off at the right times,
40 * and prevent the execution of an interrupt while the pullup resistor
41 * is switched off */
42 #ifdef USB_CFG_PULLUP_IOPORTNAME
43 #undef usbDeviceConnect
44 #define usbDeviceConnect() do { \
45 USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT); \
46 USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT); \
47 USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); \
48 } while(0);
49 #undef usbDeviceDisconnect
50 #define usbDeviceDisconnect() do { \
51 USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); \
52 USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT); \
53 USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT); \
54 } while(0);
55 #endif
56
57 #define USBRQ_SEND 1
58 #define USBRQ_IR_STATE 2
59 #define USBRQ_IR_READ 3
60
61 struct usb_state_t {
62 enum {
63 USB_STATE_IDLE = 0,
64 USB_STATE_SEND = 1,
65 } state;
66
67 usbMsgLen_t bytes_remaining;
68 };
69
70 struct usb_state_t usb;
71
72 USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8])
73 {
74 usbRequest_t *req = (void *)data;
75 usbMsgLen_t len = 0;
76 static uint8_t buf[8];
77
78 /* set global data pointer to local buffer */
79 usbMsgPtr = buf;
80
81 if (req->bRequest == USBRQ_SEND && req->wLength.word > 0) {
82 usb.state = USB_STATE_SEND;
83 if (req->wLength.word < 256) {
84 usb.bytes_remaining = req->wLength.bytes[0];
85 return USB_NO_MSG;
86 } else {
87 /* too long */
88 buf[0] = 1;
89 len = 1;
90 }
91 } else if (req->bRequest == USBRQ_IR_STATE) {
92 /* read or set state? */
93 if (req->bmRequestType & USBRQ_DIR_MASK) {
94 /* read */
95 buf[0] = ir_global.mode;
96 len = 1;
97 } else {
98 /* write */
99 uint8_t new_state = req->wValue.bytes[0];
100 if (new_state <= IR_RECEIVE)
101 ir_set_mode(new_state);
102 }
103 } else if (req->bRequest == USBRQ_IR_READ) {
104 if (ir_global.mode == IR_DISABLED) {
105 usbMsgPtr = (void *)ir_global.time;
106 return 2*ir_global.pos;
107 }
108 }
109
110 return len;
111 }
112
113 uchar usbFunctionWrite(uchar *data, uchar len)
114 {
115 if (len > usb.bytes_remaining)
116 len = usb.bytes_remaining;
117
118 usb.bytes_remaining -= len;
119
120 while (len--) {
121 /* ugly hack: busy wait until the fifo is ready for another byte... */
122 while (fifo_full(&global_uart.tx));
123 uart_putc(*data++);
124 }
125
126 if (usb.bytes_remaining == 0) {
127 return true;
128 usb.state == USB_STATE_IDLE;
129 } else
130 return len;
131 }
132
133 void usb_init(void)
134 {
135 usbInit();
136 }
137
138 void usb_enable(void)
139 {
140 usbDeviceConnect();
141 usb_status = true;
142 }
143
144 void usb_disable(void)
145 {
146 usbDeviceDisconnect();
147 usb_status = false;
148 }
149
150 bool usb_enabled(void)
151 {
152 return usb_status;
153 }
154
155 void usb_poll(void)
156 {
157 if (usb_status)
158 usbPoll();
159 }
Impressum, Datenschutz