Changes in uspace/lib/usbhost/src/ddf_helpers.c [1d758fc:b7fd2a0] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbhost/src/ddf_helpers.c
r1d758fc rb7fd2a0 31 31 */ 32 32 /** @file 33 * Helpers to work with the DDF interface. 34 */ 33 * 34 */ 35 36 #include <usb/classes/classes.h> 37 #include <usb/debug.h> 38 #include <usb/descriptor.h> 39 #include <usb/request.h> 40 #include <usb/usb.h> 35 41 36 42 #include <adt/list.h> … … 41 47 #include <device/hw_res_parsed.h> 42 48 #include <errno.h> 49 #include <fibril_synch.h> 50 #include <macros.h> 51 #include <stdio.h> 52 #include <stdlib.h> 43 53 #include <str_error.h> 44 #include <usb/classes/classes.h>45 #include <usb/debug.h>46 #include <usb/descriptor.h>47 #include <usb/usb.h>48 #include <usb/dma_buffer.h>49 54 #include <usb_iface.h> 50 #include <usbhc_iface.h>51 52 #include "bus.h"53 #include "endpoint.h"54 55 55 56 #include "ddf_helpers.h" 56 57 57 /** 58 * DDF usbhc_iface callback. Passes the endpoint descriptors, fills the pipe 59 * descriptor according to the contents of the endpoint. 60 * 61 * @param[in] fun DDF function of the device in question. 62 * @param[out] pipe_desc The pipe descriptor to be filled. 63 * @param[in] endpoint_desc Endpoint descriptors from the device. 58 #define CTRL_PIPE_MIN_PACKET_SIZE 8 59 60 typedef struct usb_dev { 61 link_t link; 62 list_t devices; 63 fibril_mutex_t guard; 64 ddf_fun_t *fun; 65 usb_address_t address; 66 usb_speed_t speed; 67 usb_address_t tt_address; 68 unsigned port; 69 } usb_dev_t; 70 71 typedef struct hc_dev { 72 ddf_fun_t *ctl_fun; 73 hcd_t hcd; 74 usb_dev_t *root_hub; 75 } hc_dev_t; 76 77 static hc_dev_t *dev_to_hc_dev(ddf_dev_t *dev) 78 { 79 return ddf_dev_data_get(dev); 80 } 81 82 hcd_t *dev_to_hcd(ddf_dev_t *dev) 83 { 84 hc_dev_t *hc_dev = dev_to_hc_dev(dev); 85 if (!hc_dev) { 86 usb_log_error("Invalid HCD device.\n"); 87 return NULL; 88 } 89 return &hc_dev->hcd; 90 } 91 92 93 static errno_t hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port); 94 static errno_t hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port); 95 96 97 /* DDF INTERFACE */ 98 99 /** Register endpoint interface function. 100 * @param fun DDF function. 101 * @param address USB address of the device. 102 * @param endpoint USB endpoint number to be registered. 103 * @param transfer_type Endpoint's transfer type. 104 * @param direction USB communication direction the endpoint is capable of. 105 * @param max_packet_size Maximu size of packets the endpoint accepts. 106 * @param interval Preferred timeout between communication. 64 107 * @return Error code. 65 108 */ 66 static errno_t register_endpoint(ddf_fun_t *fun, usb_pipe_desc_t *pipe_desc, 67 const usb_endpoint_descriptors_t *ep_desc) 109 static errno_t register_endpoint( 110 ddf_fun_t *fun, usb_endpoint_t endpoint, 111 usb_transfer_type_t transfer_type, usb_direction_t direction, 112 size_t max_packet_size, unsigned packets, unsigned interval) 68 113 { 69 114 assert(fun); 70 hc _device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun));71 device_t *dev = ddf_fun_data_get(fun);115 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 116 usb_dev_t *dev = ddf_fun_data_get(fun); 72 117 assert(hcd); 73 assert(hcd->bus);74 118 assert(dev); 75 76 endpoint_t *ep; 77 const int err = bus_endpoint_add(dev, ep_desc, &ep); 78 if (err) 79 return err; 80 81 if (pipe_desc) { 82 pipe_desc->endpoint_no = ep->endpoint; 83 pipe_desc->direction = ep->direction; 84 pipe_desc->transfer_type = ep->transfer_type; 85 pipe_desc->max_transfer_size = ep->max_transfer_size; 86 pipe_desc->transfer_buffer_policy = ep->transfer_buffer_policy; 87 } 88 endpoint_del_ref(ep); 89 119 const size_t size = max_packet_size; 120 const usb_target_t target = 121 {{.address = dev->address, .endpoint = endpoint}}; 122 123 usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n", 124 dev->address, endpoint, usb_str_transfer_type(transfer_type), 125 usb_str_direction(direction), max_packet_size, interval); 126 127 return hcd_add_ep(hcd, target, direction, transfer_type, 128 max_packet_size, packets, size, dev->tt_address, dev->port); 129 } 130 131 /** Unregister endpoint interface function. 132 * @param fun DDF function. 133 * @param address USB address of the endpoint. 134 * @param endpoint USB endpoint number. 135 * @param direction Communication direction of the enpdoint to unregister. 136 * @return Error code. 137 */ 138 static errno_t unregister_endpoint( 139 ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction) 140 { 141 assert(fun); 142 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 143 usb_dev_t *dev = ddf_fun_data_get(fun); 144 assert(hcd); 145 assert(dev); 146 const usb_target_t target = 147 {{.address = dev->address, .endpoint = endpoint}}; 148 usb_log_debug("Unregister endpoint %d:%d %s.\n", 149 dev->address, endpoint, usb_str_direction(direction)); 150 return hcd_remove_ep(hcd, target, direction); 151 } 152 153 static errno_t reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) 154 { 155 assert(fun); 156 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 157 usb_dev_t *dev = ddf_fun_data_get(fun); 158 assert(hcd); 159 assert(dev); 160 161 usb_log_debug("Device %d requested default address at %s speed\n", 162 dev->address, usb_str_speed(speed)); 163 return hcd_reserve_default_address(hcd, speed); 164 } 165 166 static errno_t release_default_address(ddf_fun_t *fun) 167 { 168 assert(fun); 169 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 170 usb_dev_t *dev = ddf_fun_data_get(fun); 171 assert(hcd); 172 assert(dev); 173 174 usb_log_debug("Device %d released default address\n", dev->address); 175 return hcd_release_default_address(hcd); 176 } 177 178 static errno_t device_enumerate(ddf_fun_t *fun, unsigned port) 179 { 180 assert(fun); 181 ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun); 182 usb_dev_t *dev = ddf_fun_data_get(fun); 183 assert(ddf_dev); 184 assert(dev); 185 usb_log_debug("Hub %d reported a new USB device on port: %u\n", 186 dev->address, port); 187 return hcd_ddf_new_device(ddf_dev, dev, port); 188 } 189 190 static errno_t device_remove(ddf_fun_t *fun, unsigned port) 191 { 192 assert(fun); 193 ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun); 194 usb_dev_t *dev = ddf_fun_data_get(fun); 195 assert(ddf_dev); 196 assert(dev); 197 usb_log_debug("Hub `%s' reported removal of device on port %u\n", 198 ddf_fun_get_name(fun), port); 199 return hcd_ddf_remove_device(ddf_dev, dev, port); 200 } 201 202 /** Gets handle of the respective device. 203 * 204 * @param[in] fun Device function. 205 * @param[out] handle Place to write the handle. 206 * @return Error code. 207 */ 208 static errno_t get_my_device_handle(ddf_fun_t *fun, devman_handle_t *handle) 209 { 210 assert(fun); 211 if (handle) 212 *handle = ddf_fun_get_handle(fun); 90 213 return EOK; 91 214 } 92 215 93 /** 94 * DDF usbhc_iface callback. Unregister endpoint that makes the other end of 95 * the pipe described. 96 * 97 * @param fun DDF function of the device in question. 98 * @param pipe_desc Pipe description. 99 * @return Error code. 100 */ 101 static errno_t unregister_endpoint(ddf_fun_t *fun, const usb_pipe_desc_t *pipe_desc) 102 { 103 assert(fun); 104 hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 105 device_t *dev = ddf_fun_data_get(fun); 106 assert(hcd); 107 assert(hcd->bus); 108 assert(dev); 109 110 endpoint_t *ep = bus_find_endpoint(dev, pipe_desc->endpoint_no, pipe_desc->direction); 111 if (!ep) 112 return ENOENT; 113 114 const errno_t err = bus_endpoint_remove(ep); 115 116 endpoint_del_ref(ep); 117 return err; 118 } 119 120 /** 121 * DDF usbhc_iface callback. Calls the respective bus operation directly. 122 * 123 * @param fun DDF function of the device (hub) requesting the address. 124 */ 125 static errno_t default_address_reservation(ddf_fun_t *fun, bool reserve) 126 { 127 assert(fun); 128 hc_device_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 129 device_t *dev = ddf_fun_data_get(fun); 130 assert(hcd); 131 assert(hcd->bus); 132 assert(dev); 133 134 usb_log_debug("Device %d %s default address", dev->address, reserve ? "requested" : "releasing"); 135 if (reserve) { 136 return bus_reserve_default_address(hcd->bus, dev); 137 } else { 138 bus_release_default_address(hcd->bus, dev); 139 return EOK; 140 } 141 } 142 143 /** 144 * DDF usbhc_iface callback. Calls the bus operation directly. 145 * 146 * @param fun DDF function of the device (hub) requesting the address. 147 * @param speed USB speed of the new device 148 */ 149 static errno_t device_enumerate(ddf_fun_t *fun, unsigned port, usb_speed_t speed) 150 { 151 assert(fun); 152 ddf_dev_t *hc = ddf_fun_get_dev(fun); 153 assert(hc); 154 hc_device_t *hcd = dev_to_hcd(hc); 155 assert(hcd); 156 device_t *hub = ddf_fun_data_get(fun); 157 assert(hub); 158 159 errno_t err; 160 161 if (!usb_speed_is_valid(speed)) 162 return EINVAL; 163 164 usb_log_debug("Hub %d reported a new %s speed device on port: %u", 165 hub->address, usb_str_speed(speed), port); 166 167 device_t *dev = hcd_ddf_fun_create(hcd, speed); 168 if (!dev) { 169 usb_log_error("Failed to create USB device function."); 170 return ENOMEM; 171 } 172 173 dev->hub = hub; 174 dev->tier = hub->tier + 1; 175 dev->port = port; 176 dev->speed = speed; 177 178 if ((err = bus_device_enumerate(dev))) { 179 usb_log_error("Failed to initialize USB dev memory structures."); 180 goto err_usb_dev; 181 } 182 183 /* If the driver didn't name the dev when enumerating, 184 * do it in some generic way. 185 */ 186 if (!ddf_fun_get_name(dev->fun)) { 187 bus_device_set_default_name(dev); 188 } 189 190 if ((err = ddf_fun_bind(dev->fun))) { 191 usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err)); 192 goto err_usb_dev; 193 } 194 195 return EOK; 196 197 err_usb_dev: 198 hcd_ddf_fun_destroy(dev); 199 return err; 200 } 201 202 static errno_t device_remove(ddf_fun_t *fun, unsigned port) 203 { 204 assert(fun); 205 device_t *hub = ddf_fun_data_get(fun); 206 assert(hub); 207 usb_log_debug("Hub `%s' reported removal of device on port %u", 208 ddf_fun_get_name(fun), port); 209 210 device_t *victim = NULL; 211 212 fibril_mutex_lock(&hub->guard); 213 list_foreach(hub->devices, link, device_t, it) { 214 if (it->port == port) { 215 victim = it; 216 break; 217 } 218 } 219 fibril_mutex_unlock(&hub->guard); 220 221 if (!victim) { 222 usb_log_warning("Hub '%s' tried to remove non-existent" 223 " device.", ddf_fun_get_name(fun)); 224 return ENOENT; 225 } 226 227 assert(victim->fun); 228 assert(victim->port == port); 229 assert(victim->hub == hub); 230 231 bus_device_gone(victim); 232 return EOK; 233 } 234 235 /** 236 * Gets description of the device that is calling. 237 * 238 * @param[in] fun Device function. 239 * @param[out] desc Device descriptor to be filled. 240 * @return Error code. 241 */ 242 static errno_t get_device_description(ddf_fun_t *fun, usb_device_desc_t *desc) 243 { 244 assert(fun); 245 device_t *dev = ddf_fun_data_get(fun); 246 assert(dev); 247 248 if (!desc) 249 return EOK; 250 251 *desc = (usb_device_desc_t) { 252 .address = dev->address, 253 .depth = dev->tier, 254 .speed = dev->speed, 255 .handle = ddf_fun_get_handle(fun), 256 .iface = -1, 257 }; 258 return EOK; 259 } 260 261 /** 262 * Transfer issuing interface function. 263 * 216 /** Inbound communication interface function. 264 217 * @param fun DDF function. 265 218 * @param target Communication target. 266 * @param dir Communication direction.267 219 * @param setup_data Data to use in setup stage (control transfers). 268 220 * @param data Pointer to data buffer. … … 272 224 * @return Error code. 273 225 */ 274 static errno_t transfer(ddf_fun_t *fun,275 const usbhc_iface_transfer_request_t *ifreq,276 usbhc_iface_transfer_ callback_t callback, void *arg)226 static errno_t dev_read(ddf_fun_t *fun, usb_endpoint_t endpoint, 227 uint64_t setup_data, uint8_t *data, size_t size, 228 usbhc_iface_transfer_in_callback_t callback, void *arg) 277 229 { 278 230 assert(fun); 279 device_t *dev = ddf_fun_data_get(fun); 280 assert(dev); 281 231 usb_dev_t *usb_dev = ddf_fun_data_get(fun); 232 assert(usb_dev); 282 233 const usb_target_t target = {{ 283 .address = dev->address, 284 .endpoint = ifreq->endpoint, 285 .stream = ifreq->stream, 234 .address = usb_dev->address, 235 .endpoint = endpoint, 286 236 }}; 287 288 if (!usb_target_is_valid(&target)) 289 return EINVAL; 290 291 if (ifreq->offset > 0 && ifreq->size == 0) 292 return EINVAL; 293 294 if (ifreq->size > 0 && !dma_buffer_is_set(&ifreq->buffer)) 295 return EBADMEM; 296 297 if (!callback && arg) 298 return EBADMEM; 299 300 const transfer_request_t request = { 301 .target = target, 302 .dir = ifreq->dir, 303 .buffer = ifreq->buffer, 304 .offset = ifreq->offset, 305 .size = ifreq->size, 306 .setup = ifreq->setup, 307 .on_complete = callback, 308 .arg = arg, 309 .name = (ifreq->dir == USB_DIRECTION_IN) ? "READ" : "WRITE", 310 }; 311 312 return bus_issue_transfer(dev, &request); 237 return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)), target, 238 USB_DIRECTION_IN, data, size, setup_data, callback, NULL, arg, 239 "READ"); 240 } 241 242 /** Outbound communication interface function. 243 * @param fun DDF function. 244 * @param target Communication target. 245 * @param setup_data Data to use in setup stage (control transfers). 246 * @param data Pointer to data buffer. 247 * @param size Size of the data buffer. 248 * @param callback Function to call on communication end. 249 * @param arg Argument passed to the callback function. 250 * @return Error code. 251 */ 252 static errno_t dev_write(ddf_fun_t *fun, usb_endpoint_t endpoint, 253 uint64_t setup_data, const uint8_t *data, size_t size, 254 usbhc_iface_transfer_out_callback_t callback, void *arg) 255 { 256 assert(fun); 257 usb_dev_t *usb_dev = ddf_fun_data_get(fun); 258 assert(usb_dev); 259 const usb_target_t target = {{ 260 .address = usb_dev->address, 261 .endpoint = endpoint, 262 }}; 263 return hcd_send_batch(dev_to_hcd(ddf_fun_get_dev(fun)), 264 target, USB_DIRECTION_OUT, (uint8_t*)data, size, setup_data, NULL, 265 callback, arg, "WRITE"); 313 266 } 314 267 315 268 /** USB device interface */ 316 269 static usb_iface_t usb_iface = { 317 .get_my_description = get_device_description, 318 }; 319 320 /** USB host controller interface */ 321 static usbhc_iface_t usbhc_iface = { 322 .default_address_reservation = default_address_reservation, 270 .get_my_device_handle = get_my_device_handle, 271 272 .reserve_default_address = reserve_default_address, 273 .release_default_address = release_default_address, 323 274 324 275 .device_enumerate = device_enumerate, … … 328 279 .unregister_endpoint = unregister_endpoint, 329 280 330 .transfer = transfer, 281 .read = dev_read, 282 .write = dev_write, 331 283 }; 332 284 … … 334 286 static ddf_dev_ops_t usb_ops = { 335 287 .interfaces[USB_DEV_IFACE] = &usb_iface, 336 .interfaces[USBHC_DEV_IFACE] = &usbhc_iface,337 288 }; 338 289 339 290 340 291 /* DDF HELPERS */ 292 293 #define GET_DEVICE_DESC(size) \ 294 { \ 295 .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \ 296 | (USB_REQUEST_TYPE_STANDARD << 5) \ 297 | USB_REQUEST_RECIPIENT_DEVICE, \ 298 .request = USB_DEVREQ_GET_DESCRIPTOR, \ 299 .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \ 300 .index = uint16_host2usb(0), \ 301 .length = uint16_host2usb(size), \ 302 }; 303 304 #define SET_ADDRESS(address) \ 305 { \ 306 .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \ 307 | (USB_REQUEST_TYPE_STANDARD << 5) \ 308 | USB_REQUEST_RECIPIENT_DEVICE, \ 309 .request = USB_DEVREQ_SET_ADDRESS, \ 310 .value = uint16_host2usb(address), \ 311 .index = uint16_host2usb(0), \ 312 .length = uint16_host2usb(0), \ 313 }; 314 315 static errno_t hcd_ddf_add_device(ddf_dev_t *parent, usb_dev_t *hub_dev, 316 unsigned port, usb_address_t address, usb_speed_t speed, const char *name, 317 const match_id_list_t *mids) 318 { 319 assert(parent); 320 321 char default_name[10] = { 0 }; /* usbxyz-ss */ 322 if (!name) { 323 snprintf(default_name, sizeof(default_name) - 1, 324 "usb%u-%cs", address, usb_str_speed(speed)[0]); 325 name = default_name; 326 } 327 328 ddf_fun_t *fun = ddf_fun_create(parent, fun_inner, name); 329 if (!fun) 330 return ENOMEM; 331 usb_dev_t *info = ddf_fun_data_alloc(fun, sizeof(usb_dev_t)); 332 if (!info) { 333 ddf_fun_destroy(fun); 334 return ENOMEM; 335 } 336 info->address = address; 337 info->speed = speed; 338 info->fun = fun; 339 info->port = port; 340 info->tt_address = hub_dev ? hub_dev->tt_address : -1; 341 link_initialize(&info->link); 342 list_initialize(&info->devices); 343 fibril_mutex_initialize(&info->guard); 344 345 if (hub_dev && hub_dev->speed == USB_SPEED_HIGH && usb_speed_is_11(speed)) 346 info->tt_address = hub_dev->address; 347 348 ddf_fun_set_ops(fun, &usb_ops); 349 list_foreach(mids->ids, link, const match_id_t, mid) { 350 ddf_fun_add_match_id(fun, mid->id, mid->score); 351 } 352 353 errno_t ret = ddf_fun_bind(fun); 354 if (ret != EOK) { 355 ddf_fun_destroy(fun); 356 return ret; 357 } 358 359 if (hub_dev) { 360 fibril_mutex_lock(&hub_dev->guard); 361 list_append(&info->link, &hub_dev->devices); 362 fibril_mutex_unlock(&hub_dev->guard); 363 } else { 364 hc_dev_t *hc_dev = dev_to_hc_dev(parent); 365 assert(hc_dev->root_hub == NULL); 366 hc_dev->root_hub = info; 367 } 368 return EOK; 369 } 341 370 342 371 #define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \ … … 365 394 assert(l); 366 395 assert(d); 367 396 368 397 if (d->vendor_id != 0) { 369 398 /* First, with release number. */ … … 372 401 d->vendor_id, d->product_id, (d->device_version >> 8), 373 402 (d->device_version & 0xff)); 374 403 375 404 /* Next, without release number. */ 376 405 ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x", … … 386 415 387 416 return EOK; 388 } 389 390 device_t *hcd_ddf_fun_create(hc_device_t *hc, usb_speed_t speed) 391 { 392 /* Create DDF function for the new device */ 393 ddf_fun_t *fun = ddf_fun_create(hc->ddf_dev, fun_inner, NULL); 394 if (!fun) 395 return NULL; 396 397 ddf_fun_set_ops(fun, &usb_ops); 398 399 /* Create USB device node for the new device */ 400 device_t *dev = ddf_fun_data_alloc(fun, hc->bus->device_size); 401 if (!dev) { 402 ddf_fun_destroy(fun); 403 return NULL; 404 } 405 406 bus_device_init(dev, hc->bus); 407 dev->fun = fun; 408 dev->speed = speed; 409 return dev; 410 } 411 412 void hcd_ddf_fun_destroy(device_t *dev) 413 { 414 assert(dev); 415 assert(dev->fun); 416 ddf_fun_destroy(dev->fun); 417 } 418 419 errno_t hcd_ddf_setup_match_ids(device_t *device, usb_standard_device_descriptor_t *desc) 420 { 421 errno_t err; 417 418 } 419 420 static errno_t hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, 421 unsigned port) 422 { 423 assert(device); 424 425 hcd_t *hcd = dev_to_hcd(device); 426 assert(hcd); 427 428 hc_dev_t *hc_dev = dev_to_hc_dev(device); 429 assert(hc_dev); 430 431 fibril_mutex_lock(&hub->guard); 432 433 usb_dev_t *victim = NULL; 434 435 list_foreach(hub->devices, link, usb_dev_t, it) { 436 if (it->port == port) { 437 victim = it; 438 break; 439 } 440 } 441 if (victim) { 442 assert(victim->port == port); 443 list_remove(&victim->link); 444 fibril_mutex_unlock(&hub->guard); 445 const errno_t ret = ddf_fun_unbind(victim->fun); 446 if (ret == EOK) { 447 usb_address_t address = victim->address; 448 ddf_fun_destroy(victim->fun); 449 hcd_release_address(hcd, address); 450 } else { 451 usb_log_warning("Failed to unbind device `%s': %s\n", 452 ddf_fun_get_name(victim->fun), str_error(ret)); 453 } 454 return EOK; 455 } 456 fibril_mutex_unlock(&hub->guard); 457 return ENOENT; 458 } 459 460 static errno_t hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port) 461 { 462 assert(device); 463 464 hcd_t *hcd = dev_to_hcd(device); 465 assert(hcd); 466 467 usb_speed_t speed = USB_SPEED_MAX; 468 469 /* This checks whether the default address is reserved and gets speed */ 470 errno_t ret = usb_bus_get_speed(&hcd->bus, USB_ADDRESS_DEFAULT, &speed); 471 if (ret != EOK) { 472 usb_log_error("Failed to verify speed: %s.", str_error(ret)); 473 return ret; 474 } 475 476 usb_log_debug("Found new %s speed USB device.", usb_str_speed(speed)); 477 478 static const usb_target_t default_target = {{ 479 .address = USB_ADDRESS_DEFAULT, 480 .endpoint = 0, 481 }}; 482 483 usb_address_t address; 484 ret = hcd_request_address(hcd, speed, &address); 485 if (ret != EOK) { 486 usb_log_error("Failed to reserve new address: %s.", 487 str_error(ret)); 488 return ret; 489 } 490 491 usb_log_debug("Reserved new address: %d\n", address); 492 493 const usb_target_t target = {{ 494 .address = address, 495 .endpoint = 0, 496 }}; 497 498 const usb_address_t tt_address = hub ? hub->tt_address : -1; 499 500 /* Add default pipe on default address */ 501 usb_log_debug("Device(%d): Adding default target(0:0)\n", address); 502 ret = hcd_add_ep(hcd, 503 default_target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, 504 CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1, 505 tt_address, port); 506 if (ret != EOK) { 507 usb_log_error("Device(%d): Failed to add default target: %s.", 508 address, str_error(ret)); 509 hcd_release_address(hcd, address); 510 return ret; 511 } 512 513 /* Get max packet size for default pipe */ 514 usb_standard_device_descriptor_t desc = { 0 }; 515 const usb_device_request_setup_packet_t get_device_desc_8 = 516 GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE); 517 518 // TODO CALLBACKS 519 usb_log_debug("Device(%d): Requesting first 8B of device descriptor.", 520 address); 521 size_t got; 522 ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN, 523 &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8, 524 "read first 8 bytes of dev descriptor", &got); 525 526 if (ret == EOK && got != CTRL_PIPE_MIN_PACKET_SIZE) { 527 ret = EOVERFLOW; 528 } 529 530 if (ret != EOK) { 531 usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.", 532 address, str_error(ret)); 533 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH); 534 hcd_release_address(hcd, address); 535 return ret; 536 } 537 538 /* Register EP on the new address */ 539 usb_log_debug("Device(%d): Registering control EP.", address); 540 ret = hcd_add_ep(hcd, target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, 541 ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)), 542 ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)), 543 ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)), 544 tt_address, port); 545 if (ret != EOK) { 546 usb_log_error("Device(%d): Failed to register EP0: %s", 547 address, str_error(ret)); 548 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH); 549 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 550 hcd_release_address(hcd, address); 551 return ret; 552 } 553 554 /* Set new address */ 555 const usb_device_request_setup_packet_t set_address = 556 SET_ADDRESS(target.address); 557 558 usb_log_debug("Device(%d): Setting USB address.", address); 559 ret = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT, 560 NULL, 0, *(uint64_t *)&set_address, "set address", &got); 561 562 usb_log_debug("Device(%d): Removing default (0:0) EP.", address); 563 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH); 564 565 if (ret != EOK) { 566 usb_log_error("Device(%d): Failed to set new address: %s.", 567 address, str_error(ret)); 568 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 569 hcd_release_address(hcd, address); 570 return ret; 571 } 572 573 /* Get std device descriptor */ 574 const usb_device_request_setup_packet_t get_device_desc = 575 GET_DEVICE_DESC(sizeof(desc)); 576 577 usb_log_debug("Device(%d): Requesting full device descriptor.", 578 address); 579 ret = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN, 580 &desc, sizeof(desc), *(uint64_t *)&get_device_desc, 581 "read device descriptor", &got); 582 if (ret != EOK) { 583 usb_log_error("Device(%d): Failed to set get dev descriptor: %s", 584 address, str_error(ret)); 585 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 586 hcd_release_address(hcd, target.address); 587 return ret; 588 } 589 590 /* Create match ids from the device descriptor */ 422 591 match_id_list_t mids; 423 424 592 init_match_ids(&mids); 425 593 426 /* Create match ids from the device descriptor */ 427 usb_log_debug("Device(%d): Creating match IDs.", device->address); 428 if ((err = create_match_ids(&mids, desc))) { 429 return err; 430 } 431 432 list_foreach(mids.ids, link, const match_id_t, mid) { 433 ddf_fun_add_match_id(device->fun, mid->id, mid->score); 434 } 435 436 return EOK; 594 usb_log_debug("Device(%d): Creating match IDs.", address); 595 ret = create_match_ids(&mids, &desc); 596 if (ret != EOK) { 597 usb_log_error("Device(%d): Failed to create match ids: %s", 598 address, str_error(ret)); 599 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 600 hcd_release_address(hcd, target.address); 601 return ret; 602 } 603 604 /* Register device */ 605 usb_log_debug("Device(%d): Registering DDF device.", address); 606 ret = hcd_ddf_add_device(device, hub, port, address, speed, NULL, &mids); 607 clean_match_ids(&mids); 608 if (ret != EOK) { 609 usb_log_error("Device(%d): Failed to register: %s.", 610 address, str_error(ret)); 611 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 612 hcd_release_address(hcd, target.address); 613 } 614 615 return ret; 616 } 617 618 /** Announce root hub to the DDF 619 * 620 * @param[in] device Host controller ddf device 621 * @return Error code 622 */ 623 errno_t hcd_ddf_setup_root_hub(ddf_dev_t *device) 624 { 625 assert(device); 626 hcd_t *hcd = dev_to_hcd(device); 627 assert(hcd); 628 629 hcd_reserve_default_address(hcd, hcd->bus.max_speed); 630 const errno_t ret = hcd_ddf_new_device(device, NULL, 0); 631 hcd_release_default_address(hcd); 632 return ret; 437 633 } 438 634 … … 447 643 * This function does all the ddf work for hc driver. 448 644 */ 449 errno_t hcd_ddf_setup_hc(ddf_dev_t *device, size_t size) 645 errno_t hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed, 646 size_t bw, bw_count_func_t bw_count) 450 647 { 451 648 assert(device); 452 649 453 hc_dev ice_t *instance = ddf_dev_data_alloc(device, size);650 hc_dev_t *instance = ddf_dev_data_alloc(device, sizeof(hc_dev_t)); 454 651 if (instance == NULL) { 455 usb_log_error("Failed to allocate HCD ddf structure. ");652 usb_log_error("Failed to allocate HCD ddf structure.\n"); 456 653 return ENOMEM; 457 654 } 458 instance->ddf_dev = device; 655 instance->root_hub = NULL; 656 hcd_init(&instance->hcd, max_speed, bw, bw_count); 459 657 460 658 errno_t ret = ENOMEM; 461 659 instance->ctl_fun = ddf_fun_create(device, fun_exposed, "ctl"); 462 660 if (!instance->ctl_fun) { 463 usb_log_error("Failed to create HCD ddf fun. ");661 usb_log_error("Failed to create HCD ddf fun.\n"); 464 662 goto err_destroy_fun; 465 663 } … … 467 665 ret = ddf_fun_bind(instance->ctl_fun); 468 666 if (ret != EOK) { 469 usb_log_error("Failed to bind ctl_fun: %s. ", str_error(ret));667 usb_log_error("Failed to bind ctl_fun: %s.\n", str_error(ret)); 470 668 goto err_destroy_fun; 471 669 } … … 473 671 ret = ddf_fun_add_to_category(instance->ctl_fun, USB_HC_CATEGORY); 474 672 if (ret != EOK) { 475 usb_log_error("Failed to add fun to category: %s. ",673 usb_log_error("Failed to add fun to category: %s.\n", 476 674 str_error(ret)); 477 675 ddf_fun_unbind(instance->ctl_fun); … … 488 686 } 489 687 490 void hcd_ddf_clean_hc(hc_device_t *hcd) 491 { 492 if (ddf_fun_unbind(hcd->ctl_fun) == EOK) 493 ddf_fun_destroy(hcd->ctl_fun); 494 } 495 688 void hcd_ddf_clean_hc(ddf_dev_t *device) 689 { 690 assert(device); 691 hc_dev_t *hc = dev_to_hc_dev(device); 692 assert(hc); 693 const errno_t ret = ddf_fun_unbind(hc->ctl_fun); 694 if (ret == EOK) 695 ddf_fun_destroy(hc->ctl_fun); 696 } 697 698 //TODO: Cache parent session in HCD 496 699 /** Call the parent driver with a request to enable interrupt 497 700 * … … 500 703 * @return Error code. 501 704 */ 502 errno_t hcd_ddf_enable_interrupt( hc_device_t *hcd, int inum)503 { 504 async_sess_t *parent_sess = ddf_dev_parent_sess_get( hcd->ddf_dev);705 errno_t hcd_ddf_enable_interrupt(ddf_dev_t *device, int inum) 706 { 707 async_sess_t *parent_sess = ddf_dev_parent_sess_get(device); 505 708 if (parent_sess == NULL) 506 709 return EIO; … … 509 712 } 510 713 511 errno_t hcd_ddf_get_registers(hc_device_t *hcd, hw_res_list_parsed_t *hw_res) 512 { 513 async_sess_t *parent_sess = ddf_dev_parent_sess_get(hcd->ddf_dev); 714 //TODO: Cache parent session in HCD 715 errno_t hcd_ddf_get_registers(ddf_dev_t *device, hw_res_list_parsed_t *hw_res) 716 { 717 async_sess_t *parent_sess = ddf_dev_parent_sess_get(device); 514 718 if (parent_sess == NULL) 515 719 return EIO; … … 522 726 } 523 727 728 // TODO: move this someplace else 729 static inline void irq_code_clean(irq_code_t *code) 730 { 731 if (code) { 732 free(code->ranges); 733 free(code->cmds); 734 code->ranges = NULL; 735 code->cmds = NULL; 736 code->rangecount = 0; 737 code->cmdcount = 0; 738 } 739 } 740 741 /** Register interrupt handler 742 * 743 * @param[in] device Host controller DDF device 744 * @param[in] regs Register range 745 * @param[in] irq Interrupt number 746 * @paran[in] handler Interrupt handler 747 * @param[in] gen_irq_code IRQ code generator. 748 * 749 * @param[out] handle IRQ capability handle on success. 750 * 751 * @return Error code. 752 */ 753 errno_t hcd_ddf_setup_interrupts(ddf_dev_t *device, 754 const hw_res_list_parsed_t *hw_res, 755 interrupt_handler_t handler, 756 errno_t (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *, int *), 757 cap_handle_t *handle) 758 { 759 760 assert(device); 761 if (!handler || !gen_irq_code) 762 return ENOTSUP; 763 764 irq_code_t irq_code = {0}; 765 766 int irq; 767 errno_t ret = gen_irq_code(&irq_code, hw_res, &irq); 768 if (ret != EOK) { 769 usb_log_error("Failed to generate IRQ code: %s.\n", 770 str_error(ret)); 771 return ret; 772 } 773 774 /* Register handler to avoid interrupt lockup */ 775 ret = register_interrupt_handler(device, irq, handler, 776 &irq_code, handle); 777 irq_code_clean(&irq_code); 778 if (ret != EOK) { 779 usb_log_error("Failed to register interrupt handler: %s.\n", 780 str_error(ret)); 781 return ret; 782 } 783 784 /* Enable interrupts */ 785 ret = hcd_ddf_enable_interrupt(device, irq); 786 if (ret != EOK) { 787 usb_log_error("Failed to register interrupt handler: %s.\n", 788 str_error(ret)); 789 unregister_interrupt_handler(device, *handle); 790 } 791 return ret; 792 } 793 794 /** IRQ handling callback, forward status from call to diver structure. 795 * 796 * @param[in] dev DDF instance of the device to use. 797 * @param[in] call Pointer to the call from kernel. 798 */ 799 void ddf_hcd_gen_irq_handler(ipc_call_t *call, ddf_dev_t *dev) 800 { 801 assert(dev); 802 hcd_t *hcd = dev_to_hcd(dev); 803 if (!hcd || !hcd->ops.irq_hook) { 804 usb_log_error("Interrupt on not yet initialized device.\n"); 805 return; 806 } 807 const uint32_t status = IPC_GET_ARG1(*call); 808 hcd->ops.irq_hook(hcd, status); 809 } 810 811 static errno_t interrupt_polling(void *arg) 812 { 813 hcd_t *hcd = arg; 814 assert(hcd); 815 if (!hcd->ops.status_hook || !hcd->ops.irq_hook) 816 return ENOTSUP; 817 uint32_t status = 0; 818 while (hcd->ops.status_hook(hcd, &status) == EOK) { 819 hcd->ops.irq_hook(hcd, status); 820 status = 0; 821 /* We should wait 1 frame - 1ms here, but this polling is a 822 * lame crutch anyway so don't hog the system. 10ms is still 823 * good enough for emergency mode */ 824 async_usleep(10000); 825 } 826 return EOK; 827 } 828 829 /** Initialize hc and rh DDF structures and their respective drivers. 830 * 831 * @param device DDF instance of the device to use 832 * @param speed Maximum supported speed 833 * @param bw Available bandwidth (arbitrary units) 834 * @param bw_count Bandwidth computing function 835 * @param irq_handler IRQ handling function 836 * @param gen_irq_code Function to generate IRQ pseudocode 837 * (it needs to return used irq number) 838 * @param driver_init Function to initialize HC driver 839 * @param driver_fini Function to cleanup HC driver 840 * @return Error code 841 * 842 * This function does all the preparatory work for hc and rh drivers: 843 * - gets device's hw resources 844 * - attempts to enable interrupts 845 * - registers interrupt handler 846 * - calls driver specific initialization 847 * - registers root hub 848 */ 849 errno_t hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver) 850 { 851 assert(driver); 852 static const struct { size_t bw; bw_count_func_t bw_count; }bw[] = { 853 [USB_SPEED_FULL] = { .bw = BANDWIDTH_AVAILABLE_USB11, 854 .bw_count = bandwidth_count_usb11 }, 855 [USB_SPEED_HIGH] = { .bw = BANDWIDTH_AVAILABLE_USB11, 856 .bw_count = bandwidth_count_usb11 }, 857 }; 858 859 errno_t ret = EOK; 860 const usb_speed_t speed = driver->hc_speed; 861 if (speed >= ARRAY_SIZE(bw) || bw[speed].bw == 0) { 862 usb_log_error("Driver `%s' reported unsupported speed: %s", 863 driver->name, usb_str_speed(speed)); 864 return ENOTSUP; 865 } 866 867 hw_res_list_parsed_t hw_res; 868 ret = hcd_ddf_get_registers(device, &hw_res); 869 if (ret != EOK) { 870 usb_log_error("Failed to get register memory addresses " 871 "for `%s': %s.\n", ddf_dev_get_name(device), 872 str_error(ret)); 873 return ret; 874 } 875 876 ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count); 877 if (ret != EOK) { 878 usb_log_error("Failed to setup generic HCD.\n"); 879 hw_res_list_parsed_clean(&hw_res); 880 return ret; 881 } 882 883 interrupt_handler_t *irq_handler = 884 driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler; 885 int irq_cap; 886 errno_t irq_ret = hcd_ddf_setup_interrupts(device, &hw_res, 887 irq_handler, driver->irq_code_gen, &irq_cap); 888 bool irqs_enabled = (irq_ret == EOK); 889 if (irqs_enabled) { 890 usb_log_debug("Hw interrupts enabled.\n"); 891 } 892 893 if (driver->claim) { 894 ret = driver->claim(device); 895 if (ret != EOK) { 896 usb_log_error("Failed to claim `%s' for driver `%s'", 897 ddf_dev_get_name(device), driver->name); 898 return ret; 899 } 900 } 901 902 903 /* Init hw driver */ 904 hcd_t *hcd = dev_to_hcd(device); 905 ret = driver->init(hcd, &hw_res, irqs_enabled); 906 hw_res_list_parsed_clean(&hw_res); 907 if (ret != EOK) { 908 usb_log_error("Failed to init HCD: %s.\n", str_error(ret)); 909 goto irq_unregister; 910 } 911 912 /* Need working irq replacement to setup root hub */ 913 if (!irqs_enabled && hcd->ops.status_hook) { 914 hcd->polling_fibril = fibril_create(interrupt_polling, hcd); 915 if (hcd->polling_fibril == 0) { 916 usb_log_error("Failed to create polling fibril\n"); 917 ret = ENOMEM; 918 goto irq_unregister; 919 } 920 fibril_add_ready(hcd->polling_fibril); 921 usb_log_warning("Failed to enable interrupts: %s." 922 " Falling back to polling.\n", str_error(irq_ret)); 923 } 924 925 /* 926 * Creating root hub registers a new USB device so HC 927 * needs to be ready at this time. 928 */ 929 ret = hcd_ddf_setup_root_hub(device); 930 if (ret != EOK) { 931 usb_log_error("Failed to setup HC root hub: %s.\n", 932 str_error(ret)); 933 driver->fini(dev_to_hcd(device)); 934 irq_unregister: 935 /* Unregistering non-existent should be ok */ 936 unregister_interrupt_handler(device, irq_cap); 937 hcd_ddf_clean_hc(device); 938 return ret; 939 } 940 941 usb_log_info("Controlling new `%s' device `%s'.\n", 942 driver->name, ddf_dev_get_name(device)); 943 return EOK; 944 } 524 945 /** 525 946 * @}
Note:
See TracChangeset
for help on using the changeset viewer.