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, USBPacket *p) 42 { 43 int l, ret = 0; 44 int len = p->len; 45 uint8_t *data = p->data; 46 47 switch(p->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); 59 break; 60 case USB_TOKEN_SETUP: 61 if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr) 62 return USB_RET_NODEV; 63 if (len != 8) 64 goto fail; 65 memcpy(s->setup_buf, data, 8); 66 s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; 67 s->setup_index = 0; 68 if (s->setup_buf[0] & USB_DIR_IN) { 69 ret = s->handle_control(s, 70 (s->setup_buf[0] << 8) | s->setup_buf[1], 71 (s->setup_buf[3] << 8) | s->setup_buf[2], 72 (s->setup_buf[5] << 8) | s->setup_buf[4], 73 s->setup_len, 74 s->data_buf); 75 if (ret < 0) 76 return ret; 77 if (ret < s->setup_len) 78 s->setup_len = ret; 79 s->setup_state = SETUP_STATE_DATA; 80 } else { 81 if (s->setup_len == 0) 82 s->setup_state = SETUP_STATE_ACK; 83 else 84 s->setup_state = SETUP_STATE_DATA; 85 } 86 break; 87 case USB_TOKEN_IN: 88 if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr) 89 return USB_RET_NODEV; 90 switch(p->devep) { 91 case 0: 92 switch(s->setup_state) { 93 case SETUP_STATE_ACK: 94 if (!(s->setup_buf[0] & USB_DIR_IN)) { 95 s->setup_state = SETUP_STATE_IDLE; 96 ret = s->handle_control(s, 97 (s->setup_buf[0] << 8) | s->setup_buf[1], 98 (s->setup_buf[3] << 8) | s->setup_buf[2], 99 (s->setup_buf[5] << 8) | s->setup_buf[4], 100 s->setup_len, 101 s->data_buf); 102 if (ret > 0) 103 ret = 0; 104 } else { 105 /* return 0 byte */ 106 } 107 break; 108 case SETUP_STATE_DATA: 109 if (s->setup_buf[0] & USB_DIR_IN) { 110 l = s->setup_len - s->setup_index; 111 if (l > len) 112 l = len; 113 memcpy(data, s->data_buf + s->setup_index, l); 114 s->setup_index += l; 115 if (s->setup_index >= s->setup_len) 116 s->setup_state = SETUP_STATE_ACK; 117 ret = l; 118 } else { 119 s->setup_state = SETUP_STATE_IDLE; 120 goto fail; 121 } 122 break; 123 default: 124 goto fail; 125 } 126 break; 127 default: 128 ret = s->handle_data(s, p); 129 break; 130 } 131 break; 132 case USB_TOKEN_OUT: 133 if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr) 134 return USB_RET_NODEV; 135 switch(p->devep) { 136 case 0: 137 switch(s->setup_state) { 138 case SETUP_STATE_ACK: 139 if (s->setup_buf[0] & USB_DIR_IN) { 140 s->setup_state = SETUP_STATE_IDLE; 141 /* transfer OK */ 142 } else { 143 /* ignore additionnal output */ 144 } 145 break; 146 case SETUP_STATE_DATA: 147 if (!(s->setup_buf[0] & USB_DIR_IN)) { 148 l = s->setup_len - s->setup_index; 149 if (l > len) 150 l = len; 151 memcpy(s->data_buf + s->setup_index, data, l); 152 s->setup_index += l; 153 if (s->setup_index >= s->setup_len) 154 s->setup_state = SETUP_STATE_ACK; 155 ret = l; 156 } else { 157 s->setup_state = SETUP_STATE_IDLE; 158 goto fail; 159 } 160 break; 161 default: 162 goto fail; 163 } 164 break; 165 default: 166 ret = s->handle_data(s, p); 167 break; 168 } 169 break; 170 default: 171 fail: 172 ret = USB_RET_STALL; 173 break; 174 } 175 return ret; 176 } 177 178 /* XXX: fix overflow */ 179 int set_usb_string(uint8_t *buf, const char *str) 180 { 181 int len, i; 182 uint8_t *q; 183 184 q = buf; 185 len = strlen(str); 186 *q++ = 2 * len + 2; 187 *q++ = 3; 188 for(i = 0; i < len; i++) { 189 *q++ = str[i]; 190 *q++ = 0; 191 } 192 return q - buf; 193 } 194 195 /* Send an internal message to a USB device. */ 196 void usb_send_msg(USBDevice *dev, int msg) 197 { 198 USBPacket p; 199 memset(&p, 0, sizeof(p)); 200 p.pid = msg; 201 dev->handle_packet(dev, &p); 202 } 203 204