~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/usb.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * QEMU USB emulation
 
3
 *
 
4
 * Copyright (c) 2005 Fabrice Bellard
 
5
 *
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
7
 * of this software and associated documentation files (the "Software"), to deal
 
8
 * in the Software without restriction, including without limitation the rights
 
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
10
 * copies of the Software, and to permit persons to whom the Software is
 
11
 * furnished to do so, subject to the following conditions:
 
12
 *
 
13
 * The above copyright notice and this permission notice shall be included in
 
14
 * all copies or substantial portions of the Software.
 
15
 *
 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
22
 * THE SOFTWARE.
 
23
 */
 
24
#include "qemu-common.h"
 
25
#include "usb.h"
 
26
 
 
27
void usb_attach(USBPort *port, USBDevice *dev)
 
28
{
 
29
    port->attach(port, dev);
 
30
}
 
31
 
 
32
/**********************/
 
33
/* generic USB device helpers (you are not forced to use them when
 
34
   writing your USB device driver, but they help handling the
 
35
   protocol)
 
36
*/
 
37
 
 
38
#define SETUP_STATE_IDLE 0
 
39
#define SETUP_STATE_DATA 1
 
40
#define SETUP_STATE_ACK  2
 
41
 
 
42
int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
 
43
{
 
44
    int l, ret = 0;
 
45
    int len = p->len;
 
46
    uint8_t *data = p->data;
 
47
 
 
48
    switch(p->pid) {
 
49
    case USB_MSG_ATTACH:
 
50
        s->state = USB_STATE_ATTACHED;
 
51
        break;
 
52
    case USB_MSG_DETACH:
 
53
        s->state = USB_STATE_NOTATTACHED;
 
54
        break;
 
55
    case USB_MSG_RESET:
 
56
        s->remote_wakeup = 0;
 
57
        s->addr = 0;
 
58
        s->state = USB_STATE_DEFAULT;
 
59
        s->handle_reset(s);
 
60
        break;
 
61
    case USB_TOKEN_SETUP:
 
62
        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
 
63
            return USB_RET_NODEV;
 
64
        if (len != 8)
 
65
            goto fail;
 
66
        memcpy(s->setup_buf, data, 8);
 
67
        s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
 
68
        s->setup_index = 0;
 
69
        if (s->setup_buf[0] & USB_DIR_IN) {
 
70
            ret = s->handle_control(s,
 
71
                                    (s->setup_buf[0] << 8) | s->setup_buf[1],
 
72
                                    (s->setup_buf[3] << 8) | s->setup_buf[2],
 
73
                                    (s->setup_buf[5] << 8) | s->setup_buf[4],
 
74
                                    s->setup_len,
 
75
                                    s->data_buf);
 
76
            if (ret < 0)
 
77
                return ret;
 
78
            if (ret < s->setup_len)
 
79
                s->setup_len = ret;
 
80
            s->setup_state = SETUP_STATE_DATA;
 
81
        } else {
 
82
            if (s->setup_len == 0)
 
83
                s->setup_state = SETUP_STATE_ACK;
 
84
            else
 
85
                s->setup_state = SETUP_STATE_DATA;
 
86
        }
 
87
        break;
 
88
    case USB_TOKEN_IN:
 
89
        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
 
90
            return USB_RET_NODEV;
 
91
        switch(p->devep) {
 
92
        case 0:
 
93
            switch(s->setup_state) {
 
94
            case SETUP_STATE_ACK:
 
95
                if (!(s->setup_buf[0] & USB_DIR_IN)) {
 
96
                    s->setup_state = SETUP_STATE_IDLE;
 
97
                    ret = s->handle_control(s,
 
98
                                      (s->setup_buf[0] << 8) | s->setup_buf[1],
 
99
                                      (s->setup_buf[3] << 8) | s->setup_buf[2],
 
100
                                      (s->setup_buf[5] << 8) | s->setup_buf[4],
 
101
                                      s->setup_len,
 
102
                                      s->data_buf);
 
103
                    if (ret > 0)
 
104
                        ret = 0;
 
105
                } else {
 
106
                    /* return 0 byte */
 
107
                }
 
108
                break;
 
109
            case SETUP_STATE_DATA:
 
110
                if (s->setup_buf[0] & USB_DIR_IN) {
 
111
                    l = s->setup_len - s->setup_index;
 
112
                    if (l > len)
 
113
                        l = len;
 
114
                    memcpy(data, s->data_buf + s->setup_index, l);
 
115
                    s->setup_index += l;
 
116
                    if (s->setup_index >= s->setup_len)
 
117
                        s->setup_state = SETUP_STATE_ACK;
 
118
                    ret = l;
 
119
                } else {
 
120
                    s->setup_state = SETUP_STATE_IDLE;
 
121
                    goto fail;
 
122
                }
 
123
                break;
 
124
            default:
 
125
                goto fail;
 
126
            }
 
127
            break;
 
128
        default:
 
129
            ret = s->handle_data(s, p);
 
130
            break;
 
131
        }
 
132
        break;
 
133
    case USB_TOKEN_OUT:
 
134
        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
 
135
            return USB_RET_NODEV;
 
136
        switch(p->devep) {
 
137
        case 0:
 
138
            switch(s->setup_state) {
 
139
            case SETUP_STATE_ACK:
 
140
                if (s->setup_buf[0] & USB_DIR_IN) {
 
141
                    s->setup_state = SETUP_STATE_IDLE;
 
142
                    /* transfer OK */
 
143
                } else {
 
144
                    /* ignore additional output */
 
145
                }
 
146
                break;
 
147
            case SETUP_STATE_DATA:
 
148
                if (!(s->setup_buf[0] & USB_DIR_IN)) {
 
149
                    l = s->setup_len - s->setup_index;
 
150
                    if (l > len)
 
151
                        l = len;
 
152
                    memcpy(s->data_buf + s->setup_index, data, l);
 
153
                    s->setup_index += l;
 
154
                    if (s->setup_index >= s->setup_len)
 
155
                        s->setup_state = SETUP_STATE_ACK;
 
156
                    ret = l;
 
157
                } else {
 
158
                    s->setup_state = SETUP_STATE_IDLE;
 
159
                    goto fail;
 
160
                }
 
161
                break;
 
162
            default:
 
163
                goto fail;
 
164
            }
 
165
            break;
 
166
        default:
 
167
            ret = s->handle_data(s, p);
 
168
            break;
 
169
        }
 
170
        break;
 
171
    default:
 
172
    fail:
 
173
        ret = USB_RET_STALL;
 
174
        break;
 
175
    }
 
176
    return ret;
 
177
}
 
178
 
 
179
/* XXX: fix overflow */
 
180
int set_usb_string(uint8_t *buf, const char *str)
 
181
{
 
182
    int len, i;
 
183
    uint8_t *q;
 
184
 
 
185
    q = buf;
 
186
    len = strlen(str);
 
187
    *q++ = 2 * len + 2;
 
188
    *q++ = 3;
 
189
    for(i = 0; i < len; i++) {
 
190
        *q++ = str[i];
 
191
        *q++ = 0;
 
192
    }
 
193
    return q - buf;
 
194
}
 
195
 
 
196
/* Send an internal message to a USB device.  */
 
197
void usb_send_msg(USBDevice *dev, int msg)
 
198
{
 
199
    USBPacket p;
 
200
    memset(&p, 0, sizeof(p));
 
201
    p.pid = msg;
 
202
    dev->handle_packet(dev, &p);
 
203
}
 
204