Werner's Miscellanea
Sign in or create your account | Project List | Help
Werner's Miscellanea Git Source Tree
Root/
Source at commit 51106cf9b34d773e72aa00385c80a9abb76b28df created 10 years 3 months ago. By Werner Almesberger, ircstat/ML: update for 11/2013 | |
---|---|
1 | /* |
2 | * labsw/ep0.c - EP0 extension protocol |
3 | * |
4 | * Written 2008-2011 by Werner Almesberger |
5 | * Copyright 2008-2011 Werner Almesberger |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | */ |
12 | |
13 | |
14 | #include <stdint.h> |
15 | |
16 | #ifndef NULL |
17 | #define NULL 0 |
18 | #endif |
19 | |
20 | #include "regs.h" |
21 | #include "usb.h" |
22 | #include "labsw/ep0.h" |
23 | #include "io.h" |
24 | #include "version.h" |
25 | |
26 | |
27 | extern int local; |
28 | |
29 | |
30 | /* |
31 | * SDCC 2.8.0 had a number of code generation bugs that appeared in the big |
32 | * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the |
33 | * "size" variable to be written to memory. This work-around doesn't seem |
34 | * to be necessary with 2.9.0, but we keep it around, just in case. |
35 | * |
36 | * Unfortunately, the setup->bRequest garbling bug is still with us. Without |
37 | * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the |
38 | * value of setup->bRequest and then rejects all SETUP requests. |
39 | */ |
40 | |
41 | #define SDCC_FORCE_EVAL(type, value) \ |
42 | do { \ |
43 | static volatile type foo; \ |
44 | foo = value; \ |
45 | } while (0) |
46 | |
47 | #define SDCC_FORCE_UPDATE(type, var) \ |
48 | do { \ |
49 | volatile type foo; \ |
50 | foo = var; \ |
51 | var = foo; \ |
52 | } while (0) |
53 | |
54 | |
55 | static uint8_t id[3] = { |
56 | EP0LABSW_MAJOR, EP0LABSW_MINOR, |
57 | /* hw type is set at run time */ |
58 | }; |
59 | |
60 | static __xdata uint8_t buf[128]; |
61 | |
62 | |
63 | #define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ |
64 | |
65 | |
66 | static __bit my_setup(struct setup_request *setup) __reentrant |
67 | { |
68 | uint32_t tmp; |
69 | uint8_t size, i; |
70 | |
71 | switch (setup->bmRequestType | setup->bRequest << 8) { |
72 | case LABSW_FROM_DEV(LABSW_ID): |
73 | size = setup->wLength; |
74 | if (size > 3) |
75 | size = 3; |
76 | id[2] = 0; /* hardware type */ |
77 | usb_send(&ep0, id, size, NULL, NULL); |
78 | return 1; |
79 | case LABSW_FROM_DEV(LABSW_BUILD): |
80 | tmp = build_number; |
81 | for (i = BUILD_OFFSET-2; tmp; i--) { |
82 | buf[i] = (tmp % 10)+'0'; |
83 | tmp /= 10; |
84 | } |
85 | buf[i] = '#'; |
86 | buf[BUILD_OFFSET-1] = ' '; |
87 | for (size = 0; build_date[size]; size++) |
88 | buf[BUILD_OFFSET+size] = build_date[size]; |
89 | size += BUILD_OFFSET-i+1; |
90 | SDCC_FORCE_EVAL(uint8_t, setup->bRequest); |
91 | if (size > setup->wLength) |
92 | return 0; |
93 | usb_send(&ep0, buf+i, size, NULL, NULL); |
94 | return 1; |
95 | |
96 | case LABSW_TO_DEV(LABSW_RESET): |
97 | RSTSRC = SWRSF; |
98 | while (1); |
99 | |
100 | case LABSW_FROM_DEV(LABSW_GET): |
101 | size = setup->wLength; |
102 | if (size > 2) |
103 | size = 2; |
104 | buf[0] = |
105 | (IN_1 ? 0 : LABSW_IN1) | |
106 | (IN_2 ? 0 : LABSW_IN2) | |
107 | (IN_3 ? 0 : LABSW_IN3) | |
108 | (IN_4 ? 0 : LABSW_IN4); |
109 | buf[1] = |
110 | (BUT_MAIN ? 0 : LABSW_BUT_MAIN) | |
111 | (BUT_CH1 ? 0 : LABSW_BUT_CH1) | |
112 | (BUT_CH2 ? 0 : LABSW_BUT_CH2); |
113 | usb_send(&ep0, buf, size, NULL, NULL); |
114 | return 1; |
115 | |
116 | case LABSW_TO_DEV(LABSW_SET): |
117 | local = !setup->wIndex; |
118 | |
119 | if (setup->wIndex & LABSW_CH1_RELAY) |
120 | CH1_RELAY = setup->wValue & LABSW_CH1_RELAY ? 1 : 0; |
121 | if (setup->wIndex & LABSW_CH1_OPT) |
122 | CH1_OPT = setup->wValue & LABSW_CH1_OPT ? 0 : 1; |
123 | if (setup->wIndex & LABSW_CH2_RELAY) |
124 | CH2_RELAY = setup->wValue & LABSW_CH2_RELAY ? 1 : 0; |
125 | if (setup->wIndex & LABSW_CH2_OPT) |
126 | CH2_OPT = setup->wValue & LABSW_CH2_OPT ? 0 : 1; |
127 | |
128 | if (setup->wIndex & LABSW_OUT1) |
129 | OUT_1 = setup->wValue & LABSW_OUT1 ? 0 : 1; |
130 | if (setup->wIndex & LABSW_OUT2) |
131 | OUT_2 = setup->wValue & LABSW_OUT2 ? 0 : 1; |
132 | if (setup->wIndex & LABSW_OUT3) |
133 | OUT_3 = setup->wValue & LABSW_OUT3 ? 0 : 1; |
134 | if (setup->wIndex & LABSW_OUT4) |
135 | OUT_4 = setup->wValue & LABSW_OUT4 ? 0 : 1; |
136 | |
137 | if (setup->wIndex & LABSW_MAIN_R) |
138 | LED_MAIN_R = setup->wValue & LABSW_MAIN_R ? 1 : 0; |
139 | if (setup->wIndex & LABSW_MAIN_G) |
140 | LED_MAIN_G = setup->wValue & LABSW_MAIN_G ? 1 : 0; |
141 | if (setup->wIndex & LABSW_CH1_R) |
142 | LED_CH1_R = setup->wValue & LABSW_CH1_R ? 1 : 0; |
143 | if (setup->wIndex & LABSW_CH1_G) |
144 | LED_CH1_G = setup->wValue & LABSW_CH1_G ? 1 : 0; |
145 | if (setup->wIndex & LABSW_CH2_R) |
146 | LED_CH2_R = setup->wValue & LABSW_CH2_R ? 1 : 0; |
147 | if (setup->wIndex & LABSW_CH2_G) |
148 | LED_CH2_G = setup->wValue & LABSW_CH2_G ? 1 : 0; |
149 | return 1; |
150 | |
151 | default: |
152 | return 0; |
153 | } |
154 | } |
155 | |
156 | |
157 | void ep0_init(void) |
158 | { |
159 | user_setup = my_setup; |
160 | } |
161 |
Branches:
master