4 * Copyright (c) 2005 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 #include "qemu-common.h"
27 void usb_attach(USBPort
*port
, USBDevice
*dev
)
29 port
->attach(port
, dev
);
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
38 #define SETUP_STATE_IDLE 0
39 #define SETUP_STATE_DATA 1
40 #define SETUP_STATE_ACK 2
42 int usb_generic_handle_packet(USBDevice
*s
, USBPacket
*p
)
46 uint8_t *data
= p
->data
;
50 s
->state
= USB_STATE_ATTACHED
;
53 s
->state
= USB_STATE_NOTATTACHED
;
58 s
->state
= USB_STATE_DEFAULT
;
62 if (s
->state
< USB_STATE_DEFAULT
|| p
->devaddr
!= s
->addr
)
66 memcpy(s
->setup_buf
, data
, 8);
67 s
->setup_len
= (s
->setup_buf
[7] << 8) | s
->setup_buf
[6];
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],
78 if (ret
< s
->setup_len
)
80 s
->setup_state
= SETUP_STATE_DATA
;
82 if (s
->setup_len
== 0)
83 s
->setup_state
= SETUP_STATE_ACK
;
85 s
->setup_state
= SETUP_STATE_DATA
;
89 if (s
->state
< USB_STATE_DEFAULT
|| p
->devaddr
!= s
->addr
)
93 switch(s
->setup_state
) {
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],
109 case SETUP_STATE_DATA
:
110 if (s
->setup_buf
[0] & USB_DIR_IN
) {
111 l
= s
->setup_len
- s
->setup_index
;
114 memcpy(data
, s
->data_buf
+ s
->setup_index
, l
);
116 if (s
->setup_index
>= s
->setup_len
)
117 s
->setup_state
= SETUP_STATE_ACK
;
120 s
->setup_state
= SETUP_STATE_IDLE
;
129 ret
= s
->handle_data(s
, p
);
134 if (s
->state
< USB_STATE_DEFAULT
|| p
->devaddr
!= s
->addr
)
135 return USB_RET_NODEV
;
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
;
144 /* ignore additional output */
147 case SETUP_STATE_DATA
:
148 if (!(s
->setup_buf
[0] & USB_DIR_IN
)) {
149 l
= s
->setup_len
- s
->setup_index
;
152 memcpy(s
->data_buf
+ s
->setup_index
, data
, l
);
154 if (s
->setup_index
>= s
->setup_len
)
155 s
->setup_state
= SETUP_STATE_ACK
;
158 s
->setup_state
= SETUP_STATE_IDLE
;
167 ret
= s
->handle_data(s
, p
);
179 /* XXX: fix overflow */
180 int set_usb_string(uint8_t *buf
, const char *str
)
189 for(i
= 0; i
< len
; i
++) {
196 /* Send an internal message to a USB device. */
197 void usb_send_msg(USBDevice
*dev
, int msg
)
200 memset(&p
, 0, sizeof(p
));
202 dev
->handle_packet(dev
, &p
);