2 * fw/usb/usb.c - USB hardware setup and standard device requests
4 * Written 2008-2011, 2013, 2015 by Werner Almesberger
5 * Copyright 2008-2011, 2013, 2015 Werner Almesberger
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.
16 * - should support EP clearing and stalling
31 extern void panic(void);
32 #define BUG_ON(cond) do { if (cond) panic(); } while (0)
37 bool (*user_setup)(const struct setup_request *setup);
38 void (*user_set_interface)(int nth);
39 bool (*user_get_descriptor)(uint8_t type, uint8_t index,
40 const uint8_t **reply, uint8_t *size);
41 void (*user_reset)(void);
44 void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
45 uint8_t size, void (*callback)(void *user), void *user)
51 ep->callback = callback;
57 static bool get_descriptor(uint8_t type, uint8_t index, uint16_t length)
64 reply = device_descriptor;
70 reply = config_descriptor;
74 if (!user_get_descriptor)
76 if (!user_get_descriptor(type, index, &reply, &size))
81 usb_send(&eps[0], reply, size, NULL, NULL);
86 bool handle_setup(const struct setup_request *setup)
88 switch (setup->bmRequestType | setup->bRequest << 8) {
93 * See http://www.beyondlogic.org/usbnutshell/usb6.htm
96 case FROM_DEVICE(GET_STATUS):
97 if (setup->wLength != 2)
99 usb_send(&eps[0], "\000", 2, NULL, NULL);
101 case TO_DEVICE(CLEAR_FEATURE):
103 case TO_DEVICE(SET_FEATURE):
105 case TO_DEVICE(SET_ADDRESS):
106 set_addr(setup->wValue);
108 case FROM_DEVICE(GET_DESCRIPTOR):
109 case FROM_INTERFACE(GET_DESCRIPTOR):
110 if (!get_descriptor(setup->wValue >> 8, setup->wValue,
114 case TO_DEVICE(SET_DESCRIPTOR):
116 case FROM_DEVICE(GET_CONFIGURATION):
117 usb_send(&eps[0], "", 1, NULL, NULL);
119 case TO_DEVICE(SET_CONFIGURATION):
120 if (setup->wValue != config_descriptor[5])
128 case FROM_INTERFACE(GET_STATUS):
130 case TO_INTERFACE(CLEAR_FEATURE):
132 case TO_INTERFACE(SET_FEATURE):
134 case FROM_INTERFACE(GET_INTERFACE):
136 case TO_INTERFACE(SET_INTERFACE):
138 const uint8_t *interface_descriptor =
144 for (p = interface_descriptor;
145 p != config_descriptor+config_descriptor[2];
147 if (p[1] != USB_DT_INTERFACE)
149 if (p[2] == setup->wIndex &&
150 p[3] == setup->wValue) {
151 if (user_set_interface)
152 user_set_interface(i);
165 case FROM_ENDPOINT(GET_STATUS):
167 case TO_ENDPOINT(CLEAR_FEATURE):
169 case TO_ENDPOINT(SET_FEATURE):
171 case FROM_ENDPOINT(SYNCH_FRAME):
176 return user_setup(setup);