IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Git Source Tree
Root/
Source at commit 983d3302949f9c1fd73a5fbf7a25829bef9ba6db created 13 years 1 month ago. By Werner Almesberger, atusb/fw3: split USB driver into chip-specifc and general part | |
---|---|
1 | /* |
2 | * u/usb.c - USB hardware setup and standard device requests |
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 | * Known issues: |
15 | * - no suspend/resume |
16 | * - EP0-sized packets cause an (otherwise harmless) SUEND at the end of the |
17 | * packet |
18 | * - #ifdef hell |
19 | */ |
20 | |
21 | /* |
22 | * This code follows the register read/write sequences from the examples in |
23 | * SiLabs/MCU/Examples/C8051F326_7/USB_Interrupt/Firmware/F326_USB_Main.c and |
24 | * SiLabs/MCU/Examples/C8051F326_7/USB_Interrupt/Firmware/F326_USB_ISR.c |
25 | * |
26 | * More resources: |
27 | * http://www.beyondlogic.org/usbnutshell/usb1.htm |
28 | */ |
29 | |
30 | #include <stdint.h> |
31 | |
32 | #include "usb.h" |
33 | #include "../board.h" |
34 | |
35 | |
36 | #ifndef NULL |
37 | #define NULL 0 |
38 | #endif |
39 | |
40 | #define NUM_EPS 1 |
41 | |
42 | #if 1 |
43 | extern void panic(void); |
44 | #define BUG_ON(cond) do { if (cond) panic(); } while (0) |
45 | #else |
46 | #define BUG_ON(cond) |
47 | #endif |
48 | |
49 | int (*user_setup)(const struct setup_request *setup); |
50 | int (*user_get_descriptor)(uint8_t type, uint8_t index, |
51 | const uint8_t * const *reply, uint8_t *size); |
52 | void (*user_reset)(void); |
53 | |
54 | |
55 | void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf, |
56 | uint8_t size, void (*callback)(void *user), void *user) |
57 | { |
58 | BUG_ON(ep->state); |
59 | ep->state = state; |
60 | ep->buf = buf; |
61 | ep->end = buf+size; |
62 | ep->callback = callback; |
63 | ep->user = user; |
64 | } |
65 | |
66 | |
67 | static int get_descriptor(uint8_t type, uint8_t index, uint16_t length) |
68 | { |
69 | const uint8_t *reply; |
70 | uint8_t size; |
71 | |
72 | switch (type) { |
73 | case USB_DT_DEVICE: |
74 | reply = device_descriptor; |
75 | size = reply[0]; |
76 | break; |
77 | case USB_DT_CONFIG: |
78 | if (index) |
79 | return 0; |
80 | reply = config_descriptor; |
81 | size = reply[2]; |
82 | break; |
83 | default: |
84 | if (!user_get_descriptor) |
85 | return 0; |
86 | if (!user_get_descriptor(type, index, &reply, &size)) |
87 | return 0; |
88 | } |
89 | if (length < size) |
90 | size = length; |
91 | usb_send(&eps[0], reply, size, NULL, NULL); |
92 | return 1; |
93 | } |
94 | |
95 | |
96 | int handle_setup(const struct setup_request *setup) |
97 | { |
98 | switch (setup->bmRequestType | setup->bRequest << 8) { |
99 | |
100 | /* |
101 | * Device request |
102 | * |
103 | * See http://www.beyondlogic.org/usbnutshell/usb6.htm |
104 | */ |
105 | |
106 | case FROM_DEVICE(GET_STATUS): |
107 | if (setup->wLength != 2) |
108 | return 0; |
109 | usb_send(&eps[0], "\000", 2, NULL, NULL); |
110 | break; |
111 | case TO_DEVICE(CLEAR_FEATURE): |
112 | break; |
113 | case TO_DEVICE(SET_FEATURE): |
114 | return 0; |
115 | case TO_DEVICE(SET_ADDRESS): |
116 | set_addr(setup->wValue); |
117 | break; |
118 | case FROM_DEVICE(GET_DESCRIPTOR): |
119 | if (!get_descriptor(setup->wValue >> 8, setup->wValue, |
120 | setup->wLength)) |
121 | return 0; |
122 | break; |
123 | case TO_DEVICE(SET_DESCRIPTOR): |
124 | return 0; |
125 | case FROM_DEVICE(GET_CONFIGURATION): |
126 | usb_send(&eps[0], "", 1, NULL, NULL); |
127 | break; |
128 | case TO_DEVICE(SET_CONFIGURATION): |
129 | if (setup->wValue != config_descriptor[5]) |
130 | return 0; |
131 | break; |
132 | |
133 | /* |
134 | * Interface request |
135 | */ |
136 | |
137 | case FROM_INTERFACE(GET_STATUS): |
138 | return 0; |
139 | case TO_INTERFACE(CLEAR_FEATURE): |
140 | return 0; |
141 | case TO_INTERFACE(SET_FEATURE): |
142 | return 0; |
143 | case FROM_INTERFACE(GET_INTERFACE): |
144 | return 0; |
145 | case TO_INTERFACE(SET_INTERFACE): |
146 | { |
147 | const uint8_t *interface_descriptor = |
148 | config_descriptor+9; |
149 | |
150 | if (setup->wIndex != interface_descriptor[2] || |
151 | setup->wValue != interface_descriptor[3]) |
152 | return 0; |
153 | } |
154 | break; |
155 | |
156 | /* |
157 | * Endpoint request |
158 | */ |
159 | |
160 | case FROM_ENDPOINT(GET_STATUS): |
161 | return 0; |
162 | case TO_ENDPOINT(CLEAR_FEATURE): |
163 | return 0; |
164 | case TO_ENDPOINT(SET_FEATURE): |
165 | return 0; |
166 | case FROM_ENDPOINT(SYNCH_FRAME): |
167 | return 0; |
168 | |
169 | default: |
170 | if (!user_setup) |
171 | return 0; |
172 | return user_setup(setup); |
173 | } |
174 | |
175 | return 1; |
176 | } |
177 |