Root/atusb/fw/usb/usb.c

Source at commit 4b6f390830dda49bf712f689239c9ecbd98fb2be created 4 years 7 months ago.
By Werner Almesberger, atusb/fw/usb/usb.c (handle_setup): also pass interface-level GET_DESCRIPTOR to get_descriptor
1/*
2 * fw/usb/usb.c - USB hardware setup and standard device requests
3 *
4 * Written 2008-2011, 2013 by Werner Almesberger
5 * Copyright 2008-2011, 2013 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 * - should support EP clearing and stalling
17 */
18
19#include <stdbool.h>
20#include <stdint.h>
21
22#include "usb.h"
23#include "board.h"
24
25
26#ifndef NULL
27#define NULL 0
28#endif
29
30#if 1
31extern void panic(void);
32#define BUG_ON(cond) do { if (cond) panic(); } while (0)
33#else
34#define BUG_ON(cond)
35#endif
36
37bool (*user_setup)(const struct setup_request *setup);
38void (*user_set_interface)(int nth);
39bool (*user_get_descriptor)(uint8_t type, uint8_t index,
40    const uint8_t **reply, uint8_t *size);
41void (*user_reset)(void);
42
43
44void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
45    uint8_t size, void (*callback)(void *user), void *user)
46{
47    BUG_ON(ep->state);
48    ep->state = state;
49    ep->buf = buf;
50    ep->end = buf+size;
51    ep->callback = callback;
52    ep->user = user;
53    usb_ep_change(ep);
54}
55
56
57static bool get_descriptor(uint8_t type, uint8_t index, uint16_t length)
58{
59    const uint8_t *reply;
60    uint8_t size;
61
62    switch (type) {
63    case USB_DT_DEVICE:
64        reply = device_descriptor;
65        size = reply[0];
66        break;
67    case USB_DT_CONFIG:
68        if (index)
69            return 0;
70        reply = config_descriptor;
71        size = reply[2];
72        break;
73    default:
74        if (!user_get_descriptor)
75            return 0;
76        if (!user_get_descriptor(type, index, &reply, &size))
77            return 0;
78    }
79    if (length < size)
80        size = length;
81    usb_send(&eps[0], reply, size, NULL, NULL);
82    return 1;
83}
84
85
86bool handle_setup(const struct setup_request *setup)
87{
88    switch (setup->bmRequestType | setup->bRequest << 8) {
89
90    /*
91     * Device request
92     *
93     * See http://www.beyondlogic.org/usbnutshell/usb6.htm
94     */
95
96    case FROM_DEVICE(GET_STATUS):
97        if (setup->wLength != 2)
98            return 0;
99        usb_send(&eps[0], "\000", 2, NULL, NULL);
100        break;
101    case TO_DEVICE(CLEAR_FEATURE):
102        break;
103    case TO_DEVICE(SET_FEATURE):
104        return 0;
105    case TO_DEVICE(SET_ADDRESS):
106        set_addr(setup->wValue);
107        break;
108    case FROM_DEVICE(GET_DESCRIPTOR):
109    case FROM_INTERFACE(GET_DESCRIPTOR):
110        if (!get_descriptor(setup->wValue >> 8, setup->wValue,
111            setup->wLength))
112            return 0;
113        break;
114    case TO_DEVICE(SET_DESCRIPTOR):
115        return 0;
116    case FROM_DEVICE(GET_CONFIGURATION):
117        usb_send(&eps[0], "", 1, NULL, NULL);
118        break;
119    case TO_DEVICE(SET_CONFIGURATION):
120        if (setup->wValue != config_descriptor[5])
121            return 0;
122        usb_enable_bus_reset();
123        break;
124
125    /*
126     * Interface request
127     */
128
129    case FROM_INTERFACE(GET_STATUS):
130        return 0;
131    case TO_INTERFACE(CLEAR_FEATURE):
132        return 0;
133    case TO_INTERFACE(SET_FEATURE):
134        return 0;
135    case FROM_INTERFACE(GET_INTERFACE):
136        return 0;
137    case TO_INTERFACE(SET_INTERFACE):
138        {
139            const uint8_t *interface_descriptor =
140                config_descriptor+9;
141            const uint8_t *p;
142            int i;
143
144            i = 0;
145            for (p = interface_descriptor;
146                p != config_descriptor+config_descriptor[2];
147                p += p[0]) {
148                if (p[2] == setup->wIndex &&
149                    p[3] == setup->wValue) {
150                    if (user_set_interface)
151                        user_set_interface(i);
152                    return 1;
153                }
154                i++;
155            }
156            return 0;
157        }
158        break;
159
160    /*
161     * Endpoint request
162     */
163
164    case FROM_ENDPOINT(GET_STATUS):
165        return 0;
166    case TO_ENDPOINT(CLEAR_FEATURE):
167        return 0;
168    case TO_ENDPOINT(SET_FEATURE):
169        return 0;
170    case FROM_ENDPOINT(SYNCH_FRAME):
171        return 0;
172
173    default:
174        if (user_setup)
175            return user_setup(setup);
176        return 0;
177    }
178
179    return 1;
180}
181

Archive Download this file



interactive