Mercurial > ~darius > hgwebdir.cgi > avr
annotate usb.c @ 48:94f71ddb0cda
Move declaration of error table up with the function declarations.
author | darius@Inchoate |
---|---|
date | Wed, 29 Oct 2008 16:03:16 +1030 |
parents | 5898fba6593c |
children |
rev | line source |
---|---|
23 | 1 #include <stdlib.h> |
2 #include <avr/io.h> | |
3 #include <avr/pgmspace.h> | |
4 #include <avr/interrupt.h> | |
5 #include <avr/eeprom.h> | |
6 #include <util/delay.h> | |
7 | |
8 #include "usb.h" | |
31 | 9 #include "1wire.h" |
23 | 10 |
31 | 11 /* Maximum FIFO sizes for each endpoint */ |
12 #define EP0_FIFO_SZ 16 | |
13 #define EP1_FIFO_SZ 16 | |
14 #define EP2_FIFO_SZ 64 | |
23 | 15 |
31 | 16 /* PDIUSBD12 mode */ |
23 | 17 #define D12_MODE_0 0x14 /* Endpoint config = 0, SoftConnect = 1, IRQ Mode = 1, |
18 * Clock running = 0, No Lazy Clock = 0 | |
19 */ | |
20 #define D12_MODE_1 0x02 /* SOF mode = 0, Set-to-one = 0, Clock div = 2 (16Mhz) */ | |
31 | 21 |
23 | 22 /* Debugging stuff */ |
23 void uart_putsP(const char *addr); | |
24 void uart_puts(const char *addr); | |
25 int uart_putc(char c); | |
26 void uart_puts_dec(uint8_t a, uint8_t l); | |
27 void uart_puts_hex(uint8_t a); | |
28 | |
31 | 29 void parsebuf(uint8_t *buffer, uint8_t ep); |
30 | |
23 | 31 /* USB administrivia */ |
32 uint8_t deviceaddress; | |
33 uint8_t deviceconfigured; | |
34 | |
31 | 35 /* Endpoint buffers and such */ |
36 /* EP0 in */ | |
37 static const uint8_t *sendbuffer0; | |
38 static uint8_t sendbytes0; | |
39 | |
40 /* EP0 out */ | |
41 /* This is unbuffered as we don't handle packets > EP0_FIFO_SZ */ | |
23 | 42 |
31 | 43 /* EP1 */ |
44 /* Unbuffered as yet */ | |
45 static uint8_t packet1[270]; | |
46 static uint16_t packetlen1; | |
23 | 47 |
31 | 48 /* EP2 in */ |
49 static const uint8_t *sendbuffer2; | |
50 static uint8_t sendbytes2; | |
51 | |
52 /* EP2 out */ | |
23 | 53 static uint8_t packet2[270]; |
54 static uint16_t packetlen2; | |
55 | |
56 /* XXX: Not actually used */ | |
57 void (*bootloader)(void) = (void*)0xe000; | |
58 | |
59 /* Device/endpoint/etc descriptions */ | |
60 const USB_DEVICE_DESCRIPTOR DeviceDescriptor = { | |
61 sizeof(USB_DEVICE_DESCRIPTOR), /* bLength */ | |
62 TYPE_DEVICE_DESCRIPTOR, /* bDescriptorType */ | |
63 0x0110, /* bcdUSB USB Version 1.1 */ | |
64 0, /* bDeviceClass */ | |
65 0, /* bDeviceSubclass */ | |
66 0, /* bDeviceProtocol */ | |
31 | 67 EP0_FIFO_SZ, /* bMaxPacketSize in Bytes */ |
68 0x4753, /* idVendor (unofficial GS) */ | |
23 | 69 0x0001, /* idProduct */ |
70 0x0100, /* bcdDevice */ | |
71 1, /* iManufacturer String Index */ | |
72 2, /* iProduct String Index */ | |
73 3, /* iSerialNumber String Index */ | |
74 1 /* bNumberConfigurations */ | |
75 }; | |
76 | |
77 const USB_CONFIG_DATA ConfigurationDescriptor = { | |
78 { /* configuration descriptor */ | |
79 sizeof(USB_CONFIGURATION_DESCRIPTOR), /* bLength */ | |
80 TYPE_CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ | |
81 sizeof(USB_CONFIG_DATA), /* wTotalLength */ | |
82 2, /* bNumInterfaces */ | |
83 1, /* bConfigurationValue */ | |
84 0, /* iConfiguration String Index */ | |
85 0x80, /* bmAttributes Bus Powered, No Remote Wakeup */ | |
86 100/2 /* bMaxPower in mA */ | |
87 }, | |
88 { /* interface descriptor */ | |
89 sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */ | |
90 TYPE_INTERFACE_DESCRIPTOR, /* bDescriptorType */ | |
91 0, /* bInterface Number */ | |
92 0, /* bAlternateSetting */ | |
93 2, /* bNumEndpoints */ | |
31 | 94 0xff, /* bInterfaceClass (Vendor specific) */ |
23 | 95 0x02, /* bInterfaceSubClass */ |
96 0x00, /* bInterfaceProtocol */ | |
97 0 /* iInterface String Index */ | |
98 }, | |
99 { /* endpoint descriptor */ | |
100 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
101 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
102 0x02, /* bEndpoint Address EP2 OUT */ | |
103 0x02, /* bmAttributes - Bulk */ | |
104 0x0040, /* wMaxPacketSize */ | |
105 0x00 /* bInterval */ | |
106 }, | |
107 { /* endpoint descriptor */ | |
108 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
109 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
110 0x82, /* bEndpoint Address EP2 IN */ | |
111 0x02, /* bmAttributes - Bulk */ | |
112 0x0040, /* wMaxPacketSize */ | |
113 0x00 /* bInterval */ | |
114 }, | |
115 { /* interface descriptor */ | |
116 sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */ | |
117 TYPE_INTERFACE_DESCRIPTOR, /* bDescriptorType */ | |
118 1, /* bInterface Number */ | |
119 0, /* bAlternateSetting */ | |
120 2, /* bNumEndpoints */ | |
31 | 121 0xff, /* bInterfaceClass (Vendor specific) */ |
23 | 122 0x02, /* bInterfaceSubClass */ |
123 0x00, /* bInterfaceProtocol */ | |
124 0 /* iInterface String Index */ | |
125 }, | |
126 { /* endpoint descriptor */ | |
127 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
128 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
129 0x01, /* bEndpoint Address EP1 OUT */ | |
130 0x02, /* bmAttributes - Bulk */ | |
131 0x0010, /* wMaxPacketSize */ | |
132 0x00 /* bInterval */ | |
133 }, | |
134 { /* endpoint descriptor */ | |
135 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
136 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
137 0x81, /* bEndpoint Address EP1 IN */ | |
138 0x02, /* bmAttributes - Bulk */ | |
139 0x0010, /* wMaxPacketSize */ | |
140 0x00 /* bInterval */ | |
141 } | |
142 }; | |
143 const LANGID_DESCRIPTOR LANGID_Descriptor = { /* LANGID String Descriptor | |
144 * Zero */ | |
145 sizeof(LANGID_DESCRIPTOR), /* bLength - must match string below */ | |
146 TYPE_STRING_DESCRIPTOR, /* bDescriptorType */ | |
147 0x0409 /* LANGID US English */ | |
148 }; | |
149 | |
26 | 150 STRING_DESCRIPTOR Manufacturer_Descriptor = { |
151 sizeof(STRING_DESCRIPTOR) + 32, /* bLength */ | |
152 TYPE_STRING_DESCRIPTOR, /* bDescriptorType */ | |
153 "G\0e\0n\0e\0s\0i\0s\0 \0S\0o\0f\0t\0w\0a\0r\0e\0" /* ManufacturerString in | |
154 * UNICODE */ | |
23 | 155 }; |
156 | |
26 | 157 STRING_DESCRIPTOR Product_Descriptor = { |
158 sizeof(STRING_DESCRIPTOR) + 48, /* bLength */ | |
23 | 159 TYPE_STRING_DESCRIPTOR, /* bDescriptorType */ |
160 /* ProductString in | |
161 * UNICODE */ | |
162 "R\0S\0""-\0""4\0""8\0""5\0"" \0M\0u\0l\0t\0i\0d\0r\0o\0p\0 \0A\0d\0a\0p\0t\0e\0r\0" | |
163 /* XXX: dunno why I need the double quote magic above.. */ | |
26 | 164 }; |
23 | 165 |
26 | 166 STRING_DESCRIPTOR Serial_Descriptor; |
167 STRING_DESCRIPTOR EE_Serial_Descriptor __attribute__ ((section (".eeprom"))) = { /* SerialString 3 */ | |
168 sizeof(STRING_DESCRIPTOR) + 20, /* bLength - must match string below */ | |
23 | 169 TYPE_STRING_DESCRIPTOR, /* bDescriptorType */ |
170 "1\02\03\0" | |
171 }; | |
172 | |
31 | 173 /******************************************************************************* |
174 ** d12_get_data | |
175 ** | |
176 ** Read a data byte | |
177 */ | |
23 | 178 uint8_t |
179 d12_get_data(void) { | |
180 uint8_t data; | |
26 | 181 |
31 | 182 _delay_us(1); |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
183 PDICTL &= ~_BV(PDIA0); /* Data phase */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
184 PDIDDR = 0x00; /* Set to input */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
185 PDICTL &= ~_BV(PDIRD); /* Pull RD_N low */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
186 PDICTL &= ~_BV(PDIRD); /* Delay 40ns */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
187 PDICTL &= ~_BV(PDIRD); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
188 PDICTL &= ~_BV(PDIRD); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
189 data = PINA; /* Read the data */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
190 PDICTL |= _BV(PDIRD); /* Pull RD_N high */ |
31 | 191 |
23 | 192 return(data); |
193 } | |
194 | |
31 | 195 /******************************************************************************* |
196 ** d12_set_data | |
197 ** | |
198 ** Write a data byte | |
199 */ | |
23 | 200 void |
31 | 201 d12_set_data(uint8_t data) { |
202 _delay_us(1); | |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
203 PDICTL &= ~_BV(PDIA0); /* Data phase */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
204 PDIDDR = 0xff; /* Set to output */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
205 PDIPORT = data; /* Put the data on the bus */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
206 PDICTL &= ~_BV(PDIWR); /* Pull WR_N low */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
207 PDICTL &= ~_BV(PDIWR); /* Delay 40ns */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
208 PDICTL &= ~_BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
209 PDICTL &= ~_BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
210 PDICTL |= _BV(PDIWR); /* Pull WR_N high */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
211 PDICTL |= _BV(PDIWR); /* Delay 40 ns */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
212 PDICTL |= _BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
213 PDICTL |= _BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
214 PDIDDR = 0x00; /* Back to input */ |
23 | 215 } |
216 | |
31 | 217 /******************************************************************************* |
218 ** d12_set_cmd | |
219 ** | |
220 ** Start a command | |
221 */ | |
23 | 222 void |
31 | 223 d12_set_cmd(uint8_t cmd) { |
224 _delay_us(1); | |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
225 PDICTL |= _BV(PDIA0); /* Command phase */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
226 PDIDDR = 0xff; /* Set to output */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
227 PDIPORT = cmd; /* Put the data on the bus */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
228 PDICTL &= ~_BV(PDIWR); /* Pull WR_N low */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
229 PDICTL &= ~_BV(PDIWR); /* Delay 40ns */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
230 PDICTL &= ~_BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
231 PDICTL &= ~_BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
232 PDICTL |= _BV(PDIWR); /* Pull WR_N high */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
233 PDICTL |= _BV(PDIWR); /* Delay 40ns */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
234 PDICTL |= _BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
235 PDICTL |= _BV(PDIWR); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
236 PDIDDR = 0x00; /* Back to input */ |
23 | 237 } |
238 | |
31 | 239 /******************************************************************************* |
240 ** d12_write_cmd | |
241 ** | |
242 ** Issue a command with associated data | |
243 */ | |
23 | 244 void |
245 d12_write_cmd(uint8_t command, const uint8_t *buffer, uint8_t count) { | |
246 uint8_t i; | |
247 | |
31 | 248 d12_set_cmd(command); |
23 | 249 if (count) { |
250 for (i = 0; i < count; i++) { | |
31 | 251 d12_set_data(buffer[i]); |
23 | 252 } |
253 } | |
254 } | |
255 | |
31 | 256 /******************************************************************************* |
257 ** d12_read_cmd | |
258 ** | |
259 ** Issue a command and read back the data | |
260 */ | |
23 | 261 void |
262 d12_read_cmd(uint8_t command, uint8_t *buffer, uint8_t count) { | |
263 uint8_t i; | |
264 | |
31 | 265 d12_set_cmd(command); |
23 | 266 if (count) { |
267 for (i = 0; i < count; i++) { | |
268 buffer[i] = d12_get_data(); | |
269 } | |
270 } | |
271 } | |
272 | |
31 | 273 /******************************************************************************* |
274 ** usb_init | |
275 ** | |
276 ** Configure the PDIUSBD12 | |
277 */ | |
23 | 278 void |
279 usb_init(void) { | |
280 uint8_t buffer[2]; | |
281 | |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
282 /* Check the device is present */ |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
283 d12_read_cmd(D12_READ_CHIP_ID, buffer, 2); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
284 if (buffer[0] != 0x12 || buffer[1] != 0x10) { |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
285 uart_putsP(PSTR("PDIUSBD12 does not appear to be present/working, chip ID = 0x")); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
286 uart_puts_hex(buffer[0]); |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
287 uart_puts_hex(buffer[1]); |
41 | 288 uart_putsP(PSTR(", expected 0x1210\r\n")); |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
289 return; |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
290 } |
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
291 |
23 | 292 /* pull EE_Serial_Descriptor into RAM */ |
26 | 293 eeprom_read_block(&Serial_Descriptor, &EE_Serial_Descriptor, EE_Serial_Descriptor.bLength); |
23 | 294 |
295 /* Set Address to zero (default) and enable function */ | |
296 buffer[0] = 0x80; | |
297 d12_write_cmd(D12_SET_ADDRESS_ENABLE, buffer, 1); | |
298 | |
299 /* Enable function generic endpoints */ | |
300 buffer[0] = 0x01; | |
301 d12_write_cmd(D12_SET_ENDPOINT_ENABLE, buffer, 1); | |
302 | |
303 /* Configure the device (soft connect off) */ | |
304 buffer[0] = D12_MODE_0 & 0xef; | |
305 buffer[1] = D12_MODE_1; | |
306 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
307 | |
308 /* Delay long enough for the PC to notice the disconnect */ | |
309 _delay_us(1000); | |
310 | |
311 buffer[0] |= 0x10; /* Soft connect on */ | |
312 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
313 | |
314 /* Endpoint 2 IN/OUT IRQ enable */ | |
315 buffer[0] = 0xc0; | |
316 d12_write_cmd(D12_SET_DMA, buffer, 1); | |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
317 |
23 | 318 } |
319 | |
31 | 320 /******************************************************************************* |
321 ** usb_intr | |
322 ** | |
323 ** Process any pending interrupts | |
324 */ | |
23 | 325 void |
326 usb_intr(void) { | |
327 uint8_t irq[2]; | |
328 uint8_t buffer[8]; | |
329 | |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
330 d12_read_cmd(D12_READ_INTERRUPT_REGISTER, irq, 2); |
23 | 331 |
332 /* Why do we get interrupts when this is 0? */ | |
333 if (irq[0] == 0) | |
334 return; | |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
335 |
41 | 336 uart_putsP(PSTR("usb_intr() called\r\n")); |
23 | 337 |
338 if (irq[0] & D12_INT_BUS_RESET) { | |
41 | 339 uart_putsP(PSTR("Bus reset\r\n")); |
23 | 340 usb_init(); |
341 return; | |
342 } | |
343 | |
344 if (irq[0] & D12_INT_SUSPEND) { | |
41 | 345 uart_putsP(PSTR("Suspend change\r\n")); |
23 | 346 } |
347 | |
348 if (irq[0] & D12_INT_EP0_IN) { | |
349 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP0_IN, buffer, 1); | |
31 | 350 if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) { |
351 uart_putsP(PSTR("EP0_IN error ")); | |
352 uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1); | |
41 | 353 uart_putsP(PSTR("\r\n")); |
31 | 354 } |
23 | 355 |
356 /* Handle any outgoing data for EP0 */ | |
31 | 357 d12_send_data_ep0(); |
23 | 358 } |
359 | |
360 /* Handle configuration and misc stuff */ | |
361 if (irq[0] & D12_INT_EP0_OUT) { | |
31 | 362 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP0_OUT, buffer, 1); |
363 if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) { | |
364 uart_putsP(PSTR("EP0_OUT error ")); | |
365 uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1); | |
41 | 366 uart_putsP(PSTR("\r\n")); |
31 | 367 } |
368 | |
369 if (buffer[0] & D12_LAST_TRAN_SETUP) | |
370 d12_handle_setup(); | |
371 else { | |
372 /* Data packet */ | |
373 } | |
23 | 374 } |
375 | |
376 /* EPx_IN is when the host has had a packet of data and is expecting more */ | |
377 if (irq[0] & D12_INT_EP1_IN) { | |
31 | 378 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP1_IN, buffer, 1); |
379 if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) { | |
380 uart_putsP(PSTR("EP1_IN error ")); | |
381 uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1); | |
41 | 382 uart_putsP(PSTR("\r\n")); |
31 | 383 } |
384 | |
385 /* Select endpoint */ | |
386 d12_read_cmd(D12_ENDPOINT_EP1_IN, buffer, 1); | |
387 | |
388 if (buffer[0] & 0x01) | |
41 | 389 uart_putsP(PSTR("EP1_IN is full\r\n")); |
31 | 390 |
391 if (buffer[0] & 0x02) | |
41 | 392 uart_putsP(PSTR("EP1_IN is stalled\r\n")); |
31 | 393 |
394 d12_write_endpt(D12_ENDPOINT_EP1_IN, NULL, 0); | |
23 | 395 } |
396 | |
397 /* EPx_OUT is when we have gotten a packet from the host */ | |
398 if (irq[0] & D12_INT_EP1_OUT) { | |
31 | 399 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP1_OUT, buffer, 1); |
400 if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) { | |
401 uart_putsP(PSTR("EP1_OUT error ")); | |
402 uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1); | |
41 | 403 uart_putsP(PSTR("\r\n")); |
31 | 404 } |
405 | |
406 d12_receive_data_ep1(); | |
23 | 407 } |
408 | |
31 | 409 if (irq[0] & D12_INT_EP2_IN) { |
23 | 410 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP2_IN, buffer, 1); |
31 | 411 if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) { |
412 uart_putsP(PSTR("EP2_IN error ")); | |
413 uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1); | |
41 | 414 uart_putsP(PSTR("\r\n")); |
31 | 415 } |
416 | |
23 | 417 d12_send_data_ep2(); |
418 } | |
419 | |
420 if (irq[0] & D12_INT_EP2_OUT) { | |
421 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP2_OUT, buffer, 1); | |
31 | 422 if ((buffer[0] & D12_LAST_TRAN_ERRMSK) != 0) { |
423 uart_putsP(PSTR("EP2_OUT error ")); | |
424 uart_puts_hex((buffer[0] & D12_LAST_TRAN_ERRMSK) >> 1); | |
41 | 425 uart_putsP(PSTR("\r\n")); |
31 | 426 } |
23 | 427 d12_receive_data_ep2(); |
428 } | |
429 } | |
430 | |
31 | 431 /******************************************************************************* |
432 ** usb_gendata | |
433 ** | |
434 ** Fake up some data for testing purposes | |
435 */ | |
23 | 436 void |
437 usb_gendata(void) { | |
438 packet2[0] = 'a'; | |
439 packet2[1] = 'b'; | |
440 packet2[2] = 'c'; | |
441 packet2[3] = '\n'; | |
442 packet2[4] = '\r'; | |
31 | 443 sendbytes2 = 5; |
444 sendbuffer2 = (uint8_t *)&packet2[0]; | |
23 | 445 |
446 /* Kick off the data transfer */ | |
447 d12_send_data_ep2(); | |
448 } | |
449 | |
31 | 450 /******************************************************************************* |
451 ** d12_handle_setup | |
452 ** | |
453 ** Handle setup packet stuff for endpoint 0 | |
454 */ | |
23 | 455 void |
31 | 456 d12_handle_setup(void) { |
23 | 457 uint8_t buffer[2]; |
458 USB_SETUP_REQUEST setuppkt; | |
459 | |
31 | 460 /* Read the setup packet */ |
461 d12_read_endpt(D12_ENDPOINT_EP0_OUT, (uint8_t *)&setuppkt); | |
462 | |
463 /* Ack the packet to EP0_OUT */ | |
464 d12_write_cmd(D12_ENDPOINT_EP0_OUT, NULL, 0); | |
465 d12_write_cmd(D12_ACK_SETUP, NULL, 0); | |
466 d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0); | |
23 | 467 |
31 | 468 /* Ack the packet to EP0_IN */ |
469 d12_write_cmd(D12_ENDPOINT_EP0_IN, NULL, 0); | |
470 d12_write_cmd(D12_ACK_SETUP, NULL, 0); | |
23 | 471 |
31 | 472 /* Parse request type */ |
473 switch (setuppkt.bmRequestType & 0x7f) { | |
474 case STANDARD_DEVICE_REQUEST: | |
475 switch (setuppkt.bRequest) { | |
476 case GET_STATUS: | |
477 /* Get status request should return remote | |
478 * wakeup and self powered status | |
479 */ | |
480 buffer[0] = 0x01; | |
481 buffer[1] = 0x00; | |
482 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2); | |
483 break; | |
484 case CLEAR_FEATURE: | |
485 case SET_FEATURE: | |
486 /* We don't support DEVICE_REMOTE_WAKEUP or | |
487 * TEST_MODE | |
488 */ | |
489 | |
490 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
491 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
492 break; | |
23 | 493 |
31 | 494 case SET_ADDRESS: |
495 deviceaddress = setuppkt.wValue | 0x80; | |
496 d12_write_cmd(D12_SET_ADDRESS_ENABLE, &deviceaddress, 1); | |
497 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
498 break; | |
23 | 499 |
31 | 500 case GET_DESCRIPTOR: |
501 d12_getdescriptor(&setuppkt); | |
502 break; | |
23 | 503 |
31 | 504 case GET_CONFIGURATION: |
505 d12_write_endpt(D12_ENDPOINT_EP0_IN, &deviceconfigured, 1); | |
506 break; | |
23 | 507 |
31 | 508 case SET_CONFIGURATION: |
509 deviceconfigured = setuppkt.wValue & 0xff; | |
510 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
511 break; | |
23 | 512 |
513 | |
31 | 514 case SET_DESCRIPTOR: |
515 default: | |
516 /* Unsupported, stall */ | |
517 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
518 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
519 break; | |
520 } | |
521 break; | |
23 | 522 |
31 | 523 case STANDARD_INTERFACE_REQUEST: |
524 switch (setuppkt.bRequest) { | |
525 case GET_STATUS: | |
526 /* Should return 0, 0 (reserved) */ | |
527 buffer[0] = 0x00; | |
528 buffer[1] = 0x00; | |
529 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2); | |
530 break; | |
531 | |
532 case SET_INTERFACE: | |
533 if (setuppkt.wIndex == 0 && setuppkt.wValue == 0) | |
534 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
535 else { | |
536 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
537 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
538 } | |
539 | |
540 break; | |
541 | |
542 case GET_INTERFACE: | |
543 /* Can only handle interface 0 ... */ | |
544 if (setuppkt.wIndex == 0) { | |
545 buffer[0] = 0; | |
546 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 1); | |
23 | 547 break; |
31 | 548 } |
549 /* .. otherwise fall through to error */ | |
23 | 550 |
31 | 551 case CLEAR_FEATURE: |
552 case SET_FEATURE: | |
553 default: | |
554 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
555 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
556 break; | |
557 } | |
558 break; | |
559 | |
560 case STANDARD_ENDPOINT_REQUEST: | |
561 switch (setuppkt.bRequest) { | |
562 case CLEAR_FEATURE: | |
563 case SET_FEATURE: | |
564 /* Halt(stall) is required to be implemented on | |
565 * interrupt and bulk endpoints. | |
566 */ | |
567 if (setuppkt.wValue == ENDPOINT_HALT) { | |
568 if (setuppkt.bRequest == CLEAR_FEATURE) | |
569 buffer[0] = 0x00; | |
570 else | |
571 buffer[0] = 0x01; | |
23 | 572 switch (setuppkt.wIndex & 0xFF) { |
573 case 0x01: | |
31 | 574 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ |
575 D12_ENDPOINT_EP1_OUT, buffer, 1); | |
23 | 576 break; |
577 case 0x81: | |
31 | 578 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ |
579 D12_ENDPOINT_EP1_IN, buffer, 1); | |
23 | 580 break; |
581 case 0x02: | |
31 | 582 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ |
583 D12_ENDPOINT_EP2_OUT, buffer, 1); | |
23 | 584 break; |
585 case 0x82: | |
31 | 586 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ |
587 D12_ENDPOINT_EP2_IN, buffer, 1); | |
23 | 588 break; |
589 default: /* Invalid Endpoint - | |
31 | 590 * RequestError */ |
591 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
592 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
23 | 593 break; |
594 } | |
595 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
31 | 596 } else { |
597 /* | |
598 * No other Features for Endpoint - | |
599 * Request Error | |
600 */ | |
601 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
602 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
603 } | |
23 | 604 break; |
605 | |
31 | 606 case GET_STATUS: |
607 /* | |
608 * Get Status Request to Endpoint should | |
609 * return Halt Status in D0 for Interrupt and Bulk | |
610 */ | |
611 switch (setuppkt.wIndex & 0xFF) { | |
612 case 0x01: | |
613 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
614 D12_ENDPOINT_EP1_OUT, buffer, 1); | |
615 break; | |
616 case 0x81: | |
617 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
618 D12_ENDPOINT_EP1_IN, buffer, 1); | |
619 break; | |
620 case 0x02: | |
621 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
622 D12_ENDPOINT_EP2_OUT, buffer, 1); | |
623 break; | |
624 case 0x82: | |
625 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
626 D12_ENDPOINT_EP2_IN, buffer, 1); | |
627 break; | |
628 default: /* Invalid Endpoint - | |
629 * RequestError */ | |
630 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
631 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
632 break; | |
633 } | |
634 if (buffer[0] & 0x08) | |
635 buffer[0] = 0x01; | |
636 else | |
637 buffer[0] = 0x00; | |
638 buffer[1] = 0x00; | |
639 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2); | |
23 | 640 break; |
641 | |
642 default: | |
31 | 643 /* Unsupported - Request Error - Stall */ |
644 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
645 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
646 break; | |
23 | 647 } |
31 | 648 break; |
649 case VENDOR_DEVICE_REQUEST: | |
650 case VENDOR_ENDPOINT_REQUEST: | |
651 switch (setuppkt.bRequest) { | |
652 case VENDOR_RESET: | |
653 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
654 _delay_us(1000); | |
655 /* disconnect from USB */ | |
656 buffer[0] = D12_MODE_0 & 0xef; | |
657 buffer[1] = D12_MODE_1; | |
658 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
659 _delay_us(1000); | |
660 cli(); | |
661 reset(); | |
662 /* NOT REACHED */ | |
663 break; | |
664 | |
665 case VENDOR_UPDATE: | |
666 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
667 _delay_us(1000); | |
668 /* disconnect from USB */ | |
669 buffer[0] = D12_MODE_0 & 0xef; | |
670 buffer[1] = D12_MODE_1; | |
671 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
672 _delay_us(1000); | |
673 cli(); | |
674 bootloader(); | |
675 /* NOT REACHED */ | |
676 break; | |
677 | |
678 default: | |
679 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
680 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
681 break; | |
23 | 682 } |
31 | 683 break; |
684 case VENDOR_INTERFACE_REQUEST: | |
685 switch (setuppkt.bRequest) { | |
686 default: | |
687 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
688 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
689 break; | |
690 } | |
23 | 691 break; |
692 default: | |
31 | 693 d12_stallendpt(D12_ENDPOINT_EP0_IN); |
694 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
23 | 695 break; |
696 } | |
697 } | |
698 | |
699 | |
31 | 700 /******************************************************************************* |
701 ** reset | |
702 ** | |
703 ** Reset the micro by triggering the watchdog timer. | |
704 ** | |
705 */ | |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
706 void |
31 | 707 reset(void) { |
41 | 708 uart_putsP(PSTR("Resetting!\r\n")); |
31 | 709 _delay_us(1000); |
710 | |
711 /* Disable the interrupts */ | |
712 MCUCR = _BV(IVCE); | |
713 MCUCR = 0; | |
714 | |
715 /* Enable watchdog, smallest prescaler */ | |
716 WDTCR = _BV(WDE); | |
717 | |
718 /* Wait for oblivion! */ | |
719 for (;;) | |
720 ; | |
721 } | |
722 | |
723 /******************************************************************************* | |
724 ** d12_getdescriptor | |
725 ** | |
726 ** Handle returning the various descriptor to the host | |
727 ** | |
728 ** Note: that we need to truncate the request because the host first | |
729 ** requests the first 2 bytes to find out then size, then requests the | |
730 ** rest. | |
731 */ | |
23 | 732 void |
31 | 733 d12_getdescriptor(USB_SETUP_REQUEST *setuppkt) { |
734 switch ((setuppkt->wValue & 0xff00) >> 8) { | |
735 case TYPE_DEVICE_DESCRIPTOR: | |
736 sendbuffer0 = (const uint8_t *)&DeviceDescriptor; | |
737 sendbytes0 = DeviceDescriptor.bLength; | |
738 if (sendbytes0 >= setuppkt->wLength) | |
739 sendbytes0 = setuppkt->wLength; | |
740 | |
741 d12_send_data_ep0(); | |
742 break; | |
743 | |
744 case TYPE_CONFIGURATION_DESCRIPTOR: | |
745 sendbuffer0 = (const uint8_t *)&ConfigurationDescriptor; | |
746 sendbytes0 = sizeof(ConfigurationDescriptor); | |
747 if (sendbytes0 >= setuppkt->wLength) | |
748 sendbytes0 = setuppkt->wLength; | |
749 | |
750 d12_send_data_ep0(); | |
751 break; | |
752 | |
753 case TYPE_STRING_DESCRIPTOR: | |
754 switch (setuppkt->wValue & 0xFF) { | |
755 case 0: | |
756 sendbuffer0 = (const uint8_t *)&LANGID_Descriptor; | |
757 sendbytes0 = LANGID_Descriptor.bLength; | |
758 break; | |
759 | |
760 case 1: | |
761 sendbuffer0 = (const uint8_t *)&Manufacturer_Descriptor; | |
762 sendbytes0 = Manufacturer_Descriptor.bLength; | |
763 break; | |
764 | |
765 case 2: | |
766 sendbuffer0 = (const uint8_t *)&Product_Descriptor; | |
767 sendbytes0 = Product_Descriptor.bLength; | |
768 break; | |
769 | |
770 case 3: | |
771 sendbuffer0 = (const uint8_t *)&Serial_Descriptor; | |
772 sendbytes0 = Serial_Descriptor.bLength; | |
773 break; | |
774 | |
775 default: | |
776 sendbuffer0 = NULL; | |
777 sendbytes0 = 0; | |
778 } | |
779 if (sendbytes0 >= setuppkt->wLength) | |
780 sendbytes0 = setuppkt->wLength; | |
781 | |
782 d12_send_data_ep0(); | |
783 break; | |
784 | |
785 default: | |
786 d12_stallendpt(D12_ENDPOINT_EP0_IN); | |
787 d12_stallendpt(D12_ENDPOINT_EP0_OUT); | |
788 break; | |
789 } | |
790 } | |
791 | |
792 /******************************************************************************* | |
793 ** d12_stallendpt | |
794 ** | |
795 ** Stall the nominated endpoint. | |
796 ** | |
797 */ | |
798 void | |
799 d12_stallendpt(uint8_t ep) { | |
800 uint8_t buffer[] = {0x01}; | |
801 | |
802 d12_write_cmd(D12_SET_ENDPOINT_STATUS + ep, buffer, 1); | |
23 | 803 } |
804 | |
31 | 805 /******************************************************************************* |
806 ** d12_read_cmd | |
807 ** | |
808 ** Read data from the nominated endpoint if it's full. | |
809 ** | |
810 */ | |
23 | 811 uint8_t |
812 d12_read_endpt(uint8_t endpt, uint8_t *buffer) { | |
31 | 813 uint8_t d12header[2], status, i; |
23 | 814 |
31 | 815 d12header[1] = 0; |
816 | |
23 | 817 /* Select Endpoint */ |
818 d12_read_cmd(endpt, &status, 1); | |
819 | |
31 | 820 /* Check if buffer is Full */ |
23 | 821 if (status & 0x01) { |
31 | 822 d12_set_cmd(D12_READ_BUFFER); |
23 | 823 d12header[0] = d12_get_data(); |
824 d12header[1] = d12_get_data(); | |
825 if (d12header[1]) { | |
826 for (i = 0; i < d12header[1]; i++) | |
827 buffer[i] = d12_get_data(); | |
828 } | |
829 /* Allow new packets to be accepted */ | |
830 d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0); | |
831 | |
832 } | |
833 return d12header[1]; | |
834 } | |
835 | |
31 | 836 /******************************************************************************* |
837 ** d12_read_cmd | |
838 ** | |
839 ** Write data to the nominated endpoint. | |
840 ** | |
841 */ | |
23 | 842 void |
843 d12_write_endpt(uint8_t endpt, const uint8_t *buffer, uint8_t bytes) { | |
31 | 844 uint8_t status, i; |
23 | 845 |
846 /* Select Endpoint */ | |
847 d12_read_cmd(endpt, &status, 1); | |
31 | 848 if ((status & 0x01) != 0) { |
849 uart_putsP(PSTR("Endpoint ")); | |
850 uart_puts_dec(endpt / 2, 0); | |
41 | 851 uart_putsP(PSTR(" IN is full..\r\n")); |
23 | 852 return; |
853 } | |
854 | |
31 | 855 /* Write Header */ |
856 d12_set_cmd(D12_WRITE_BUFFER); | |
857 d12_set_data(0x00); | |
858 d12_set_data(bytes); | |
859 /* Write Packet */ | |
860 if (bytes) { | |
861 for (i = 0; i < bytes; i++) | |
862 d12_set_data(buffer[i]); | |
863 } | |
864 /* Validate buffer */ | |
865 d12_write_cmd(D12_VALIDATE_BUFFER, NULL, 0); | |
866 } | |
867 | |
868 /******************************************************************************* | |
869 ** d12_send_data_ep0 | |
870 ** | |
871 ** Send the next FIFOs worth of data to the endpoint and update the | |
872 ** pointer and counters. | |
873 ** | |
874 ** d12_send_data_epX should be collapsed together but it's more | |
875 ** complex than it looks. | |
876 ** | |
877 */ | |
878 void | |
879 d12_send_data_ep0(void) { | |
880 uint8_t status; | |
881 | |
882 /* Select endpoint */ | |
883 d12_read_cmd(D12_ENDPOINT_EP0_IN, &status, 1); | |
884 | |
885 if (status & 0x01) /* Bail if the buffer is full */ | |
886 return; | |
887 | |
888 if (sendbytes0 == 0) { | |
889 /* Nothing to do */ | |
890 } else if (sendbytes0 >= EP0_FIFO_SZ) { | |
891 /* Write another EP0_FIFO_SZ Bytes to buffer and send */ | |
892 d12_write_endpt(D12_ENDPOINT_EP0_IN, sendbuffer0, EP0_FIFO_SZ); | |
893 sendbuffer0 += EP0_FIFO_SZ; | |
894 sendbytes0 -= EP0_FIFO_SZ; | |
895 } else { | |
896 /* Buffer must have less than EP0_FIFO_SZ bytes left */ | |
897 d12_write_endpt(D12_ENDPOINT_EP0_IN, sendbuffer0, sendbytes0); | |
898 sendbytes0 = 0; | |
899 } | |
900 } | |
901 | |
902 /******************************************************************************* | |
903 ** d12_send_data_ep2 | |
904 ** | |
905 ** Send the next FIFOs worth of data to the endpoint and update the | |
906 ** pointer and counters. | |
907 ** | |
908 */ | |
909 void | |
910 d12_send_data_ep2(void) { | |
911 uint8_t status; | |
912 | |
913 /* Select endpoint */ | |
914 d12_read_cmd(D12_ENDPOINT_EP2_IN, &status, 1); | |
915 | |
916 if (status & 0x01) /* Bail if the buffer is full */ | |
917 return; | |
918 | |
919 if (sendbytes2 == 0) { | |
920 /* Nothing to do */ | |
921 } else if (sendbytes2 >= EP2_FIFO_SZ) { | |
922 /* Write another EP2_FIFO_SZ Bytes to buffer and send */ | |
923 d12_write_endpt(D12_ENDPOINT_EP2_IN, sendbuffer2, EP2_FIFO_SZ); | |
924 sendbuffer2 += EP2_FIFO_SZ; | |
925 sendbytes2 -= EP2_FIFO_SZ; | |
23 | 926 } else { |
31 | 927 /* Buffer must have less than EP2_FIFO_SZ bytes left */ |
928 d12_write_endpt(D12_ENDPOINT_EP2_IN, sendbuffer2, sendbytes2); | |
929 sendbytes2 = 0; | |
930 } | |
931 } | |
932 | |
933 /******************************************************************************* | |
934 ** d12_receive_data_ep2 | |
935 ** | |
936 ** Get the next FIFOs worth of data from the endpoint | |
937 ** | |
938 */ | |
939 void | |
940 d12_receive_data_ep2(void) { | |
941 uint8_t d12header[2], bytes, i, status; | |
942 | |
943 /* Select Endpoint */ | |
944 d12_read_cmd(D12_ENDPOINT_EP2_OUT, &status, 1); | |
945 | |
946 if (!(status & 0x01)) /* Bail if the buffer is empty */ | |
947 return; | |
948 | |
949 /* Read header */ | |
950 d12_set_cmd(D12_READ_BUFFER); | |
951 d12header[0] = d12_get_data(); | |
952 d12header[1] = d12_get_data(); | |
953 bytes = d12header[1]; | |
954 | |
955 packetlen2 = 0; | |
956 | |
957 for (i = 0; i < bytes; i++) | |
958 packet2[i] = d12_get_data(); | |
959 | |
960 packetlen2 += bytes; | |
961 | |
962 /* Allow new packets to be accepted */ | |
963 d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0); | |
964 | |
965 uart_putsP(PSTR("Got ")); | |
966 uart_puts_dec(bytes, 0); | |
41 | 967 uart_putsP(PSTR(" bytes from the host\r\n")); |
23 | 968 |
31 | 969 parsebuf(packet2, D12_ENDPOINT_EP2_IN); |
970 | |
971 } | |
972 | |
973 /******************************************************************************* | |
974 ** d12_receive_data_ep1 | |
975 ** | |
976 ** Get the next FIFOs worth of data from the endpoint | |
977 ** | |
978 */ | |
979 void | |
980 d12_receive_data_ep1(void) { | |
981 uint8_t d12header[2], bytes, i, status; | |
982 | |
983 /* Select Endpoint */ | |
984 d12_read_cmd(D12_ENDPOINT_EP1_OUT, &status, 1); | |
985 | |
986 /* Check if Buffer is Full */ | |
987 if (!(status & 0x01)) | |
988 return; | |
989 | |
990 /* Read header */ | |
991 d12_set_cmd(D12_READ_BUFFER); | |
992 d12header[0] = d12_get_data(); | |
993 d12header[1] = d12_get_data(); | |
994 bytes = d12header[1]; | |
995 | |
996 packetlen1 = 0; | |
997 | |
998 for (i = 0; i < bytes; i++) | |
999 packet1[i] = d12_get_data(); | |
1000 | |
1001 packetlen1 += bytes; | |
1002 | |
1003 uart_putsP(PSTR("Got ")); | |
1004 uart_puts_dec(bytes, 0); | |
41 | 1005 uart_putsP(PSTR(" bytes from the host\r\n")); |
31 | 1006 |
1007 /* Allow new packets to be accepted */ | |
1008 d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0); | |
1009 | |
1010 parsebuf(packet1, D12_ENDPOINT_EP1_IN); | |
23 | 1011 } |
1012 | |
1013 void | |
31 | 1014 parsebuf(uint8_t *buffer, uint8_t ep) { |
1015 int i; | |
1016 | |
1017 switch (buffer[0]) { | |
1018 case 0x00: | |
41 | 1019 uart_putsP(PSTR("OWTouchReset()\r\n")); |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
1020 buffer[0] = OWTouchReset(); |
31 | 1021 d12_write_endpt(ep, buffer, 1); |
1022 break; | |
1023 | |
1024 case 0x01: | |
41 | 1025 uart_putsP(PSTR("OWFirst()\r\n")); |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
1026 buffer[0] = OWFirst(&buffer[1], 1, 0); |
31 | 1027 for (i = 0; i < 9; i++) { |
1028 uart_puts_hex(buffer[i + 1]); | |
1029 uart_putsP(PSTR(" ")); | |
1030 } | |
41 | 1031 uart_putsP(PSTR("\r\n")); |
31 | 1032 d12_write_endpt(ep, buffer, 9); |
1033 break; | |
23 | 1034 |
31 | 1035 case 0x02: |
41 | 1036 uart_putsP(PSTR("OWNext()\r\n")); |
35
fed32b382de2
Tidy up, hide details behind macros to make it more obvious what we
darius
parents:
31
diff
changeset
|
1037 buffer[0] = OWNext(&buffer[1], 1, 0); |
31 | 1038 d12_write_endpt(ep, buffer, 9); |
1039 break; | |
1040 | |
1041 case 0x03: | |
1042 uart_putsP(PSTR(" bytes, asked to do temperature conversion for ")); | |
1043 for (i = 0; i < 8; i++) { | |
1044 uart_puts_hex(buffer[i + 1]); | |
1045 if (i != 7) | |
1046 uart_putsP(PSTR(":")); | |
1047 } | |
1048 | |
41 | 1049 uart_putsP(PSTR("\r\n")); |
31 | 1050 d12_write_endpt(ep, buffer, 9); |
1051 | |
1052 break; | |
1053 | |
1054 default: | |
41 | 1055 uart_putsP(PSTR("Unknown command on endpoint 1\r\n")); |
31 | 1056 break; |
23 | 1057 } |
1058 } |