Mercurial > ~darius > hgwebdir.cgi > tempctrl
comparison usb.c @ 23:845934a4e7fe
Add code to talk to a Phillips PDIUSBB12.
author | darius |
---|---|
date | Mon, 12 Dec 2005 23:32:59 +1030 |
parents | |
children | 350e8655cbb7 |
comparison
equal
deleted
inserted
replaced
22:bd792ebf813d | 23:845934a4e7fe |
---|---|
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" | |
9 | |
10 #define EP0_SIZE 16 | |
11 | |
12 #define D12_MODE_0 0x14 /* Endpoint config = 0, SoftConnect = 1, IRQ Mode = 1, | |
13 * Clock running = 0, No Lazy Clock = 0 | |
14 */ | |
15 #define D12_MODE_1 0x02 /* SOF mode = 0, Set-to-one = 0, Clock div = 2 (16Mhz) */ | |
16 /* Debugging stuff */ | |
17 void uart_putsP(const char *addr); | |
18 void uart_puts(const char *addr); | |
19 int uart_putc(char c); | |
20 void uart_puts_dec(uint8_t a, uint8_t l); | |
21 void uart_puts_hex(uint8_t a); | |
22 | |
23 /* USB administrivia */ | |
24 uint8_t deviceaddress; | |
25 uint8_t deviceconfigured; | |
26 | |
27 /* End point buffer points and such */ | |
28 const uint8_t *pSendBuffer; | |
29 uint8_t BytesToSend; | |
30 static uint8_t send_Bytes; | |
31 static uint8_t exact_Bytes; | |
32 | |
33 static const uint8_t *pSendBuffer2; | |
34 static uint8_t BytesToSend2; | |
35 | |
36 /* Data packet buffer */ | |
37 static uint8_t send_packet2; | |
38 static uint8_t packet2[270]; | |
39 static uint16_t packetlen2; | |
40 | |
41 /* XXX: Not actually used */ | |
42 void (*bootloader)(void) = (void*)0xe000; | |
43 | |
44 /* Device/endpoint/etc descriptions */ | |
45 const USB_DEVICE_DESCRIPTOR DeviceDescriptor = { | |
46 sizeof(USB_DEVICE_DESCRIPTOR), /* bLength */ | |
47 TYPE_DEVICE_DESCRIPTOR, /* bDescriptorType */ | |
48 0x0110, /* bcdUSB USB Version 1.1 */ | |
49 0, /* bDeviceClass */ | |
50 0, /* bDeviceSubclass */ | |
51 0, /* bDeviceProtocol */ | |
52 EP0_SIZE, /* bMaxPacketSize in Bytes */ | |
53 0x4753, /* idVendor (inofficial GS) */ | |
54 0x0001, /* idProduct */ | |
55 0x0100, /* bcdDevice */ | |
56 1, /* iManufacturer String Index */ | |
57 2, /* iProduct String Index */ | |
58 3, /* iSerialNumber String Index */ | |
59 1 /* bNumberConfigurations */ | |
60 }; | |
61 | |
62 const USB_CONFIG_DATA ConfigurationDescriptor = { | |
63 { /* configuration descriptor */ | |
64 sizeof(USB_CONFIGURATION_DESCRIPTOR), /* bLength */ | |
65 TYPE_CONFIGURATION_DESCRIPTOR, /* bDescriptorType */ | |
66 sizeof(USB_CONFIG_DATA), /* wTotalLength */ | |
67 2, /* bNumInterfaces */ | |
68 1, /* bConfigurationValue */ | |
69 0, /* iConfiguration String Index */ | |
70 0x80, /* bmAttributes Bus Powered, No Remote Wakeup */ | |
71 100/2 /* bMaxPower in mA */ | |
72 }, | |
73 { /* interface descriptor */ | |
74 sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */ | |
75 TYPE_INTERFACE_DESCRIPTOR, /* bDescriptorType */ | |
76 0, /* bInterface Number */ | |
77 0, /* bAlternateSetting */ | |
78 2, /* bNumEndpoints */ | |
79 0xFF, /* bInterfaceClass (Vendor specific) */ | |
80 0x02, /* bInterfaceSubClass */ | |
81 0x00, /* bInterfaceProtocol */ | |
82 0 /* iInterface String Index */ | |
83 }, | |
84 { /* endpoint descriptor */ | |
85 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
86 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
87 0x02, /* bEndpoint Address EP2 OUT */ | |
88 0x02, /* bmAttributes - Bulk */ | |
89 0x0040, /* wMaxPacketSize */ | |
90 0x00 /* bInterval */ | |
91 }, | |
92 { /* endpoint descriptor */ | |
93 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
94 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
95 0x82, /* bEndpoint Address EP2 IN */ | |
96 0x02, /* bmAttributes - Bulk */ | |
97 0x0040, /* wMaxPacketSize */ | |
98 0x00 /* bInterval */ | |
99 }, | |
100 { /* interface descriptor */ | |
101 sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */ | |
102 TYPE_INTERFACE_DESCRIPTOR, /* bDescriptorType */ | |
103 1, /* bInterface Number */ | |
104 0, /* bAlternateSetting */ | |
105 2, /* bNumEndpoints */ | |
106 0xFF, /* bInterfaceClass (Vendor specific) */ | |
107 0x02, /* bInterfaceSubClass */ | |
108 0x00, /* bInterfaceProtocol */ | |
109 0 /* iInterface String Index */ | |
110 }, | |
111 { /* endpoint descriptor */ | |
112 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
113 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
114 0x01, /* bEndpoint Address EP1 OUT */ | |
115 0x02, /* bmAttributes - Bulk */ | |
116 0x0010, /* wMaxPacketSize */ | |
117 0x00 /* bInterval */ | |
118 }, | |
119 { /* endpoint descriptor */ | |
120 sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ | |
121 TYPE_ENDPOINT_DESCRIPTOR, /* bDescriptorType */ | |
122 0x81, /* bEndpoint Address EP1 IN */ | |
123 0x02, /* bmAttributes - Bulk */ | |
124 0x0010, /* wMaxPacketSize */ | |
125 0x00 /* bInterval */ | |
126 } | |
127 }; | |
128 const LANGID_DESCRIPTOR LANGID_Descriptor = { /* LANGID String Descriptor | |
129 * Zero */ | |
130 sizeof(LANGID_DESCRIPTOR), /* bLength - must match string below */ | |
131 TYPE_STRING_DESCRIPTOR, /* bDescriptorType */ | |
132 0x0409 /* LANGID US English */ | |
133 }; | |
134 | |
135 /* These are really STRING_DESCRIPTOR's but we can't statically | |
136 * declare them as that and have the compiler generate the right size | |
137 * structure */ | |
138 typedef struct { | |
139 uint8_t bLenght; | |
140 uint8_t bDescriptorType; | |
141 char bString[32]; | |
142 } MANUFACTURER_DESCRIPTOR, *PMANUFACTURER_DESCRIPTOR; | |
143 | |
144 const MANUFACTURER_DESCRIPTOR Manufacturer_Descriptor = { /* ManufacturerString 1 */ | |
145 sizeof(MANUFACTURER_DESCRIPTOR), /* bLength */ | |
146 TYPE_STRING_DESCRIPTOR, /* bDescriptorType */ | |
147 "G\0e\0n\0e\0s\0i\0s\0 \0S\0o\0f\0t\0w\0a\0r\0e\0" /* ManufacturerString in | |
148 * UNICODE */ | |
149 }; | |
150 | |
151 typedef struct { | |
152 uint8_t bLenght; | |
153 uint8_t bDescriptorType; | |
154 char bString[48]; | |
155 } PRODUCT_DESCRIPTOR, *PPRODUCT_DESCRIPTOR; | |
156 | |
157 const PRODUCT_DESCRIPTOR Product_Descriptor = { /* ProductString 2 */ | |
158 sizeof(PRODUCT_DESCRIPTOR), /* bLength */ | |
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.. */ | |
164 }; | |
165 | |
166 typedef struct { | |
167 uint8_t bLenght; | |
168 uint8_t bDescriptorType; | |
169 char bString[20]; | |
170 } SERIAL_DESCRIPTOR, *PSERIAL_DESCRIPTOR; | |
171 | |
172 const SERIAL_DESCRIPTOR EE_Serial_Descriptor __attribute__ ((section (".eeprom"))) = { /* SerialString 3 */ | |
173 sizeof(SERIAL_DESCRIPTOR), /* bLength - must match string below */ | |
174 TYPE_STRING_DESCRIPTOR, /* bDescriptorType */ | |
175 "1\02\03\0" | |
176 }; | |
177 | |
178 SERIAL_DESCRIPTOR Serial_Descriptor; | |
179 | |
180 /* | |
181 * The PDIUSBD12 is wired up like so | |
182 * | |
183 * PDI AVR | |
184 * ====================== | |
185 * D7:0 <=> PA7:0 | |
186 * INT_N => PB0 | |
187 * RD_N <= PB1 | |
188 * WR_N <= PB2 | |
189 * A0 <= PB3 (0 = data, 1 = cmd) | |
190 * SUSPEND <=> PB4 | |
191 */ | |
192 uint8_t | |
193 d12_get_data(void) { | |
194 uint8_t data; | |
195 #if 0 | |
196 _delay_us(1); | |
197 #endif | |
198 PORTB &= ~_BV(PB3); /* Data phase */ | |
199 DDRA = 0x00; /* Set to input */ | |
200 PORTB &= ~_BV(PB1); /* Pull RD_N low */ | |
201 PORTB &= ~_BV(PB1); /* Delay 40ns */ | |
202 PORTB &= ~_BV(PB1); | |
203 PORTB &= ~_BV(PB1); | |
204 data = PINA; /* Read the data */ | |
205 PORTB |= _BV(PB1); /* Pull RD_N high */ | |
206 return(data); | |
207 } | |
208 | |
209 void | |
210 set_d12_data(uint8_t data) { | |
211 #if 0 | |
212 _delay_us(1); | |
213 #endif | |
214 PORTB &= ~_BV(PB3); /* Data phase */ | |
215 DDRA = 0xff; /* Set to output */ | |
216 PORTA = data; /* Put the data on the bus */ | |
217 PORTB &= ~_BV(PB2); /* Pull WR_N low */ | |
218 PORTB &= ~_BV(PB2); /* Delay 40ns */ | |
219 PORTB &= ~_BV(PB2); | |
220 PORTB &= ~_BV(PB2); | |
221 PORTB |= _BV(PB2); /* Pull WR_N high */ | |
222 PORTB |= _BV(PB2); /* Delay 40 ns */ | |
223 PORTB |= _BV(PB2); | |
224 PORTB |= _BV(PB2); | |
225 DDRA = 0x00; /* Back to input */ | |
226 } | |
227 | |
228 void | |
229 set_d12_cmd(uint8_t cmd) { | |
230 #if 0 | |
231 _delay_us(1); | |
232 #endif | |
233 PORTB |= _BV(PB3); /* Command phase */ | |
234 DDRA = 0xff; /* Set to output */ | |
235 PORTA = cmd; /* Put the data on the bus */ | |
236 PORTB &= ~_BV(PB2); /* Pull WR_N low */ | |
237 PORTB &= ~_BV(PB2); /* Delay 40ns */ | |
238 PORTB &= ~_BV(PB2); | |
239 PORTB &= ~_BV(PB2); | |
240 PORTB |= _BV(PB2); /* Pull WR_N high */ | |
241 PORTB |= _BV(PB2); /* Delay 40ns */ | |
242 PORTB |= _BV(PB2); | |
243 PORTB |= _BV(PB2); | |
244 DDRA = 0x00; /* Back to input */ | |
245 } | |
246 | |
247 void | |
248 d12_write_cmd(uint8_t command, const uint8_t *buffer, uint8_t count) { | |
249 uint8_t i; | |
250 | |
251 set_d12_cmd(command); | |
252 #if 0 | |
253 _delay_us(1); | |
254 #endif | |
255 if (count) { | |
256 for (i = 0; i < count; i++) { | |
257 set_d12_data(buffer[i]); | |
258 } | |
259 } | |
260 } | |
261 | |
262 void | |
263 d12_read_cmd(uint8_t command, uint8_t *buffer, uint8_t count) { | |
264 uint8_t i; | |
265 | |
266 set_d12_cmd(command); | |
267 if (count) { | |
268 for (i = 0; i < count; i++) { | |
269 buffer[i] = d12_get_data(); | |
270 } | |
271 } | |
272 } | |
273 | |
274 /* Set up the PDIUSBD12 */ | |
275 void | |
276 usb_init(void) { | |
277 uint8_t buffer[2]; | |
278 | |
279 /* pull EE_Serial_Descriptor into RAM */ | |
280 eeprom_read_block(&Serial_Descriptor, &EE_Serial_Descriptor, sizeof(Serial_Descriptor)); | |
281 | |
282 /* Set Address to zero (default) and enable function */ | |
283 buffer[0] = 0x80; | |
284 d12_write_cmd(D12_SET_ADDRESS_ENABLE, buffer, 1); | |
285 | |
286 /* Enable function generic endpoints */ | |
287 buffer[0] = 0x01; | |
288 d12_write_cmd(D12_SET_ENDPOINT_ENABLE, buffer, 1); | |
289 | |
290 /* Configure the device (soft connect off) */ | |
291 buffer[0] = D12_MODE_0 & 0xef; | |
292 buffer[1] = D12_MODE_1; | |
293 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
294 | |
295 /* Delay long enough for the PC to notice the disconnect */ | |
296 _delay_us(1000); | |
297 | |
298 buffer[0] |= 0x10; /* Soft connect on */ | |
299 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
300 | |
301 /* Endpoint 2 IN/OUT IRQ enable */ | |
302 buffer[0] = 0xc0; | |
303 d12_write_cmd(D12_SET_DMA, buffer, 1); | |
304 } | |
305 | |
306 /* Process an interrupt */ | |
307 void | |
308 usb_intr(void) { | |
309 uint8_t irq[2]; | |
310 uint8_t buffer[8]; | |
311 | |
312 d12_read_cmd(D12_READ_INTERRUPT_REGISTER, (uint8_t *)&irq, 2); | |
313 | |
314 /* Why do we get interrupts when this is 0? */ | |
315 if (irq[0] == 0) | |
316 return; | |
317 | |
318 if (irq[0] & D12_INT_BUS_RESET) { | |
319 uart_putsP(PSTR("Bus reset\n\r")); | |
320 usb_init(); | |
321 return; | |
322 } | |
323 | |
324 if (irq[0] & D12_INT_SUSPEND) { | |
325 uart_putsP(PSTR("Suspend change\n\r")); | |
326 } | |
327 | |
328 if (irq[0] & D12_INT_EP0_IN) { | |
329 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP0_IN, buffer, 1); | |
330 | |
331 /* Handle any outgoing data for EP0 */ | |
332 d12_write_buffer_ep0(); | |
333 } | |
334 | |
335 /* Handle configuration and misc stuff */ | |
336 if (irq[0] & D12_INT_EP0_OUT) { | |
337 d12_ep0_irq(); | |
338 } | |
339 | |
340 /* EPx_IN is when the host has had a packet of data and is expecting more */ | |
341 if (irq[0] & D12_INT_EP1_IN) { | |
342 /* XXX: Not yet implemented */ | |
343 } | |
344 | |
345 /* EPx_OUT is when we have gotten a packet from the host */ | |
346 if (irq[0] & D12_INT_EP1_OUT) { | |
347 /* XXX: Not yet implemented */ | |
348 } | |
349 | |
350 if (irq[0] & D12_INT_EP2_IN) { | |
351 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP2_IN, buffer, 1); | |
352 d12_send_data_ep2(); | |
353 } | |
354 | |
355 if (irq[0] & D12_INT_EP2_OUT) { | |
356 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP2_OUT, buffer, 1); | |
357 d12_receive_data_ep2(); | |
358 } | |
359 } | |
360 | |
361 void | |
362 usb_gendata(void) { | |
363 packet2[0] = 'a'; | |
364 packet2[1] = 'b'; | |
365 packet2[2] = 'c'; | |
366 packet2[3] = '\n'; | |
367 packet2[4] = '\r'; | |
368 BytesToSend2 = 5; | |
369 pSendBuffer2 = (uint8_t *)&packet2[0]; | |
370 send_packet2 = 1; | |
371 | |
372 /* Kick off the data transfer */ | |
373 d12_send_data_ep2(); | |
374 } | |
375 | |
376 void | |
377 d12_ep0_irq(void) { | |
378 uint8_t buffer[2]; | |
379 USB_SETUP_REQUEST setuppkt; | |
380 | |
381 d12_read_cmd(D12_READ_LAST_TRANSACTION + D12_ENDPOINT_EP0_OUT, buffer, 1); | |
382 | |
383 if (buffer[0] & D12_LAST_TRAN_SETUP) { | |
384 /* Read the setup packet */ | |
385 d12_read_endpt(D12_ENDPOINT_EP0_OUT, (uint8_t *)&setuppkt); | |
386 | |
387 /* Ack the packet to EP0_OUT */ | |
388 d12_write_cmd(D12_ENDPOINT_EP0_OUT, NULL, 0); | |
389 d12_write_cmd(D12_ACK_SETUP, NULL, 0); | |
390 d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0); | |
391 | |
392 /* Ack the packet to EP0_IN */ | |
393 d12_write_cmd(D12_ENDPOINT_EP0_IN, NULL, 0); | |
394 d12_write_cmd(D12_ACK_SETUP, NULL, 0); | |
395 | |
396 /* It's a new xfer, so forget about any old one */ | |
397 send_Bytes = 0; | |
398 | |
399 /* Parse request type */ | |
400 switch (setuppkt.bmRequestType & 0x7f) { | |
401 case STANDARD_DEVICE_REQUEST: | |
402 switch (setuppkt.bRequest) { | |
403 case GET_STATUS: | |
404 /* Get status request should return remote | |
405 * wakeup and self powered status | |
406 */ | |
407 buffer[0] = 0x01; | |
408 buffer[1] = 0x00; | |
409 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2); | |
410 break; | |
411 case CLEAR_FEATURE: | |
412 case SET_FEATURE: | |
413 /* We don't support DEVICE_REMOTE_WAKEUP or | |
414 * TEST_MODE | |
415 */ | |
416 d12_stallctrlendpt(); | |
417 break; | |
418 | |
419 case SET_ADDRESS: | |
420 deviceaddress = setuppkt.wValue | 0x80; | |
421 d12_write_cmd(D12_SET_ADDRESS_ENABLE, &deviceaddress, 1); | |
422 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
423 break; | |
424 | |
425 case GET_DESCRIPTOR: | |
426 d12_getdescriptor(&setuppkt); | |
427 break; | |
428 | |
429 case GET_CONFIGURATION: | |
430 d12_write_endpt(D12_ENDPOINT_EP0_IN, &deviceconfigured, 1); | |
431 break; | |
432 | |
433 case SET_CONFIGURATION: | |
434 deviceconfigured = setuppkt.wValue & 0xff; | |
435 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
436 break; | |
437 | |
438 | |
439 case SET_DESCRIPTOR: | |
440 default: | |
441 /* Unsupported, stall */ | |
442 d12_stallctrlendpt(); | |
443 break; | |
444 } | |
445 break; | |
446 | |
447 case STANDARD_INTERFACE_REQUEST: | |
448 switch (setuppkt.bRequest) { | |
449 case GET_STATUS: | |
450 /* Should return 0, 0 (reserved) */ | |
451 buffer[0] = 0x00; | |
452 buffer[1] = 0x00; | |
453 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2); | |
454 break; | |
455 | |
456 case SET_INTERFACE: | |
457 if (setuppkt.wIndex == 0 && setuppkt.wValue == 0) | |
458 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
459 else | |
460 d12_stallctrlendpt(); | |
461 break; | |
462 | |
463 case GET_INTERFACE: | |
464 /* Can only handle interface 0 ... */ | |
465 if (setuppkt.wIndex == 0) { | |
466 buffer[0] = 0; | |
467 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 1); | |
468 break; | |
469 } | |
470 /* .. otherwise fall through to error */ | |
471 | |
472 case CLEAR_FEATURE: | |
473 case SET_FEATURE: | |
474 default: | |
475 d12_stallctrlendpt(); | |
476 break; | |
477 } | |
478 break; | |
479 | |
480 case STANDARD_ENDPOINT_REQUEST: | |
481 switch (setuppkt.bRequest) { | |
482 case CLEAR_FEATURE: | |
483 case SET_FEATURE: | |
484 /* Halt(stall) is required to be implemented on | |
485 * interrupt and bulk endpoints. | |
486 */ | |
487 if (setuppkt.wValue == ENDPOINT_HALT) { | |
488 if (setuppkt.bRequest == CLEAR_FEATURE) | |
489 buffer[0] = 0x00; | |
490 else | |
491 buffer[0] = 0x01; | |
492 switch (setuppkt.wIndex & 0xFF) { | |
493 case 0x01: | |
494 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ | |
495 D12_ENDPOINT_EP1_OUT, buffer, 1); | |
496 break; | |
497 case 0x81: | |
498 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ | |
499 D12_ENDPOINT_EP1_IN, buffer, 1); | |
500 break; | |
501 case 0x02: | |
502 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ | |
503 D12_ENDPOINT_EP2_OUT, buffer, 1); | |
504 break; | |
505 case 0x82: | |
506 d12_write_cmd(D12_SET_ENDPOINT_STATUS + \ | |
507 D12_ENDPOINT_EP2_IN, buffer, 1); | |
508 break; | |
509 default: /* Invalid Endpoint - | |
510 * RequestError */ | |
511 d12_stallctrlendpt(); | |
512 break; | |
513 } | |
514 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
515 } else { | |
516 /* | |
517 * No other Features for Endpoint - | |
518 * Request Error | |
519 */ | |
520 d12_stallctrlendpt(); | |
521 } | |
522 break; | |
523 | |
524 case GET_STATUS: | |
525 /* | |
526 * Get Status Request to Endpoint should | |
527 * return Halt Status in D0 for Interrupt and Bulk | |
528 */ | |
529 switch (setuppkt.wIndex & 0xFF) { | |
530 case 0x01: | |
531 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
532 D12_ENDPOINT_EP1_OUT, buffer, 1); | |
533 break; | |
534 case 0x81: | |
535 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
536 D12_ENDPOINT_EP1_IN, buffer, 1); | |
537 break; | |
538 case 0x02: | |
539 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
540 D12_ENDPOINT_EP2_OUT, buffer, 1); | |
541 break; | |
542 case 0x82: | |
543 d12_read_cmd(D12_READ_ENDPOINT_STATUS + \ | |
544 D12_ENDPOINT_EP2_IN, buffer, 1); | |
545 break; | |
546 default: /* Invalid Endpoint - | |
547 * RequestError */ | |
548 d12_stallctrlendpt(); | |
549 break; | |
550 } | |
551 if (buffer[0] & 0x08) | |
552 buffer[0] = 0x01; | |
553 else | |
554 buffer[0] = 0x00; | |
555 buffer[1] = 0x00; | |
556 d12_write_endpt(D12_ENDPOINT_EP0_IN, buffer, 2); | |
557 break; | |
558 | |
559 default: | |
560 /* Unsupported - Request Error - Stall */ | |
561 d12_stallctrlendpt(); | |
562 break; | |
563 } | |
564 break; | |
565 case VENDOR_DEVICE_REQUEST: | |
566 case VENDOR_ENDPOINT_REQUEST: | |
567 switch (setuppkt.bRequest) { | |
568 case VENDOR_RESET: | |
569 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
570 _delay_us(1000); | |
571 /* disconnect from USB */ | |
572 buffer[0] = D12_MODE_0 & 0xef; | |
573 buffer[1] = D12_MODE_1; | |
574 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
575 _delay_us(1000); | |
576 cli(); | |
577 reset(); | |
578 /* NOT REACHED */ | |
579 break; | |
580 case VENDOR_UPDATE: | |
581 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
582 _delay_us(1000); | |
583 /* disconnect from USB */ | |
584 buffer[0] = D12_MODE_0 & 0xef; | |
585 buffer[1] = D12_MODE_1; | |
586 d12_write_cmd(D12_SET_MODE, buffer, 2); | |
587 _delay_us(1000); | |
588 cli(); | |
589 bootloader(); | |
590 /* NOT REACHED */ | |
591 break; | |
592 default: | |
593 d12_stallctrlendpt(); | |
594 break; | |
595 } | |
596 break; | |
597 case VENDOR_INTERFACE_REQUEST: | |
598 switch (setuppkt.bRequest) { | |
599 default: | |
600 d12_stallctrlendpt(); | |
601 break; | |
602 } | |
603 break; | |
604 default: | |
605 d12_stallctrlendpt(); | |
606 break; | |
607 } | |
608 } else { | |
609 /* This is a Data Packet */ | |
610 } | |
611 | |
612 } | |
613 | |
614 /* Reset the micro | |
615 static void | |
616 reset(void) { | |
617 MCUCR = _BV(IVCE); | |
618 MCUCR = 0; | |
619 WDTCR = _BV(WDE); | |
620 for (;;) | |
621 ; | |
622 } | |
623 | |
624 void | |
625 d12_getdescriptor(USB_SETUP_REQUEST *setuppkt) { | |
626 switch ((setuppkt->wValue & 0xff00) >> 8) { | |
627 case TYPE_DEVICE_DESCRIPTOR: | |
628 pSendBuffer = (const uint8_t *)&DeviceDescriptor; | |
629 BytesToSend = DeviceDescriptor.bLength; | |
630 send_Bytes = 1; | |
631 if (BytesToSend >= setuppkt->wLength) { | |
632 BytesToSend = setuppkt->wLength; | |
633 exact_Bytes = 1; | |
634 } else { | |
635 exact_Bytes = 0; | |
636 } | |
637 d12_write_buffer_ep0(); | |
638 break; | |
639 | |
640 case TYPE_CONFIGURATION_DESCRIPTOR: | |
641 pSendBuffer = (const uint8_t *)&ConfigurationDescriptor; | |
642 BytesToSend = sizeof(ConfigurationDescriptor); | |
643 send_Bytes = 1; | |
644 if (BytesToSend >= setuppkt->wLength) { | |
645 BytesToSend = setuppkt->wLength; | |
646 exact_Bytes = 1; | |
647 } else { | |
648 exact_Bytes = 0; | |
649 } | |
650 d12_write_buffer_ep0(); | |
651 break; | |
652 | |
653 case TYPE_STRING_DESCRIPTOR: | |
654 switch (setuppkt->wValue & 0xFF) { | |
655 | |
656 case 0: | |
657 pSendBuffer = (const uint8_t *)&LANGID_Descriptor; | |
658 BytesToSend = sizeof(LANGID_Descriptor); | |
659 break; | |
660 | |
661 case 1: | |
662 pSendBuffer = (const uint8_t *)&Manufacturer_Descriptor; | |
663 BytesToSend = sizeof(Manufacturer_Descriptor); | |
664 break; | |
665 | |
666 case 2: | |
667 pSendBuffer = (const uint8_t *)&Product_Descriptor; | |
668 BytesToSend = sizeof(Product_Descriptor); | |
669 break; | |
670 | |
671 case 3: | |
672 pSendBuffer = (const uint8_t *)&Serial_Descriptor; | |
673 BytesToSend = sizeof(Serial_Descriptor); | |
674 break; | |
675 | |
676 default: | |
677 pSendBuffer = NULL; | |
678 BytesToSend = 0; | |
679 } | |
680 send_Bytes = 1; | |
681 if (BytesToSend >= setuppkt->wLength) { | |
682 BytesToSend = setuppkt->wLength; | |
683 exact_Bytes = 1; | |
684 } else { | |
685 exact_Bytes = 0; | |
686 } | |
687 d12_write_buffer_ep0(); | |
688 break; | |
689 default: | |
690 d12_stallctrlendpt(); | |
691 break; | |
692 } | |
693 } | |
694 | |
695 | |
696 void | |
697 d12_stallctrlendpt(void) { | |
698 uint8_t Buffer[] = {0x01}; | |
699 /* | |
700 * 9.2.7 RequestError - return STALL PID in response to next DATA | |
701 * Stage Transaction | |
702 */ | |
703 d12_write_cmd(D12_SET_ENDPOINT_STATUS + D12_ENDPOINT_EP0_IN, Buffer, 1); | |
704 /* or in the status stage of the message. */ | |
705 d12_write_cmd(D12_SET_ENDPOINT_STATUS + D12_ENDPOINT_EP0_OUT, Buffer, 1); | |
706 } | |
707 | |
708 uint8_t | |
709 d12_read_endpt(uint8_t endpt, uint8_t *buffer) { | |
710 uint8_t d12header[2]; | |
711 uint8_t status = 0; | |
712 uint8_t i; | |
713 | |
714 /* Select Endpoint */ | |
715 d12_read_cmd(endpt, &status, 1); | |
716 | |
717 /* Check if Buffer is Full */ | |
718 if (status & 0x01) { | |
719 set_d12_cmd(D12_READ_BUFFER); | |
720 d12header[0] = d12_get_data(); | |
721 d12header[1] = d12_get_data(); | |
722 if (d12header[1]) { | |
723 for (i = 0; i < d12header[1]; i++) | |
724 buffer[i] = d12_get_data(); | |
725 } | |
726 /* Allow new packets to be accepted */ | |
727 d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0); | |
728 | |
729 } | |
730 return d12header[1]; | |
731 } | |
732 | |
733 void | |
734 d12_write_endpt(uint8_t endpt, const uint8_t *buffer, uint8_t bytes) { | |
735 uint8_t status = 0; | |
736 uint8_t i; | |
737 | |
738 /* Select Endpoint */ | |
739 d12_read_cmd(endpt, &status, 1); | |
740 /* Write Header */ | |
741 set_d12_cmd(D12_WRITE_BUFFER); | |
742 set_d12_data(0x00); | |
743 set_d12_data(bytes); | |
744 /* Write Packet */ | |
745 if (bytes) { | |
746 for (i = 0; i < bytes; i++) { | |
747 set_d12_data(buffer[i]); | |
748 } | |
749 } | |
750 /* Validate Buffer */ | |
751 d12_write_cmd(D12_VALIDATE_BUFFER, NULL, 0); | |
752 } | |
753 | |
754 void | |
755 d12_write_buffer_ep0(void) { | |
756 uint8_t BufferStatus = 1; | |
757 | |
758 if (send_Bytes == 0) { | |
759 return; | |
760 } | |
761 | |
762 /* Read Buffer Full Status */ | |
763 d12_read_cmd(D12_ENDPOINT_EP0_IN, &BufferStatus, 1); | |
764 if (BufferStatus != 0) {/* Buffer Full */ | |
765 return; | |
766 } | |
767 | |
768 if (BytesToSend == 0) { | |
769 /* | |
770 * If BytesToSend is Zero and we get called again, assume | |
771 * buffer is smaller | |
772 * than Setup Request Size and indicate end by sending Zero | |
773 * Lenght packet | |
774 */ | |
775 d12_write_endpt(D12_ENDPOINT_EP0_IN, NULL, 0); | |
776 send_Bytes = 0; | |
777 } else if (BytesToSend >= EP0_SIZE) { | |
778 /* Write another EP0_SIZE Bytes to buffer and send */ | |
779 d12_write_endpt(D12_ENDPOINT_EP0_IN, pSendBuffer, EP0_SIZE); | |
780 pSendBuffer += EP0_SIZE; | |
781 BytesToSend -= EP0_SIZE; | |
782 if (BytesToSend == 0 && exact_Bytes) { | |
783 send_Bytes = 0; | |
784 } | |
785 } else { | |
786 /* Buffer must have less than EP0_SIZE bytes left */ | |
787 d12_write_endpt(D12_ENDPOINT_EP0_IN, pSendBuffer, BytesToSend); | |
788 | |
789 BytesToSend = 0; | |
790 send_Bytes = 0; | |
791 } | |
792 } | |
793 | |
794 void | |
795 d12_send_data_ep2(void) { | |
796 uint8_t BufferStatus = 1; | |
797 | |
798 /* Read Buffer Full Status */ | |
799 d12_read_cmd(D12_ENDPOINT_EP2_IN, &BufferStatus, 1); | |
800 if (BufferStatus == 0) { /* Buffer Empty */ | |
801 if (BytesToSend2 == 0) { | |
802 /* Nothing to do */ | |
803 send_packet2 = 0; | |
804 } else if (BytesToSend2 >= 64) { | |
805 /* Write another 64 Bytes to buffer and send */ | |
806 d12_write_endpt(D12_ENDPOINT_EP2_IN, pSendBuffer2, 64); | |
807 pSendBuffer2 += 64; | |
808 BytesToSend2 -= 64; | |
809 } else { | |
810 /* Buffer must have less than 64 bytes left */ | |
811 d12_write_endpt(D12_ENDPOINT_EP2_IN, pSendBuffer2, BytesToSend2); | |
812 BytesToSend2 = 0; | |
813 send_packet2 = 0; | |
814 } | |
815 } | |
816 } | |
817 | |
818 void | |
819 d12_receive_data_ep2(void) { | |
820 uint8_t D12Header[2]; | |
821 uint8_t bytes; | |
822 uint8_t BufferStatus = 0; | |
823 uint8_t i; | |
824 | |
825 /* Select Endpoint */ | |
826 d12_read_cmd(D12_ENDPOINT_EP2_OUT, &BufferStatus, 1); | |
827 /* Check if Buffer is Full */ | |
828 if (BufferStatus & 0x01) { | |
829 /* Read header */ | |
830 set_d12_cmd(D12_READ_BUFFER); | |
831 D12Header[0] = d12_get_data(); | |
832 D12Header[1] = d12_get_data(); | |
833 bytes = D12Header[1]; | |
834 /* TODO check if the packet is not too long */ | |
835 uart_putsP(PSTR("Got data\n\r")); | |
836 for (i = 0; i < bytes; i++) { | |
837 packet2[packetlen2 + i] = d12_get_data(); | |
838 uart_puts_hex(packet2[packetlen2 + i]); | |
839 uart_putsP(PSTR(" ")); | |
840 } | |
841 uart_putsP(PSTR("\n\r")); | |
842 packetlen2 += bytes; | |
843 /* Allow new packets to be accepted */ | |
844 d12_write_cmd(D12_CLEAR_BUFFER, NULL, 0); | |
845 if (bytes == 0 || bytes < 64) { /* request complete */ | |
846 pSendBuffer2 = packet2; | |
847 send_packet2 = 1; | |
848 packetlen2 = 0; | |
849 d12_send_data_ep2(); | |
850 } | |
851 } | |
852 } |