1/* 2 * Copyright (c) 2007-2013 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10/* 11 * Copyright (c) 2007-2013 ETH Zurich. 12 * All rights reserved. 13 * 14 * This file is distributed under the terms in the attached LICENSE file. 15 * If you do not find this file, copies can be found by writing to: 16 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 17 */ 18 19#include <stdlib.h> 20#include <stdio.h> 21#include <barrelfish/barrelfish.h> 22 23#include <usb/usb.h> 24 25#include <usb/usb_request.h> 26 27#include <usb_device.h> 28#include <usb_hub.h> 29#include <usb_request.h> 30 31usb_error_t usb_hub_clear_hub_feature(struct usb_device *hub, uint16_t feature) 32{ 33 struct usb_device_request req; 34 req.bType.direction = USB_REQUEST_WRITE; 35 req.bType.recipient = USB_REQUEST_RECIPIENT_DEVICE; 36 req.bType.type = USB_REQUEST_TYPE_CLASS; 37 req.bRequest = USB_HUB_REQ_CLEAR_FEATURE; 38 req.wValue = feature; 39 req.wLength = 0; 40 req.wIndex = 0; 41 return (usb_exec_request(hub, 0, &req, NULL, NULL)); 42} 43 44usb_error_t usb_hub_clear_port_feature(struct usb_device *hub, uint16_t feature, 45 uint8_t port) 46{ 47 struct usb_device_request req; 48 req.bType.direction = USB_REQUEST_WRITE; 49 req.bType.recipient = USB_REQUEST_RECIPIENT_OTHER; 50 req.bType.type = USB_REQUEST_TYPE_CLASS; 51 req.bRequest = USB_HUB_REQ_CLEAR_FEATURE; 52 req.wValue = feature; 53 req.wLength = 0; 54 req.wIndex = port; 55 return (usb_exec_request(hub, 0, &req, NULL, NULL)); 56} 57 58usb_error_t usb_hub_clear_tt_buffer(struct usb_device *hub, uint8_t dev_addr, 59 uint8_t ep_num, uint8_t ep_type, uint8_t direction, uint16_t tt_port) 60{ 61 struct usb_device_request req; 62 63 if (hub->device_desc.bDeviceClass == USB_HUB_CLASS_CODE 64 && hub->device_desc.bDeviceProtocol == USB_HUB_PROTOCOL_HSHUBSTT) { 65 /* 66 * if there is just a single transaction translator in the hub, 67 * the port should be 1 68 */ 69 tt_port = 1; 70 } 71 72 uint16_t wValue = (ep_num & 0xF) | ((dev_addr & 0x7F) << 4) 73 | ((ep_num & 0x80) << 8) | ((ep_type & 0x3) << 12); 74 75 req.bType.direction = USB_REQUEST_WRITE; 76 req.bType.recipient = USB_REQUEST_RECIPIENT_OTHER; 77 req.bType.type = USB_REQUEST_TYPE_CLASS; 78 req.bRequest = USB_HUB_REQ_CLEAR_TT_BUFFER; 79 req.wValue = wValue; 80 req.wLength = 0; 81 req.wIndex = tt_port; 82 return (usb_exec_request(hub, 0, &req, NULL, NULL)); 83} 84 85usb_error_t usb_hub_get_hub_status(struct usb_device *hub, 86 struct usb_hub_status *ret_status) 87 88{ 89 USB_DEBUG_TR_ENTER; 90 struct usb_device_request req; 91 92 req.bType.direction = USB_REQUEST_READ; 93 req.bType.recipient = USB_REQUEST_RECIPIENT_DEVICE; 94 req.bType.type = USB_REQUEST_TYPE_CLASS; 95 req.bRequest = USB_HUB_REQ_GET_STATUS; 96 req.wValue = 0; 97 req.wLength = sizeof(struct usb_hub_status); 98 req.wIndex = 0; 99 return (usb_exec_request(hub, 0, &req, ret_status, NULL)); 100} 101 102usb_error_t usb_hub_get_port_status(struct usb_device *hub, uint16_t port, 103 struct usb_hub_port_status *ret_status) 104{ 105 USB_DEBUG_TR_ENTER; 106 107 struct usb_device_request req; 108 109 req.bType.direction = USB_REQUEST_READ; 110 req.bType.recipient = USB_REQUEST_RECIPIENT_OTHER; 111 req.bType.type = USB_REQUEST_TYPE_CLASS; 112 req.bRequest = USB_HUB_REQ_GET_STATUS; 113 req.wValue = 0; 114 req.wLength = sizeof(struct usb_hub_port_status); 115 req.wIndex = port; 116 return (usb_exec_request(hub, 0, &req, ret_status, NULL)); 117} 118 119usb_error_t usb_hub_reset_tt(struct usb_device *hub, uint16_t port) 120{ 121 USB_DEBUG_TR_ENTER; 122 123 struct usb_device_request req; 124 125 if (hub->device_desc.bDeviceClass == USB_HUB_CLASS_CODE 126 && hub->device_desc.bDeviceProtocol == USB_HUB_PROTOCOL_HSHUBSTT) { 127 /* 128 * if there is just a single transaction translator in the hub, 129 * the port should be 1 130 */ 131 port = 1; 132 } 133 134 req.bType.direction = USB_REQUEST_WRITE; 135 req.bType.recipient = USB_REQUEST_RECIPIENT_OTHER; 136 req.bType.type = USB_REQUEST_TYPE_CLASS; 137 req.bRequest = USB_HUB_REQ_RESET_TT; 138 req.wValue = 0; 139 req.wLength = 0; 140 req.wIndex = port; 141 return (usb_exec_request(hub, 0, &req, NULL, NULL)); 142} 143 144usb_error_t usb_hub_set_hub_feature(struct usb_device *hub, uint16_t feature) 145{ 146 struct usb_device_request req; 147 148 req.bType.direction = USB_REQUEST_WRITE; 149 req.bType.recipient = USB_REQUEST_RECIPIENT_DEVICE; 150 req.bType.type = USB_REQUEST_TYPE_CLASS; 151 req.bRequest = USB_HUB_REQ_SET_FEATURE; 152 req.wValue = feature; 153 req.wLength = 0; 154 req.wIndex = 0; 155 return (usb_exec_request(hub, 0, &req, NULL, NULL)); 156} 157 158usb_error_t usb_hub_set_port_feature(struct usb_device *hub, uint16_t feature, 159 uint8_t port) 160{ 161 struct usb_device_request req; 162 163 req.bType.direction = USB_REQUEST_WRITE; 164 req.bType.recipient = USB_REQUEST_RECIPIENT_OTHER; 165 req.bType.type = USB_REQUEST_TYPE_CLASS; 166 req.bRequest = USB_HUB_REQ_SET_FEATURE; 167 req.wValue = feature; 168 req.wLength = 0; 169 req.wIndex = port; 170 return (usb_exec_request(hub, 0, &req, NULL, NULL)); 171} 172 173usb_error_t usb_hub_get_tt_state(struct usb_device *hub, uint16_t flags, 174 uint16_t port, uint16_t max_length, uint16_t ret_length, 175 void *ret_state) 176{ 177 assert(!"NYI: usb_hub_get_tt_state()\n"); 178 return (USB_ERR_BAD_REQUEST); 179} 180 181usb_error_t usb_hub_stop_tt(struct usb_device *hub, uint16_t port) 182{ 183 assert(!"NYI: usb_hub_stop_tt()\n"); 184 return (USB_ERR_BAD_REQUEST); 185} 186 187usb_error_t usb_hub_get_hub_descriptor(struct usb_device *hub, uint16_t nports, 188 struct usb_hub_descriptor *ret_desc) 189{ 190 USB_DEBUG_TR_ENTER; 191 struct usb_device_request req; 192 193 uint16_t wLength = (nports + 7 + (8 * 8)) / 8; 194 195 req.bType.direction = USB_REQUEST_READ; 196 req.bType.recipient = USB_REQUEST_RECIPIENT_DEVICE; 197 req.bType.type = USB_REQUEST_TYPE_CLASS; 198 req.bRequest = USB_HUB_REQ_GET_DESCRIPTOR; 199 req.wValue = USB_DESCRIPTOR_TYPE_HUB<<8; 200 req.wLength = wLength; 201 req.wIndex = 0; 202 return (usb_exec_request(hub, 0, &req, ret_desc, NULL)); 203} 204 205usb_error_t usb_hub_set_hub_descriptor(struct usb_device *hub, 206 uint16_t desc_length, struct usb_hub_descriptor *desc) 207{ 208 return (USB_ERR_BAD_REQUEST); 209} 210 211usb_error_t usb_hub_re_enumerate(struct usb_device *hub) 212{ 213 return (USB_ERR_BAD_REQUEST); 214} 215 216usb_error_t usb_hub_reset_port(struct usb_device *hub, uint8_t port) 217{ 218 USB_DEBUG_TR_ENTER; 219 usb_error_t err; 220 struct usb_hub_port_status ps; 221 222 /* clear port reset changes (if any) */ 223 err = usb_hub_clear_port_feature(hub, USB_HUB_FEATURE_C_PORT_RESET, port); 224 if (err != USB_ERR_OK) { 225 USB_DEBUG("ERROR: could not clear port reset on port %u\n", port); 226 USB_DEBUG_TR_RETURN; 227 return (err); 228 } 229 230 /* initate the rest sequence */ 231 err = usb_hub_set_port_feature(hub, USB_HUB_FEATURE_PORT_RESET, port); 232 if (err != USB_ERR_OK) { 233 USB_DEBUG("ERROR: port reset could not reset port %u\n", port); 234 USB_DEBUG_TR_RETURN; 235 return (err); 236 } 237 238 uint16_t timeout = 0; 239 240 /* wait till the reset sequence is over */ 241 while (1) { 242 lib_usb_wait(USB_DELAY_PORT_RESET); 243 244 timeout += USB_DELAY_PORT_RESET; 245 246 err = usb_hub_get_port_status(hub, port, &ps); 247 if (err != USB_ERR_OK) { 248 USB_DEBUG("ERROR: could not get port status\n"); 249 USB_DEBUG_TR_RETURN; 250 return (err); 251 } 252 253 if (!ps.wPortStatus.connection) { 254 /* the devie has disappeared, so give up */ 255 USB_DEBUG("NOTICE: Device %i has disappeared...\n", hub->device_address); 256 USB_DEBUG_TR_RETURN; 257 return (err); 258 } 259 260 if (ps.wPortChange.is_reset) { 261 /* the reset sequence is over */ 262 break; 263 } 264 265 if (!ps.wPortStatus.reset) { 266 /* check if reset is no longer asserted */ 267 break; 268 } 269 270 if (timeout > 10000) { 271 timeout = 0; 272 break; 273 } 274 } 275 276 /* 277 * clear the port reset feature, just in case it was not cleared 278 * automatically 279 */ 280 err = usb_hub_clear_port_feature(hub, USB_HUB_FEATURE_C_PORT_RESET, port); 281 if (err != USB_ERR_OK) { 282 USB_DEBUG("ERROR: Could not reset port feature\n"); 283 USB_DEBUG_TR_RETURN; 284 return (err); 285 } 286 287 if (timeout == 0) { 288 USB_DEBUG("ERROR: timeout happened during reset\n"); 289 USB_DEBUG_TR_RETURN; 290 return (USB_ERR_TIMEOUT); 291 } 292 293 /* give the device time to recover from reset */ 294 lib_usb_wait(USB_DELAY_PORT_RECOVERY); 295 296 USB_DEBUG_TR_RETURN; 297 return (err); 298} 299 300