Root/atusb/fw/usb/usb.c

Source at commit c5f9cc1 created 4 years 24 days ago.
By Werner Almesberger, atusb/fw/: let include path find board.h instead of using ../board.h
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        if (!get_descriptor(setup->wValue >> 8, setup->wValue,
110            setup->wLength))
111            return 0;
112        break;
113    case TO_DEVICE(SET_DESCRIPTOR):
114        return 0;
115    case FROM_DEVICE(GET_CONFIGURATION):
116        usb_send(&eps[0], "", 1, NULL, NULL);
117        break;
118    case TO_DEVICE(SET_CONFIGURATION):
119        if (setup->wValue != config_descriptor[5])
120            return 0;
121        usb_enable_bus_reset();
122        break;
123
124    /*
125     * Interface request
126     */
127
128    case FROM_INTERFACE(GET_STATUS):
129        return 0;
130    case TO_INTERFACE(CLEAR_FEATURE):
131        return 0;
132    case TO_INTERFACE(SET_FEATURE):
133        return 0;
134    case FROM_INTERFACE(GET_INTERFACE):
135        return 0;
136    case TO_INTERFACE(SET_INTERFACE):
137        {
138            const uint8_t *interface_descriptor =
139                config_descriptor+9;
140            const uint8_t *p;
141            int i;
142
143            i = 0;
144            for (p = interface_descriptor;
145                p != config_descriptor+config_descriptor[2];
146                p += p[0]) {
147                if (p[2] == setup->wIndex &&
148                    p[3] == setup->wValue) {
149                    if (user_set_interface)
150                        user_set_interface(i);
151                    return 1;
152                }
153                i++;
154            }
155            return 0;
156        }
157        break;
158
159    /*
160     * Endpoint request
161     */
162
163    case FROM_ENDPOINT(GET_STATUS):
164        return 0;
165    case TO_ENDPOINT(CLEAR_FEATURE):
166        return 0;
167    case TO_ENDPOINT(SET_FEATURE):
168        return 0;
169    case FROM_ENDPOINT(SYNCH_FRAME):
170        return 0;
171
172    default:
173        if (user_setup)
174            return user_setup(setup);
175        return 0;
176    }
177
178    return 1;
179}
180

Archive Download this file



interactive