Root/atusb/fw/usb/usb.c

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

Archive Download this file



interactive