new clock logic: cpu ticks and virtual clocks are no longer proportional - added...
[qemu] / hw / usb.c
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 "vl.h"
25
26 void usb_attach(USBPort *port, USBDevice *dev)
27 {
28     port->attach(port, dev);
29 }
30
31 /**********************/
32 /* generic USB device helpers (you are not forced to use them when
33    writing your USB device driver, but they help handling the
34    protocol) 
35 */
36
37 #define SETUP_STATE_IDLE 0
38 #define SETUP_STATE_DATA 1
39 #define SETUP_STATE_ACK  2
40
41 int usb_generic_handle_packet(USBDevice *s, int pid, 
42                               uint8_t devaddr, uint8_t devep,
43                               uint8_t *data, int len)
44 {
45     int l, ret = 0;
46
47     switch(pid) {
48     case USB_MSG_ATTACH:
49         s->state = USB_STATE_ATTACHED;
50         break;
51     case USB_MSG_DETACH:
52         s->state = USB_STATE_NOTATTACHED;
53         break;
54     case USB_MSG_RESET:
55         s->remote_wakeup = 0;
56         s->addr = 0;
57         s->state = USB_STATE_DEFAULT;
58         s->handle_reset(s, 0);
59         break;
60     case USB_MSG_DESTROY:
61         s->handle_reset(s, 1);
62         break;
63     case USB_TOKEN_SETUP:
64         if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
65             return USB_RET_NODEV;
66         if (len != 8)
67             goto fail;
68         memcpy(s->setup_buf, data, 8);
69         s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
70         s->setup_index = 0;
71         if (s->setup_buf[0] & USB_DIR_IN) {
72             ret = s->handle_control(s, 
73                                     (s->setup_buf[0] << 8) | s->setup_buf[1],
74                                     (s->setup_buf[3] << 8) | s->setup_buf[2],
75                                     (s->setup_buf[5] << 8) | s->setup_buf[4],
76                                     s->setup_len,
77                                     s->data_buf);
78             if (ret < 0)
79                 return ret;
80             if (ret < s->setup_len)
81                 s->setup_len = ret;
82             s->setup_state = SETUP_STATE_DATA;
83         } else {
84             if (s->setup_len == 0)
85                 s->setup_state = SETUP_STATE_ACK;
86             else
87                 s->setup_state = SETUP_STATE_DATA;
88         }
89         break;
90     case USB_TOKEN_IN:
91         if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
92             return USB_RET_NODEV;
93         switch(devep) {
94         case 0:
95             switch(s->setup_state) {
96             case SETUP_STATE_ACK:
97                 if (!(s->setup_buf[0] & USB_DIR_IN)) {
98                     s->setup_state = SETUP_STATE_IDLE;
99                     ret = s->handle_control(s, 
100                                       (s->setup_buf[0] << 8) | s->setup_buf[1],
101                                       (s->setup_buf[3] << 8) | s->setup_buf[2],
102                                       (s->setup_buf[5] << 8) | s->setup_buf[4],
103                                       s->setup_len,
104                                       s->data_buf);
105                     if (ret > 0)
106                         ret = 0;
107                 } else {
108                     /* return 0 byte */
109                 }
110                 break;
111             case SETUP_STATE_DATA:
112                 if (s->setup_buf[0] & USB_DIR_IN) {
113                     l = s->setup_len - s->setup_index;
114                     if (l > len)
115                         l = len;
116                     memcpy(data, s->data_buf + s->setup_index, l);
117                     s->setup_index += l;
118                     if (s->setup_index >= s->setup_len)
119                         s->setup_state = SETUP_STATE_ACK;
120                     ret = l;
121                 } else {
122                     s->setup_state = SETUP_STATE_IDLE;
123                     goto fail;
124                 }
125                 break;
126             default:
127                 goto fail;
128             }
129             break;
130         default:
131             ret = s->handle_data(s, pid, devep, data, len);
132             break;
133         }
134         break;
135     case USB_TOKEN_OUT:
136         if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
137             return USB_RET_NODEV;
138         switch(devep) {
139         case 0:
140             switch(s->setup_state) {
141             case SETUP_STATE_ACK:
142                 if (s->setup_buf[0] & USB_DIR_IN) {
143                     s->setup_state = SETUP_STATE_IDLE;
144                     /* transfer OK */
145                 } else {
146                     /* ignore additionnal output */
147                 }
148                 break;
149             case SETUP_STATE_DATA:
150                 if (!(s->setup_buf[0] & USB_DIR_IN)) {
151                     l = s->setup_len - s->setup_index;
152                     if (l > len)
153                         l = len;
154                     memcpy(s->data_buf + s->setup_index, data, l);
155                     s->setup_index += l;
156                     if (s->setup_index >= s->setup_len)
157                         s->setup_state = SETUP_STATE_ACK;
158                     ret = l;
159                 } else {
160                     s->setup_state = SETUP_STATE_IDLE;
161                     goto fail;
162                 }
163                 break;
164             default:
165                 goto fail;
166             }
167             break;
168         default:
169             ret = s->handle_data(s, pid, devep, data, len);
170             break;
171         }
172         break;
173     default:
174     fail:
175         ret = USB_RET_STALL;
176         break;
177     }
178     return ret;
179 }
180
181 /* XXX: fix overflow */
182 int set_usb_string(uint8_t *buf, const char *str)
183 {
184     int len, i;
185     uint8_t *q;
186
187     q = buf;
188     len = strlen(str);
189     *q++ = 2 * len + 2;
190     *q++ = 3;
191     for(i = 0; i < len; i++) {
192         *q++ = str[i];
193         *q++ = 0;
194     }
195     return q - buf;
196 }