Root/atusb/fw/usb/usb.c

Source at commit 78cfc8ffeb03a6fd6a1e63295c9d807eda84017d created 8 years 5 months ago.
By Werner Almesberger, moved atusb/fw3/ to atusb/fw/
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#define NUM_EPS 1
30
31#if 1
32extern void panic(void);
33#define BUG_ON(cond) do { if (cond) panic(); } while (0)
34#else
35#define BUG_ON(cond)
36#endif
37
38int (*user_setup)(const struct setup_request *setup);
39int (*user_get_descriptor)(uint8_t type, uint8_t index,
40    const uint8_t * const *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}
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
139            if (setup->wIndex != interface_descriptor[2] ||
140                setup->wValue != interface_descriptor[3])
141                return 0;
142        }
143        break;
144
145    /*
146     * Endpoint request
147     */
148
149    case FROM_ENDPOINT(GET_STATUS):
150        return 0;
151    case TO_ENDPOINT(CLEAR_FEATURE):
152        return 0;
153    case TO_ENDPOINT(SET_FEATURE):
154        return 0;
155    case FROM_ENDPOINT(SYNCH_FRAME):
156        return 0;
157
158    default:
159        if (!user_setup)
160            return 0;
161        return user_setup(setup);
162    }
163
164    return 1;
165}
166

Archive Download this file



interactive