]>
git.proxmox.com Git - qemu.git/blob - hw/usb.c
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
26 void usb_attach(USBPort
*port
, USBDevice
*dev
)
28 port
->attach(port
, dev
);
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
37 #define SETUP_STATE_IDLE 0
38 #define SETUP_STATE_DATA 1
39 #define SETUP_STATE_ACK 2
41 int usb_generic_handle_packet(USBDevice
*s
, int pid
,
42 uint8_t devaddr
, uint8_t devep
,
43 uint8_t *data
, int len
)
49 s
->state
= USB_STATE_ATTACHED
;
52 s
->state
= USB_STATE_NOTATTACHED
;
57 s
->state
= USB_STATE_DEFAULT
;
58 s
->handle_reset(s
, 0);
61 s
->handle_reset(s
, 1);
64 if (s
->state
< USB_STATE_DEFAULT
|| devaddr
!= s
->addr
)
68 memcpy(s
->setup_buf
, data
, 8);
69 s
->setup_len
= (s
->setup_buf
[7] << 8) | s
->setup_buf
[6];
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],
80 if (ret
< s
->setup_len
)
82 s
->setup_state
= SETUP_STATE_DATA
;
84 if (s
->setup_len
== 0)
85 s
->setup_state
= SETUP_STATE_ACK
;
87 s
->setup_state
= SETUP_STATE_DATA
;
91 if (s
->state
< USB_STATE_DEFAULT
|| devaddr
!= s
->addr
)
95 switch(s
->setup_state
) {
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],
111 case SETUP_STATE_DATA
:
112 if (s
->setup_buf
[0] & USB_DIR_IN
) {
113 l
= s
->setup_len
- s
->setup_index
;
116 memcpy(data
, s
->data_buf
+ s
->setup_index
, l
);
118 if (s
->setup_index
>= s
->setup_len
)
119 s
->setup_state
= SETUP_STATE_ACK
;
122 s
->setup_state
= SETUP_STATE_IDLE
;
131 ret
= s
->handle_data(s
, pid
, devep
, data
, len
);
136 if (s
->state
< USB_STATE_DEFAULT
|| devaddr
!= s
->addr
)
137 return USB_RET_NODEV
;
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
;
146 /* ignore additionnal output */
149 case SETUP_STATE_DATA
:
150 if (!(s
->setup_buf
[0] & USB_DIR_IN
)) {
151 l
= s
->setup_len
- s
->setup_index
;
154 memcpy(s
->data_buf
+ s
->setup_index
, data
, l
);
156 if (s
->setup_index
>= s
->setup_len
)
157 s
->setup_state
= SETUP_STATE_ACK
;
160 s
->setup_state
= SETUP_STATE_IDLE
;
169 ret
= s
->handle_data(s
, pid
, devep
, data
, len
);
181 /* XXX: fix overflow */
182 int set_usb_string(uint8_t *buf
, const char *str
)
191 for(i
= 0; i
< len
; i
++) {