Changeset 6843a9c in mainline for uspace/drv/bus
- Timestamp:
- 2012-06-29T13:02:14Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 722912e
- Parents:
- ba72f2b (diff), 0bbd13e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace/drv/bus
- Files:
-
- 2 added
- 2 deleted
- 66 edited
- 6 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/isa/Makefile
rba72f2b r6843a9c 34 34 35 35 SOURCES = \ 36 dma_controller.c \36 i8237.c \ 37 37 isa.c 38 38 -
uspace/drv/bus/isa/i8237.h
rba72f2b r6843a9c 1 1 /* 2 * Copyright (c) 2011 Vojtech Horky2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup drvusbehci29 /** @addtogroup isa 30 30 * @{ 31 31 */ 32 32 33 /** @file 33 * Common EHCI definitions.34 * @brief DMA memory management 34 35 */ 35 #ifndef DRV_EHCI_EHCI_H36 #define DRV_EHCI_EHCI_H37 36 38 #include <usbhc_iface.h> 37 #ifndef DRV_BUS_ISA_I8237_H 38 #define DRV_BUS_ISA_I8237_H 39 39 40 #define NAME "ehci" 41 42 extern usbhc_iface_t ehci_hc_iface; 40 extern int dma_setup_channel(unsigned int, uint32_t, uint16_t, uint8_t); 43 41 44 42 #endif 43 45 44 /** 46 45 * @} 47 46 */ 48 -
uspace/drv/bus/isa/isa.c
rba72f2b r6843a9c 52 52 #include <dirent.h> 53 53 #include <fcntl.h> 54 #include <ipc/irc.h> 55 #include <ipc/services.h> 56 #include <sysinfo.h> 57 #include <ns.h> 54 58 #include <sys/stat.h> 55 59 #include <ipc/irc.h> … … 62 66 #include <ops/hw_res.h> 63 67 64 #include <devman.h>65 #include <ipc/devman.h>66 68 #include <device/hw_res.h> 67 69 68 #include " dma_controller.h"70 #include "i8237.h" 69 71 70 72 #define NAME "isa" … … 146 148 147 149 static int isa_dma_channel_fun_setup(ddf_fun_t *fnode, 148 unsigned channel, uint32_t pa, uint16_t size, uint8_t mode)150 unsigned int channel, uint32_t pa, uint16_t size, uint8_t mode) 149 151 { 150 152 assert(fnode); … … 152 154 const hw_resource_list_t *res = &isa_fun->hw_resources; 153 155 assert(res); 154 const int ch = channel; 156 157 const unsigned int ch = channel; 155 158 for (size_t i = 0; i < res->count; ++i) { 156 if (( res->resources[i].type == DMA_CHANNEL_16&&157 res->resources[i].res.dma_channel.dma16 == ch) ||158 ( res->resources[i].type == DMA_CHANNEL_8&&159 res->resources[i].res.dma_channel.dma8 == ch)) {159 if (((res->resources[i].type == DMA_CHANNEL_16) && 160 (res->resources[i].res.dma_channel.dma16 == ch)) || 161 ((res->resources[i].type == DMA_CHANNEL_8) && 162 (res->resources[i].res.dma_channel.dma8 == ch))) { 160 163 return dma_setup_channel(channel, pa, size, mode); 161 164 } 162 165 } 166 163 167 return EINVAL; 164 168 } … … 172 176 static ddf_dev_ops_t isa_fun_ops; 173 177 174 static int isa_ add_device(ddf_dev_t *dev);178 static int isa_dev_add(ddf_dev_t *dev); 175 179 static int isa_dev_remove(ddf_dev_t *dev); 176 180 static int isa_fun_online(ddf_fun_t *fun); … … 179 183 /** The isa device driver's standard operations */ 180 184 static driver_ops_t isa_ops = { 181 . add_device = &isa_add_device,185 .dev_add = &isa_dev_add, 182 186 .dev_remove = &isa_dev_remove, 183 187 .fun_online = &isa_fun_online, … … 198 202 199 203 isa_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(isa_fun_t)); 200 if (fun == NULL) 204 if (fun == NULL) { 205 ddf_fun_destroy(fnode); 201 206 return NULL; 207 } 202 208 203 209 fibril_mutex_initialize(&fun->mutex); … … 344 350 size_t count = fun->hw_resources.count; 345 351 hw_resource_t *resources = fun->hw_resources.resources; 346 352 347 353 if (count < ISA_MAX_HW_RES) { 348 if ( dma > 0 && dma < 4) {354 if ((dma > 0) && (dma < 4)) { 349 355 resources[count].type = DMA_CHANNEL_8; 350 356 resources[count].res.dma_channel.dma8 = dma; 351 357 352 358 fun->hw_resources.count++; 353 359 ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma, 354 360 fun->fnode->name); 361 355 362 return; 356 363 } 357 364 358 if ( dma > 4 && dma < 8) {365 if ((dma > 4) && (dma < 8)) { 359 366 resources[count].type = DMA_CHANNEL_16; 360 367 resources[count].res.dma_channel.dma16 = dma; 361 368 362 369 fun->hw_resources.count++; 363 370 ddf_msg(LVL_NOTE, "Added dma 0x%x to function %s", dma, 364 371 fun->fnode->name); 372 365 373 return; 366 374 } 367 375 368 376 ddf_msg(LVL_WARN, "Skipped dma 0x%x for function %s", dma, 369 377 fun->fnode->name); … … 396 404 397 405 val = skip_spaces(val); 398 irq = (int) strtol(val, &end, 0x10);406 irq = (int) strtol(val, &end, 10); 399 407 400 408 if (val != end) … … 404 412 static void fun_parse_dma(isa_fun_t *fun, char *val) 405 413 { 406 int dma = 0;414 unsigned int dma = 0; 407 415 char *end = NULL; 408 416 409 417 val = skip_spaces(val); 410 dma = ( int)strtol(val, &end, 10);411 418 dma = (unsigned int) strtol(val, &end, 10); 419 412 420 if (val != end) 413 421 isa_fun_set_dma(fun, dma); … … 589 597 } 590 598 591 static int isa_ add_device(ddf_dev_t *dev)599 static int isa_dev_add(ddf_dev_t *dev) 592 600 { 593 601 isa_bus_t *isa; 594 602 595 ddf_msg(LVL_DEBUG, "isa_ add_device, device handle = %d",603 ddf_msg(LVL_DEBUG, "isa_dev_add, device handle = %d", 596 604 (int) dev->handle); 597 605 -
uspace/drv/bus/isa/isa.dev
rba72f2b r6843a9c 9 9 io_range 2f8 8 10 10 11 keyboard:12 match 100 isa/ keyboard11 i8042: 12 match 100 isa/i8042 13 13 irq 1 14 io_range 060 10 14 irq 12 15 io_range 060 5 16 17 ne2k: 18 match 100 isa/ne2k 19 irq 5 20 io_range 300 20 15 21 16 22 sb16: -
uspace/drv/bus/isa/isa.ma
rba72f2b r6843a9c 1 9 pci/ven=8086&dev=70001 9 pci/class=06&subclass=01 -
uspace/drv/bus/pci/pciintel/pci.c
rba72f2b r6843a9c 78 78 #define PCI_BUS_FROM_FUN(fun) ((fun)->busptr) 79 79 80 /** Max is 47, align to something nice. */ 81 #define ID_MAX_STR_LEN 50 82 80 83 static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode) 81 84 { … … 89 92 static bool pciintel_enable_interrupt(ddf_fun_t *fnode) 90 93 { 91 /* This is an old ugly way , copied from ne2000 driver*/94 /* This is an old ugly way */ 92 95 assert(fnode); 93 96 pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data; … … 202 205 }; 203 206 204 static int pci_ add_device(ddf_dev_t *);207 static int pci_dev_add(ddf_dev_t *); 205 208 static int pci_fun_online(ddf_fun_t *); 206 209 static int pci_fun_offline(ddf_fun_t *); … … 208 211 /** PCI bus driver standard operations */ 209 212 static driver_ops_t pci_ops = { 210 . add_device = &pci_add_device,213 .dev_add = &pci_dev_add, 211 214 .fun_online = &pci_fun_online, 212 215 .fun_offline = &pci_fun_offline, … … 225 228 fibril_mutex_lock(&bus->conf_mutex); 226 229 227 uint32_t conf_addr; 228 conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 230 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 229 231 void *addr = bus->conf_data_port + (reg & 3); 230 232 … … 311 313 void pci_fun_create_match_ids(pci_fun_t *fun) 312 314 { 313 char *match_id_str;314 315 int rc; 315 316 asprintf(&match_id_str, "pci/ven=%04x&dev=%04x", 316 char match_id_str[ID_MAX_STR_LEN]; 317 318 /* Vendor ID & Device ID, length(incl \0) 22 */ 319 rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/ven=%04x&dev=%04x", 317 320 fun->vendor_id, fun->device_id); 318 319 if (match_id_str == NULL) { 320 ddf_msg(LVL_ERROR, "Out of memory creating match ID."); 321 return; 321 if (rc < 0) { 322 ddf_msg(LVL_ERROR, "Failed creating match ID str: %s", 323 str_error(rc)); 322 324 } 323 325 324 326 rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90); 325 327 if (rc != EOK) { 326 ddf_msg(LVL_ERROR, "Failed adding match ID: %s", 328 ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc)); 329 } 330 331 /* Class, subclass, prog IF, revision, length(incl \0) 47 */ 332 rc = snprintf(match_id_str, ID_MAX_STR_LEN, 333 "pci/class=%02x&subclass=%02x&progif=%02x&revision=%02x", 334 fun->class_code, fun->subclass_code, fun->prog_if, fun->revision); 335 if (rc < 0) { 336 ddf_msg(LVL_ERROR, "Failed creating match ID str: %s", 327 337 str_error(rc)); 328 338 } 329 330 free(match_id_str); 331 332 /* TODO add more ids (with subsys ids, using class id etc.) */ 339 340 rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 70); 341 if (rc != EOK) { 342 ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc)); 343 } 344 345 /* Class, subclass, prog IF, length(incl \0) 35 */ 346 rc = snprintf(match_id_str, ID_MAX_STR_LEN, 347 "pci/class=%02x&subclass=%02x&progif=%02x", 348 fun->class_code, fun->subclass_code, fun->prog_if); 349 if (rc < 0) { 350 ddf_msg(LVL_ERROR, "Failed creating match ID str: %s", 351 str_error(rc)); 352 } 353 354 rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 60); 355 if (rc != EOK) { 356 ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc)); 357 } 358 359 /* Class, subclass, length(incl \0) 25 */ 360 rc = snprintf(match_id_str, ID_MAX_STR_LEN, 361 "pci/class=%02x&subclass=%02x", 362 fun->class_code, fun->subclass_code); 363 if (rc < 0) { 364 ddf_msg(LVL_ERROR, "Failed creating match ID str: %s", 365 str_error(rc)); 366 } 367 368 rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 50); 369 if (rc != EOK) { 370 ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc)); 371 } 372 373 /* Class, length(incl \0) 13 */ 374 rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/class=%02x", 375 fun->class_code); 376 if (rc < 0) { 377 ddf_msg(LVL_ERROR, "Failed creating match ID str: %s", 378 str_error(rc)); 379 } 380 381 rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 40); 382 if (rc != EOK) { 383 ddf_msg(LVL_ERROR, "Failed adding match ID: %s", str_error(rc)); 384 } 385 386 /* TODO add subsys ids, but those exist only in header type 0 */ 333 387 } 334 388 … … 481 535 for (fnum = 0; multi && fnum < 8; fnum++) { 482 536 pci_fun_init(fun, bus_num, dnum, fnum); 483 fun->vendor_id = pci_conf_read_16(fun,484 PCI_VENDOR_ID);485 fun->device_id = pci_conf_read_16(fun,486 PCI_DEVICE_ID);487 537 if (fun->vendor_id == 0xffff) { 488 538 /* … … 511 561 512 562 fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name); 563 free(fun_name); 513 564 if (fnode == NULL) { 514 565 ddf_msg(LVL_ERROR, "Failed creating function."); … … 516 567 } 517 568 518 free(fun_name);519 569 fun->fnode = fnode; 520 570 … … 560 610 } 561 611 562 static int pci_ add_device(ddf_dev_t *dnode)612 static int pci_dev_add(ddf_dev_t *dnode) 563 613 { 564 614 pci_bus_t *bus = NULL; … … 567 617 int rc; 568 618 569 ddf_msg(LVL_DEBUG, "pci_ add_device");619 ddf_msg(LVL_DEBUG, "pci_dev_add"); 570 620 dnode->parent_sess = NULL; 571 621 572 622 bus = ddf_dev_data_alloc(dnode, sizeof(pci_bus_t)); 573 623 if (bus == NULL) { 574 ddf_msg(LVL_ERROR, "pci_ add_deviceallocation failed.");624 ddf_msg(LVL_ERROR, "pci_dev_add allocation failed."); 575 625 rc = ENOMEM; 576 626 goto fail; … … 584 634 dnode->handle, IPC_FLAG_BLOCKING); 585 635 if (!dnode->parent_sess) { 586 ddf_msg(LVL_ERROR, "pci_ add_devicefailed to connect to the "636 ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the " 587 637 "parent driver."); 588 638 rc = ENOENT; … … 594 644 rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources); 595 645 if (rc != EOK) { 596 ddf_msg(LVL_ERROR, "pci_ add_devicefailed to get hw resources "646 ddf_msg(LVL_ERROR, "pci_dev_add failed to get hw resources " 597 647 "for the device."); 598 648 goto fail; … … 691 741 fun->dev = dev; 692 742 fun->fn = fn; 743 fun->vendor_id = pci_conf_read_16(fun, PCI_VENDOR_ID); 744 fun->device_id = pci_conf_read_16(fun, PCI_DEVICE_ID); 745 fun->class_code = pci_conf_read_8(fun, PCI_BASE_CLASS); 746 fun->subclass_code = pci_conf_read_8(fun, PCI_SUB_CLASS); 747 fun->prog_if = pci_conf_read_8(fun, PCI_PROG_IF); 748 fun->revision = pci_conf_read_8(fun, PCI_REVISION_ID); 693 749 } 694 750 … … 711 767 bool pci_alloc_resource_list(pci_fun_t *fun) 712 768 { 713 fun->hw_resources.resources = 714 (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t)); 715 return fun->hw_resources.resources != NULL; 769 fun->hw_resources.resources = fun->resources; 770 return true; 716 771 } 717 772 718 773 void pci_clean_resource_list(pci_fun_t *fun) 719 774 { 720 if (fun->hw_resources.resources != NULL) { 721 free(fun->hw_resources.resources); 722 fun->hw_resources.resources = NULL; 723 } 775 fun->hw_resources.resources = NULL; 724 776 } 725 777 -
uspace/drv/bus/pci/pciintel/pci.h
rba72f2b r6843a9c 60 60 int vendor_id; 61 61 int device_id; 62 uint8_t class_code; 63 uint8_t subclass_code; 64 uint8_t prog_if; 65 uint8_t revision; 62 66 hw_resource_list_t hw_resources; 67 hw_resource_t resources[PCI_MAX_HW_RES]; 63 68 } pci_fun_t; 64 69 -
uspace/drv/bus/usb/ehci/Makefile
rba72f2b r6843a9c 42 42 43 43 SOURCES = \ 44 hc_iface.c \45 44 main.c \ 46 pci.c45 res.c 47 46 48 47 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/bus/usb/ehci/ehci.ma
rba72f2b r6843a9c 1 10 pci/ven=1002&dev=4345 2 10 pci/ven=1002&dev=4386 3 10 pci/ven=1002&dev=4396 4 10 pci/ven=1002&dev=4373 5 10 pci/ven=1022&dev=7463 6 10 pci/ven=1022&dev=7808 7 10 pci/ven=102f&dev=01b5 8 10 pci/ven=10cf&dev=1415 9 10 pci/ven=10de&dev=00e8 10 10 pci/ven=10de&dev=055f 11 10 pci/ven=10de&dev=056a 12 10 pci/ven=10de&dev=077c 13 10 pci/ven=10de&dev=077e 14 10 pci/ven=10de&dev=0aa6 15 10 pci/ven=10de&dev=0aa9 16 10 pci/ven=10de&dev=0aaa 17 10 pci/ven=10de&dev=0d9d 18 10 pci/ven=1166&dev=0414 19 10 pci/ven=1166&dev=0416 20 10 pci/ven=1414&dev=5805 21 10 pci/ven=1414&dev=5807 22 10 pci/ven=15ad&dev=0770 23 10 pci/ven=17a0&dev=8084 24 10 pci/ven=8086&dev=24cd 25 10 pci/ven=8086&dev=24dd 26 10 pci/ven=8086&dev=265c 27 10 pci/ven=8086&dev=268c 28 10 pci/ven=8086&dev=27cc 29 10 pci/ven=8086&dev=2836 30 10 pci/ven=8086&dev=283a 31 10 pci/ven=8086&dev=293a 32 10 pci/ven=8086&dev=293c 33 10 pci/ven=8086&dev=3a3a 34 10 pci/ven=8086&dev=3a3c 35 10 pci/ven=8086&dev=3a6a 36 10 pci/ven=8086&dev=3a6c 37 10 pci/ven=8086&dev=8117 38 10 pci/ven=8086&dev=8807 39 10 pci/ven=8086&dev=880f 1 10 pci/class=0c&subclass=03&progif=20 -
uspace/drv/bus/usb/ehci/main.c
rba72f2b r6843a9c 42 42 #include <usb/ddfiface.h> 43 43 #include <usb/debug.h> 44 #include <usb/host/hcd.h> 44 45 45 #include "pci.h" 46 #include "ehci.h" 46 #include "res.h" 47 47 48 static int ehci_add_device(ddf_dev_t *device); 48 #define NAME "ehci" 49 50 static int ehci_dev_add(ddf_dev_t *device); 49 51 /*----------------------------------------------------------------------------*/ 50 52 static driver_ops_t ehci_driver_ops = { 51 . add_device = ehci_add_device,53 .dev_add = ehci_dev_add, 52 54 }; 53 55 /*----------------------------------------------------------------------------*/ … … 57 59 }; 58 60 static ddf_dev_ops_t hc_ops = { 59 .interfaces[USBHC_DEV_IFACE] = & ehci_hc_iface,61 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, 60 62 }; 61 63 … … 66 68 * @return Error code. 67 69 */ 68 static int ehci_ add_device(ddf_dev_t *device)70 static int ehci_dev_add(ddf_dev_t *device) 69 71 { 70 72 assert(device); … … 79 81 int irq = 0; 80 82 81 int ret = pci_get_my_registers(device, ®_base, ®_size, &irq);83 int ret = get_my_registers(device, ®_base, ®_size, &irq); 82 84 CHECK_RET_RETURN(ret, 83 85 "Failed to get memory addresses for %" PRIun ": %s.\n", … … 86 88 reg_base, reg_size, irq); 87 89 88 ret = pci_disable_legacy(device, reg_base, reg_size, irq);90 ret = disable_legacy(device, reg_base, reg_size); 89 91 CHECK_RET_RETURN(ret, 90 92 "Failed to disable legacy USB: %s.\n", str_error(ret)); … … 95 97 return ENOMEM; 96 98 } 99 hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t)); 100 if (ehci_hc == NULL) { 101 usb_log_error("Failed to alloc generic HC driver.\n"); 102 return ENOMEM; 103 } 104 /* High Speed, no bandwidth */ 105 hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL); 97 106 hc_fun->ops = &hc_ops; 98 107 -
uspace/drv/bus/usb/ehci/res.h
rba72f2b r6843a9c 38 38 #include <ddf/driver.h> 39 39 40 int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);41 int pci_enable_interrupts(const ddf_dev_t *);42 int pci_disable_legacy(const ddf_dev_t *, uintptr_t, size_t, int);40 int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *); 41 int enable_interrupts(const ddf_dev_t *); 42 int disable_legacy(const ddf_dev_t *, uintptr_t, size_t); 43 43 44 44 #endif -
uspace/drv/bus/usb/ohci/Makefile
rba72f2b r6843a9c 50 50 ohci_batch.c \ 51 51 ohci_endpoint.c \ 52 pci.c \52 res.c \ 53 53 root_hub.c \ 54 54 hw_struct/endpoint_descriptor.c \ -
uspace/drv/bus/usb/ohci/endpoint_list.c
rba72f2b r6843a9c 73 73 * Does not check whether this replaces an existing list. 74 74 */ 75 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next) 75 void endpoint_list_set_next( 76 const endpoint_list_t *instance, const endpoint_list_t *next) 76 77 { 77 78 assert(instance); -
uspace/drv/bus/usb/ohci/endpoint_list.h
rba72f2b r6843a9c 68 68 69 69 int endpoint_list_init(endpoint_list_t *instance, const char *name); 70 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next); 70 void endpoint_list_set_next( 71 const endpoint_list_t *instance, const endpoint_list_t *next); 71 72 void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); 72 73 void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep); -
uspace/drv/bus/usb/ohci/hc.c
rba72f2b r6843a9c 47 47 (I_SO | I_WDH | I_UE | I_RHSC) 48 48 49 static const irq_cmd_t ohci_irq_commands[] = 50 { 51 { .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ }, 49 static const irq_pio_range_t ohci_pio_ranges[] = { 50 { 51 .base = 0, /* filled later */ 52 .size = sizeof(ohci_regs_t) 53 } 54 }; 55 56 static const irq_cmd_t ohci_irq_commands[] = { 57 { .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ }, 52 58 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS }, 53 59 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 }, 54 { .cmd = CMD_ MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },60 { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ }, 55 61 { .cmd = CMD_ACCEPT }, 56 62 }; … … 63 69 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 64 70 /*----------------------------------------------------------------------------*/ 71 /** Get number of PIO ranges used in IRQ code. 72 * @return Number of ranges. 73 */ 74 size_t hc_irq_pio_range_count(void) 75 { 76 return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t); 77 } 78 /*----------------------------------------------------------------------------*/ 79 /*----------------------------------------------------------------------------*/ 65 80 /** Get number of commands used in IRQ code. 66 81 * @return Number of commands. … … 71 86 } 72 87 /*----------------------------------------------------------------------------*/ 73 /** Generate IRQ code commands. 74 * @param[out] cmds Place to store the commands. 75 * @param[in] cmd_size Size of the place (bytes). 88 /** Generate IRQ code. 89 * @param[out] ranges PIO ranges buffer. 90 * @param[in] ranges_size Size of the ranges buffer (bytes). 91 * @param[out] cmds Commands buffer. 92 * @param[in] cmds_size Size of the commands buffer (bytes). 76 93 * @param[in] regs Physical address of device's registers. 77 94 * @param[in] reg_size Size of the register area (bytes). … … 79 96 * @return Error code. 80 97 */ 81 int hc_get_irq_commands( 82 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size) 83 { 84 if (cmd_size < sizeof(ohci_irq_commands) 85 || reg_size < sizeof(ohci_regs_t)) 98 int 99 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[], 100 size_t cmds_size, uintptr_t regs, size_t reg_size) 101 { 102 if ((ranges_size < sizeof(ohci_pio_ranges)) || 103 (cmds_size < sizeof(ohci_irq_commands)) || 104 (reg_size < sizeof(ohci_regs_t))) 86 105 return EOVERFLOW; 87 106 88 /* Create register mapping to use in IRQ handler. 89 * This mapping should be present in kernel only. 90 * Remove it from here when kernel knows how to create mappings 91 * and accepts physical addresses in IRQ code. 92 * TODO: remove */ 93 ohci_regs_t *registers; 94 const int ret = pio_enable((void*)regs, reg_size, (void**)®isters); 95 if (ret != EOK) 96 return ret; 97 98 /* Some bogus access to force create mapping. DO NOT remove, 99 * unless whole virtual addresses in irq is replaced 100 * NOTE: Compiler won't remove this as ohci_regs_t members 101 * are declared volatile. 102 * 103 * Introducing CMD_MEM set of IRQ code commands broke 104 * assumption that IRQ code does not cause page faults. 105 * If this happens during idling (THREAD == NULL) 106 * it causes kernel panic. 107 */ 108 registers->revision; 107 memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges)); 108 ranges[0].base = regs; 109 109 110 110 memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 111 112 void *address = (void*)®isters->interrupt_status;113 cmds[ 0].addr = address;114 cmds[3].addr = address; 111 ohci_regs_t *registers = (ohci_regs_t *) regs; 112 cmds[0].addr = (void *) ®isters->interrupt_status; 113 cmds[3].addr = (void *) ®isters->interrupt_status; 114 115 115 return EOK; 116 116 } … … 127 127 assert(hub_fun); 128 128 129 const usb_address_t hub_address = 130 usb_device_manager_get_free_address( 131 &instance->generic.dev_manager, USB_SPEED_FULL); 132 if (hub_address <= 0) { 129 /* Try to get address 1 for root hub. */ 130 instance->rh.address = 1; 131 int ret = usb_device_manager_request_address( 132 &instance->generic.dev_manager, &instance->rh.address, false, 133 USB_SPEED_FULL); 134 if (ret != EOK) { 133 135 usb_log_error("Failed to get OHCI root hub address: %s\n", 134 str_error(hub_address)); 135 return hub_address; 136 } 137 instance->rh.address = hub_address; 138 usb_device_manager_bind( 139 &instance->generic.dev_manager, hub_address, hub_fun->handle); 136 str_error(ret)); 137 return ret; 138 } 140 139 141 140 #define CHECK_RET_UNREG_RETURN(ret, message...) \ 142 141 if (ret != EOK) { \ 143 142 usb_log_error(message); \ 144 usb_endpoint_manager_unregister_ep( \ 145 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\ 146 usb_device_manager_release( \ 147 &instance->generic.dev_manager, hub_address); \ 143 usb_endpoint_manager_remove_ep( \ 144 &instance->generic.ep_manager, instance->rh.address, 0, \ 145 USB_DIRECTION_BOTH, NULL, NULL); \ 146 usb_device_manager_release_address( \ 147 &instance->generic.dev_manager, instance->rh.address); \ 148 148 return ret; \ 149 149 } else (void)0 150 int ret = usb_endpoint_manager_add_ep( 151 &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, 152 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0); 150 151 ret = usb_endpoint_manager_add_ep( 152 &instance->generic.ep_manager, instance->rh.address, 0, 153 USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 154 0, NULL, NULL); 153 155 CHECK_RET_UNREG_RETURN(ret, 154 156 "Failed to register root hub control endpoint: %s.\n", … … 162 164 CHECK_RET_UNREG_RETURN(ret, 163 165 "Failed to bind root hub function: %s.\n", str_error(ret)); 166 167 ret = usb_device_manager_bind_address(&instance->generic.dev_manager, 168 instance->rh.address, hub_fun->handle); 169 if (ret != EOK) 170 usb_log_warning("Failed to bind root hub address: %s.\n", 171 str_error(ret)); 164 172 165 173 return EOK; … … 192 200 list_initialize(&instance->pending_batches); 193 201 194 ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11, 195 bandwidth_count_usb11); 196 CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n", 197 str_error(ret)); 202 hcd_init(&instance->generic, USB_SPEED_FULL, 203 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 198 204 instance->generic.private_data = instance; 199 205 instance->generic.schedule = hc_schedule; 200 206 instance->generic.ep_add_hook = ohci_endpoint_init; 207 instance->generic.ep_remove_hook = ohci_endpoint_fini; 201 208 202 209 ret = hc_init_memory(instance); … … 221 228 } 222 229 /*----------------------------------------------------------------------------*/ 223 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep) 224 { 230 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) 231 { 232 assert(instance); 233 assert(ep); 234 225 235 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 226 236 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 237 assert(list); 238 assert(ohci_ep); 239 227 240 /* Enqueue ep */ 228 241 switch (ep->transfer_type) { … … 247 260 } 248 261 /*----------------------------------------------------------------------------*/ 249 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep) 250 { 262 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep) 263 { 264 assert(instance); 265 assert(ep); 266 251 267 /* Dequeue ep */ 252 268 endpoint_list_t *list = &instance->lists[ep->transfer_type]; 253 269 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep); 270 271 assert(list); 272 assert(ohci_ep); 254 273 switch (ep->transfer_type) { 255 274 case USB_TRANSFER_CONTROL: -
uspace/drv/bus/usb/ohci/hc.h
rba72f2b r6843a9c 74 74 } hc_t; 75 75 76 size_t hc_irq_pio_range_count(void); 76 77 size_t hc_irq_cmd_count(void); 77 int hc_get_irq_co mmands(78 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);78 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t, 79 size_t); 79 80 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun); 80 81 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts); … … 86 87 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 87 88 88 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep);89 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep);89 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep); 90 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep); 90 91 91 92 void hc_interrupt(hc_t *instance, uint32_t status); -
uspace/drv/bus/usb/ohci/hw_struct/hcca.h
rba72f2b r6843a9c 46 46 uint16_t pad1; 47 47 uint32_t done_head; 48 uint32_t reserved[ 29];49 } __attribute__((packed, aligned))hcca_t;48 uint32_t reserved[30]; 49 } hcca_t; 50 50 51 51 static inline void * hcca_get(void) -
uspace/drv/bus/usb/ohci/main.c
rba72f2b r6843a9c 48 48 * @return Error code. 49 49 */ 50 static int ohci_ add_device(ddf_dev_t *device)50 static int ohci_dev_add(ddf_dev_t *device) 51 51 { 52 usb_log_debug("ohci_ add_device() called\n");52 usb_log_debug("ohci_dev_add() called\n"); 53 53 assert(device); 54 54 … … 65 65 /*----------------------------------------------------------------------------*/ 66 66 static driver_ops_t ohci_driver_ops = { 67 . add_device = ohci_add_device,67 .dev_add = ohci_dev_add, 68 68 }; 69 69 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/ohci/ohci.c
rba72f2b r6843a9c 42 42 43 43 #include "ohci.h" 44 #include " pci.h"44 #include "res.h" 45 45 #include "hc.h" 46 46 … … 76 76 } 77 77 /*----------------------------------------------------------------------------*/ 78 /** Get address of the device identified by handle. 79 * 80 * @param[in] dev DDF instance of the device to use. 81 * @param[in] iid (Unused). 82 * @param[in] call Pointer to the call that represents interrupt. 83 */ 84 static int usb_iface_get_address( 85 ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address) 78 /** Get USB address assigned to root hub. 79 * 80 * @param[in] fun Root hub function. 81 * @param[out] address Store the address here. 82 * @return Error code. 83 */ 84 static int rh_get_my_address(ddf_fun_t *fun, usb_address_t *address) 86 85 { 87 86 assert(fun); 88 usb_device_manager_t *manager =89 &dev_to_ohci(fun->dev)->hc.generic.dev_manager;90 91 const usb_address_t addr = usb_device_manager_find(manager, handle);92 if (addr < 0) {93 return addr;94 }95 87 96 88 if (address != NULL) { 97 *address = addr;89 *address = dev_to_ohci(fun->dev)->hc.rh.address; 98 90 } 99 91 … … 107 99 * @return Error code. 108 100 */ 109 static int usb_iface_get_hc_handle(101 static int rh_get_hc_handle( 110 102 ddf_fun_t *fun, devman_handle_t *handle) 111 103 { … … 121 113 /** Root hub USB interface */ 122 114 static usb_iface_t usb_iface = { 123 .get_hc_handle = usb_iface_get_hc_handle,124 .get_ address = usb_iface_get_address115 .get_hc_handle = rh_get_hc_handle, 116 .get_my_address = rh_get_my_address, 125 117 }; 126 118 /*----------------------------------------------------------------------------*/ … … 148 140 int device_setup_ohci(ddf_dev_t *device) 149 141 { 150 assert(device); 151 152 ohci_t *instance = malloc(sizeof(ohci_t)); 142 if (device == NULL) 143 return EBADMEM; 144 145 ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t)); 153 146 if (instance == NULL) { 154 147 usb_log_error("Failed to allocate OHCI driver.\n"); 155 148 return ENOMEM; 156 149 } 157 instance->rh_fun = NULL;158 instance->hc_fun = NULL;159 150 160 151 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 161 152 if (ret != EOK) { \ 162 153 if (instance->hc_fun) { \ 154 instance->hc_fun->driver_data = NULL; \ 163 155 ddf_fun_destroy(instance->hc_fun); \ 164 156 } \ 165 157 if (instance->rh_fun) { \ 158 instance->rh_fun->driver_data = NULL; \ 166 159 ddf_fun_destroy(instance->rh_fun); \ 167 160 } \ 168 free(instance); \169 161 usb_log_error(message); \ 170 162 return ret; \ … … 188 180 int irq = 0; 189 181 190 ret = pci_get_my_registers(device, ®_base, ®_size, &irq);182 ret = get_my_registers(device, ®_base, ®_size, &irq); 191 183 CHECK_RET_DEST_FREE_RETURN(ret, 192 184 "Failed to get register memory addresses for %" PRIun ": %s.\n", … … 195 187 (void *) reg_base, reg_size, irq); 196 188 197 const size_t cmd_count = hc_irq_cmd_count(); 198 irq_cmd_t irq_cmds[cmd_count]; 199 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds }; 200 201 ret = 202 hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size); 203 CHECK_RET_DEST_FREE_RETURN(ret, 204 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 189 const size_t ranges_count = hc_irq_pio_range_count(); 190 const size_t cmds_count = hc_irq_cmd_count(); 191 irq_pio_range_t irq_ranges[ranges_count]; 192 irq_cmd_t irq_cmds[cmds_count]; 193 irq_code_t irq_code = { 194 .rangecount = ranges_count, 195 .ranges = irq_ranges, 196 .cmdcount = cmds_count, 197 .cmds = irq_cmds 198 }; 199 200 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 201 sizeof(irq_cmds), reg_base, reg_size); 202 CHECK_RET_DEST_FREE_RETURN(ret, 203 "Failed to generate IRQ code: %s.\n", str_error(ret)); 205 204 206 205 … … 212 211 /* Try to enable interrupts */ 213 212 bool interrupts = false; 214 ret = pci_enable_interrupts(device);213 ret = enable_interrupts(device); 215 214 if (ret != EOK) { 216 215 usb_log_warning("Failed to enable interrupts: %s." … … 227 226 "Failed to init ohci_hcd: %s.\n", str_error(ret)); 228 227 229 device->driver_data = instance;230 231 228 #define CHECK_RET_FINI_RETURN(ret, message...) \ 232 229 if (ret != EOK) { \ -
uspace/drv/bus/usb/ohci/ohci.ma
rba72f2b r6843a9c 1 10 pci/ven=106b&dev=0026 2 10 pci/ven=106b&dev=003f 3 10 pci/ven=10de&dev=0aa5 4 5 10 pci/ven=1002&dev=4374 6 10 pci/ven=1002&dev=4375 7 8 10 pci/ven=1002&dev=4387 9 10 pci/ven=1002&dev=4388 10 10 pci/ven=1002&dev=4389 11 10 pci/ven=1002&dev=438a 12 10 pci/ven=1002&dev=438b 13 10 pci/ven=1002&dev=4397 14 10 pci/ven=1002&dev=4398 15 10 pci/ven=1002&dev=4399 1 10 pci/class=0c&subclass=03&progif=10 -
uspace/drv/bus/usb/ohci/ohci_batch.c
rba72f2b r6843a9c 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h> 36 37 37 38 #include <usb/usb.h> … … 53 54 return; 54 55 if (ohci_batch->tds) { 56 const ohci_endpoint_t *ohci_ep = 57 ohci_endpoint_get(ohci_batch->usb_batch->ep); 58 assert(ohci_ep); 55 59 for (unsigned i = 0; i < ohci_batch->td_count; ++i) { 56 if ( i != ohci_batch->leave_td)60 if (ohci_batch->tds[i] != ohci_ep->td) 57 61 free32(ohci_batch->tds[i]); 58 62 } 59 63 free(ohci_batch->tds); 60 64 } 61 usb_transfer_batch_d ispose(ohci_batch->usb_batch);65 usb_transfer_batch_destroy(ohci_batch->usb_batch); 62 66 free32(ohci_batch->device_buffer); 63 67 free(ohci_batch); 64 68 } 65 69 /*----------------------------------------------------------------------------*/ 70 /** Finishes usb_transfer_batch and destroys the structure. 71 * 72 * @param[in] uhci_batch Instance to finish and destroy. 73 */ 66 74 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch) 67 75 { … … 69 77 assert(ohci_batch->usb_batch); 70 78 usb_transfer_batch_finish(ohci_batch->usb_batch, 71 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size, 72 ohci_batch->usb_batch->buffer_size); 79 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size); 73 80 ohci_transfer_batch_dispose(ohci_batch); 74 81 } 75 82 /*----------------------------------------------------------------------------*/ 83 /** Allocate memory and initialize internal data structure. 84 * 85 * @param[in] usb_batch Pointer to generic USB batch structure. 86 * @return Valid pointer if all structures were successfully created, 87 * NULL otherwise. 88 * 89 * Determines the number of needed transfer descriptors (TDs). 90 * Prepares a transport buffer (that is accessible by the hardware). 91 * Initializes parameters needed for the transfer and callback. 92 */ 76 93 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 77 94 { … … 105 122 ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed; 106 123 ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td; 107 ohci_batch->leave_td = 0;108 124 109 125 for (unsigned i = 1; i <= ohci_batch->td_count; ++i) { … … 152 168 * completes with the last TD. 153 169 */ 154 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *ohci_batch)170 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch) 155 171 { 156 172 assert(ohci_batch); … … 174 190 175 191 /* Assume we will leave the last(unused) TD behind */ 176 ohci_batch->leave_td = ohci_batch->td_count;192 unsigned leave_td = ohci_batch->td_count; 177 193 178 194 /* Check all TDs */ … … 212 228 * It will be the one TD we leave behind. 213 229 */ 214 ohci_batch->leave_td = i + 1;230 leave_td = i + 1; 215 231 216 232 /* Check TD assumption */ 217 const uint32_t pa = addr_to_phys(218 ohci_batch->tds[ohci_batch->leave_td]);219 assert((ohci_batch->ed->td_head & ED_TD TAIL_PTR_MASK)233 const uint32_t pa = 234 addr_to_phys(ohci_batch->tds[leave_td]); 235 assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK) 220 236 == pa); 221 237 222 238 ed_set_tail_td(ohci_batch->ed, 223 ohci_batch->tds[ ohci_batch->leave_td]);239 ohci_batch->tds[leave_td]); 224 240 225 241 /* Clear possible ED HALT */ … … 234 250 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 235 251 assert(ohci_ep); 236 ohci_ep->td = ohci_batch->tds[ ohci_batch->leave_td];252 ohci_ep->td = ohci_batch->tds[leave_td]; 237 253 238 254 /* Make sure that we are leaving the right TD behind */ … … 248 264 * @param[in] ohci_batch Batch structure to use 249 265 */ 250 void ohci_transfer_batch_commit( ohci_transfer_batch_t *ohci_batch)266 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *ohci_batch) 251 267 { 252 268 assert(ohci_batch); … … 295 311 while (remain_size > 0) { 296 312 const size_t transfer_size = 297 remain_size > OHCI_TD_MAX_TRANSFER ? 298 OHCI_TD_MAX_TRANSFER : remain_size; 313 min(remain_size, OHCI_TD_MAX_TRANSFER); 299 314 toggle = 1 - toggle; 300 315 … … 378 393 } 379 394 /*----------------------------------------------------------------------------*/ 395 /** Transfer setup table. */ 380 396 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) = 381 397 { -
uspace/drv/bus/usb/ohci/ohci_batch.h
rba72f2b r6843a9c 53 53 /** Number of TDs used by the transfer */ 54 54 size_t td_count; 55 /** Dummy TD to be left at the ED and used by the next transfer */56 size_t leave_td;57 55 /** Data buffer, must be accessible by the OHCI hw. */ 58 56 char *device_buffer; … … 62 60 63 61 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 64 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *batch);65 void ohci_transfer_batch_commit( ohci_transfer_batch_t *batch);62 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch); 63 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch); 66 64 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 67 65 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/ohci/ohci_endpoint.c
rba72f2b r6843a9c 62 62 } 63 63 /*----------------------------------------------------------------------------*/ 64 /** Disposes hcd endpoint structure65 *66 * @param[in] hcd_ep endpoint structure67 */68 static void ohci_endpoint_fini(endpoint_t *ep)69 {70 ohci_endpoint_t *instance = ep->hc_data.data;71 hc_dequeue_endpoint(instance->hcd->private_data, ep);72 if (instance) {73 free32(instance->ed);74 free32(instance->td);75 free(instance);76 }77 }78 /*----------------------------------------------------------------------------*/79 64 /** Creates new hcd endpoint representation. 80 65 * 81 66 * @param[in] ep USBD endpoint structure 82 * @return pointer to a new hcd endpoint structure, NULL on failure.67 * @return Error code. 83 68 */ 84 69 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep) … … 104 89 ed_init(ohci_ep->ed, ep, ohci_ep->td); 105 90 endpoint_set_hc_data( 106 ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set); 107 ohci_ep->hcd = hcd; 91 ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set); 108 92 hc_enqueue_endpoint(hcd->private_data, ep); 109 93 return EOK; 94 } 95 /*----------------------------------------------------------------------------*/ 96 /** Disposes hcd endpoint structure 97 * 98 * @param[in] hcd driver using this instance. 99 * @param[in] ep endpoint structure. 100 */ 101 void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep) 102 { 103 assert(hcd); 104 assert(ep); 105 ohci_endpoint_t *instance = ohci_endpoint_get(ep); 106 hc_dequeue_endpoint(hcd->private_data, ep); 107 if (instance) { 108 free32(instance->ed); 109 free32(instance->td); 110 free(instance); 111 } 112 endpoint_clear_hc_data(ep); 110 113 } 111 114 /** -
uspace/drv/bus/usb/ohci/ohci_endpoint.h
rba72f2b r6843a9c 51 51 /** Linked list used by driver software */ 52 52 link_t link; 53 /** Device using this ep */54 hcd_t *hcd;55 53 } ohci_endpoint_t; 56 54 57 55 int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep); 56 void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep); 58 57 59 58 /** Get and convert assigned ohci_endpoint_t structure … … 61 60 * @return Pointer to assigned hcd endpoint structure 62 61 */ 63 static inline ohci_endpoint_t * ohci_endpoint_get( endpoint_t *ep)62 static inline ohci_endpoint_t * ohci_endpoint_get(const endpoint_t *ep) 64 63 { 65 64 assert(ep); -
uspace/drv/bus/usb/ohci/ohci_regs.h
rba72f2b r6843a9c 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbohci hc28 /** @addtogroup drvusbohci 29 29 * @{ 30 30 */ -
uspace/drv/bus/usb/ohci/res.c
rba72f2b r6843a9c 38 38 #include <errno.h> 39 39 #include <assert.h> 40 #include <as.h>41 40 #include <devman.h> 42 #include <ddi.h> 43 #include <libarch/ddi.h> 44 #include <device/hw_res.h> 41 #include <device/hw_res_parsed.h> 45 42 46 43 #include <usb/debug.h> 47 #include <pci_dev_iface.h>48 44 49 #include " pci.h"45 #include "res.h" 50 46 51 47 /** Get address of registers and IRQ for given device. … … 57 53 * @return Error code. 58 54 */ 59 int pci_get_my_registers(ddf_dev_t *dev,55 int get_my_registers(const ddf_dev_t *dev, 60 56 uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no) 61 57 { 62 58 assert(dev); 63 assert(mem_reg_address);64 assert(mem_reg_size);65 assert(irq_no);66 59 67 60 async_sess_t *parent_sess = … … 71 64 return ENOMEM; 72 65 73 hw_resource_list_t hw_resources; 74 int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 66 hw_res_list_parsed_t hw_res; 67 hw_res_list_parsed_init(&hw_res); 68 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0); 75 69 async_hangup(parent_sess); 76 if (r c!= EOK) {77 return r c;70 if (ret != EOK) { 71 return ret; 78 72 } 79 73 80 uintptr_t mem_address = 0; 81 size_t mem_size = 0; 82 bool mem_found = false; 74 /* We want one irq and one mem range. */ 75 if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) { 76 hw_res_list_parsed_clean(&hw_res); 77 return EINVAL; 78 } 83 79 84 int irq = 0; 85 bool irq_found = false; 80 if (mem_reg_address) 81 *mem_reg_address = hw_res.mem_ranges.ranges[0].address; 82 if (mem_reg_size) 83 *mem_reg_size = hw_res.mem_ranges.ranges[0].size; 84 if (irq_no) 85 *irq_no = hw_res.irqs.irqs[0]; 86 86 87 for (size_t i = 0; i < hw_resources.count; i++) { 88 hw_resource_t *res = &hw_resources.resources[i]; 89 switch (res->type) { 90 case INTERRUPT: 91 irq = res->res.interrupt.irq; 92 irq_found = true; 93 usb_log_debug2("Found interrupt: %d.\n", irq); 94 break; 95 case MEM_RANGE: 96 if (res->res.mem_range.address != 0 97 && res->res.mem_range.size != 0 ) { 98 mem_address = res->res.mem_range.address; 99 mem_size = res->res.mem_range.size; 100 usb_log_debug2("Found mem: %p %zu.\n", 101 (void *) mem_address, mem_size); 102 mem_found = true; 103 } 104 default: 105 break; 106 } 107 } 108 free(hw_resources.resources); 109 110 if (mem_found && irq_found) { 111 *mem_reg_address = mem_address; 112 *mem_reg_size = mem_size; 113 *irq_no = irq; 114 return EOK; 115 } 116 return ENOENT; 87 hw_res_list_parsed_clean(&hw_res); 88 return EOK; 117 89 } 118 90 … … 122 94 * @return Error code. 123 95 */ 124 int pci_enable_interrupts(ddf_dev_t *device)96 int enable_interrupts(const ddf_dev_t *device) 125 97 { 126 98 async_sess_t *parent_sess = … … 130 102 return ENOMEM; 131 103 132 bool enabled = hw_res_enable_interrupt(parent_sess);104 const bool enabled = hw_res_enable_interrupt(parent_sess); 133 105 async_hangup(parent_sess); 134 106 -
uspace/drv/bus/usb/ohci/res.h
rba72f2b r6843a9c 32 32 * PCI related functions needed by OHCI driver. 33 33 */ 34 #ifndef DRV_OHCI_ PCI_H35 #define DRV_OHCI_ PCI_H34 #ifndef DRV_OHCI_RES_H 35 #define DRV_OHCI_RES_H 36 36 37 37 #include <ddf/driver.h> 38 38 39 int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *); 40 int pci_enable_interrupts(ddf_dev_t *); 41 int pci_disable_legacy(ddf_dev_t *); 39 int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *); 40 int enable_interrupts(const ddf_dev_t *); 42 41 43 42 #endif -
uspace/drv/bus/usb/ohci/root_hub.c
rba72f2b r6843a9c 100 100 .attributes = USB_TRANSFER_INTERRUPT, 101 101 .descriptor_type = USB_DESCTYPE_ENDPOINT, 102 .endpoint_address = 1 +(1 << 7),102 .endpoint_address = 1 | (1 << 7), 103 103 .length = sizeof(usb_standard_endpoint_descriptor_t), 104 104 .max_packet_size = 2, … … 109 109 static void rh_init_descriptors(rh_t *instance); 110 110 static uint16_t create_interrupt_mask(const rh_t *instance); 111 static intget_status(const rh_t *instance, usb_transfer_batch_t *request);112 static intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request);113 static intset_feature(const rh_t *instance, usb_transfer_batch_t *request);114 static intclear_feature(const rh_t *instance, usb_transfer_batch_t *request);111 static void get_status(const rh_t *instance, usb_transfer_batch_t *request); 112 static void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request); 113 static void set_feature(const rh_t *instance, usb_transfer_batch_t *request); 114 static void clear_feature(const rh_t *instance, usb_transfer_batch_t *request); 115 115 static int set_feature_port( 116 116 const rh_t *instance, uint16_t feature, uint16_t port); 117 117 static int clear_feature_port( 118 118 const rh_t *instance, uint16_t feature, uint16_t port); 119 static intcontrol_request(rh_t *instance, usb_transfer_batch_t *request);119 static void control_request(rh_t *instance, usb_transfer_batch_t *request); 120 120 static inline void interrupt_request( 121 121 usb_transfer_batch_t *request, uint16_t mask, size_t size) 122 122 { 123 123 assert(request); 124 125 request->transfered_size = size;126 124 usb_transfer_batch_finish_error(request, &mask, size, EOK); 127 } 128 129 #define TRANSFER_OK(bytes) \ 125 usb_transfer_batch_destroy(request); 126 } 127 128 #define TRANSFER_END_DATA(request, data, bytes) \ 130 129 do { \ 131 request->transfered_size = bytes; \ 132 return EOK; \ 130 usb_transfer_batch_finish_error(request, data, bytes, EOK); \ 131 usb_transfer_batch_destroy(request); \ 132 return; \ 133 } while (0) 134 135 #define TRANSFER_END(request, error) \ 136 do { \ 137 usb_transfer_batch_finish_error(request, NULL, 0, error); \ 138 usb_transfer_batch_destroy(request); \ 139 return; \ 133 140 } while (0) 134 141 … … 212 219 case USB_TRANSFER_CONTROL: 213 220 usb_log_debug("Root hub got CONTROL packet\n"); 214 const int ret = control_request(instance, request); 215 usb_transfer_batch_finish_error(request, NULL, 0, ret); 221 control_request(instance, request); 216 222 break; 223 217 224 case USB_TRANSFER_INTERRUPT: 218 225 usb_log_debug("Root hub got INTERRUPT packet\n"); 219 226 fibril_mutex_lock(&instance->guard); 220 227 assert(instance->unfinished_interrupt_transfer == NULL); 221 constuint16_t mask = create_interrupt_mask(instance);228 uint16_t mask = create_interrupt_mask(instance); 222 229 if (mask == 0) { 223 usb_log_debug("No changes.. \n");230 usb_log_debug("No changes...\n"); 224 231 instance->unfinished_interrupt_transfer = request; 225 fibril_mutex_unlock(&instance->guard); 226 return; 232 } else { 233 usb_log_debug("Processing changes...\n"); 234 interrupt_request( 235 request, mask, instance->interrupt_mask_size); 227 236 } 228 usb_log_debug("Processing changes...\n");229 interrupt_request(request, mask, instance->interrupt_mask_size);230 237 fibril_mutex_unlock(&instance->guard); 231 238 break; … … 233 240 default: 234 241 usb_log_error("Root hub got unsupported request.\n"); 235 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 236 } 237 usb_transfer_batch_dispose(request); 242 TRANSFER_END(request, ENOTSUP); 243 } 238 244 } 239 245 /*----------------------------------------------------------------------------*/ … … 251 257 if (instance->unfinished_interrupt_transfer) { 252 258 usb_log_debug("Finalizing interrupt transfer\n"); 253 constuint16_t mask = create_interrupt_mask(instance);259 uint16_t mask = create_interrupt_mask(instance); 254 260 interrupt_request(instance->unfinished_interrupt_transfer, 255 261 mask, instance->interrupt_mask_size); 256 usb_transfer_batch_dispose(257 instance->unfinished_interrupt_transfer);258 262 instance->unfinished_interrupt_transfer = NULL; 259 263 } … … 274 278 275 279 /* 7 bytes + 2 port bit fields (port count + global bit) */ 276 constsize_t size = 7 + (instance->interrupt_mask_size * 2);280 size_t size = 7 + (instance->interrupt_mask_size * 2); 277 281 assert(size <= HUB_DESCRIPTOR_MAX_SIZE); 278 282 instance->hub_descriptor_size = size; 279 283 280 constuint32_t hub_desc = instance->registers->rh_desc_a;281 constuint32_t port_desc = instance->registers->rh_desc_b;284 uint32_t hub_desc = instance->registers->rh_desc_a; 285 uint32_t port_desc = instance->registers->rh_desc_b; 282 286 283 287 /* bDescLength */ … … 384 388 * @return error code 385 389 */ 386 intget_status(const rh_t *instance, usb_transfer_batch_t *request)390 void get_status(const rh_t *instance, usb_transfer_batch_t *request) 387 391 { 388 392 assert(instance); 389 393 assert(request); 390 394 391 const usb_device_request_setup_packet_t *request_packet = 395 396 usb_device_request_setup_packet_t *request_packet = 392 397 (usb_device_request_setup_packet_t*)request->setup_buffer; 393 398 394 if (request->buffer_size < 4) { 395 usb_log_error("Buffer too small for get status request.\n"); 396 return EOVERFLOW; 397 } 398 399 switch (request_packet->request_type) 400 { 401 case USB_HUB_REQ_TYPE_GET_HUB_STATUS: 399 402 /* Hub status: just filter relevant info from rh_status reg */ 400 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) { 401 const uint32_t data = instance->registers->rh_status & 402 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 403 memcpy(request->buffer, &data, sizeof(data)); 404 TRANSFER_OK(sizeof(data)); 405 } 403 if (request->buffer_size < 4) { 404 usb_log_error("Buffer(%zu) too small for hub get " 405 "status request.\n", request->buffer_size); 406 TRANSFER_END(request, EOVERFLOW); 407 } else { 408 uint32_t data = instance->registers->rh_status & 409 (RHS_LPS_FLAG | RHS_LPSC_FLAG 410 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 411 TRANSFER_END_DATA(request, &data, sizeof(data)); 412 } 406 413 407 414 /* Copy appropriate rh_port_status register, OHCI designers were 408 415 * kind enough to make those bit values match USB specification */ 409 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) { 410 const unsigned port = request_packet->index; 411 if (port < 1 || port > instance->port_count) 412 return EINVAL; 413 414 const uint32_t data = 415 instance->registers->rh_port_status[port - 1]; 416 memcpy(request->buffer, &data, sizeof(data)); 417 TRANSFER_OK(sizeof(data)); 418 } 419 420 return ENOTSUP; 416 case USB_HUB_REQ_TYPE_GET_PORT_STATUS: 417 if (request->buffer_size < 4) { 418 usb_log_error("Buffer(%zu) too small for hub get " 419 "status request.\n", request->buffer_size); 420 TRANSFER_END(request, EOVERFLOW); 421 } else { 422 unsigned port = request_packet->index; 423 if (port < 1 || port > instance->port_count) 424 TRANSFER_END(request, EINVAL); 425 426 uint32_t data = 427 instance->registers->rh_port_status[port - 1]; 428 TRANSFER_END_DATA(request, &data, sizeof(data)); 429 } 430 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE): 431 if (request->buffer_size < 2) { 432 usb_log_error("Buffer(%zu) too small for hub generic " 433 "get status request.\n", request->buffer_size); 434 TRANSFER_END(request, EOVERFLOW); 435 } else { 436 uint16_t data = 437 uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED); 438 TRANSFER_END_DATA(request, &data, sizeof(data)); 439 } 440 441 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE): 442 /* Hubs are allowed to have only one interface */ 443 if (request_packet->index != 0) 444 TRANSFER_END(request, EINVAL); 445 /* Fall through, as the answer will be the same: 0x0000 */ 446 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT): 447 /* Endpoint 0 (default control) and 1 (interrupt) */ 448 if (request_packet->index >= 2) 449 TRANSFER_END(request, EINVAL); 450 451 if (request->buffer_size < 2) { 452 usb_log_error("Buffer(%zu) too small for hub generic " 453 "get status request.\n", request->buffer_size); 454 TRANSFER_END(request, EOVERFLOW); 455 } else { 456 /* Endpoints are OK. (We don't halt) */ 457 uint16_t data = 0; 458 TRANSFER_END_DATA(request, &data, sizeof(data)); 459 } 460 461 default: 462 usb_log_error("Unsupported GET_STATUS request.\n"); 463 TRANSFER_END(request, ENOTSUP); 464 } 465 421 466 } 422 467 /*----------------------------------------------------------------------------*/ … … 430 475 * @return Error code 431 476 */ 432 intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request)477 void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request) 433 478 { 434 479 assert(instance); 435 480 assert(request); 436 481 437 constusb_device_request_setup_packet_t *setup_request =482 usb_device_request_setup_packet_t *setup_request = 438 483 (usb_device_request_setup_packet_t *) request->setup_buffer; 439 size_t size; 440 const void *descriptor = NULL; 441 const uint16_t setup_request_value = setup_request->value_high; 442 //(setup_request->value_low << 8); 484 uint16_t setup_request_value = setup_request->value_high; 443 485 switch (setup_request_value) 444 486 { 445 487 case USB_DESCTYPE_HUB: 446 488 usb_log_debug2("USB_DESCTYPE_HUB\n"); 447 /* Hub descriptor was generated locally */448 descriptor = instance->descriptors.hub;449 size = instance->hub_descriptor_size;450 break;489 /* Hub descriptor was generated locally. 490 * Class specific request. */ 491 TRANSFER_END_DATA(request, instance->descriptors.hub, 492 instance->hub_descriptor_size); 451 493 452 494 case USB_DESCTYPE_DEVICE: 453 495 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 454 /* Device descriptor is shared (No one should ask for it)*/ 455 descriptor = &ohci_rh_device_descriptor; 456 size = sizeof(ohci_rh_device_descriptor); 457 break; 496 /* Device descriptor is shared 497 * (No one should ask for it, as the device is already setup) 498 * Standard USB device request. */ 499 TRANSFER_END_DATA(request, &ohci_rh_device_descriptor, 500 sizeof(ohci_rh_device_descriptor)); 458 501 459 502 case USB_DESCTYPE_CONFIGURATION: 460 503 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 461 504 /* Start with configuration and add others depending on 462 * request size */ 463 descriptor = &instance->descriptors; 464 size = instance->descriptors.configuration.total_length; 465 break; 505 * request size. Standard USB request. */ 506 TRANSFER_END_DATA(request, &instance->descriptors, 507 instance->descriptors.configuration.total_length); 466 508 467 509 case USB_DESCTYPE_INTERFACE: 468 510 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 469 511 /* Use local interface descriptor. There is one and it 470 * might be modified */471 descriptor = &instance->descriptors.interface;472 size = sizeof(instance->descriptors.interface);473 break;512 * might be modified. Hub driver should not ask or this 513 * descriptor as it is not part of standard requests set. */ 514 TRANSFER_END_DATA(request, &instance->descriptors.interface, 515 sizeof(instance->descriptors.interface)); 474 516 475 517 case USB_DESCTYPE_ENDPOINT: 476 518 /* Use local endpoint descriptor. There is one 477 * it might have max_packet_size field modified*/ 519 * it might have max_packet_size field modified. Hub driver 520 * should not ask for this descriptor as it is not part 521 * of standard requests set. */ 478 522 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 479 descriptor = &instance->descriptors.endpoint; 480 size = sizeof(instance->descriptors.endpoint); 481 break; 523 TRANSFER_END_DATA(request, &instance->descriptors.endpoint, 524 sizeof(instance->descriptors.endpoint)); 482 525 483 526 default: … … 489 532 setup_request_value, setup_request->index, 490 533 setup_request->length); 491 return EINVAL; 492 } 493 if (request->buffer_size < size) { 494 size = request->buffer_size; 495 } 496 497 memcpy(request->buffer, descriptor, size); 498 TRANSFER_OK(size); 534 TRANSFER_END(request, EINVAL); 535 } 536 537 TRANSFER_END(request, ENOTSUP); 499 538 } 500 539 /*----------------------------------------------------------------------------*/ … … 604 643 * @return error code 605 644 */ 606 intset_feature(const rh_t *instance, usb_transfer_batch_t *request)645 void set_feature(const rh_t *instance, usb_transfer_batch_t *request) 607 646 { 608 647 assert(instance); 609 648 assert(request); 610 649 611 constusb_device_request_setup_packet_t *setup_request =650 usb_device_request_setup_packet_t *setup_request = 612 651 (usb_device_request_setup_packet_t *) request->setup_buffer; 613 652 switch (setup_request->request_type) … … 615 654 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 616 655 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 617 returnset_feature_port(instance,656 int ret = set_feature_port(instance, 618 657 setup_request->value, setup_request->index); 658 TRANSFER_END(request, ret); 619 659 620 660 case USB_HUB_REQ_TYPE_SET_HUB_FEATURE: … … 623 663 * features. It makes no sense to SET either. */ 624 664 usb_log_error("Invalid HUB set feature request.\n"); 625 return ENOTSUP; 665 TRANSFER_END(request, ENOTSUP); 666 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 626 667 default: 627 668 usb_log_error("Invalid set feature request type: %d\n", 628 669 setup_request->request_type); 629 return EINVAL;670 TRANSFER_END(request, ENOTSUP); 630 671 } 631 672 } … … 640 681 * @return error code 641 682 */ 642 intclear_feature(const rh_t *instance, usb_transfer_batch_t *request)683 void clear_feature(const rh_t *instance, usb_transfer_batch_t *request) 643 684 { 644 685 assert(instance); 645 686 assert(request); 646 687 647 constusb_device_request_setup_packet_t *setup_request =688 usb_device_request_setup_packet_t *setup_request = 648 689 (usb_device_request_setup_packet_t *) request->setup_buffer; 649 650 request->transfered_size = 0;651 690 652 691 switch (setup_request->request_type) … … 654 693 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 655 694 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 656 returnclear_feature_port(instance,695 int ret = clear_feature_port(instance, 657 696 setup_request->value, setup_request->index); 697 TRANSFER_END(request, ret); 658 698 659 699 case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE: … … 668 708 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 669 709 instance->registers->rh_status = RHS_OCIC_FLAG; 670 TRANSFER_ OK(0);710 TRANSFER_END(request, EOK); 671 711 } 712 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 672 713 default: 673 714 usb_log_error("Invalid clear feature request type: %d\n", 674 715 setup_request->request_type); 675 return EINVAL;716 TRANSFER_END(request, ENOTSUP); 676 717 } 677 718 } … … 695 736 * @return error code 696 737 */ 697 intcontrol_request(rh_t *instance, usb_transfer_batch_t *request)738 void control_request(rh_t *instance, usb_transfer_batch_t *request) 698 739 { 699 740 assert(instance); … … 702 743 if (!request->setup_buffer) { 703 744 usb_log_error("Root hub received empty transaction!"); 704 return EINVAL;745 TRANSFER_END(request, EBADMEM); 705 746 } 706 747 707 748 if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) { 708 749 usb_log_error("Setup packet too small\n"); 709 return EOVERFLOW;750 TRANSFER_END(request, EOVERFLOW); 710 751 } 711 752 712 753 usb_log_debug2("CTRL packet: %s.\n", 713 754 usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8)); 714 constusb_device_request_setup_packet_t *setup_request =755 usb_device_request_setup_packet_t *setup_request = 715 756 (usb_device_request_setup_packet_t *) request->setup_buffer; 716 757 switch (setup_request->request) … … 718 759 case USB_DEVREQ_GET_STATUS: 719 760 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 720 return get_status(instance, request); 761 get_status(instance, request); 762 break; 721 763 722 764 case USB_DEVREQ_GET_DESCRIPTOR: 723 765 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 724 return get_descriptor(instance, request); 766 get_descriptor(instance, request); 767 break; 725 768 726 769 case USB_DEVREQ_GET_CONFIGURATION: 727 770 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 728 if (request->buffer_size != 1)729 return EINVAL;730 request->buffer[0]= 1;731 TRANSFER_ OK(1);771 if (request->buffer_size == 0) 772 TRANSFER_END(request, EOVERFLOW); 773 uint8_t config = 1; 774 TRANSFER_END_DATA(request, &config, sizeof(config)); 732 775 733 776 case USB_DEVREQ_CLEAR_FEATURE: 734 usb_log_debug2(" Processing request without "735 "additional data\n");736 return clear_feature(instance, request);777 usb_log_debug2("USB_DEVREQ_CLEAR_FEATURE\n"); 778 clear_feature(instance, request); 779 break; 737 780 738 781 case USB_DEVREQ_SET_FEATURE: 739 usb_log_debug2(" Processing request without "740 "additional data\n");741 return set_feature(instance, request);782 usb_log_debug2("USB_DEVREQ_SET_FEATURE\n"); 783 set_feature(instance, request); 784 break; 742 785 743 786 case USB_DEVREQ_SET_ADDRESS: 744 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 787 usb_log_debug("USB_DEVREQ_SET_ADDRESS: %u\n", 788 setup_request->value); 789 if (uint16_usb2host(setup_request->value) > 127) 790 TRANSFER_END(request, EINVAL); 791 745 792 instance->address = setup_request->value; 746 TRANSFER_ OK(0);793 TRANSFER_END(request, EOK); 747 794 748 795 case USB_DEVREQ_SET_CONFIGURATION: 749 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n"); 750 /* We don't need to do anything */ 751 TRANSFER_OK(0); 752 753 case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */ 796 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n", 797 setup_request->value); 798 /* We have only one configuration, it's number is 1 */ 799 if (uint16_usb2host(setup_request->value) != 1) 800 TRANSFER_END(request, EINVAL); 801 TRANSFER_END(request, EOK); 802 803 /* Both class specific and std is optional for hubs */ 804 case USB_DEVREQ_SET_DESCRIPTOR: 805 /* Hubs have only one interface GET/SET is not supported */ 806 case USB_DEVREQ_GET_INTERFACE: 807 case USB_DEVREQ_SET_INTERFACE: 754 808 default: 809 /* Hub class GET_STATE(2) falls in here too. */ 755 810 usb_log_error("Received unsupported request: %d.\n", 756 811 setup_request->request); 757 return ENOTSUP; 758 } 759 } 760 812 TRANSFER_END(request, ENOTSUP); 813 } 814 } 761 815 /** 762 816 * @} -
uspace/drv/bus/usb/ohci/utils/malloc32.h
rba72f2b r6843a9c 37 37 #include <assert.h> 38 38 #include <malloc.h> 39 #include <unistd.h> 39 40 #include <errno.h> 40 41 #include <mem.h> … … 56 57 uintptr_t result; 57 58 int ret = as_get_physical_mapping(addr, &result); 58 59 59 60 if (ret != EOK) 60 61 return 0; 61 return (result | ((uintptr_t)addr & 0xfff)); 62 63 return result; 62 64 } 63 65 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/uhci/Makefile
rba72f2b r6843a9c 44 44 hc.c \ 45 45 main.c \ 46 pci.c \46 res.c \ 47 47 root_hub.c \ 48 48 transfer_list.c \ -
uspace/drv/bus/usb/uhci/hc.c
rba72f2b r6843a9c 48 48 (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT) 49 49 50 51 static const irq_cmd_t uhci_irq_commands[] = 52 { 50 static const irq_pio_range_t uhci_irq_pio_ranges[] = { 51 { 52 .base = 0, /* filled later */ 53 .size = sizeof(uhci_regs_t) 54 } 55 }; 56 57 static const irq_cmd_t uhci_irq_commands[] = { 53 58 { .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/}, 54 59 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, … … 68 73 69 74 /*----------------------------------------------------------------------------*/ 75 /** Get number of PIO ranges used in IRQ code. 76 * @return Number of ranges. 77 */ 78 size_t hc_irq_pio_range_count(void) 79 { 80 return sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t); 81 } 82 /*----------------------------------------------------------------------------*/ 70 83 /** Get number of commands used in IRQ code. 71 84 * @return Number of commands. … … 76 89 } 77 90 /*----------------------------------------------------------------------------*/ 78 /** Generate IRQ code commands. 79 * @param[out] cmds Place to store the commands. 80 * @param[in] cmd_size Size of the place (bytes). 91 /** Generate IRQ code. 92 * @param[out] ranges PIO ranges buffer. 93 * @param[in] ranges_size Size of the ranges buffer (bytes). 94 * @param[out] cmds Commands buffer. 95 * @param[in] cmds_size Size of the commands buffer (bytes). 81 96 * @param[in] regs Physical address of device's registers. 82 97 * @param[in] reg_size Size of the register area (bytes). … … 84 99 * @return Error code. 85 100 */ 86 int hc_get_irq_commands( 87 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size) 88 { 89 if (cmd_size < sizeof(uhci_irq_commands) 90 || reg_size < sizeof(uhci_regs_t)) 101 int 102 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[], 103 size_t cmds_size, uintptr_t regs, size_t reg_size) 104 { 105 if ((ranges_size < sizeof(uhci_irq_pio_ranges)) || 106 (cmds_size < sizeof(uhci_irq_commands)) || 107 (reg_size < sizeof(uhci_regs_t))) 91 108 return EOVERFLOW; 92 109 93 uhci_regs_t *registers = (uhci_regs_t*)regs; 110 memcpy(ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges)); 111 ranges[0].base = regs; 94 112 95 113 memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands)); 96 97 cmds[0].addr = (void*)®isters->usbsts; 98 cmds[3].addr = (void*)®isters->usbsts; 114 uhci_regs_t *registers = (uhci_regs_t *) regs; 115 cmds[0].addr = ®isters->usbsts; 116 cmds[3].addr = ®isters->usbsts; 117 99 118 return EOK; 100 119 } … … 130 149 uhci_transfer_batch_t *batch = 131 150 uhci_transfer_batch_from_link(item); 132 uhci_transfer_batch_ call_dispose(batch);151 uhci_transfer_batch_finish_dispose(batch); 133 152 } 134 153 } … … 192 211 "Device registers at %p (%zuB) accessible.\n", io, reg_size); 193 212 194 ret = hc d_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,195 bandwidth_count_usb11);196 CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",213 ret = hc_init_mem_structures(instance); 214 CHECK_RET_RETURN(ret, 215 "Failed to initialize UHCI memory structures: %s.\n", 197 216 str_error(ret)); 217 218 #undef CHECK_RET_RETURN 219 220 hcd_init(&instance->generic, USB_SPEED_FULL, 221 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 198 222 199 223 instance->generic.private_data = instance; 200 224 instance->generic.schedule = hc_schedule; 201 225 instance->generic.ep_add_hook = NULL; 202 203 #undef CHECK_RET_DEST_FUN_RETURN204 205 ret = hc_init_mem_structures(instance);206 if (ret != EOK) {207 usb_log_error(208 "Failed to initialize UHCI memory structures: %s.\n",209 str_error(ret));210 hcd_destroy(&instance->generic);211 return ret;212 }213 226 214 227 hc_init_hw(instance); -
uspace/drv/bus/usb/uhci/hc.h
rba72f2b r6843a9c 121 121 } hc_t; 122 122 123 size_t hc_irq_pio_range_count(void); 123 124 size_t hc_irq_cmd_count(void); 124 int hc_get_irq_co mmands(125 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);125 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t, 126 size_t); 126 127 void hc_interrupt(hc_t *instance, uint16_t status); 127 128 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts); -
uspace/drv/bus/usb/uhci/main.c
rba72f2b r6843a9c 43 43 #define NAME "uhci" 44 44 45 static int uhci_ add_device(ddf_dev_t *device);45 static int uhci_dev_add(ddf_dev_t *device); 46 46 /*----------------------------------------------------------------------------*/ 47 47 static driver_ops_t uhci_driver_ops = { 48 . add_device = uhci_add_device,48 .dev_add = uhci_dev_add, 49 49 }; 50 50 /*----------------------------------------------------------------------------*/ … … 59 59 * @return Error code. 60 60 */ 61 int uhci_ add_device(ddf_dev_t *device)61 int uhci_dev_add(ddf_dev_t *device) 62 62 { 63 usb_log_debug2("uhci_ add_device() called\n");63 usb_log_debug2("uhci_dev_add() called\n"); 64 64 assert(device); 65 65 -
uspace/drv/bus/usb/uhci/res.c
rba72f2b r6843a9c 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** 30 29 * @addtogroup drvusbuhcihc … … 39 38 #include <assert.h> 40 39 #include <devman.h> 41 #include <device/hw_res.h> 40 #include <device/hw_res_parsed.h> 41 #include <device/pci.h> 42 42 43 #include <usb/debug.h> 44 #include <pci_dev_iface.h> 45 46 #include "pci.h" 43 #include "res.h" 47 44 48 45 /** Get I/O address of registers and IRQ for given device. … … 54 51 * @return Error code. 55 52 */ 56 int pci_get_my_registers(const ddf_dev_t *dev,53 int get_my_registers(const ddf_dev_t *dev, 57 54 uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no) 58 55 { 59 56 assert(dev); 60 assert(io_reg_address);61 assert(io_reg_size);62 assert(irq_no);63 57 64 58 async_sess_t *parent_sess = … … 68 62 return ENOMEM; 69 63 70 hw_resource_list_t hw_resources; 71 const int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 64 hw_res_list_parsed_t hw_res; 65 hw_res_list_parsed_init(&hw_res); 66 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0); 72 67 async_hangup(parent_sess); 73 if (r c!= EOK) {74 return r c;68 if (ret != EOK) { 69 return ret; 75 70 } 76 71 77 uintptr_t io_address = 0; 78 size_t io_size = 0; 79 bool io_found = false; 72 /* We want one irq and one io range. */ 73 if (hw_res.irqs.count != 1 || hw_res.io_ranges.count != 1) { 74 hw_res_list_parsed_clean(&hw_res); 75 return EINVAL; 76 } 80 77 81 int irq = 0; 82 bool irq_found = false; 78 if (io_reg_address) 79 *io_reg_address = hw_res.io_ranges.ranges[0].address; 80 if (io_reg_size) 81 *io_reg_size = hw_res.io_ranges.ranges[0].size; 82 if (irq_no) 83 *irq_no = hw_res.irqs.irqs[0]; 83 84 84 for (size_t i = 0; i < hw_resources.count; i++) { 85 const hw_resource_t *res = &hw_resources.resources[i]; 86 switch (res->type) { 87 case INTERRUPT: 88 irq = res->res.interrupt.irq; 89 irq_found = true; 90 usb_log_debug2("Found interrupt: %d.\n", irq); 91 break; 92 case IO_RANGE: 93 io_address = res->res.io_range.address; 94 io_size = res->res.io_range.size; 95 usb_log_debug2("Found io: %" PRIx64" %zu.\n", 96 res->res.io_range.address, res->res.io_range.size); 97 io_found = true; 98 break; 99 default: 100 break; 101 } 102 } 103 free(hw_resources.resources); 104 105 if (!io_found || !irq_found) 106 return ENOENT; 107 108 *io_reg_address = io_address; 109 *io_reg_size = io_size; 110 *irq_no = irq; 111 85 hw_res_list_parsed_clean(&hw_res); 112 86 return EOK; 113 87 } 114 /*----------------------------------------------------------------------------*/ 88 115 89 /** Call the PCI driver with a request to enable interrupts 116 90 * … … 118 92 * @return Error code. 119 93 */ 120 int pci_enable_interrupts(const ddf_dev_t *device)94 int enable_interrupts(const ddf_dev_t *device) 121 95 { 122 96 async_sess_t *parent_sess = … … 131 105 return enabled ? EOK : EIO; 132 106 } 133 /*----------------------------------------------------------------------------*/ 107 134 108 /** Call the PCI driver with a request to clear legacy support register 135 109 * … … 137 111 * @return Error code. 138 112 */ 139 int pci_disable_legacy(const ddf_dev_t *device)113 int disable_legacy(const ddf_dev_t *device) 140 114 { 141 115 assert(device); 142 116 143 async_sess_t *parent_sess = 144 devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle, 145 IPC_FLAG_BLOCKING); 117 async_sess_t *parent_sess = devman_parent_device_connect( 118 EXCHANGE_SERIALIZE, device->handle, IPC_FLAG_BLOCKING); 146 119 if (!parent_sess) 147 120 return ENOMEM; 148 121 149 /* See UHCI design guide for these values p.45, 150 * write all WC bits in USB legacy register */ 151 const sysarg_t address = 0xc0; 152 const sysarg_t value = 0xaf00; 122 /* See UHCI design guide page 45 for these values. 123 * Write all WC bits in USB legacy register */ 124 const int rc = pci_config_space_write_16(parent_sess, 0xc0, 0xaf00); 153 125 154 async_exch_t *exch = async_exchange_begin(parent_sess);155 156 const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE),157 IPC_M_CONFIG_SPACE_WRITE_16, address, value);158 159 async_exchange_end(exch);160 126 async_hangup(parent_sess); 161 162 127 return rc; 163 128 } -
uspace/drv/bus/usb/uhci/res.h
rba72f2b r6843a9c 38 38 #include <ddf/driver.h> 39 39 40 int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);41 int pci_enable_interrupts(const ddf_dev_t *);42 int pci_disable_legacy(const ddf_dev_t *);40 int get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *); 41 int enable_interrupts(const ddf_dev_t *); 42 int disable_legacy(const ddf_dev_t *); 43 43 44 44 #endif -
uspace/drv/bus/usb/uhci/transfer_list.c
rba72f2b r6843a9c 110 110 assert(instance); 111 111 assert(uhci_batch); 112 usb_log_debug2(" Queue %s: Adding batch(%p).\n", instance->name,113 uhci_batch->usb_batch );112 usb_log_debug2("Batch %p adding to queue %s.\n", 113 uhci_batch->usb_batch, instance->name); 114 114 115 115 fibril_mutex_lock(&instance->guard); … … 139 139 list_append(&uhci_batch->link, &instance->batch_list); 140 140 141 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",142 uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),143 instance->name);141 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT 142 " scheduled in queue %s.\n", uhci_batch->usb_batch, 143 USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch), instance->name); 144 144 fibril_mutex_unlock(&instance->guard); 145 145 } … … 184 184 uhci_transfer_batch_from_link(current); 185 185 transfer_list_remove_batch(instance, batch); 186 batch->usb_batch->error = EINTR; 187 uhci_transfer_batch_call_dispose(batch); 186 uhci_transfer_batch_abort(batch); 188 187 } 189 188 fibril_mutex_unlock(&instance->guard); … … 206 205 assert(fibril_mutex_is_locked(&instance->guard)); 207 206 208 usb_log_debug2(" Queue %s: removing batch(%p).\n",209 instance->name, uhci_batch->usb_batch);207 usb_log_debug2("Batch %p removing from queue %s.\n", 208 uhci_batch->usb_batch, instance->name); 210 209 211 210 /* Assume I'm the first */ … … 229 228 list_remove(&uhci_batch->link); 230 229 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) " 231 "from %s, next: %x.\n", 232 uhci_batch,USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),230 "from %s, next: %x.\n", uhci_batch->usb_batch, 231 USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch), 233 232 qpos, instance->name, uhci_batch->qh->next); 234 233 } -
uspace/drv/bus/usb/uhci/uhci.c
rba72f2b r6843a9c 41 41 42 42 #include "uhci.h" 43 #include "pci.h" 44 43 44 #include "res.h" 45 45 #include "hc.h" 46 46 #include "root_hub.h" … … 49 49 * and USB root hub */ 50 50 typedef struct uhci { 51 /** Pointer to DDF represen ation of UHCI host controller */51 /** Pointer to DDF representation of UHCI host controller */ 52 52 ddf_fun_t *hc_fun; 53 /** Pointer to DDF represen ation of UHCI root hub */53 /** Pointer to DDF representation of UHCI root hub */ 54 54 ddf_fun_t *rh_fun; 55 55 56 /** Internal driver's represen ation of UHCI host controller */56 /** Internal driver's representation of UHCI host controller */ 57 57 hc_t hc; 58 /** Internal driver's represen ation of UHCI root hub */58 /** Internal driver's representation of UHCI root hub */ 59 59 rh_t rh; 60 60 } uhci_t; … … 89 89 }; 90 90 /*----------------------------------------------------------------------------*/ 91 /** Get address of the device identified by handle.92 *93 * @param[in] fun DDF instance of the function to use.94 * @param[in] handle DDF handle of the driver seeking its USB address.95 * @param[out] address Found address.96 */97 static int usb_iface_get_address(98 ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)99 {100 assert(fun);101 usb_device_manager_t *manager =102 &dev_to_uhci(fun->dev)->hc.generic.dev_manager;103 const usb_address_t addr = usb_device_manager_find(manager, handle);104 105 if (addr < 0) {106 return addr;107 }108 109 if (address != NULL) {110 *address = addr;111 }112 113 return EOK;114 }115 /*----------------------------------------------------------------------------*/116 91 /** Gets handle of the respective hc. 117 92 * … … 134 109 static usb_iface_t usb_iface = { 135 110 .get_hc_handle = usb_iface_get_hc_handle, 136 .get_address = usb_iface_get_address137 111 }; 138 112 /*----------------------------------------------------------------------------*/ … … 174 148 int device_setup_uhci(ddf_dev_t *device) 175 149 { 176 assert(device); 177 uhci_t *instance = malloc(sizeof(uhci_t)); 150 if (!device) 151 return EBADMEM; 152 153 uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t)); 178 154 if (instance == NULL) { 179 155 usb_log_error("Failed to allocate OHCI driver.\n"); … … 184 160 if (ret != EOK) { \ 185 161 if (instance->hc_fun) \ 186 instance->hc_fun->ops = NULL; \187 162 instance->hc_fun->driver_data = NULL; \ 188 163 ddf_fun_destroy(instance->hc_fun); \ 189 164 if (instance->rh_fun) {\ 190 instance->rh_fun->ops = NULL; \191 165 instance->rh_fun->driver_data = NULL; \ 192 166 ddf_fun_destroy(instance->rh_fun); \ 193 167 } \ 194 device->driver_data = NULL; \195 168 usb_log_error(message); \ 196 169 return ret; \ … … 214 187 int irq = 0; 215 188 216 ret = pci_get_my_registers(device, ®_base, ®_size, &irq);189 ret = get_my_registers(device, ®_base, ®_size, &irq); 217 190 CHECK_RET_DEST_FREE_RETURN(ret, 218 191 "Failed to get I/O addresses for %" PRIun ": %s.\n", … … 221 194 (void *) reg_base, reg_size, irq); 222 195 223 ret = pci_disable_legacy(device);196 ret = disable_legacy(device); 224 197 CHECK_RET_DEST_FREE_RETURN(ret, 225 198 "Failed to disable legacy USB: %s.\n", str_error(ret)); 226 199 227 const size_t cmd_count = hc_irq_cmd_count(); 228 irq_cmd_t irq_cmds[cmd_count]; 229 ret = 230 hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size); 200 const size_t ranges_count = hc_irq_pio_range_count(); 201 const size_t cmds_count = hc_irq_cmd_count(); 202 irq_pio_range_t irq_ranges[ranges_count]; 203 irq_cmd_t irq_cmds[cmds_count]; 204 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 205 sizeof(irq_cmds), reg_base, reg_size); 231 206 CHECK_RET_DEST_FREE_RETURN(ret, 232 207 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 233 208 234 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds }; 209 irq_code_t irq_code = { 210 .rangecount = ranges_count, 211 .ranges = irq_ranges, 212 .cmdcount = cmds_count, 213 .cmds = irq_cmds 214 }; 235 215 236 216 /* Register handler to avoid interrupt lockup */ … … 240 220 241 221 bool interrupts = false; 242 ret = pci_enable_interrupts(device);222 ret = enable_interrupts(device); 243 223 if (ret != EOK) { 244 224 usb_log_warning("Failed to enable interrupts: %s." … … 253 233 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 254 234 255 device->driver_data = instance;256 257 235 #define CHECK_RET_FINI_RETURN(ret, message...) \ 258 236 if (ret != EOK) { \ -
uspace/drv/bus/usb/uhci/uhci.ma
rba72f2b r6843a9c 1 10 pci/ven=8086&dev=7020 2 10 pci/ven=8086&dev=7112 3 4 10 pci/ven=8086&dev=27c8 5 10 pci/ven=8086&dev=27c9 6 10 pci/ven=8086&dev=27ca 7 10 pci/ven=8086&dev=27cb 8 9 10 pci/ven=8086&dev=2830 10 10 pci/ven=8086&dev=2831 11 10 pci/ven=8086&dev=2832 12 10 pci/ven=8086&dev=2834 13 10 pci/ven=8086&dev=2835 14 15 10 pci/ven=8086&dev=2934 16 10 pci/ven=8086&dev=2935 17 10 pci/ven=8086&dev=2936 18 10 pci/ven=8086&dev=2937 19 10 pci/ven=8086&dev=2938 20 10 pci/ven=8086&dev=2939 21 22 10 pci/ven=8086&dev=24c2 23 10 pci/ven=8086&dev=24c4 24 10 pci/ven=8086&dev=24c7 25 26 10 pci/ven=8086&dev=2688 27 10 pci/ven=8086&dev=2689 28 10 pci/ven=8086&dev=268a 29 10 pci/ven=8086&dev=268b 1 10 pci/class=0c&subclass=03&progif=00 -
uspace/drv/bus/usb/uhci/uhci_batch.c
rba72f2b r6843a9c 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h> 36 37 37 38 #include <usb/usb.h> … … 45 46 #define DEFAULT_ERROR_COUNT 3 46 47 48 /** Safely destructs uhci_transfer_batch_t structure. 49 * 50 * @param[in] uhci_batch Instance to destroy. 51 */ 47 52 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch) 48 53 { 49 54 if (uhci_batch) { 50 usb_transfer_batch_d ispose(uhci_batch->usb_batch);55 usb_transfer_batch_destroy(uhci_batch->usb_batch); 51 56 free32(uhci_batch->device_buffer); 52 57 free(uhci_batch); … … 54 59 } 55 60 /*----------------------------------------------------------------------------*/ 56 /** Safely destructs uhci_transfer_batch_t structure57 * 58 * @param[in] uhci_batch Instance to destroy.59 */ 60 void uhci_transfer_batch_ call_dispose(uhci_transfer_batch_t *uhci_batch)61 /** Finishes usb_transfer_batch and destroys the structure. 62 * 63 * @param[in] uhci_batch Instance to finish and destroy. 64 */ 65 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch) 61 66 { 62 67 assert(uhci_batch); 63 68 assert(uhci_batch->usb_batch); 64 69 usb_transfer_batch_finish(uhci_batch->usb_batch, 65 uhci_transfer_batch_data_buffer(uhci_batch), 66 uhci_batch->usb_batch->buffer_size); 70 uhci_transfer_batch_data_buffer(uhci_batch)); 67 71 uhci_transfer_batch_dispose(uhci_batch); 68 72 } 69 73 /*----------------------------------------------------------------------------*/ 74 /** Transfer batch setup table. */ 70 75 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t); 71 76 /*----------------------------------------------------------------------------*/ 72 77 /** Allocate memory and initialize internal data structure. 73 78 * 74 * @param[in] fun DDF function to pass to callback. 75 * @param[in] ep Communication target 76 * @param[in] buffer Data source/destination. 77 * @param[in] buffer_size Size of the buffer. 78 * @param[in] setup_buffer Setup data source (if not NULL) 79 * @param[in] setup_size Size of setup_buffer (should be always 8) 80 * @param[in] func_in function to call on inbound transfer completion 81 * @param[in] func_out function to call on outbound transfer completion 82 * @param[in] arg additional parameter to func_in or func_out 79 * @param[in] usb_batch Pointer to generic USB batch structure. 83 80 * @return Valid pointer if all structures were successfully created, 84 81 * NULL otherwise. … … 156 153 * is reached. 157 154 */ 158 bool uhci_transfer_batch_is_complete( uhci_transfer_batch_t *uhci_batch)155 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch) 159 156 { 160 157 assert(uhci_batch); … … 177 174 assert(uhci_batch->usb_batch->ep != NULL); 178 175 179 usb_log_debug("Batch (%p) found error TD(%zu):%"176 usb_log_debug("Batch %p found error TD(%zu->%p):%" 180 177 PRIx32 ".\n", uhci_batch->usb_batch, i, 181 uhci_batch->tds[i].status);178 &uhci_batch->tds[i], uhci_batch->tds[i].status); 182 179 td_print_status(&uhci_batch->tds[i]); 183 180 … … 200 197 } 201 198 /*----------------------------------------------------------------------------*/ 199 /** Direction to pid conversion table */ 202 200 static const usb_packet_id direction_pids[] = { 203 201 [USB_DIRECTION_IN] = USB_PID_IN, … … 237 235 238 236 while (remain_size > 0) { 239 const size_t packet_size = 240 (remain_size < mps) ? remain_size : mps; 237 const size_t packet_size = min(remain_size, mps); 241 238 242 239 const td_t *next_td = (td + 1 < uhci_batch->td_count) … … 309 306 310 307 while (remain_size > 0) { 311 const size_t packet_size = 312 (remain_size < mps) ? remain_size : mps; 308 const size_t packet_size = min(remain_size, mps); 313 309 314 310 td_init( -
uspace/drv/bus/usb/uhci/uhci_batch.h
rba72f2b r6843a9c 61 61 62 62 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch); 63 void uhci_transfer_batch_ call_dispose(uhci_transfer_batch_t *uhci_batch);64 bool uhci_transfer_batch_is_complete( uhci_transfer_batch_t *uhci_batch);63 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch); 64 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch); 65 65 66 /** Get offset to setup buffer accessible to the HC hw. 67 * @param uhci_batch UHCI batch structure. 68 * @return Pointer to the setup buffer. 69 */ 66 70 static inline void * uhci_transfer_batch_setup_buffer( 67 71 const uhci_transfer_batch_t *uhci_batch) … … 73 77 } 74 78 /*----------------------------------------------------------------------------*/ 79 /** Get offset to data buffer accessible to the HC hw. 80 * @param uhci_batch UHCI batch structure. 81 * @return Pointer to the data buffer. 82 */ 75 83 static inline void * uhci_transfer_batch_data_buffer( 76 84 const uhci_transfer_batch_t *uhci_batch) … … 82 90 } 83 91 /*----------------------------------------------------------------------------*/ 92 /** Aborts the batch. 93 * Sets error to EINTR and size off transferd data to 0, before finishing the 94 * batch. 95 * @param uhci_batch Batch to abort. 96 */ 97 static inline void uhci_transfer_batch_abort(uhci_transfer_batch_t *uhci_batch) 98 { 99 assert(uhci_batch); 100 assert(uhci_batch->usb_batch); 101 uhci_batch->usb_batch->error = EINTR; 102 uhci_batch->usb_batch->transfered_size = 0; 103 uhci_transfer_batch_finish_dispose(uhci_batch); 104 } 105 /*----------------------------------------------------------------------------*/ 106 /** Linked list conversion wrapper. 107 * @param l Linked list link. 108 * @return Pointer to the uhci batch structure. 109 */ 84 110 static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l) 85 111 { -
uspace/drv/bus/usb/uhci/utils/malloc32.h
rba72f2b r6843a9c 36 36 37 37 #include <assert.h> 38 #include <unistd.h> 38 39 #include <errno.h> 39 40 #include <malloc.h> … … 54 55 if (addr == NULL) 55 56 return 0; 56 57 57 58 uintptr_t result; 58 59 const int ret = as_get_physical_mapping(addr, &result); 59 60 if (ret != EOK) 60 61 return 0; 61 return (result | ((uintptr_t)addr & 0xfff)); 62 63 return result; 62 64 } 63 65 /*----------------------------------------------------------------------------*/ … … 97 99 static inline void * get_page(void) 98 100 { 99 void *free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE); 100 if (free_address == 0) 101 void *address = as_area_create(AS_AREA_ANY, UHCI_REQUIRED_PAGE_SIZE, 102 AS_AREA_READ | AS_AREA_WRITE); 103 if (address == AS_MAP_FAILED) 101 104 return NULL; 102 void *address = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE, 103 AS_AREA_READ | AS_AREA_WRITE); 104 if (address != free_address) 105 return NULL; 105 106 106 return address; 107 107 } -
uspace/drv/bus/usb/uhcirh/main.c
rba72f2b r6843a9c 36 36 #include <ddf/driver.h> 37 37 #include <devman.h> 38 #include <device/hw_res .h>38 #include <device/hw_res_parsed.h> 39 39 #include <errno.h> 40 40 #include <str_error.h> … … 51 51 uintptr_t *io_reg_address, size_t *io_reg_size); 52 52 53 static int uhci_rh_ add_device(ddf_dev_t *device);53 static int uhci_rh_dev_add(ddf_dev_t *device); 54 54 55 55 static driver_ops_t uhci_rh_driver_ops = { 56 . add_device = uhci_rh_add_device,56 .dev_add = uhci_rh_dev_add, 57 57 }; 58 58 … … 82 82 * @return Error code. 83 83 */ 84 static int uhci_rh_ add_device(ddf_dev_t *device)84 static int uhci_rh_dev_add(ddf_dev_t *device) 85 85 { 86 86 if (!device) 87 87 return EINVAL; 88 88 89 usb_log_debug2("uhci_rh_ add_device(handle=%" PRIun ")\n",89 usb_log_debug2("uhci_rh_dev_add(handle=%" PRIun ")\n", 90 90 device->handle); 91 91 … … 136 136 { 137 137 assert(dev); 138 138 139 139 async_sess_t *parent_sess = 140 140 devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, … … 142 142 if (!parent_sess) 143 143 return ENOMEM; 144 145 hw_resource_list_t hw_resources; 146 const int ret = hw_res_get_resource_list(parent_sess, &hw_resources); 144 145 hw_res_list_parsed_t hw_res; 146 hw_res_list_parsed_init(&hw_res); 147 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0); 148 async_hangup(parent_sess); 147 149 if (ret != EOK) { 148 async_hangup(parent_sess);149 150 return ret; 150 151 } 151 152 uintptr_t io_address = 0; 153 size_t io_size = 0; 154 bool io_found = false; 155 156 size_t i = 0; 157 for (; i < hw_resources.count; i++) { 158 hw_resource_t *res = &hw_resources.resources[i]; 159 if (res->type == IO_RANGE) { 160 io_address = res->res.io_range.address; 161 io_size = res->res.io_range.size; 162 io_found = true; 163 } 164 152 153 if (hw_res.io_ranges.count != 1) { 154 hw_res_list_parsed_clean(&hw_res); 155 return EINVAL; 165 156 } 166 async_hangup(parent_sess); 167 168 if (!io_found) 169 return ENOENT; 170 157 171 158 if (io_reg_address != NULL) 172 *io_reg_address = io_address;173 159 *io_reg_address = hw_res.io_ranges.ranges[0].address; 160 174 161 if (io_reg_size != NULL) 175 *io_reg_size = io_size; 176 162 *io_reg_size = hw_res.io_ranges.ranges[0].size; 163 164 hw_res_list_parsed_clean(&hw_res); 177 165 return EOK; 178 166 } -
uspace/drv/bus/usb/uhcirh/port.c
rba72f2b r6843a9c 37 37 #include <str_error.h> 38 38 #include <async.h> 39 #include <devman.h>40 39 41 40 #include <usb/usb.h> /* usb_address_t */ … … 260 259 { 261 260 assert(port); 262 assert(usb_hc_connection_is_opened(&port->hc_connection));263 261 264 262 usb_log_debug("%s: Detected new device.\n", port->id_string); … … 314 312 315 313 /* Driver stopped, free used address */ 316 ret = usb_h c_unregister_device(&port->hc_connection,317 port->attached_device.address);314 ret = usb_hub_unregister_device(&port->hc_connection, 315 &port->attached_device); 318 316 if (ret != EOK) { 319 317 usb_log_error("%s: Failed to unregister address of removed " -
uspace/drv/bus/usb/usbflbk/main.c
rba72f2b r6843a9c 93 93 return EOK; 94 94 } 95 95 96 /** USB fallback driver ops. */ 96 static usb_driver_ops_t usbfallback_driver_ops = {97 static const usb_driver_ops_t usbfallback_driver_ops = { 97 98 .device_add = usbfallback_device_add, 99 .device_rem = usbfallback_device_gone, 98 100 .device_gone = usbfallback_device_gone, 99 101 }; 100 102 101 103 /** USB fallback driver. */ 102 static usb_driver_t usbfallback_driver = {104 static const usb_driver_t usbfallback_driver = { 103 105 .name = NAME, 104 106 .ops = &usbfallback_driver_ops, -
uspace/drv/bus/usb/usbhid/generic/hiddev.c
rba72f2b r6843a9c 61 61 62 62 /*----------------------------------------------------------------------------*/ 63 64 63 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun); 65 66 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 64 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 67 65 size_t size, size_t *act_size, int *event_nr, unsigned int flags); 68 69 66 static int usb_generic_hid_client_connected(ddf_fun_t *fun); 70 71 67 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun); 72 73 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 68 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 74 69 size_t size, size_t *actual_size); 75 76 /*----------------------------------------------------------------------------*/ 77 70 /*----------------------------------------------------------------------------*/ 78 71 static usbhid_iface_t usb_generic_iface = { 79 72 .get_event = usb_generic_hid_get_event, … … 82 75 .get_report_descriptor = usb_generic_get_report_descriptor 83 76 }; 84 77 /*----------------------------------------------------------------------------*/ 85 78 static ddf_dev_ops_t usb_generic_hid_ops = { 86 79 .interfaces[USBHID_DEV_IFACE] = &usb_generic_iface, 87 80 .open = usb_generic_hid_client_connected 88 81 }; 89 90 /*----------------------------------------------------------------------------*/ 91 82 /*----------------------------------------------------------------------------*/ 92 83 static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun) 93 84 { … … 99 90 } 100 91 101 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;92 const usb_hid_dev_t *hid_dev = fun->driver_data; 102 93 103 94 usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n", … … 106 97 return hid_dev->max_input_report_size; 107 98 } 108 109 /*----------------------------------------------------------------------------*/ 110 111 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 99 /*----------------------------------------------------------------------------*/ 100 static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 112 101 size_t size, size_t *act_size, int *event_nr, unsigned int flags) 113 102 { … … 120 109 } 121 110 122 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;111 const usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data; 123 112 124 113 if (hid_dev->input_report_size > size) { 125 usb_log_debug("input_report_size > size (%zu, %zu)\n", 114 usb_log_debug("input_report_size > size (%zu, %zu)\n", 126 115 hid_dev->input_report_size, size); 127 116 return EINVAL; // TODO: other error code … … 129 118 130 119 /*! @todo This should probably be somehow atomic. */ 131 memcpy(buffer, hid_dev->input_report, 120 memcpy(buffer, hid_dev->input_report, 132 121 hid_dev->input_report_size); 133 122 *act_size = hid_dev->input_report_size; … … 138 127 return EOK; 139 128 } 140 141 /*----------------------------------------------------------------------------*/ 142 129 /*----------------------------------------------------------------------------*/ 143 130 static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun) 144 131 { … … 150 137 } 151 138 152 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;153 154 usb_log_debug2("hid_dev->report_desc_size = %zu\n", 139 const usb_hid_dev_t *hid_dev = fun->driver_data; 140 141 usb_log_debug2("hid_dev->report_desc_size = %zu\n", 155 142 hid_dev->report_desc_size); 156 143 157 144 return hid_dev->report_desc_size; 158 145 } 159 160 /*----------------------------------------------------------------------------*/ 161 162 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 146 /*----------------------------------------------------------------------------*/ 147 static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 163 148 size_t size, size_t *actual_size) 164 149 { … … 170 155 } 171 156 172 usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;157 const usb_hid_dev_t *hid_dev = fun->driver_data; 173 158 174 159 if (hid_dev->report_desc_size > size) { … … 181 166 return EOK; 182 167 } 183 184 /*----------------------------------------------------------------------------*/ 185 168 /*----------------------------------------------------------------------------*/ 186 169 static int usb_generic_hid_client_connected(ddf_fun_t *fun) 187 170 { … … 189 172 return EOK; 190 173 } 191 192 /*----------------------------------------------------------------------------*/ 193 174 /*----------------------------------------------------------------------------*/ 194 175 void usb_generic_hid_deinit(usb_hid_dev_t *hid_dev, void *data) 195 176 { 196 177 ddf_fun_t *fun = data; 197 const int ret = ddf_fun_unbind(fun); 198 if (ret != EOK) { 178 if (fun == NULL) 179 return; 180 181 if (ddf_fun_unbind(fun) != EOK) { 199 182 usb_log_error("Failed to unbind generic hid fun.\n"); 200 183 return; … … 206 189 ddf_fun_destroy(fun); 207 190 } 208 209 /*----------------------------------------------------------------------------*/ 210 191 /*----------------------------------------------------------------------------*/ 211 192 int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data) 212 193 { … … 216 197 217 198 /* Create the exposed function. */ 218 /** @todo Generate numbers for the devices? */219 199 usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME); 220 200 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, … … 225 205 } 226 206 207 /* This is nasty, both device and this function have the same 208 * driver data, thus destruction causes to double free */ 209 fun->driver_data = hid_dev; 227 210 fun->ops = &usb_generic_hid_ops; 228 211 … … 231 214 usb_log_error("Could not bind DDF function: %s.\n", 232 215 str_error(rc)); 216 fun->driver_data = NULL; 233 217 ddf_fun_destroy(fun); 234 218 return rc; 235 219 } 236 /* This is nasty both device and this function have the same237 * driver data, thus destruction would lead to double free */238 fun->driver_data = hid_dev;239 220 240 221 usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle); … … 243 224 return EOK; 244 225 } 245 246 /*----------------------------------------------------------------------------*/ 247 226 /*----------------------------------------------------------------------------*/ 248 227 bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data) 249 228 { 250 229 return true; 251 230 } 252 253 231 /** 254 232 * @} -
uspace/drv/bus/usb/usbhid/kbd/kbddev.c
rba72f2b r6843a9c 41 41 #include <io/keycode.h> 42 42 #include <io/console.h> 43 #include <abi/ipc/methods.h> 43 44 #include <ipc/kbdev.h> 44 45 #include <async.h> … … 86 87 87 88 /*----------------------------------------------------------------------------*/ 88 89 89 /** Keyboard polling endpoint description for boot protocol class. */ 90 90 const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = { … … 101 101 102 102 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev); 103 104 /*----------------------------------------------------------------------------*/ 105 106 enum { 107 USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63 103 /*----------------------------------------------------------------------------*/ 104 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[] = { 105 0x05, 0x01, /* Usage Page (Generic Desktop), */ 106 0x09, 0x06, /* Usage (Keyboard), */ 107 0xA1, 0x01, /* Collection (Application), */ 108 0x75, 0x01, /* Report Size (1), */ 109 0x95, 0x08, /* Report Count (8), */ 110 0x05, 0x07, /* Usage Page (Key Codes); */ 111 0x19, 0xE0, /* Usage Minimum (224), */ 112 0x29, 0xE7, /* Usage Maximum (231), */ 113 0x15, 0x00, /* Logical Minimum (0), */ 114 0x25, 0x01, /* Logical Maximum (1), */ 115 0x81, 0x02, /* Input (Data, Variable, Absolute), ; Modifier byte */ 116 0x95, 0x01, /* Report Count (1), */ 117 0x75, 0x08, /* Report Size (8), */ 118 0x81, 0x01, /* Input (Constant), ; Reserved byte */ 119 0x95, 0x05, /* Report Count (5), */ 120 0x75, 0x01, /* Report Size (1), */ 121 0x05, 0x08, /* Usage Page (Page# for LEDs), */ 122 0x19, 0x01, /* Usage Minimum (1), */ 123 0x29, 0x05, /* Usage Maxmimum (5), */ 124 0x91, 0x02, /* Output (Data, Variable, Absolute), ; LED report */ 125 0x95, 0x01, /* Report Count (1), */ 126 0x75, 0x03, /* Report Size (3), */ 127 0x91, 0x01, /* Output (Constant), ; LED report padding */ 128 0x95, 0x06, /* Report Count (6), */ 129 0x75, 0x08, /* Report Size (8), */ 130 0x15, 0x00, /* Logical Minimum (0), */ 131 0x25, 0xff, /* Logical Maximum (255), */ 132 0x05, 0x07, /* Usage Page (Key Codes), */ 133 0x19, 0x00, /* Usage Minimum (0), */ 134 0x29, 0xff, /* Usage Maximum (255), */ 135 0x81, 0x00, /* Input (Data, Array), ; Key arrays (6 bytes) */ 136 0xC0 /* End Collection */ 108 137 }; 109 110 static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[ 111 USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = { 112 0x05, 0x01, // Usage Page (Generic Desktop), 113 0x09, 0x06, // Usage (Keyboard), 114 0xA1, 0x01, // Collection (Application), 115 0x75, 0x01, // Report Size (1), 116 0x95, 0x08, // Report Count (8), 117 0x05, 0x07, // Usage Page (Key Codes); 118 0x19, 0xE0, // Usage Minimum (224), 119 0x29, 0xE7, // Usage Maximum (231), 120 0x15, 0x00, // Logical Minimum (0), 121 0x25, 0x01, // Logical Maximum (1), 122 0x81, 0x02, // Input (Data, Variable, Absolute), ; Modifier byte 123 0x95, 0x01, // Report Count (1), 124 0x75, 0x08, // Report Size (8), 125 0x81, 0x01, // Input (Constant), ; Reserved byte 126 0x95, 0x05, // Report Count (5), 127 0x75, 0x01, // Report Size (1), 128 0x05, 0x08, // Usage Page (Page# for LEDs), 129 0x19, 0x01, // Usage Minimum (1), 130 0x29, 0x05, // Usage Maxmimum (5), 131 0x91, 0x02, // Output (Data, Variable, Absolute), ; LED report 132 0x95, 0x01, // Report Count (1), 133 0x75, 0x03, // Report Size (3), 134 0x91, 0x01, // Output (Constant), ; LED report padding 135 0x95, 0x06, // Report Count (6), 136 0x75, 0x08, // Report Size (8), 137 0x15, 0x00, // Logical Minimum (0), 138 0x25, 0xff, // Logical Maximum (255), 139 0x05, 0x07, // Usage Page (Key Codes), 140 0x19, 0x00, // Usage Minimum (0), 141 0x29, 0xff, // Usage Maximum (255), 142 0x81, 0x00, // Input (Data, Array), ; Key arrays (6 bytes) 143 0xC0 // End Collection 144 145 }; 146 147 /*----------------------------------------------------------------------------*/ 148 138 /*----------------------------------------------------------------------------*/ 149 139 typedef enum usb_kbd_flags { 150 140 USB_KBD_STATUS_UNINITIALIZED = 0, … … 152 142 USB_KBD_STATUS_TO_DESTROY = -1 153 143 } usb_kbd_flags; 154 155 144 /*----------------------------------------------------------------------------*/ 156 145 /* IPC method handler */ 157 146 /*----------------------------------------------------------------------------*/ 158 159 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);160 161 147 /** 162 148 * Default handler for IPC methods not handled by DDF. 163 149 * 164 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it 165 * assumes the caller is the console and thus it stores IPC session to it for 166 * later use by the driver to notify about key events. 150 * Currently recognizes only two methods (IPC_M_CONNECT_TO_ME and KBDEV_SET_IND) 151 * IPC_M_CONNECT_TO_ME assumes the caller is the console and stores IPC 152 * session to it for later use by the driver to notify about key events. 153 * KBDEV_SET_IND sets LED keyboard indicators. 167 154 * 168 155 * @param fun Device function handling the call. … … 173 160 ipc_callid_t icallid, ipc_call_t *icall) 174 161 { 175 sysarg_t method = IPC_GET_IMETHOD(*icall); 176 177 usb_kbd_t *kbd_dev = (usb_kbd_t *) fun->driver_data; 178 if (kbd_dev == NULL) { 179 usb_log_debug("default_connection_handler: " 180 "Missing parameter.\n"); 162 if (fun == NULL || fun->driver_data == NULL) { 163 usb_log_error("%s: Missing parameter.\n", __FUNCTION__); 181 164 async_answer_0(icallid, EINVAL); 182 165 return; 183 166 } 184 167 185 async_sess_t *sess = 186 async_callback_receive_start(EXCHANGE_SERIALIZE, icall); 187 if (sess != NULL) { 168 const sysarg_t method = IPC_GET_IMETHOD(*icall); 169 usb_kbd_t *kbd_dev = fun->driver_data; 170 171 switch (method) { 172 case KBDEV_SET_IND: 173 kbd_dev->mods = IPC_GET_ARG1(*icall); 174 usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev); 175 async_answer_0(icallid, EOK); 176 break; 177 /* This might be ugly but async_callback_receive_start makes no 178 * difference for incorrect call and malloc failure. */ 179 case IPC_M_CONNECT_TO_ME: { 180 async_sess_t *sess = 181 async_callback_receive_start(EXCHANGE_SERIALIZE, icall); 182 /* Probably ENOMEM error, try again. */ 183 if (sess == NULL) { 184 usb_log_warning( 185 "Failed to create start console session.\n"); 186 async_answer_0(icallid, EAGAIN); 187 break; 188 } 188 189 if (kbd_dev->console_sess == NULL) { 189 190 kbd_dev->console_sess = sess; 190 usb_log_debug(" default_connection_handler: OK\n");191 usb_log_debug("%s: OK\n", __FUNCTION__); 191 192 async_answer_0(icallid, EOK); 192 193 } else { 193 usb_log_ debug("default_connection_handler: "194 "console session already set\n");194 usb_log_error("%s: console session already set\n", 195 __FUNCTION__); 195 196 async_answer_0(icallid, ELIMIT); 196 197 } 197 } else { 198 switch (method) { 199 case KBDEV_SET_IND: 200 kbd_dev->mods = IPC_GET_ARG1(*icall); 201 usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev); 202 async_answer_0(icallid, EOK); 203 break; 204 default: 205 usb_log_debug("default_connection_handler: Wrong function.\n"); 198 break; 199 } 200 default: 201 usb_log_error("%s: Unknown method: %d.\n", 202 __FUNCTION__, (int) method); 206 203 async_answer_0(icallid, EINVAL); 207 204 break; 208 } 209 } 210 } 211 205 } 206 207 } 212 208 /*----------------------------------------------------------------------------*/ 213 209 /* Key processing functions */ … … 226 222 * @param kbd_dev Keyboard device structure. 227 223 */ 228 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 224 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 229 225 { 230 226 if (kbd_dev->output_size == 0) { … … 274 270 } 275 271 276 usb_log_debug("Output report buffer: %s\n", 277 usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 272 usb_log_debug("Output report buffer: %s\n", 273 usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 278 274 0)); 279 275 280 usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,281 hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 276 rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe, 277 hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 282 278 kbd_dev->output_buffer, kbd_dev->output_size); 283 } 284 279 if (rc != EOK) { 280 usb_log_warning("Failed to set kbd indicators.\n"); 281 } 282 } 285 283 /*----------------------------------------------------------------------------*/ 286 284 /** Send key event. … … 291 289 * @param key Key code 292 290 */ 293 void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type, 294 unsigned int key) 291 void usb_kbd_push_ev(usb_kbd_t *kbd_dev, int type, unsigned key) 295 292 { 296 293 usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key); … … 302 299 303 300 async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess); 304 async_msg_2(exch, KBDEV_EVENT, type, key); 305 async_exchange_end(exch); 306 } 307 308 /*----------------------------------------------------------------------------*/ 309 310 static inline int usb_kbd_is_lock(unsigned int key_code) 301 if (exch != NULL) { 302 async_msg_2(exch, KBDEV_EVENT, type, key); 303 async_exchange_end(exch); 304 } else { 305 usb_log_warning("Failed to send key to console.\n"); 306 } 307 } 308 /*----------------------------------------------------------------------------*/ 309 static inline int usb_kbd_is_lock(unsigned int key_code) 311 310 { 312 311 return (key_code == KC_NUM_LOCK … … 314 313 || key_code == KC_CAPS_LOCK); 315 314 } 316 315 /*----------------------------------------------------------------------------*/ 317 316 static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size) 318 317 { … … 325 324 return (size_t) -1; 326 325 } 327 328 326 /*----------------------------------------------------------------------------*/ 329 327 /** … … 342 340 * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop() 343 341 */ 344 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 342 static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 345 343 usb_kbd_t *kbd_dev) 346 344 { 347 unsigned int key;348 size_t i;349 345 350 346 /* … … 356 352 * whole input report. 357 353 */ 358 i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,354 size_t i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys, 359 355 kbd_dev->key_count); 360 356 if (i != (size_t) -1) { 361 usb_log_ debug("Detected phantom state.\n");357 usb_log_error("Detected phantom state.\n"); 362 358 return; 363 359 } … … 367 363 */ 368 364 for (i = 0; i < kbd_dev->key_count; i++) { 369 int32_t old_key = kbd_dev->keys_old[i];365 const int32_t old_key = kbd_dev->keys_old[i]; 370 366 /* Find the old key among currently pressed keys. */ 371 size_t pos = find_in_array_int32(old_key, kbd_dev->keys,367 const size_t pos = find_in_array_int32(old_key, kbd_dev->keys, 372 368 kbd_dev->key_count); 373 369 /* If the key was not found, we need to signal release. */ 374 370 if (pos == (size_t) -1) { 375 key = usbhid_parse_scancode(old_key);371 const unsigned key = usbhid_parse_scancode(old_key); 376 372 if (!usb_kbd_is_lock(key)) { 377 373 usb_kbd_repeat_stop(kbd_dev, key); 378 374 } 379 usb_kbd_push_ev( hid_dev,kbd_dev, KEY_RELEASE, key);375 usb_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 380 376 usb_log_debug2("Key released: %u " 381 377 "(USB code %" PRIu32 ")\n", key, old_key); … … 387 383 */ 388 384 for (i = 0; i < kbd_dev->key_count; ++i) { 389 int32_t new_key = kbd_dev->keys[i];385 const int32_t new_key = kbd_dev->keys[i]; 390 386 /* Find the new key among already pressed keys. */ 391 size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,392 kbd_dev->key _count);387 const size_t pos = find_in_array_int32(new_key, 388 kbd_dev->keys_old, kbd_dev->key_count); 393 389 /* If the key was not found, we need to signal press. */ 394 390 if (pos == (size_t) -1) { 395 key = usbhid_parse_scancode(kbd_dev->keys[i]);391 unsigned key = usbhid_parse_scancode(kbd_dev->keys[i]); 396 392 if (!usb_kbd_is_lock(key)) { 397 393 usb_kbd_repeat_start(kbd_dev, key); 398 394 } 399 usb_kbd_push_ev( hid_dev,kbd_dev, KEY_PRESS, key);395 usb_kbd_push_ev(kbd_dev, KEY_PRESS, key); 400 396 usb_log_debug2("Key pressed: %u " 401 397 "(USB code %" PRIu32 ")\n", key, new_key); … … 405 401 memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4); 406 402 403 // TODO Get rid of this 407 404 char key_buffer[512]; 408 405 ddf_dump_buffer(key_buffer, 512, … … 410 407 usb_log_debug2("Stored keys %s.\n", key_buffer); 411 408 } 412 413 409 /*----------------------------------------------------------------------------*/ 414 410 /* General kbd functions */ … … 436 432 437 433 usb_hid_report_path_t *path = usb_hid_report_path(); 438 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 439 440 usb_hid_report_path_set_report_id (path, hid_dev->report_id); 441 442 // fill in the currently pressed keys 443 434 if (path == NULL) { 435 usb_log_error("Failed to create hid/kbd report path.\n"); 436 return; 437 } 438 439 int ret = 440 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 441 if (ret != EOK) { 442 usb_log_error("Failed to append to hid/kbd report path.\n"); 443 return; 444 } 445 446 usb_hid_report_path_set_report_id(path, hid_dev->report_id); 447 448 /* Fill in the currently pressed keys. */ 444 449 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 445 450 &hid_dev->report, NULL, path, … … 449 454 450 455 while (field != NULL) { 451 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 456 usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 452 457 field, field->value, field->usage); 453 458 454 459 assert(i < kbd_dev->key_count); 455 460 456 / / save the key usage461 /* Save the key usage. */ 457 462 if (field->value != 0) { 458 463 kbd_dev->keys[i] = field->usage; … … 474 479 usb_kbd_check_key_changes(hid_dev, kbd_dev); 475 480 } 476 477 481 /*----------------------------------------------------------------------------*/ 478 482 /* HID/KBD structure manipulation */ 479 483 /*----------------------------------------------------------------------------*/ 480 481 static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)482 {483 kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;484 }485 486 /*----------------------------------------------------------------------------*/487 488 /**489 * Creates a new USB/HID keyboard structure.490 *491 * The structure returned by this function is not initialized. Use492 * usb_kbd_init() to initialize it prior to polling.493 *494 * @return New uninitialized structure for representing a USB/HID keyboard or495 * NULL if not successful (memory error).496 */497 static usb_kbd_t *usb_kbd_new(void)498 {499 usb_kbd_t *kbd_dev =500 (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));501 502 if (kbd_dev == NULL) {503 usb_log_error("No memory!\n");504 return NULL;505 }506 507 kbd_dev->console_sess = NULL;508 kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;509 510 return kbd_dev;511 }512 513 /*----------------------------------------------------------------------------*/514 515 484 static int usb_kbd_create_function(usb_kbd_t *kbd_dev) 516 485 { … … 528 497 } 529 498 530 /* 531 * Store the initialized HID device and HID ops 532 * to the DDF function. 533 */ 499 /* Store the initialized HID device and HID ops 500 * to the DDF function. */ 534 501 fun->ops = &kbd_dev->ops; 535 502 fun->driver_data = kbd_dev; … … 539 506 usb_log_error("Could not bind DDF function: %s.\n", 540 507 str_error(rc)); 541 fun->driver_data = NULL; /* We need this later*/508 fun->driver_data = NULL; /* We did not allocate this. */ 542 509 ddf_fun_destroy(fun); 543 510 return rc; … … 547 514 HID_KBD_FUN_NAME, fun->handle); 548 515 549 usb_log_debug("Adding DDF function to category %s...\n", 516 usb_log_debug("Adding DDF function to category %s...\n", 550 517 HID_KBD_CLASS_NAME); 551 518 rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME); … … 554 521 "Could not add DDF function to category %s: %s.\n", 555 522 HID_KBD_CLASS_NAME, str_error(rc)); 556 fun->driver_data = NULL; /* We need this later */ 557 ddf_fun_destroy(fun); 523 if (ddf_fun_unbind(fun) == EOK) { 524 fun->driver_data = NULL; /* We did not allocate this. */ 525 ddf_fun_destroy(fun); 526 } else { 527 usb_log_error( 528 "Failed to unbind `%s', will not destroy.\n", 529 fun->name); 530 } 558 531 return rc; 559 532 } … … 562 535 return EOK; 563 536 } 564 565 537 /*----------------------------------------------------------------------------*/ 566 538 /* API functions */ … … 591 563 592 564 if (hid_dev == NULL) { 593 usb_log_error( "Failed to init keyboard structure: no structure"594 " given.\n");565 usb_log_error( 566 "Failed to init keyboard structure: no structure given.\n"); 595 567 return EINVAL; 596 568 } 597 569 598 usb_kbd_t *kbd_dev = usb_kbd_new();570 usb_kbd_t *kbd_dev = calloc(1, sizeof(usb_kbd_t)); 599 571 if (kbd_dev == NULL) { 600 usb_log_error("Error while creating USB/HID KBD device " 601 "structure.\n"); 602 return ENOMEM; // TODO: some other code?? 603 } 572 usb_log_error("Failed to allocate KBD device structure.\n"); 573 return ENOMEM; 574 } 575 /* Default values */ 576 fibril_mutex_initialize(&kbd_dev->repeat_mtx); 577 kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED; 578 kbd_dev->ops.default_handler = default_connection_handler; 604 579 605 580 /* Store link to HID device */ 606 581 kbd_dev->hid_dev = hid_dev; 607 582 608 /* 609 * TODO: make more general 610 */ 583 /* Modifiers and locks */ 584 kbd_dev->mods = DEFAULT_ACTIVE_MODS; 585 586 /* Autorepeat */ 587 kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT; 588 kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY; 589 590 591 // TODO: make more general 611 592 usb_hid_report_path_t *path = usb_hid_report_path(); 612 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 593 if (path == NULL) { 594 usb_log_error("Failed to create kbd report path.\n"); 595 usb_kbd_destroy(kbd_dev); 596 return ENOMEM; 597 } 598 599 int ret = 600 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 601 if (ret != EOK) { 602 usb_log_error("Failed to append item to kbd report path.\n"); 603 usb_hid_report_path_free(path); 604 usb_kbd_destroy(kbd_dev); 605 return ret; 606 } 613 607 614 608 usb_hid_report_path_set_report_id(path, 0); 615 609 616 kbd_dev->key_count = usb_hid_report_size( 617 &hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT); 610 kbd_dev->key_count = 611 usb_hid_report_size(&hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT); 612 618 613 usb_hid_report_path_free(path); 619 614 … … 621 616 622 617 kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t)); 623 624 618 if (kbd_dev->keys == NULL) { 625 usb_log_error(" No memory!\n");626 free(kbd_dev);619 usb_log_error("Failed to allocate key buffer.\n"); 620 usb_kbd_destroy(kbd_dev); 627 621 return ENOMEM; 628 622 } 629 623 630 kbd_dev->keys_old = 631 (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t)); 632 624 kbd_dev->keys_old = calloc(kbd_dev->key_count, sizeof(int32_t)); 633 625 if (kbd_dev->keys_old == NULL) { 634 usb_log_error("No memory!\n"); 635 free(kbd_dev->keys); 636 free(kbd_dev); 626 usb_log_error("Failed to allocate old_key buffer.\n"); 627 usb_kbd_destroy(kbd_dev); 637 628 return ENOMEM; 638 629 } 639 630 640 /* 641 * Output report 642 */ 631 /* Output report */ 643 632 kbd_dev->output_size = 0; 644 633 kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report, 645 634 &kbd_dev->output_size, 0); 646 635 if (kbd_dev->output_buffer == NULL) { 647 usb_log_ warning("Error creating output report buffer.\n");648 free(kbd_dev->keys);636 usb_log_error("Error creating output report buffer.\n"); 637 usb_kbd_destroy(kbd_dev); 649 638 return ENOMEM; 650 639 } … … 653 642 654 643 kbd_dev->led_path = usb_hid_report_path(); 655 usb_hid_report_path_append_item( 644 if (kbd_dev->led_path == NULL) { 645 usb_log_error("Failed to create kbd led report path.\n"); 646 usb_kbd_destroy(kbd_dev); 647 return ENOMEM; 648 } 649 650 ret = usb_hid_report_path_append_item( 656 651 kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0); 652 if (ret != EOK) { 653 usb_log_error("Failed to append to kbd/led report path.\n"); 654 usb_kbd_destroy(kbd_dev); 655 return ret; 656 } 657 657 658 658 kbd_dev->led_output_size = usb_hid_report_size( 659 659 &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT); 660 660 661 usb_log_debug("Output report size (in items): %zu\n", 661 usb_log_debug("Output report size (in items): %zu\n", 662 662 kbd_dev->led_output_size); 663 663 664 kbd_dev->led_data = (int32_t *)calloc( 665 kbd_dev->led_output_size, sizeof(int32_t)); 666 664 kbd_dev->led_data = calloc(kbd_dev->led_output_size, sizeof(int32_t)); 667 665 if (kbd_dev->led_data == NULL) { 668 usb_log_warning("Error creating buffer for LED output report." 669 "\n"); 670 free(kbd_dev->keys); 671 usb_hid_report_output_free(kbd_dev->output_buffer); 672 free(kbd_dev); 666 usb_log_error("Error creating buffer for LED output report.\n"); 667 usb_kbd_destroy(kbd_dev); 673 668 return ENOMEM; 674 669 } 675 670 676 /* 677 * Modifiers and locks 678 */ 679 kbd_dev->modifiers = 0; 680 kbd_dev->mods = DEFAULT_ACTIVE_MODS; 681 kbd_dev->lock_keys = 0; 682 683 /* 684 * Autorepeat 685 */ 686 kbd_dev->repeat.key_new = 0; 687 kbd_dev->repeat.key_repeated = 0; 688 kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT; 689 kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY; 690 691 fibril_mutex_initialize(&kbd_dev->repeat_mtx); 692 693 // save the KBD device structure into the HID device structure 671 /* Set LEDs according to initial setup. 672 * Set Idle rate */ 673 usb_kbd_set_led(hid_dev, kbd_dev); 674 675 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 676 hid_dev->usb_dev->interface_no, IDLE_RATE); 677 678 /* Save the KBD device structure into the HID device structure. */ 694 679 *data = kbd_dev; 695 680 696 // set handler for incoming calls 697 kbd_dev->ops.default_handler = default_connection_handler; 698 699 /* 700 * Set LEDs according to initial setup. 701 * Set Idle rate 702 */ 703 usb_kbd_set_led(hid_dev, kbd_dev); 704 705 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 706 hid_dev->usb_dev->interface_no, IDLE_RATE); 707 708 /* 709 * Create new fibril for auto-repeat 710 */ 681 kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED; 682 usb_log_debug("HID/KBD device structure initialized.\n"); 683 684 usb_log_debug("Creating KBD function...\n"); 685 ret = usb_kbd_create_function(kbd_dev); 686 if (ret != EOK) { 687 usb_kbd_destroy(kbd_dev); 688 return ret; 689 } 690 691 /* Create new fibril for auto-repeat. */ 711 692 fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev); 712 693 if (fid == 0) { 713 694 usb_log_error("Failed to start fibril for KBD auto-repeat"); 695 usb_kbd_destroy(kbd_dev); 714 696 return ENOMEM; 715 697 } 716 698 fibril_add_ready(fid); 717 699 718 kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;719 usb_log_debug("HID/KBD device structure initialized.\n");720 721 usb_log_debug("Creating KBD function...\n");722 int rc = usb_kbd_create_function(kbd_dev);723 if (rc != EOK) {724 usb_kbd_destroy(kbd_dev);725 return rc;726 }727 728 700 return EOK; 729 701 } 730 731 /*----------------------------------------------------------------------------*/ 732 702 /*----------------------------------------------------------------------------*/ 733 703 bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data) 734 704 { 735 if (hid_dev == NULL /* || buffer == NULL*/|| data == NULL) {736 / / do not continue polling (???)705 if (hid_dev == NULL || data == NULL) { 706 /* This means something serious */ 737 707 return false; 738 708 } 739 709 740 usb_kbd_t *kbd_dev = (usb_kbd_t *)data; 741 assert(kbd_dev != NULL); 742 710 usb_kbd_t *kbd_dev = data; 743 711 // TODO: add return value from this function 744 712 usb_kbd_process_data(hid_dev, kbd_dev); … … 746 714 return true; 747 715 } 748 749 /*----------------------------------------------------------------------------*/ 750 716 /*----------------------------------------------------------------------------*/ 751 717 int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev) 752 718 { 753 719 return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED); 754 720 } 755 756 /*----------------------------------------------------------------------------*/ 757 721 /*----------------------------------------------------------------------------*/ 758 722 int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev) 759 723 { 760 724 return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY); 761 725 } 762 763 726 /*----------------------------------------------------------------------------*/ 764 727 /** … … 773 736 } 774 737 775 // hangup session to the console 776 async_hangup(kbd_dev->console_sess); 738 /* Hangup session to the console. */ 739 if (kbd_dev->console_sess) 740 async_hangup(kbd_dev->console_sess); 777 741 778 742 //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)); … … 781 745 while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {} 782 746 783 / / free all buffers747 /* Free all buffers. */ 784 748 free(kbd_dev->keys); 785 749 free(kbd_dev->keys_old); 786 750 free(kbd_dev->led_data); 787 751 788 if (kbd_dev->led_path != NULL) { 789 usb_hid_report_path_free(kbd_dev->led_path); 790 } 791 if (kbd_dev->output_buffer != NULL) { 792 usb_hid_report_output_free(kbd_dev->output_buffer); 793 } 794 795 if (ddf_fun_unbind(kbd_dev->fun) != EOK) { 796 usb_log_warning("Failed to unbind kbd function.\n"); 797 } else { 798 usb_log_debug2("%s unbound.\n", kbd_dev->fun->name); 799 kbd_dev->fun->driver_data = NULL; 800 ddf_fun_destroy(kbd_dev->fun); 801 } 802 } 803 804 /*----------------------------------------------------------------------------*/ 805 752 usb_hid_report_path_free(kbd_dev->led_path); 753 usb_hid_report_output_free(kbd_dev->output_buffer); 754 755 if (kbd_dev->fun) { 756 if (ddf_fun_unbind(kbd_dev->fun) != EOK) { 757 usb_log_warning("Failed to unbind %s.\n", 758 kbd_dev->fun->name); 759 } else { 760 usb_log_debug2("%s unbound.\n", kbd_dev->fun->name); 761 kbd_dev->fun->driver_data = NULL; 762 ddf_fun_destroy(kbd_dev->fun); 763 } 764 } 765 free(kbd_dev); 766 } 767 /*----------------------------------------------------------------------------*/ 806 768 void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data) 807 769 { 808 if (hid_dev == NULL) {809 return;810 }811 812 770 if (data != NULL) { 813 771 usb_kbd_t *kbd_dev = data; 814 772 if (usb_kbd_is_initialized(kbd_dev)) { 815 usb_kbd_mark_unusable(kbd_dev);816 /* wait for autorepeat */773 kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY; 774 /* Wait for autorepeat */ 817 775 async_usleep(CHECK_DELAY); 818 usb_kbd_destroy(kbd_dev); 819 } 820 } 821 } 822 823 /*----------------------------------------------------------------------------*/ 824 776 } 777 usb_kbd_destroy(kbd_dev); 778 } 779 } 780 /*----------------------------------------------------------------------------*/ 825 781 int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev) 826 782 { 783 assert(hid_dev); 827 784 int rc = usb_hid_parse_report_descriptor( 828 785 &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR, 829 USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);786 sizeof(USB_KBD_BOOT_REPORT_DESCRIPTOR)); 830 787 831 788 if (rc != EOK) { … … 846 803 return EOK; 847 804 } 848 849 805 /** 850 806 * @} -
uspace/drv/bus/usb/usbhid/kbd/kbddev.h
rba72f2b r6843a9c 135 135 void usb_kbd_destroy(usb_kbd_t *kbd_dev); 136 136 137 void usb_kbd_push_ev( struct usb_hid_dev *hid_dev,usb_kbd_t *kbd_dev,137 void usb_kbd_push_ev(usb_kbd_t *kbd_dev, 138 138 int type, unsigned int key); 139 139 -
uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c
rba72f2b r6843a9c 45 45 #include "kbddev.h" 46 46 47 48 49 /*----------------------------------------------------------------------------*/50 47 /** 51 48 * Main loop handling the auto-repeat of keys. … … 58 55 * If the same key is still pressed, it uses the delay between repeats stored 59 56 * in the keyboard structure to wait until the key should be repeated. 60 * 57 * 61 58 * If the currently repeated key is not pressed any more ( 62 * usb_kbd_repeat_stop() was called), it stops repeating it and starts 59 * usb_kbd_repeat_stop() was called), it stops repeating it and starts 63 60 * checking again. 64 61 * 65 62 * @note For accessing the keyboard device auto-repeat information a fibril 66 63 * mutex (repeat_mtx) from the @a kbd structure is used. 67 * 64 * 68 65 * @param kbd Keyboard device structure. 69 66 */ … … 75 72 76 73 while (true) { 77 / / check if the kbd structure is usable74 /* Check if the kbd structure is usable. */ 78 75 if (!usb_kbd_is_initialized(kbd)) { 79 76 usb_log_warning("kbd not ready, exiting autorepeat.\n"); 80 77 return; 81 78 } 82 79 83 80 fibril_mutex_lock(&kbd->repeat_mtx); 84 81 85 82 if (kbd->repeat.key_new > 0) { 86 83 if (kbd->repeat.key_new == kbd->repeat.key_repeated) { 87 usb_log_debug2("Repeating key: %u.\n", 84 usb_log_debug2("Repeating key: %u.\n", 88 85 kbd->repeat.key_repeated); 89 // ugly hack with the NULL 90 usb_kbd_push_ev(NULL, kbd, KEY_PRESS, 86 usb_kbd_push_ev(kbd, KEY_PRESS, 91 87 kbd->repeat.key_repeated); 92 88 delay = kbd->repeat.delay_between; … … 106 102 } 107 103 fibril_mutex_unlock(&kbd->repeat_mtx); 108 109 104 async_usleep(delay); 110 105 } 111 106 } 112 113 107 /*----------------------------------------------------------------------------*/ 114 108 /** … … 116 110 * 117 111 * Starts the loop for checking changes in auto-repeat. 118 * 112 * 119 113 * @param arg User-specified argument. Expects pointer to the keyboard device 120 114 * structure representing the keyboard. … … 132 126 } 133 127 134 usb_kbd_t *kbd = (usb_kbd_t *)arg;128 usb_kbd_t *kbd = arg; 135 129 136 130 usb_kbd_repeat_loop(kbd); … … 138 132 return EOK; 139 133 } 140 141 134 /*----------------------------------------------------------------------------*/ 142 135 /** … … 156 149 fibril_mutex_unlock(&kbd->repeat_mtx); 157 150 } 158 159 151 /*----------------------------------------------------------------------------*/ 160 152 /** … … 162 154 * 163 155 * @note Only one key is repeated at any time, but this function may be called 164 * even with key that is not currently repeated (in that case nothing 156 * even with key that is not currently repeated (in that case nothing 165 157 * happens). 166 158 * … … 176 168 fibril_mutex_unlock(&kbd->repeat_mtx); 177 169 } 178 179 170 /** 180 171 * @} -
uspace/drv/bus/usb/usbhid/main.c
rba72f2b r6843a9c 46 46 #include "usbhid.h" 47 47 48 /*----------------------------------------------------------------------------*/49 50 48 #define NAME "usbhid" 51 49 52 50 /** 53 * Function for adding a new device of type USB/HID/keyboard.51 * Callback for passing a new device to the driver. 54 52 * 55 * This functions initializes required structures from the device's descriptors 56 * and starts new fibril for polling the keyboard for events and another one for 57 * handling auto-repeat of keys. 53 * @note Currently, only boot-protocol keyboards are supported by this driver. 58 54 * 59 * During initialization, the keyboard is switched into boot protocol, the idle 60 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 61 * when a key is pressed or released. Finally, the LED lights are turned on 62 * according to the default setup of lock keys. 63 * 64 * @note By default, the keyboards is initialized with Num Lock turned on and 65 * other locks turned off. 66 * @note Currently supports only boot-protocol keyboards. 67 * 68 * @param dev Device to add. 69 * 70 * @retval EOK if successful. 71 * @retval ENOMEM if there 72 * @return Other error code inherited from one of functions usb_kbd_init(), 73 * ddf_fun_bind() and ddf_fun_add_to_class(). 55 * @param dev Structure representing the new device. 56 * @return Error code. 74 57 */ 75 static int usb_hid_ try_add_device(usb_device_t *dev)58 static int usb_hid_device_add(usb_device_t *dev) 76 59 { 77 assert(dev != NULL);60 usb_log_debug("%s\n", __FUNCTION__); 78 61 79 /* Initialize device (get and process descriptors, get address, etc.) */ 80 usb_log_debug("Initializing USB/HID device...\n"); 62 if (dev == NULL) { 63 usb_log_error("Wrong parameter given for add_device().\n"); 64 return EINVAL; 65 } 81 66 67 if (dev->interface_no < 0) { 68 usb_log_error("Failed to add HID device: endpoints not found." 69 "\n"); 70 return ENOTSUP; 71 } 82 72 usb_hid_dev_t *hid_dev = 83 73 usb_device_data_alloc(dev, sizeof(usb_hid_dev_t)); 84 74 if (hid_dev == NULL) { 85 usb_log_error("Error while creating USB/HID device " 86 "structure.\n"); 75 usb_log_error("Failed to create USB/HID device structure.\n"); 87 76 return ENOMEM; 88 77 } 89 78 90 79 int rc = usb_hid_init(hid_dev, dev); 91 92 80 if (rc != EOK) { 93 81 usb_log_error("Failed to initialize USB/HID device.\n"); … … 98 86 usb_log_debug("USB/HID device structure initialized.\n"); 99 87 100 /*101 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da102 * do nej.103 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi104 * vyplnenu strukturu usbhid_iface_t.105 * 3) klientska aplikacia - musi si rucne vytvorit telefon106 * (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az107 * k tej fcii.108 * pouzit usb/classes/hid/iface.h - prvy int je telefon109 */110 111 88 /* Start automated polling function. 112 89 * This will create a separate fibril that will query the device 113 * for the data continuously 114 */ 90 * for the data continuously. */ 115 91 rc = usb_device_auto_poll(dev, 116 92 /* Index of the polling pipe. */ … … 119 95 usb_hid_polling_callback, 120 96 /* How much data to request. */ 121 dev->pipes[hid_dev->poll_pipe_index].pipe ->max_packet_size,97 dev->pipes[hid_dev->poll_pipe_index].pipe.max_packet_size, 122 98 /* Callback when the polling ends. */ 123 99 usb_hid_polling_ended_callback, … … 133 109 hid_dev->running = true; 134 110 135 /*136 * Hurrah, device is initialized.137 */138 return EOK;139 }140 141 /*----------------------------------------------------------------------------*/142 /**143 * Callback for passing a new device to the driver.144 *145 * @note Currently, only boot-protocol keyboards are supported by this driver.146 *147 * @param dev Structure representing the new device.148 *149 * @retval EOK if successful.150 * @retval EREFUSED if the device is not supported.151 */152 static int usb_hid_device_add(usb_device_t *dev)153 {154 usb_log_debug("usb_hid_device_add()\n");155 156 if (dev == NULL) {157 usb_log_warning("Wrong parameter given for add_device().\n");158 return EINVAL;159 }160 161 if (dev->interface_no < 0) {162 usb_log_warning("Device is not a supported HID device.\n");163 usb_log_error("Failed to add HID device: endpoints not found."164 "\n");165 return ENOTSUP;166 }167 168 int rc = usb_hid_try_add_device(dev);169 170 if (rc != EOK) {171 usb_log_warning("Device is not a supported HID device.\n");172 usb_log_error("Failed to add HID device: %s.\n",173 str_error(rc));174 return rc;175 }176 177 111 usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name); 178 112 179 113 return EOK; 180 114 } 181 182 115 /*----------------------------------------------------------------------------*/ 183 116 /** 117 * Callback for a device about to be removed from the driver. 118 * 119 * @param dev Structure representing the device. 120 * @return Error code. 121 */ 122 static int usb_hid_device_rem(usb_device_t *dev) 123 { 124 // TODO: Stop device polling 125 // TODO: Call deinit (stops autorepeat too) 126 return ENOTSUP; 127 } 128 /*----------------------------------------------------------------------------*/ 184 129 /** 185 130 * Callback for removing a device from the driver. 186 131 * 187 132 * @param dev Structure representing the device. 188 * 189 * @retval EOK if successful. 190 * @retval EREFUSED if the device is not supported. 133 * @return Error code. 191 134 */ 192 135 static int usb_hid_device_gone(usb_device_t *dev) 193 136 { 137 assert(dev); 138 assert(dev->driver_data); 194 139 usb_hid_dev_t *hid_dev = dev->driver_data; 195 unsigned tries = 10; 196 while (hid_dev->running) { 140 unsigned tries = 100; 141 /* Wait for fail. */ 142 while (hid_dev->running && tries--) { 197 143 async_usleep(100000); 198 if (!tries--) {199 usb_log_error("Can't remove hub, still running.\n");200 return EINPROGRESS;201 }144 } 145 if (hid_dev->running) { 146 usb_log_error("Can't remove hid, still running.\n"); 147 return EBUSY; 202 148 } 203 149 204 assert(!hid_dev->running);205 150 usb_hid_deinit(hid_dev); 206 151 usb_log_debug2("%s destruction complete.\n", dev->ddf_dev->name); 207 152 return EOK; 208 153 } 209 154 /*----------------------------------------------------------------------------*/ 210 155 /** USB generic driver callbacks */ 211 static usb_driver_ops_t usb_hid_driver_ops = {156 static const usb_driver_ops_t usb_hid_driver_ops = { 212 157 .device_add = usb_hid_device_add, 158 .device_rem = usb_hid_device_rem, 213 159 .device_gone = usb_hid_device_gone, 214 160 }; 215 216 161 /*----------------------------------------------------------------------------*/ 217 162 /** The driver itself. */ 218 static usb_driver_t usb_hid_driver = {163 static const usb_driver_t usb_hid_driver = { 219 164 .name = NAME, 220 165 .ops = &usb_hid_driver_ops, 221 166 .endpoints = usb_hid_endpoints 222 167 }; 223 224 168 /*----------------------------------------------------------------------------*/ 225 226 169 int main(int argc, char *argv[]) 227 170 { … … 232 175 return usb_driver_main(&usb_hid_driver); 233 176 } 234 235 177 /** 236 178 * @} -
uspace/drv/bus/usb/usbhid/mouse/mousedev.c
rba72f2b r6843a9c 52 52 #include "../usbhid.h" 53 53 54 /** Number of simulated arrow-key presses for singel wheel step. */ 55 #define ARROWS_PER_SINGLE_WHEEL 3 56 57 #define NAME "mouse" 54 #define NAME "mouse" 58 55 59 56 /*----------------------------------------------------------------------------*/ … … 69 66 70 67 const char *HID_MOUSE_FUN_NAME = "mouse"; 71 const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";72 68 const char *HID_MOUSE_CATEGORY = "mouse"; 73 const char *HID_MOUSE_WHEEL_CATEGORY = "keyboard";74 69 75 70 /** Default idle rate for mouses. */ … … 77 72 78 73 /*----------------------------------------------------------------------------*/ 79 80 enum { 81 USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63 82 }; 83 84 static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[ 85 USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = { 74 static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[] = { 86 75 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 87 76 0x09, 0x02, // USAGE (Mouse) … … 123 112 ipc_callid_t icallid, ipc_call_t *icall) 124 113 { 125 usb_mouse_t *mouse_dev = (usb_mouse_t *)fun->driver_data;114 usb_mouse_t *mouse_dev = fun->driver_data; 126 115 127 116 if (mouse_dev == NULL) { 128 usb_log_debug("default_connection_handler: Missing " 129 "parameters.\n"); 117 usb_log_debug("%s: Missing parameters.\n", __FUNCTION__); 130 118 async_answer_0(icallid, EINVAL); 131 119 return; 132 120 } 133 121 134 usb_log_debug("default_connection_handler: fun->name: %s\n", 135 fun->name); 136 usb_log_debug("default_connection_handler: mouse_sess: %p, " 137 "wheel_sess: %p\n", mouse_dev->mouse_sess, mouse_dev->wheel_sess); 138 139 async_sess_t **sess_ptr = 140 (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) ? 141 &mouse_dev->mouse_sess : &mouse_dev->wheel_sess; 122 usb_log_debug("%s: fun->name: %s\n", __FUNCTION__, fun->name); 123 usb_log_debug("%s: mouse_sess: %p\n", 124 __FUNCTION__, mouse_dev->mouse_sess); 142 125 143 126 async_sess_t *sess = 144 127 async_callback_receive_start(EXCHANGE_SERIALIZE, icall); 145 128 if (sess != NULL) { 146 if ( *sess_ptr== NULL) {147 *sess_ptr= sess;148 usb_log_debug("Console session to mouseset ok (%p).\n",149 sess);129 if (mouse_dev->mouse_sess == NULL) { 130 mouse_dev->mouse_sess = sess; 131 usb_log_debug("Console session to %s set ok (%p).\n", 132 fun->name, sess); 150 133 async_answer_0(icallid, EOK); 151 134 } else { 152 usb_log_ debug("default_connection_handler: Console "153 "session to mouse already set.\n");135 usb_log_error("Console session to %s already set.\n", 136 fun->name); 154 137 async_answer_0(icallid, ELIMIT); 138 async_hangup(sess); 155 139 } 156 140 } else { 157 usb_log_debug(" default_connection_handler: Invalid function.\n");141 usb_log_debug("%s: Invalid function.\n", __FUNCTION__); 158 142 async_answer_0(icallid, EINVAL); 159 143 } 160 144 } 161 162 /*----------------------------------------------------------------------------*/ 163 164 static usb_mouse_t *usb_mouse_new(void) 165 { 166 usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t)); 167 if (mouse == NULL) { 168 return NULL; 169 } 170 mouse->mouse_sess = NULL; 171 mouse->wheel_sess = NULL; 172 173 return mouse; 174 } 175 176 /*----------------------------------------------------------------------------*/ 177 178 static void usb_mouse_destroy(usb_mouse_t *mouse_dev) 179 { 180 assert(mouse_dev != NULL); 181 182 // hangup session to the console 183 if (mouse_dev->mouse_sess != NULL) 184 async_hangup(mouse_dev->mouse_sess); 185 186 if (mouse_dev->wheel_sess != NULL) 187 async_hangup(mouse_dev->wheel_sess); 188 int ret = ddf_fun_unbind(mouse_dev->mouse_fun); 189 if (ret != EOK) { 190 usb_log_error("Failed to unbind mouse function.\n"); 191 } else { 192 ddf_fun_destroy(mouse_dev->mouse_fun); 193 /* Prevent double free */ 194 mouse_dev->wheel_fun->driver_data = NULL; 195 } 196 197 ret = ddf_fun_unbind(mouse_dev->wheel_fun); 198 if (ret != EOK) { 199 usb_log_error("Failed to unbind wheel function.\n"); 200 } else { 201 ddf_fun_destroy(mouse_dev->wheel_fun); 202 } 203 } 204 205 /*----------------------------------------------------------------------------*/ 206 207 static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel) 208 { 209 unsigned int key = (wheel > 0) ? KC_UP : KC_DOWN; 210 211 if (mouse_dev->wheel_sess == NULL) { 212 usb_log_warning( 213 "Connection to console not ready, wheel roll discarded.\n"); 214 return; 215 } 216 217 int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL; 218 int i; 219 220 for (i = 0; i < count; i++) { 221 /* Send arrow press and release. */ 222 usb_log_debug2("Sending key %d to the console\n", key); 223 224 async_exch_t *exch = async_exchange_begin(mouse_dev->wheel_sess); 225 226 async_msg_4(exch, KBDEV_EVENT, KEY_PRESS, key, 0, 0); 227 async_msg_4(exch, KBDEV_EVENT, KEY_RELEASE, key, 0, 0); 228 229 async_exchange_end(exch); 230 } 231 } 232 233 /*----------------------------------------------------------------------------*/ 234 145 /*----------------------------------------------------------------------------*/ 235 146 static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report, 236 147 int32_t usage) … … 267 178 } 268 179 269 int shift_x = get_mouse_axis_move_value(hid_dev->report_id,180 const int shift_x = get_mouse_axis_move_value(hid_dev->report_id, 270 181 &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X); 271 int shift_y = get_mouse_axis_move_value(hid_dev->report_id,182 const int shift_y = get_mouse_axis_move_value(hid_dev->report_id, 272 183 &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y); 273 int wheel = get_mouse_axis_move_value(hid_dev->report_id,184 const int wheel = get_mouse_axis_move_value(hid_dev->report_id, 274 185 &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL); 275 186 276 if ( (shift_x != 0) || (shift_y != 0)) {187 if (shift_x || shift_y || wheel) { 277 188 async_exch_t *exch = 278 189 async_exchange_begin(mouse_dev->mouse_sess); 279 async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y); 280 async_exchange_end(exch); 281 } 282 283 if (wheel != 0) 284 usb_mouse_send_wheel(mouse_dev, wheel); 285 286 /* 287 * Buttons 288 */ 190 if (exch != NULL) { 191 async_msg_3(exch, MOUSEEV_MOVE_EVENT, 192 shift_x, shift_y, wheel); 193 async_exchange_end(exch); 194 } 195 } 196 197 /* Buttons */ 289 198 usb_hid_report_path_t *path = usb_hid_report_path(); 290 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0); 199 if (path == NULL) { 200 usb_log_warning("Failed to create USB HID report path.\n"); 201 return true; 202 } 203 int ret = 204 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0); 205 if (ret != EOK) { 206 usb_hid_report_path_free(path); 207 usb_log_warning("Failed to add buttons to report path.\n"); 208 return true; 209 } 291 210 usb_hid_report_path_set_report_id(path, hid_dev->report_id); 292 211 … … 298 217 usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value, 299 218 field->usage); 300 301 if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0 302 && field->value != 0) { 219 assert(field->usage > field->usage_minimum); 220 const unsigned index = field->usage - field->usage_minimum; 221 assert(index < mouse_dev->buttons_count); 222 223 if (mouse_dev->buttons[index] == 0 && field->value != 0) { 303 224 async_exch_t *exch = 304 225 async_exchange_begin(mouse_dev->mouse_sess); 305 async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 1); 306 async_exchange_end(exch); 307 308 mouse_dev->buttons[field->usage - field->usage_minimum] 309 = field->value; 310 } else if (mouse_dev->buttons[field->usage - field->usage_minimum] != 0 311 && field->value == 0) { 226 if (exch != NULL) { 227 async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, 228 field->usage, 1); 229 async_exchange_end(exch); 230 mouse_dev->buttons[index] = field->value; 231 } 232 233 } else if (mouse_dev->buttons[index] != 0 && field->value == 0) { 312 234 async_exch_t *exch = 313 235 async_exchange_begin(mouse_dev->mouse_sess); 314 async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 0); 315 async_exchange_end(exch); 316 317 mouse_dev->buttons[field->usage - field->usage_minimum] = 318 field->value; 236 if (exch != NULL) { 237 async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, 238 field->usage, 0); 239 async_exchange_end(exch); 240 mouse_dev->buttons[index] = field->value; 241 } 319 242 } 320 243 … … 329 252 return true; 330 253 } 331 332 /*----------------------------------------------------------------------------*/ 333 254 /*----------------------------------------------------------------------------*/ 255 #define FUN_UNBIND_DESTROY(fun) \ 256 if (fun) { \ 257 if (ddf_fun_unbind((fun)) == EOK) { \ 258 (fun)->driver_data = NULL; \ 259 ddf_fun_destroy((fun)); \ 260 } else { \ 261 usb_log_error("Could not unbind function `%s', it " \ 262 "will not be destroyed.\n", (fun)->name); \ 263 } \ 264 } else (void)0 265 /*----------------------------------------------------------------------------*/ 334 266 static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse) 335 267 { … … 339 271 /* Create the exposed function. */ 340 272 usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME); 341 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 273 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 342 274 HID_MOUSE_FUN_NAME); 343 275 if (fun == NULL) { 344 usb_log_error("Could not create DDF function node.\n"); 276 usb_log_error("Could not create DDF function node `%s'.\n", 277 HID_MOUSE_FUN_NAME); 345 278 return ENOMEM; 346 279 } … … 351 284 int rc = ddf_fun_bind(fun); 352 285 if (rc != EOK) { 353 usb_log_error("Could not bind DDF function: %s.\n", 354 str_error(rc)); 286 usb_log_error("Could not bind DDF function `%s': %s.\n", 287 fun->name, str_error(rc)); 288 fun->driver_data = NULL; 289 ddf_fun_destroy(fun); 355 290 return rc; 356 291 } 357 292 358 usb_log_debug("Adding DDF function to category %s...\n",359 HID_MOUSE_CATEGORY);293 usb_log_debug("Adding DDF function `%s' to category %s...\n", 294 fun->name, HID_MOUSE_CATEGORY); 360 295 rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY); 361 296 if (rc != EOK) { … … 363 298 "Could not add DDF function to category %s: %s.\n", 364 299 HID_MOUSE_CATEGORY, str_error(rc)); 300 FUN_UNBIND_DESTROY(fun); 365 301 return rc; 366 302 } 367 303 mouse->mouse_fun = fun; 368 304 369 /*370 * Special function for acting as keyboard (wheel)371 */372 usb_log_debug("Creating DDF function %s...\n",373 HID_MOUSE_WHEEL_FUN_NAME);374 fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,375 HID_MOUSE_WHEEL_FUN_NAME);376 if (fun == NULL) {377 usb_log_error("Could not create DDF function node.\n");378 return ENOMEM;379 }380 381 /*382 * Store the initialized HID device and HID ops383 * to the DDF function.384 */385 fun->ops = &mouse->ops;386 fun->driver_data = mouse;387 388 rc = ddf_fun_bind(fun);389 if (rc != EOK) {390 usb_log_error("Could not bind DDF function: %s.\n",391 str_error(rc));392 return rc;393 }394 395 usb_log_debug("Adding DDF function to category %s...\n",396 HID_MOUSE_WHEEL_CATEGORY);397 rc = ddf_fun_add_to_category(fun, HID_MOUSE_WHEEL_CATEGORY);398 if (rc != EOK) {399 usb_log_error(400 "Could not add DDF function to category %s: %s.\n",401 HID_MOUSE_WHEEL_CATEGORY, str_error(rc));402 return rc;403 }404 mouse->wheel_fun = fun;405 406 305 return EOK; 407 306 } 408 409 /*----------------------------------------------------------------------------*/410 307 411 308 /** Get highest index of a button mentioned in given report. … … 448 345 return highest_button; 449 346 } 450 451 /*----------------------------------------------------------------------------*/ 452 347 /*----------------------------------------------------------------------------*/ 453 348 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data) 454 349 { … … 461 356 } 462 357 463 usb_mouse_t *mouse_dev = usb_mouse_new();358 usb_mouse_t *mouse_dev = calloc(1, sizeof(usb_mouse_t)); 464 359 if (mouse_dev == NULL) { 465 360 usb_log_error("Error while creating USB/HID Mouse device " … … 484 379 } 485 380 486 487 // save the Mouse device structure into the HID device structure488 *data = mouse_dev;489 490 381 // set handler for incoming calls 491 382 mouse_dev->ops.default_handler = default_connection_handler; 492 383 493 384 // TODO: how to know if the device supports the request??? 494 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 385 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 495 386 hid_dev->usb_dev->interface_no, IDLE_RATE); 496 387 497 388 int rc = usb_mouse_create_function(hid_dev, mouse_dev); 498 389 if (rc != EOK) { 499 usb_mouse_destroy(mouse_dev); 390 free(mouse_dev->buttons); 391 free(mouse_dev); 500 392 return rc; 501 393 } 502 394 395 /* Save the Mouse device structure into the HID device structure. */ 396 *data = mouse_dev; 397 503 398 return EOK; 504 399 } 505 506 /*----------------------------------------------------------------------------*/ 507 400 /*----------------------------------------------------------------------------*/ 508 401 bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data) 509 402 { 510 403 if (hid_dev == NULL || data == NULL) { 511 usb_log_error( "Missing argument to the mouse polling callback."512 " \n");404 usb_log_error( 405 "Missing argument to the mouse polling callback.\n"); 513 406 return false; 514 407 } 515 408 516 usb_mouse_t *mouse_dev = (usb_mouse_t *)data;517 409 usb_mouse_t *mouse_dev = data; 410 518 411 return usb_mouse_process_report(hid_dev, mouse_dev); 519 412 } 520 521 /*----------------------------------------------------------------------------*/ 522 413 /*----------------------------------------------------------------------------*/ 523 414 void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data) 524 415 { 525 if (data != NULL) { 526 usb_mouse_destroy(data); 527 } 528 } 529 530 /*----------------------------------------------------------------------------*/ 531 416 if (data == NULL) 417 return; 418 419 usb_mouse_t *mouse_dev = data; 420 421 /* Hangup session to the console */ 422 if (mouse_dev->mouse_sess != NULL) { 423 const int ret = async_hangup(mouse_dev->mouse_sess); 424 if (ret != EOK) 425 usb_log_warning("Failed to hang up mouse session: " 426 "%p, %s.\n", mouse_dev->mouse_sess, str_error(ret)); 427 } 428 429 FUN_UNBIND_DESTROY(mouse_dev->mouse_fun); 430 431 free(mouse_dev->buttons); 432 free(mouse_dev); 433 } 434 /*----------------------------------------------------------------------------*/ 532 435 int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev) 533 436 { 534 437 int rc = usb_hid_parse_report_descriptor( 535 438 &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR, 536 USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);439 sizeof(USB_MOUSE_BOOT_REPORT_DESCRIPTOR)); 537 440 538 441 if (rc != EOK) { -
uspace/drv/bus/usb/usbhid/mouse/mousedev.h
rba72f2b r6843a9c 48 48 /** IPC session to console (consumer). */ 49 49 async_sess_t *mouse_sess; 50 async_sess_t *wheel_sess;51 50 52 51 /* Mouse buttons statuses. */ … … 57 56 /* DDF mouse function */ 58 57 ddf_fun_t *mouse_fun; 59 /* DDF mouse function */60 ddf_fun_t *wheel_fun;61 58 } usb_mouse_t; 62 59 -
uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
rba72f2b r6843a9c 67 67 /** IPC session to the console device (for sending key events). */ 68 68 async_sess_t *console_sess; 69 /** DDF function */70 ddf_fun_t *fun;71 69 } usb_multimedia_t; 72 70 73 71 74 72 /*----------------------------------------------------------------------------*/ 75 /** 73 /** 76 74 * Default handler for IPC methods not handled by DDF. 77 75 * … … 88 86 { 89 87 usb_log_debug(NAME " default_connection_handler()\n"); 90 91 usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data; 92 93 if (multim_dev == NULL) { 88 if (fun == NULL || fun->driver_data == NULL) { 94 89 async_answer_0(icallid, EINVAL); 95 90 return; 96 91 } 92 93 usb_multimedia_t *multim_dev = fun->driver_data; 97 94 98 95 async_sess_t *sess = … … 109 106 async_answer_0(icallid, EINVAL); 110 107 } 111 112 /*----------------------------------------------------------------------------*/ 113 108 /*----------------------------------------------------------------------------*/ 114 109 static ddf_dev_ops_t multimedia_ops = { 115 110 .default_handler = default_connection_handler 116 111 }; 117 118 112 /*----------------------------------------------------------------------------*/ 119 113 /** … … 127 121 * sends also these keys to application (otherwise it cannot use those 128 122 * keys at all). 129 * 130 * @param hid_dev 131 * @param lgtch_dev132 * @param type Type of the event (press / release). Recognized values: 123 * 124 * @param hid_dev 125 * @param multim_dev 126 * @param type Type of the event (press / release). Recognized values: 133 127 * KEY_PRESS, KEY_RELEASE 134 128 * @param key Key code of the key according to HID Usage Tables. 135 129 */ 136 static void usb_multimedia_push_ev( usb_hid_dev_t *hid_dev,130 static void usb_multimedia_push_ev( 137 131 usb_multimedia_t *multim_dev, int type, unsigned int key) 138 132 { 139 assert(hid_dev != NULL);140 133 assert(multim_dev != NULL); 141 134 142 kbd_event_t ev;143 144 ev.type = type;145 ev.key = key;146 ev.mods = 0;147 ev.c = 0;135 const kbd_event_t ev = { 136 .type = type, 137 .key = key, 138 .mods = 0, 139 .c = 0, 140 }; 148 141 149 142 usb_log_debug2(NAME " Sending key %d to the console\n", ev.key); … … 155 148 156 149 async_exch_t *exch = async_exchange_begin(multim_dev->console_sess); 157 async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c); 158 async_exchange_end(exch); 159 } 160 161 /*----------------------------------------------------------------------------*/ 162 150 if (exch != NULL) { 151 async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c); 152 async_exchange_end(exch); 153 } else { 154 usb_log_warning("Failed to send multimedia key.\n"); 155 } 156 } 157 /*----------------------------------------------------------------------------*/ 163 158 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data) 164 159 { 165 160 if (hid_dev == NULL || hid_dev->usb_dev == NULL) { 166 return EINVAL; /*! @todo Other return code? */161 return EINVAL; 167 162 } 168 163 … … 187 182 188 183 multim_dev->console_sess = NULL; 189 multim_dev->fun = fun;190 184 191 185 //todo Autorepeat? … … 199 193 } 200 194 201 usb_log_debug( "%sfunction created (handle: %" PRIun ").\n",202 NAME,fun->handle);195 usb_log_debug(NAME " function created (handle: %" PRIun ").\n", 196 fun->handle); 203 197 204 198 rc = ddf_fun_add_to_category(fun, "keyboard"); … … 207 201 "Could not add DDF function to category 'keyboard': %s.\n", 208 202 str_error(rc)); 209 ddf_fun_destroy(fun); 203 if (ddf_fun_unbind(fun) != EOK) { 204 usb_log_error("Failed to unbind %s, won't destroy.\n", 205 fun->name); 206 } else { 207 ddf_fun_destroy(fun); 208 } 210 209 return rc; 211 210 } 212 211 213 212 /* Save the KBD device structure into the HID device structure. */ 214 *data = multim_dev;213 *data = fun; 215 214 216 215 usb_log_debug(NAME " HID/multimedia structure initialized.\n"); 217 216 return EOK; 218 217 } 219 220 /*----------------------------------------------------------------------------*/ 221 218 /*----------------------------------------------------------------------------*/ 222 219 void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data) 223 220 { 224 if (hid_dev == NULL) { 225 return; 226 } 227 228 if (data != NULL) { 229 usb_multimedia_t *multim_dev = (usb_multimedia_t *)data; 230 // hangup session to the console 231 async_hangup(multim_dev->console_sess); 232 const int ret = ddf_fun_unbind(multim_dev->fun); 233 if (ret != EOK) { 234 usb_log_error("Failed to unbind multim function.\n"); 221 ddf_fun_t *fun = data; 222 if (fun != NULL && fun->driver_data != NULL) { 223 usb_multimedia_t *multim_dev = fun->driver_data; 224 /* Hangup session to the console */ 225 if (multim_dev->console_sess) 226 async_hangup(multim_dev->console_sess); 227 if (ddf_fun_unbind(fun) != EOK) { 228 usb_log_error("Failed to unbind %s, won't destroy.\n", 229 fun->name); 235 230 } else { 236 usb_log_debug2("%s unbound.\n", multim_dev->fun->name); 237 ddf_fun_destroy(multim_dev->fun); 231 usb_log_debug2("%s unbound.\n", fun->name); 232 /* This frees multim_dev too as it was stored in 233 * fun->data */ 234 ddf_fun_destroy(fun); 238 235 } 239 } 240 } 241 242 /*----------------------------------------------------------------------------*/ 243 236 } else { 237 usb_log_error( 238 "Failed to deinit multimedia subdriver, data missing.\n"); 239 } 240 } 241 /*----------------------------------------------------------------------------*/ 244 242 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data) 245 243 { 246 244 // TODO: checks 247 if (hid_dev == NULL || data == NULL) { 245 ddf_fun_t *fun = data; 246 if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) { 248 247 return false; 249 248 } 250 249 251 usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;250 usb_multimedia_t *multim_dev = fun->driver_data; 252 251 253 252 usb_hid_report_path_t *path = usb_hid_report_path(); 254 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0); 253 if (path == NULL) 254 return true; /* This might be a temporary failure. */ 255 256 int ret = 257 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0); 258 if (ret != EOK) { 259 usb_hid_report_path_free(path); 260 return true; /* This might be a temporary failure. */ 261 } 255 262 256 263 usb_hid_report_path_set_report_id(path, hid_dev->report_id); … … 261 268 USB_HID_REPORT_TYPE_INPUT); 262 269 263 /*! @todo Is this iterating OK if done multiple times? 264 * @todo The parsing is not OK 265 */ 270 //FIXME Is this iterating OK if done multiple times? 271 //FIXME The parsing is not OK. (what's wrong?) 266 272 while (field != NULL) { 267 if (field->value != 0) {268 usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 273 if (field->value != 0) { 274 usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 269 275 field->value, field->usage); 270 unsigned int key =276 const unsigned key = 271 277 usb_multimedia_map_usage(field->usage); 272 const char *key_str = 278 const char *key_str = 273 279 usbhid_multimedia_usage_to_str(field->usage); 274 280 usb_log_info("Pressed key: %s\n", key_str); 275 usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS, 276 key); 281 usb_multimedia_push_ev(multim_dev, KEY_PRESS, key); 277 282 } 278 283 279 284 field = usb_hid_report_get_sibling( 280 285 &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END 281 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 286 | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 282 287 USB_HID_REPORT_TYPE_INPUT); 283 288 } … … 287 292 return true; 288 293 } 289 290 294 /** 291 295 * @} -
uspace/drv/bus/usb/usbhid/subdrivers.c
rba72f2b r6843a9c 98 98 } 99 99 }, 100 {NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}101 100 }; 102 101 103 const int USB_HID_MAX_SUBDRIVERS =102 const size_t USB_HID_MAX_SUBDRIVERS = 104 103 sizeof(usb_hid_subdrivers) / sizeof(usb_hid_subdrivers[0]); 105 104 -
uspace/drv/bus/usb/usbhid/subdrivers.h
rba72f2b r6843a9c 84 84 85 85 extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[]; 86 extern const int USB_HID_MAX_SUBDRIVERS;86 extern const size_t USB_HID_MAX_SUBDRIVERS; 87 87 88 88 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/usbhid/usbhid.c
rba72f2b r6843a9c 51 51 #include "subdrivers.h" 52 52 53 /*----------------------------------------------------------------------------*/54 55 53 /* Array of endpoints expected on the device, NULL terminated. */ 56 54 const usb_endpoint_description_t *usb_hid_endpoints[] = { … … 60 58 NULL 61 59 }; 62 63 /*----------------------------------------------------------------------------*/ 64 60 /*----------------------------------------------------------------------------*/ 65 61 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev) 66 62 { … … 78 74 return EOK; 79 75 } 80 81 /*----------------------------------------------------------------------------*/ 82 76 /*----------------------------------------------------------------------------*/ 83 77 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev) 84 78 { … … 92 86 hid_dev->subdriver_count = 1; 93 87 // TODO 2 should be mouse, but find a better way 94 hid_dev->subdrivers[ 2] = usb_hid_subdrivers[0].subdriver;88 hid_dev->subdrivers[0] = usb_hid_subdrivers[2].subdriver; 95 89 96 90 return EOK; 97 91 } 98 99 /*----------------------------------------------------------------------------*/ 100 92 /*----------------------------------------------------------------------------*/ 101 93 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev) 102 94 { 103 assert(hid_dev != NULL && hid_dev->subdriver_count == 0); 95 assert(hid_dev != NULL); 96 assert(hid_dev->subdriver_count == 0); 104 97 105 98 hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t)); … … 117 110 return EOK; 118 111 } 119 120 /*----------------------------------------------------------------------------*/ 121 112 /*----------------------------------------------------------------------------*/ 122 113 static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev, 123 114 const usb_hid_subdriver_mapping_t *mapping) … … 128 119 return (hid_dev->usb_dev->descriptors.device.vendor_id 129 120 == mapping->vendor_id 130 && hid_dev->usb_dev->descriptors.device.product_id 121 && hid_dev->usb_dev->descriptors.device.product_id 131 122 == mapping->product_id); 132 123 } 133 134 /*----------------------------------------------------------------------------*/ 135 124 /*----------------------------------------------------------------------------*/ 136 125 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 137 126 const usb_hid_subdriver_mapping_t *mapping) … … 145 134 return false; 146 135 } 147 int i = 0; 148 while (mapping->usage_path[i].usage != 0149 || mapping->usage_path[i].usage_page != 0 ) {136 137 for (int i = 0; mapping->usage_path[i].usage != 0 138 || mapping->usage_path[i].usage_page != 0; ++i) { 150 139 if (usb_hid_report_path_append_item(usage_path, 151 140 mapping->usage_path[i].usage_page, … … 155 144 return false; 156 145 } 157 ++i;158 146 } 159 147 … … 165 153 do { 166 154 usb_log_debug("Trying report id %u\n", report_id); 167 168 155 if (report_id != 0) { 169 156 usb_hid_report_path_set_report_id(usage_path, … … 171 158 } 172 159 173 usb_hid_report_field_t *field = usb_hid_report_get_sibling( 174 &hid_dev->report, NULL, usage_path, mapping->compare, 175 USB_HID_REPORT_TYPE_INPUT); 160 const usb_hid_report_field_t *field = 161 usb_hid_report_get_sibling( 162 &hid_dev->report, NULL, usage_path, mapping->compare, 163 USB_HID_REPORT_TYPE_INPUT); 176 164 177 165 usb_log_debug("Field: %p\n", field); … … 190 178 return matches; 191 179 } 192 193 /*----------------------------------------------------------------------------*/ 194 180 /*----------------------------------------------------------------------------*/ 195 181 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 196 const usb_hid_subdriver_t **subdrivers, int count) 197 { 198 int i; 199 200 if (count <= 0) { 182 const usb_hid_subdriver_t **subdrivers, unsigned count) 183 { 184 assert(hid_dev); 185 assert(subdrivers); 186 187 if (count == 0) { 201 188 hid_dev->subdriver_count = 0; 202 189 hid_dev->subdrivers = NULL; … … 210 197 } 211 198 212 for (i = 0; i < count; ++i) { 213 hid_dev->subdrivers[i].init = subdrivers[i]->init; 214 hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit; 215 hid_dev->subdrivers[i].poll = subdrivers[i]->poll; 216 hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end; 199 for (unsigned i = 0; i < count; ++i) { 200 hid_dev->subdrivers[i] = *subdrivers[i]; 217 201 } 218 202 … … 227 211 return EOK; 228 212 } 229 230 /*----------------------------------------------------------------------------*/ 231 213 /*----------------------------------------------------------------------------*/ 232 214 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev) 233 215 { … … 235 217 236 218 const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS]; 237 238 int i = 0, count = 0; 239 const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i]; 240 241 bool ids_matched; 242 bool matched; 243 244 while (count < USB_HID_MAX_SUBDRIVERS && 245 (mapping->usage_path != NULL 246 || mapping->vendor_id >= 0 || mapping->product_id >= 0)) { 247 // check the vendor & product ID 219 unsigned count = 0; 220 221 for (unsigned i = 0; i < USB_HID_MAX_SUBDRIVERS; ++i) { 222 const usb_hid_subdriver_mapping_t *mapping = 223 &usb_hid_subdrivers[i]; 224 /* Check the vendor & product ID. */ 248 225 if (mapping->vendor_id >= 0 && mapping->product_id < 0) { 249 usb_log_warning("Missing Product ID for Vendor ID %d\n", 250 mapping->vendor_id); 251 return EINVAL; 226 usb_log_warning("Mapping[%d]: Missing Product ID for " 227 "Vendor ID %d\n", i, mapping->vendor_id); 252 228 } 253 229 if (mapping->product_id >= 0 && mapping->vendor_id < 0) { 254 usb_log_warning("Missing Vendor ID for Product ID %d\n", 255 mapping->product_id); 256 return EINVAL; 257 } 258 259 ids_matched = false; 260 matched = false; 261 262 if (mapping->vendor_id >= 0) { 263 assert(mapping->product_id >= 0); 230 usb_log_warning("Mapping[%d]: Missing Vendor ID for " 231 "Product ID %d\n", i, mapping->product_id); 232 } 233 234 bool matched = false; 235 236 /* Check ID match. */ 237 if (mapping->vendor_id >= 0 && mapping->product_id >= 0) { 264 238 usb_log_debug("Comparing device against vendor ID %u" 265 239 " and product ID %u.\n", mapping->vendor_id, … … 267 241 if (usb_hid_ids_match(hid_dev, mapping)) { 268 242 usb_log_debug("IDs matched.\n"); 269 ids_matched = true;243 matched = true; 270 244 } 271 245 } 272 246 247 /* Check usage match. */ 273 248 if (mapping->usage_path != NULL) { 274 249 usb_log_debug("Comparing device against usage path.\n"); 275 250 if (usb_hid_path_matches(hid_dev, mapping)) { 276 / / does not matter if IDs were matched251 /* Does not matter if IDs were matched. */ 277 252 matched = true; 278 253 } 279 } else {280 // matched only if IDs were matched and there is no path281 matched = ids_matched;282 254 } 283 255 … … 286 258 subdrivers[count++] = &mapping->subdriver; 287 259 } 288 289 mapping = &usb_hid_subdrivers[++i];290 260 } 291 261 292 262 /* We have all subdrivers determined, save them into the hid device */ 293 // TODO Dowe really need this complicated stuff if there is294 // max_subdrivers limitation?295 263 return usb_hid_save_subdrivers(hid_dev, subdrivers, count); 296 264 } 297 298 /*----------------------------------------------------------------------------*/ 299 265 /*----------------------------------------------------------------------------*/ 300 266 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev) 301 267 { … … 303 269 assert(dev); 304 270 305 if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) { 306 usb_log_debug("Found keyboard endpoint.\n"); 307 // save the pipe index 308 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO; 309 } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) { 310 usb_log_debug("Found mouse endpoint.\n"); 311 // save the pipe index 312 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO; 313 } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) { 314 usb_log_debug("Found generic HID endpoint.\n"); 315 // save the pipe index 316 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO; 317 } else { 318 usb_log_error("None of supported endpoints found - probably" 319 " not a supported device.\n"); 320 return ENOTSUP; 321 } 322 323 return EOK; 324 } 325 326 /*----------------------------------------------------------------------------*/ 327 271 static const struct { 272 unsigned ep_number; 273 const char* description; 274 } endpoints[] = { 275 {USB_HID_KBD_POLL_EP_NO, "Keyboard endpoint"}, 276 {USB_HID_MOUSE_POLL_EP_NO, "Mouse endpoint"}, 277 {USB_HID_GENERIC_POLL_EP_NO, "Generic HID endpoint"}, 278 }; 279 280 for (unsigned i = 0; i < sizeof(endpoints)/sizeof(endpoints[0]); ++i) { 281 if (endpoints[i].ep_number >= dev->pipes_count) { 282 return EINVAL; 283 } 284 if (dev->pipes[endpoints[i].ep_number].present) { 285 usb_log_debug("Found: %s.\n", endpoints[i].description); 286 hid_dev->poll_pipe_index = endpoints[i].ep_number; 287 return EOK; 288 } 289 } 290 return ENOTSUP; 291 } 292 /*----------------------------------------------------------------------------*/ 328 293 static int usb_hid_init_report(usb_hid_dev_t *hid_dev) 329 294 { … … 357 322 return EOK; 358 323 } 359 360 /*----------------------------------------------------------------------------*/ 361 324 /*----------------------------------------------------------------------------*/ 325 /* 326 * This functions initializes required structures from the device's descriptors 327 * and starts new fibril for polling the keyboard for events and another one for 328 * handling auto-repeat of keys. 329 * 330 * During initialization, the keyboard is switched into boot protocol, the idle 331 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 332 * when a key is pressed or released. Finally, the LED lights are turned on 333 * according to the default setup of lock keys. 334 * 335 * @note By default, the keyboards is initialized with Num Lock turned on and 336 * other locks turned off. 337 * 338 * @param hid_dev Device to initialize, non-NULL. 339 * @param dev USB device, non-NULL. 340 * @return Error code. 341 */ 362 342 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev) 363 343 { 364 int rc, i; 344 assert(hid_dev); 345 assert(dev); 365 346 366 347 usb_log_debug("Initializing HID structure...\n"); 367 368 if (hid_dev == NULL) {369 usb_log_error("Failed to init HID structure: no structure given"370 ".\n");371 return EINVAL;372 }373 374 if (dev == NULL) {375 usb_log_error("Failed to init HID structure: no USB device"376 " given.\n");377 return EINVAL;378 }379 348 380 349 usb_hid_report_init(&hid_dev->report); … … 384 353 hid_dev->poll_pipe_index = -1; 385 354 386 rc = usb_hid_check_pipes(hid_dev, dev);355 int rc = usb_hid_check_pipes(hid_dev, dev); 387 356 if (rc != EOK) { 388 357 return rc; … … 390 359 391 360 /* Get the report descriptor and parse it. */ 392 rc = usb_hid_process_report_descriptor( hid_dev->usb_dev,393 &hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);394 395 bool fallback = false; 396 361 rc = usb_hid_process_report_descriptor( 362 hid_dev->usb_dev, &hid_dev->report, &hid_dev->report_desc, 363 &hid_dev->report_desc_size); 364 365 /* If report parsing went well, find subdrivers. */ 397 366 if (rc == EOK) { 398 // try to find subdrivers that may want to handle this device 399 rc = usb_hid_find_subdrivers(hid_dev); 400 if (rc != EOK || hid_dev->subdriver_count == 0) { 401 // try to fall back to the boot protocol if available 402 usb_log_info("No subdrivers found to handle this" 403 " device.\n"); 404 fallback = true; 405 assert(hid_dev->subdrivers == NULL); 406 assert(hid_dev->subdriver_count == 0); 407 } 367 usb_hid_find_subdrivers(hid_dev); 408 368 } else { 409 usb_log_error("Failed to parse Report descriptor.\n"); 410 // try to fall back to the boot protocol if available 411 fallback = true; 412 } 413 414 if (fallback) { 415 // fall back to boot protocol 369 usb_log_error("Failed to parse report descriptor: fallback.\n"); 370 hid_dev->subdrivers = NULL; 371 hid_dev->subdriver_count = 0; 372 } 373 374 usb_log_debug("Subdriver count(before trying boot protocol): %d\n", 375 hid_dev->subdriver_count); 376 377 /* No subdrivers, fall back to the boot protocol if available. */ 378 if (hid_dev->subdriver_count == 0) { 379 assert(hid_dev->subdrivers == NULL); 380 usb_log_info("No subdrivers found to handle device, trying " 381 "boot protocol.\n"); 382 416 383 switch (hid_dev->poll_pipe_index) { 417 384 case USB_HID_KBD_POLL_EP_NO: … … 419 386 rc = usb_kbd_set_boot_protocol(hid_dev); 420 387 if (rc == EOK) { 421 rc =usb_hid_set_boot_kbd_subdriver(hid_dev);388 usb_hid_set_boot_kbd_subdriver(hid_dev); 422 389 } 423 390 break; … … 426 393 rc = usb_mouse_set_boot_protocol(hid_dev); 427 394 if (rc == EOK) { 428 rc =usb_hid_set_boot_mouse_subdriver(hid_dev);395 usb_hid_set_boot_mouse_subdriver(hid_dev); 429 396 } 430 397 break; … … 432 399 assert(hid_dev->poll_pipe_index 433 400 == USB_HID_GENERIC_POLL_EP_NO); 434 435 401 usb_log_info("Falling back to generic HID driver.\n"); 436 rc = usb_hid_set_generic_hid_subdriver(hid_dev); 437 } 438 } 439 440 if (rc != EOK) { 441 usb_log_error("No subdriver for handling this device could be" 442 " initialized: %s.\n", str_error(rc)); 443 usb_log_debug("Subdriver count: %d\n", 444 hid_dev->subdriver_count); 445 } else { 446 bool ok = false; 447 448 usb_log_debug("Subdriver count: %d\n", 449 hid_dev->subdriver_count); 450 451 for (i = 0; i < hid_dev->subdriver_count; ++i) { 452 if (hid_dev->subdrivers[i].init != NULL) { 453 usb_log_debug("Initializing subdriver %d.\n",i); 454 rc = hid_dev->subdrivers[i].init(hid_dev, 455 &hid_dev->subdrivers[i].data); 456 if (rc != EOK) { 457 usb_log_warning("Failed to initialize" 458 " HID subdriver structure.\n"); 459 } else { 460 // at least one subdriver initialized 461 ok = true; 462 } 402 usb_hid_set_generic_hid_subdriver(hid_dev); 403 } 404 } 405 406 usb_log_debug("Subdriver count(after trying boot protocol): %d\n", 407 hid_dev->subdriver_count); 408 409 /* Still no subdrivers? */ 410 if (hid_dev->subdriver_count == 0) { 411 assert(hid_dev->subdrivers == NULL); 412 usb_log_error( 413 "No subdriver for handling this device could be found.\n"); 414 return ENOTSUP; 415 } 416 417 /* 418 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da 419 * do nej. 420 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 421 * vyplnenu strukturu usbhid_iface_t. 422 * 3) klientska aplikacia - musi si rucne vytvorit telefon 423 * (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 424 * k tej fcii. 425 * pouzit usb/classes/hid/iface.h - prvy int je telefon 426 */ 427 bool ok = false; 428 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 429 if (hid_dev->subdrivers[i].init != NULL) { 430 usb_log_debug("Initializing subdriver %d.\n",i); 431 const int pret = hid_dev->subdrivers[i].init(hid_dev, 432 &hid_dev->subdrivers[i].data); 433 if (pret != EOK) { 434 usb_log_warning("Failed to initialize" 435 " HID subdriver structure: %s.\n", 436 str_error(pret)); 437 rc = pret; 463 438 } else { 439 /* At least one subdriver initialized. */ 464 440 ok = true; 465 441 } 466 } 467 468 rc = (ok) ? EOK : -1; // what error to report 469 } 470 471 472 if (rc == EOK) { 473 // save max input report size and allocate space for the report 442 } else { 443 /* Does not need initialization. */ 444 ok = true; 445 } 446 } 447 448 if (ok) { 449 /* Save max input report size and 450 * allocate space for the report */ 474 451 rc = usb_hid_init_report(hid_dev); 475 452 if (rc != EOK) { … … 481 458 return rc; 482 459 } 483 484 /*----------------------------------------------------------------------------*/ 485 460 /*----------------------------------------------------------------------------*/ 486 461 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 487 462 size_t buffer_size, void *arg) … … 516 491 bool cont = false; 517 492 /* Continue if at least one of the subdrivers want to continue */ 518 for ( inti = 0; i < hid_dev->subdriver_count; ++i) {493 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 519 494 if (hid_dev->subdrivers[i].poll != NULL) { 520 495 cont = cont || hid_dev->subdrivers[i].poll( … … 525 500 return cont; 526 501 } 527 528 /*----------------------------------------------------------------------------*/ 529 502 /*----------------------------------------------------------------------------*/ 530 503 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg) 531 504 { … … 535 508 usb_hid_dev_t *hid_dev = arg; 536 509 537 for ( inti = 0; i < hid_dev->subdriver_count; ++i) {510 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 538 511 if (hid_dev->subdrivers[i].poll_end != NULL) { 539 512 hid_dev->subdrivers[i].poll_end( … … 544 517 hid_dev->running = false; 545 518 } 546 547 /*----------------------------------------------------------------------------*/ 548 519 /*----------------------------------------------------------------------------*/ 549 520 void usb_hid_new_report(usb_hid_dev_t *hid_dev) 550 521 { 551 522 ++hid_dev->report_nr; 552 523 } 553 554 /*----------------------------------------------------------------------------*/ 555 524 /*----------------------------------------------------------------------------*/ 556 525 int usb_hid_report_number(const usb_hid_dev_t *hid_dev) 557 526 { 558 527 return hid_dev->report_nr; 559 528 } 560 561 /*----------------------------------------------------------------------------*/ 562 529 /*----------------------------------------------------------------------------*/ 563 530 void usb_hid_deinit(usb_hid_dev_t *hid_dev) 564 531 { … … 570 537 hid_dev->subdrivers, hid_dev->subdriver_count); 571 538 572 for ( inti = 0; i < hid_dev->subdriver_count; ++i) {539 for (unsigned i = 0; i < hid_dev->subdriver_count; ++i) { 573 540 if (hid_dev->subdrivers[i].deinit != NULL) { 574 541 hid_dev->subdrivers[i].deinit(hid_dev, -
uspace/drv/bus/usb/usbhid/usbhid.h
rba72f2b r6843a9c 104 104 105 105 /** Index of the polling pipe in usb_hid_endpoints array. */ 106 intpoll_pipe_index;106 unsigned poll_pipe_index; 107 107 108 108 /** Subdrivers. */ … … 110 110 111 111 /** Number of subdrivers. */ 112 intsubdriver_count;112 unsigned subdriver_count; 113 113 114 114 /** Report descriptor. */ -
uspace/drv/bus/usb/usbhub/main.c
rba72f2b r6843a9c 47 47 * For more information see section 11.15.1 of USB 1.1 specification. 48 48 */ 49 static usb_endpoint_description_t hub_status_change_endpoint_description = { 49 static const usb_endpoint_description_t hub_status_change_endpoint_description = 50 { 50 51 .transfer_type = USB_TRANSFER_INTERRUPT, 51 52 .direction = USB_DIRECTION_IN, … … 56 57 }; 57 58 58 /** 59 * USB hub driver operations 60 * 61 * The most important one is device_add, which is set to usb_hub_device_add. 62 */ 63 static usb_driver_ops_t usb_hub_driver_ops = { 59 /** USB hub driver operations. */ 60 static const usb_driver_ops_t usb_hub_driver_ops = { 64 61 .device_add = usb_hub_device_add, 62 // .device_rem = usb_hub_device_remove, 65 63 .device_gone = usb_hub_device_gone, 66 64 }; … … 72 70 }; 73 71 /** Static usb hub driver information. */ 74 static usb_driver_t usb_hub_driver = {72 static const usb_driver_t usb_hub_driver = { 75 73 .name = NAME, 76 74 .ops = &usb_hub_driver_ops, 77 75 .endpoints = usb_hub_endpoints 78 76 }; 79 80 77 81 78 int main(int argc, char *argv[]) -
uspace/drv/bus/usb/usbhub/port.c
rba72f2b r6843a9c 35 35 36 36 #include <bool.h> 37 #include <devman.h>38 37 #include <errno.h> 39 38 #include <str_error.h> … … 288 287 port->attached_device.fun = NULL; 289 288 290 ret = usb_hc_connection_open(&hub->connection); 291 if (ret == EOK) { 292 ret = usb_hc_unregister_device(&hub->connection, 293 port->attached_device.address); 294 if (ret != EOK) { 295 usb_log_warning("Failed to unregister address of the " 296 "removed device: %s.\n", str_error(ret)); 297 } 298 ret = usb_hc_connection_close(&hub->connection); 299 if (ret != EOK) { 300 usb_log_warning("Failed to close hc connection %s.\n", 301 str_error(ret)); 302 } 303 304 } else { 305 usb_log_warning("Failed to open hc connection %s.\n", 306 str_error(ret)); 289 ret = usb_hub_unregister_device(&hub->usb_device->hc_conn, 290 &port->attached_device); 291 if (ret != EOK) { 292 usb_log_warning("Failed to unregister address of the " 293 "removed device: %s.\n", str_error(ret)); 307 294 } 308 295 … … 401 388 { 402 389 usb_hub_port_t *port = arg; 390 assert(port); 403 391 const int rc = 404 392 usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET); … … 437 425 438 426 const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 439 &data->hub-> connection, data->speed, enable_port_callback,427 &data->hub->usb_device->hc_conn, data->speed, enable_port_callback, 440 428 data->port, &new_address, NULL, NULL, &child_fun); 441 429 442 if (rc != EOK) { 430 if (rc == EOK) { 431 fibril_mutex_lock(&data->port->mutex); 432 data->port->attached_device.fun = child_fun; 433 data->port->attached_device.address = new_address; 434 fibril_mutex_unlock(&data->port->mutex); 435 436 usb_log_info("Detected new device on `%s' (port %zu), " 437 "address %d (handle %" PRIun ").\n", 438 data->hub->usb_device->ddf_dev->name, 439 data->port->port_number, new_address, child_fun->handle); 440 } else { 443 441 usb_log_error("Failed registering device on port %zu: %s.\n", 444 442 data->port->port_number, str_error(rc)); 445 goto leave; 446 } 447 448 fibril_mutex_lock(&data->port->mutex); 449 data->port->attached_device.fun = child_fun; 450 data->port->attached_device.address = new_address; 451 fibril_mutex_unlock(&data->port->mutex); 452 453 usb_log_info("Detected new device on `%s' (port %zu), " 454 "address %d (handle %" PRIun ").\n", 455 data->hub->usb_device->ddf_dev->name, data->port->port_number, 456 new_address, child_fun->handle); 457 458 leave: 443 } 444 445 459 446 fibril_mutex_lock(&data->hub->pending_ops_mutex); 460 447 assert(data->hub->pending_ops_count > 0); -
uspace/drv/bus/usb/usbhub/port.h
rba72f2b r6843a9c 44 44 /** Information about single port on a hub. */ 45 45 typedef struct { 46 /* Port number as reported in descriptors. */ 46 47 size_t port_number; 48 /** Device communication pipe. */ 47 49 usb_pipe_t *control_pipe; 48 50 /** Mutex needed not only by CV for checking port reset. */ -
uspace/drv/bus/usb/usbhub/usbhub.c
rba72f2b r6843a9c 68 68 69 69 static int usb_set_first_configuration(usb_device_t *usb_device); 70 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev);71 70 static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev); 72 71 static void usb_hub_over_current(const usb_hub_dev_t *hub_dev, … … 75 74 static void usb_hub_polling_terminated_callback(usb_device_t *device, 76 75 bool was_error, void *data); 77 /** 78 * Initialize hub device driver fibril 76 77 /** 78 * Initialize hub device driver structure. 79 79 * 80 80 * Creates hub representation and fibril that periodically checks hub's status. 81 81 * Hub representation is passed to the fibril. 82 * @param usb_dev generic usb device information 83 * @return error code 84 */ 85 int usb_hub_device_add(usb_device_t *usb_dev) 86 { 87 assert(usb_dev); 88 /* Create driver soft-state structure */ 89 usb_hub_dev_t *hub_dev = 90 usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t)); 91 if (hub_dev == NULL) { 92 usb_log_error("Failed to create hub driver structure.\n"); 93 return ENOMEM; 94 } 95 hub_dev->usb_device = usb_dev; 96 hub_dev->pending_ops_count = 0; 97 hub_dev->running = false; 98 fibril_mutex_initialize(&hub_dev->pending_ops_mutex); 99 fibril_condvar_initialize(&hub_dev->pending_ops_cv); 100 101 102 int opResult = usb_pipe_start_long_transfer(&usb_dev->ctrl_pipe); 103 if (opResult != EOK) { 104 usb_log_error("Failed to start long ctrl pipe transfer: %s\n", 105 str_error(opResult)); 106 return opResult; 107 } 108 109 /* Set hub's first configuration. (There should be only one) */ 110 opResult = usb_set_first_configuration(usb_dev); 111 if (opResult != EOK) { 112 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 113 usb_log_error("Could not set hub configuration: %s\n", 114 str_error(opResult)); 115 return opResult; 116 } 117 118 /* Get port count and create attached_devices. */ 119 opResult = usb_hub_process_hub_specific_info(hub_dev); 120 if (opResult != EOK) { 121 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 122 usb_log_error("Could process hub specific info, %s\n", 123 str_error(opResult)); 124 return opResult; 125 } 126 127 /* Create hub control function. */ 128 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n"); 129 hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev, 130 fun_exposed, HUB_FNC_NAME); 131 if (hub_dev->hub_fun == NULL) { 132 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 133 usb_log_error("Failed to create hub function.\n"); 134 return ENOMEM; 135 } 136 137 /* Bind hub control function. */ 138 opResult = ddf_fun_bind(hub_dev->hub_fun); 139 if (opResult != EOK) { 140 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 141 usb_log_error("Failed to bind hub function: %s.\n", 142 str_error(opResult)); 143 ddf_fun_destroy(hub_dev->hub_fun); 144 return opResult; 145 } 146 147 /* Start hub operation. */ 148 opResult = usb_device_auto_poll(hub_dev->usb_device, 0, 149 hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8), 150 usb_hub_polling_terminated_callback, hub_dev); 151 if (opResult != EOK) { 152 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 153 /* Function is already bound */ 154 ddf_fun_unbind(hub_dev->hub_fun); 155 ddf_fun_destroy(hub_dev->hub_fun); 156 usb_log_error("Failed to create polling fibril: %s.\n", 157 str_error(opResult)); 158 return opResult; 159 } 160 hub_dev->running = true; 161 usb_log_info("Controlling hub '%s' (%zu ports).\n", 162 hub_dev->usb_device->ddf_dev->name, hub_dev->port_count); 163 164 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 165 return EOK; 166 } 167 /*----------------------------------------------------------------------------*/ 168 /** 169 * Turn off power to all ports. 170 * 171 * @param usb_dev generic usb device information 172 * @return error code 173 */ 174 int usb_hub_device_remove(usb_device_t *usb_dev) 175 { 176 return ENOTSUP; 177 } 178 /*----------------------------------------------------------------------------*/ 179 /** 180 * Remove all attached devices 82 181 * @param usb_dev generic usb device information 83 182 * @return error code … … 121 220 } 122 221 /*----------------------------------------------------------------------------*/ 123 /**124 * Initialize hub device driver fibril125 *126 * Creates hub representation and fibril that periodically checks hub's status.127 * Hub representation is passed to the fibril.128 * @param usb_dev generic usb device information129 * @return error code130 */131 int usb_hub_device_add(usb_device_t *usb_dev)132 {133 assert(usb_dev);134 /* Create driver soft-state structure */135 usb_hub_dev_t *hub_dev = usb_hub_dev_create(usb_dev);136 if (hub_dev == NULL) {137 usb_log_error("Failed to create hun driver structure.\n");138 return ENOMEM;139 }140 141 /* Create hc connection */142 usb_log_debug("Initializing USB wire abstraction.\n");143 int opResult = usb_hc_connection_initialize_from_device(144 &hub_dev->connection, hub_dev->usb_device->ddf_dev);145 if (opResult != EOK) {146 usb_log_error("Could not initialize connection to device: %s\n",147 str_error(opResult));148 free(hub_dev);149 return opResult;150 }151 152 /* Set hub's first configuration. (There should be only one) */153 opResult = usb_set_first_configuration(usb_dev);154 if (opResult != EOK) {155 usb_log_error("Could not set hub configuration: %s\n",156 str_error(opResult));157 free(hub_dev);158 return opResult;159 }160 161 /* Get port count and create attached_devices. */162 opResult = usb_hub_process_hub_specific_info(hub_dev);163 if (opResult != EOK) {164 usb_log_error("Could process hub specific info, %s\n",165 str_error(opResult));166 free(hub_dev);167 return opResult;168 }169 170 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");171 hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,172 fun_exposed, HUB_FNC_NAME);173 if (hub_dev->hub_fun == NULL) {174 usb_log_error("Failed to create hub function.\n");175 free(hub_dev);176 return ENOMEM;177 }178 179 opResult = ddf_fun_bind(hub_dev->hub_fun);180 if (opResult != EOK) {181 usb_log_error("Failed to bind hub function: %s.\n",182 str_error(opResult));183 free(hub_dev);184 ddf_fun_destroy(hub_dev->hub_fun);185 return opResult;186 }187 188 opResult = usb_device_auto_poll(hub_dev->usb_device, 0,189 hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),190 usb_hub_polling_terminated_callback, hub_dev);191 if (opResult != EOK) {192 /* Function is already bound */193 ddf_fun_unbind(hub_dev->hub_fun);194 ddf_fun_destroy(hub_dev->hub_fun);195 free(hub_dev);196 usb_log_error("Failed to create polling fibril: %s.\n",197 str_error(opResult));198 return opResult;199 }200 hub_dev->running = true;201 usb_log_info("Controlling hub '%s' (%zu ports).\n",202 hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);203 204 return EOK;205 }206 /*----------------------------------------------------------------------------*/207 222 /** Callback for polling hub for changes. 208 223 * … … 243 258 /*----------------------------------------------------------------------------*/ 244 259 /** 245 * create usb_hub_dev_t structure246 *247 * Does only basic copying of known information into new structure.248 * @param usb_dev usb device structure249 * @return basic usb_hub_dev_t structure250 */251 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev)252 {253 assert(usb_dev);254 usb_hub_dev_t *hub_dev =255 usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));256 if (!hub_dev)257 return NULL;258 259 hub_dev->usb_device = usb_dev;260 hub_dev->ports = NULL;261 hub_dev->port_count = 0;262 hub_dev->pending_ops_count = 0;263 hub_dev->running = false;264 fibril_mutex_initialize(&hub_dev->pending_ops_mutex);265 fibril_condvar_initialize(&hub_dev->pending_ops_cv);266 267 return hub_dev;268 }269 /*----------------------------------------------------------------------------*/270 /**271 260 * Load hub-specific information into hub_dev structure and process if needed 272 261 * … … 311 300 } 312 301 313 const bool is_power_switched =302 hub_dev->power_switched = 314 303 !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG); 315 if (is_power_switched) { 316 usb_log_debug("Hub power switched\n"); 317 const bool per_port_power = descriptor.characteristics 318 & HUB_CHAR_POWER_PER_PORT_FLAG; 319 320 for (size_t port = 0; port < hub_dev->port_count; ++port) { 321 usb_log_debug("Powering port %zu.\n", port); 322 opResult = usb_hub_port_set_feature( 323 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 324 if (opResult != EOK) { 325 usb_log_error("Cannot power on port %zu: %s.\n", 326 port, str_error(opResult)); 327 } else { 328 if (!per_port_power) { 329 usb_log_debug( 330 "Ganged power switching mode, " 331 "one port is enough.\n"); 332 break; 333 } 304 hub_dev->per_port_power = 305 descriptor.characteristics & HUB_CHAR_POWER_PER_PORT_FLAG; 306 307 if (!hub_dev->power_switched) { 308 usb_log_info( 309 "Power switching not supported, ports always powered.\n"); 310 return EOK; 311 } 312 313 usb_log_info("Hub port power switching enabled.\n"); 314 315 for (size_t port = 0; port < hub_dev->port_count; ++port) { 316 usb_log_debug("Powering port %zu.\n", port); 317 const int ret = usb_hub_port_set_feature( 318 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 319 320 if (ret != EOK) { 321 usb_log_error("Cannot power on port %zu: %s.\n", 322 hub_dev->ports[port].port_number, str_error(ret)); 323 } else { 324 if (!hub_dev->per_port_power) { 325 usb_log_debug("Ganged power switching, " 326 "one port is enough.\n"); 327 break; 334 328 } 335 329 } 336 } else {337 usb_log_debug("Power not switched, ports always powered\n");338 330 } 339 331 return EOK; … … 402 394 usb_log_warning("Detected hub over-current condition, " 403 395 "all ports should be powered off."); 404 } else { 405 /* Over-current condition is gone, it is safe to turn the 406 * ports on. */ 407 for (size_t port = 0; port < hub_dev->port_count; ++port) { 408 const int opResult = usb_hub_port_set_feature( 409 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 410 // TODO: consider power policy here 411 if (opResult != EOK) { 412 usb_log_warning( 413 "HUB OVER-CURRENT GONE: Cannot power on " 414 "port %zu; %s\n", 415 port, str_error(opResult)); 416 } 417 } 418 } 419 const int opResult = usb_request_clear_feature( 420 &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS, 421 USB_REQUEST_RECIPIENT_DEVICE, 422 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); 423 if (opResult != EOK) { 424 usb_log_error( 425 "Failed to clear hub over-current change flag: %s.\n", 426 str_error(opResult)); 427 } 396 return; 397 } 398 399 /* Ports are always powered. */ 400 if (!hub_dev->power_switched) 401 return; 402 403 /* Over-current condition is gone, it is safe to turn the ports on. */ 404 for (size_t port = 0; port < hub_dev->port_count; ++port) { 405 const int ret = usb_hub_port_set_feature( 406 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 407 if (ret != EOK) { 408 usb_log_warning("HUB OVER-CURRENT GONE: Cannot power on" 409 " port %zu: %s\n", hub_dev->ports[port].port_number, 410 str_error(ret)); 411 } else { 412 if (!hub_dev->per_port_power) 413 return; 414 } 415 } 416 428 417 } 429 418 /*----------------------------------------------------------------------------*/ … … 461 450 if (status & USB_HUB_STATUS_C_OVER_CURRENT) { 462 451 usb_hub_over_current(hub_dev, status); 452 /* Ack change in hub OC flag */ 453 const int ret = usb_request_clear_feature( 454 &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS, 455 USB_REQUEST_RECIPIENT_DEVICE, 456 USB_HUB_FEATURE_C_HUB_OVER_CURRENT, 0); 457 if (ret != EOK) { 458 usb_log_error("Failed to clear hub over-current " 459 "change flag: %s.\n", str_error(opResult)); 460 } 463 461 } 464 462 … … 477 475 * Just ACK the change. 478 476 */ 479 const int opResult = usb_request_clear_feature(477 const int ret = usb_request_clear_feature( 480 478 control_pipe, USB_REQUEST_TYPE_CLASS, 481 479 USB_REQUEST_RECIPIENT_DEVICE, 482 480 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); 483 481 if (opResult != EOK) { 484 usb_log_error( 485 "Failed to clear hub power change flag: %s.\n", 486 str_error(opResult)); 482 usb_log_error("Failed to clear hub power change " 483 "flag: %s.\n", str_error(ret)); 487 484 } 488 485 } -
uspace/drv/bus/usb/usbhub/usbhub.h
rba72f2b r6843a9c 57 57 /** Port structures, one for each port */ 58 58 usb_hub_port_t *ports; 59 /** Connection to hcd */60 usb_hc_connection_t connection;61 59 /** Generic usb device data*/ 62 60 usb_device_t *usb_device; … … 77 75 /** Status indicator */ 78 76 bool running; 77 /** Hub supports port power switching. */ 78 bool power_switched; 79 /** Each port is switched individually. */ 80 bool per_port_power; 79 81 }; 80 82 81 83 int usb_hub_device_add(usb_device_t *usb_dev); 84 int usb_hub_device_remove(usb_device_t *usb_dev); 82 85 int usb_hub_device_gone(usb_device_t *usb_dev); 83 86 -
uspace/drv/bus/usb/usbmast/bo_trans.c
rba72f2b r6843a9c 67 67 int retval = EOK; 68 68 size_t act_size; 69 usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;70 usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;69 usb_pipe_t *bulk_in_pipe = &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe; 70 usb_pipe_t *bulk_out_pipe = &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe; 71 71 usb_direction_t ddir; 72 72 void *dbuf; … … 118 118 if (ddir == USB_DIRECTION_IN) { 119 119 usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe, 120 mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);120 &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe); 121 121 } else { 122 122 usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe, 123 mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);123 &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe); 124 124 } 125 125 } else if (rc != EOK) { … … 216 216 usb_massstor_reset(mdev); 217 217 usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe, 218 mdev->usb_dev->pipes[BULK_IN_EP].pipe);218 &mdev->usb_dev->pipes[BULK_IN_EP].pipe); 219 219 usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe, 220 mdev->usb_dev->pipes[BULK_OUT_EP].pipe);220 &mdev->usb_dev->pipes[BULK_OUT_EP].pipe); 221 221 } 222 222 -
uspace/drv/bus/usb/usbmast/main.c
rba72f2b r6843a9c 55 55 #define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe) 56 56 57 static usb_endpoint_description_t bulk_in_ep = {57 static const usb_endpoint_description_t bulk_in_ep = { 58 58 .transfer_type = USB_TRANSFER_BULK, 59 59 .direction = USB_DIRECTION_IN, … … 63 63 .flags = 0 64 64 }; 65 static usb_endpoint_description_t bulk_out_ep = {65 static const usb_endpoint_description_t bulk_out_ep = { 66 66 .transfer_type = USB_TRANSFER_BULK, 67 67 .direction = USB_DIRECTION_OUT, … … 106 106 } 107 107 108 /** Callback when a device is about to be removed. 109 * 110 * @param dev Representation of USB device. 111 * @return Error code. 112 */ 113 static int usbmast_device_remove(usb_device_t *dev) 114 { 115 //TODO: flush buffers, or whatever. 116 //TODO: remove device 117 return ENOTSUP; 118 } 119 108 120 /** Callback when new device is attached and recognized as a mass storage. 109 121 * 110 * @param dev Representation of a theUSB device.122 * @param dev Representation of USB device. 111 123 * @return Error code. 112 124 */ … … 128 140 129 141 usb_log_info("Initializing mass storage `%s'.\n", dev->ddf_dev->name); 130 usb_log_debug(" 131 dev->pipes[BULK_IN_EP].pipe ->endpoint_no,132 (size_t) dev->pipes[BULK_IN_EP].descriptor->max_packet_size);142 usb_log_debug("Bulk in endpoint: %d [%zuB].\n", 143 dev->pipes[BULK_IN_EP].pipe.endpoint_no, 144 dev->pipes[BULK_IN_EP].pipe.max_packet_size); 133 145 usb_log_debug("Bulk out endpoint: %d [%zuB].\n", 134 dev->pipes[BULK_OUT_EP].pipe ->endpoint_no,135 (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);146 dev->pipes[BULK_OUT_EP].pipe.endpoint_no, 147 dev->pipes[BULK_OUT_EP].pipe.max_packet_size); 136 148 137 149 usb_log_debug("Get LUN count...\n"); … … 288 300 return; 289 301 } 290 291 comm_buf = as_get_mappable_page(comm_size);292 if (comm_buf == NULL) {302 303 (void) async_share_out_finalize(callid, &comm_buf); 304 if (comm_buf == AS_MAP_FAILED) { 293 305 async_answer_0(callid, EHANGUP); 294 306 return; 295 307 } 296 297 (void) async_share_out_finalize(callid, comm_buf); 298 308 299 309 mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data; 300 310 … … 336 346 337 347 /** USB mass storage driver ops. */ 338 static usb_driver_ops_t usbmast_driver_ops = {348 static const usb_driver_ops_t usbmast_driver_ops = { 339 349 .device_add = usbmast_device_add, 350 .device_rem = usbmast_device_remove, 340 351 .device_gone = usbmast_device_gone, 341 352 }; 342 353 343 354 /** USB mass storage driver. */ 344 static usb_driver_t usbmast_driver = {355 static const usb_driver_t usbmast_driver = { 345 356 .name = NAME, 346 357 .ops = &usbmast_driver_ops, -
uspace/drv/bus/usb/usbmid/explore.c
rba72f2b r6843a9c 54 54 * @return Interface @p interface_no is already present in the list. 55 55 */ 56 static bool interface_in_list( list_t *list, int interface_no)56 static bool interface_in_list(const list_t *list, int interface_no) 57 57 { 58 58 list_foreach(*list, l) { 59 usbmid_interface_t *iface 60 = list_get_instance(l, usbmid_interface_t, link); 59 usbmid_interface_t *iface = usbmid_interface_from_link(l); 61 60 if (iface->interface_no == interface_no) { 62 61 return true; … … 82 81 }; 83 82 84 usb_dp_parser_t parser = {83 static const usb_dp_parser_t parser = { 85 84 .nesting = usb_dp_standard_descriptor_nesting 86 85 }; 87 86 88 87 const uint8_t *interface_ptr = 89 usb_dp_get_nested_descriptor(&parser, &data, data.data); 90 if (interface_ptr == NULL) { 91 return; 92 } 93 94 do { 95 if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) { 96 goto next_descriptor; 97 } 98 99 usb_standard_interface_descriptor_t *interface 88 usb_dp_get_nested_descriptor(&parser, &data, config_descriptor); 89 90 /* Walk all descriptors nested in the current configuration decriptor; 91 * i.e. all interface descriptors. */ 92 for (;interface_ptr != NULL; 93 interface_ptr = usb_dp_get_sibling_descriptor( 94 &parser, &data, config_descriptor, interface_ptr)) 95 { 96 /* The second byte is DESCTYPE byte in all desriptors. */ 97 if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) 98 continue; 99 100 const usb_standard_interface_descriptor_t *interface 100 101 = (usb_standard_interface_descriptor_t *) interface_ptr; 101 102 102 103 /* Skip alternate interfaces. */ 103 if (!interface_in_list(list, interface->interface_number)) { 104 usbmid_interface_t *iface 105 = malloc(sizeof(usbmid_interface_t)); 106 if (iface == NULL) { 107 break; 108 } 109 link_initialize(&iface->link); 110 iface->fun = NULL; 111 iface->interface_no = interface->interface_number; 112 iface->interface = interface; 113 114 list_append(&iface->link, list); 115 } 116 117 /* TODO: add the alternatives and create match ids from them 118 * as well. 119 */ 120 121 next_descriptor: 122 interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data, 123 data.data, interface_ptr); 124 125 } while (interface_ptr != NULL); 126 104 if (interface_in_list(list, interface->interface_number)) { 105 /* TODO: add the alternatives and create match ids 106 * for them. */ 107 continue; 108 } 109 usbmid_interface_t *iface = malloc(sizeof(usbmid_interface_t)); 110 if (iface == NULL) { 111 //TODO: Do something about that failure. 112 break; 113 } 114 115 link_initialize(&iface->link); 116 iface->fun = NULL; 117 iface->interface_no = interface->interface_number; 118 iface->interface = interface; 119 120 list_append(&iface->link, list); 121 } 127 122 } 128 123 … … 139 134 int rc; 140 135 141 intdev_class = dev->descriptors.device.device_class;136 unsigned dev_class = dev->descriptors.device.device_class; 142 137 if (dev_class != USB_CLASS_USE_INTERFACE) { 143 138 usb_log_warning( 144 "Device class: %d (%s), but expected class 0.\n", 145 dev_class, usb_str_class(dev_class)); 139 "Device class: %u (%s), but expected class %u.\n", 140 dev_class, usb_str_class(dev_class), 141 USB_CLASS_USE_INTERFACE); 146 142 usb_log_error("Not multi interface device, refusing.\n"); 147 143 return false; 148 144 } 149 145 150 /* Short 146 /* Shortcuts to save on typing ;-). */ 151 147 const void *config_descriptor_raw = dev->descriptors.configuration; 152 148 size_t config_descriptor_size = dev->descriptors.configuration_size; … … 163 159 } 164 160 161 /* Create driver soft-state. */ 165 162 usb_mid_t *usb_mid = usb_device_data_alloc(dev, sizeof(usb_mid_t)); 166 163 if (!usb_mid) { … … 169 166 } 170 167 171 /* Create control function */168 /* Create control function. */ 172 169 usb_mid->ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl"); 173 170 if (usb_mid->ctl_fun == NULL) { … … 175 172 return false; 176 173 } 177 178 174 usb_mid->ctl_fun->ops = &mid_device_ops; 179 175 176 /* Bind control function. */ 180 177 rc = ddf_fun_bind(usb_mid->ctl_fun); 181 178 if (rc != EOK) { … … 192 189 &usb_mid->interface_list); 193 190 191 /* Start child function for every interface. */ 194 192 list_foreach(usb_mid->interface_list, link) { 195 usbmid_interface_t *iface = list_get_instance(link, 196 usbmid_interface_t, link); 193 usbmid_interface_t *iface = usbmid_interface_from_link(link); 197 194 198 195 usb_log_info("Creating child for interface %d (%s).\n", 199 (int)iface->interface_no,196 iface->interface_no, 200 197 usb_str_class(iface->interface->interface_class)); 201 198 -
uspace/drv/bus/usb/usbmid/main.c
rba72f2b r6843a9c 53 53 usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name); 54 54 55 usb_pipe_start_long_transfer(&dev->ctrl_pipe); 56 57 bool accept = usbmid_explore_device(dev); 58 59 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 55 const bool accept = usbmid_explore_device(dev); 60 56 61 57 if (!accept) { … … 65 61 return EOK; 66 62 } 63 /*----------------------------------------------------------------------------*/ 64 /** Callback when a MID device is about to be removed from the host. 65 * 66 * @param dev USB device representing the removed device. 67 * @return Error code. 68 */ 69 static int usbmid_device_remove(usb_device_t *dev) 70 { 71 assert(dev); 72 usb_mid_t *usb_mid = dev->driver_data; 73 assert(usb_mid); 67 74 75 /* Remove ctl function */ 76 int ret = ddf_fun_unbind(usb_mid->ctl_fun); 77 if (ret != EOK) { 78 usb_log_error("Failed to unbind USB MID ctl function: %s.\n", 79 str_error(ret)); 80 return ret; 81 } 82 ddf_fun_destroy(usb_mid->ctl_fun); 83 84 /* Remove all children */ 85 while (!list_empty(&usb_mid->interface_list)) { 86 link_t *item = list_first(&usb_mid->interface_list); 87 list_remove(item); 88 89 usbmid_interface_t *iface = usbmid_interface_from_link(item); 90 91 usb_log_info("Removing child for interface %d (%s).\n", 92 iface->interface_no, 93 usb_str_class(iface->interface->interface_class)); 94 95 /* Tell the child to go off-line. */ 96 int pret = ddf_fun_offline(iface->fun); 97 if (pret != EOK) { 98 usb_log_warning("Failed to turn off child for interface" 99 " %d (%s): %s\n", iface->interface_no, 100 usb_str_class(iface->interface->interface_class), 101 str_error(pret)); 102 ret = pret; 103 } 104 105 /* Now remove the child. */ 106 pret = usbmid_interface_destroy(iface); 107 if (pret != EOK) { 108 usb_log_error("Failed to destroy child for interface " 109 "%d (%s): %s\n", iface->interface_no, 110 usb_str_class(iface->interface->interface_class), 111 str_error(pret)); 112 ret = pret; 113 } 114 } 115 return ret; 116 } 117 /*----------------------------------------------------------------------------*/ 118 /** Callback when a MID device was removed from the host. 119 * 120 * @param dev USB device representing the removed device. 121 * @return Error code. 122 */ 68 123 static int usbmid_device_gone(usb_device_t *dev) 69 124 { 70 125 assert(dev); 126 usb_mid_t *usb_mid = dev->driver_data; 127 assert(usb_mid); 128 71 129 usb_log_info("USB MID gone: `%s'.\n", dev->ddf_dev->name); 72 130 73 131 /* Remove ctl function */ 74 usb_mid_t *usb_mid = dev->driver_data;75 132 int ret = ddf_fun_unbind(usb_mid->ctl_fun); 76 133 if (ret != EOK) { … … 86 143 list_remove(item); 87 144 88 usbmid_interface_t *iface = list_get_instance(item, 89 usbmid_interface_t, link); 145 usbmid_interface_t *iface = usbmid_interface_from_link(item); 90 146 91 usb_log_info(" Removing child for interface %d (%s).\n",147 usb_log_info("Child for interface %d (%s) gone.\n", 92 148 iface->interface_no, 93 149 usb_str_class(iface->interface->interface_class)); … … 107 163 108 164 /** USB MID driver ops. */ 109 static usb_driver_ops_t mid_driver_ops = {165 static const usb_driver_ops_t mid_driver_ops = { 110 166 .device_add = usbmid_device_add, 167 .device_rem = usbmid_device_remove, 111 168 .device_gone = usbmid_device_gone, 112 169 }; 113 170 114 171 /** USB MID driver. */ 115 static usb_driver_t mid_driver = {172 static const usb_driver_t mid_driver = { 116 173 .name = NAME, 117 174 .ops = &mid_driver_ops, -
uspace/drv/bus/usb/usbmid/usbmid.c
rba72f2b r6843a9c 45 45 46 46 /** Callback for DDF USB interface. */ 47 static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle, 48 int *iface_no) 47 static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no) 49 48 { 50 49 assert(fun); … … 62 61 /** DDF interface of the child - interface function. */ 63 62 static usb_iface_t child_usb_iface = { 64 .get_hc_handle = usb_iface_get_hc_handle_ hub_child_impl,65 .get_ address = usb_iface_get_address_hub_impl,66 .get_ interface = usb_iface_get_interface_impl63 .get_hc_handle = usb_iface_get_hc_handle_device_impl, 64 .get_my_address = usb_iface_get_my_address_forward_impl, 65 .get_my_interface = usb_iface_get_interface_impl, 67 66 }; 68 67 … … 110 109 * class name something humanly understandable. 111 110 */ 112 rc = asprintf(&child_name, "%s% d",111 rc = asprintf(&child_name, "%s%hhu", 113 112 usb_str_class(interface_descriptor->interface_class), 114 (int)interface_descriptor->interface_number);113 interface_descriptor->interface_number); 115 114 if (rc < 0) { 116 115 return ENOMEM; … … 123 122 return ENOMEM; 124 123 } 125 126 iface->fun = child;127 128 child->driver_data = iface;129 child->ops = &child_device_ops;130 124 131 125 rc = usb_device_create_match_ids_from_interface(device_descriptor, … … 143 137 } 144 138 139 iface->fun = child; 140 child->driver_data = iface; 141 child->ops = &child_device_ops; 142 145 143 return EOK; 146 144 } -
uspace/drv/bus/usb/usbmid/usbmid.h
rba72f2b r6843a9c 51 51 ddf_fun_t *fun; 52 52 /** Interface descriptor. */ 53 usb_standard_interface_descriptor_t *interface;53 const usb_standard_interface_descriptor_t *interface; 54 54 /** Interface number. */ 55 55 int interface_no; … … 71 71 int usbmid_interface_destroy(usbmid_interface_t *mid_iface); 72 72 73 static inline usbmid_interface_t * usbmid_interface_from_link(link_t *item) 74 { 75 return list_get_instance(item, usbmid_interface_t, link); 76 } 77 73 78 #endif 74 79 /** -
uspace/drv/bus/usb/vhc/conndev.c
rba72f2b r6843a9c 69 69 70 70 if (data_request == 0) { 71 async_ wait_for(opening_request, NULL);71 async_forget(opening_request); 72 72 return; 73 73 } -
uspace/drv/bus/usb/vhc/connhost.c
rba72f2b r6843a9c 57 57 * @return Error code. 58 58 */ 59 static int request_address(ddf_fun_t *fun, usb_speed_t speed, 60 usb_address_t *address) 61 { 62 VHC_DATA(vhc, fun); 63 64 usb_address_t addr = usb_device_manager_get_free_address( 65 &vhc->dev_manager, USB_SPEED_HIGH); 66 if (addr < 0) { 67 return addr; 68 } 69 70 if (address != NULL) { 71 *address = addr; 72 } 73 74 return EOK; 59 static int request_address(ddf_fun_t *fun, usb_address_t *address, bool strict, 60 usb_speed_t speed) 61 { 62 VHC_DATA(vhc, fun); 63 64 assert(address); 65 return usb_device_manager_request_address( 66 &vhc->dev_manager, address, strict, speed); 75 67 } 76 68 … … 88 80 usb_log_debug("Binding handle %" PRIun " to address %d.\n", 89 81 handle, address); 90 usb_device_manager_bind (&vhc->dev_manager, address, handle);82 usb_device_manager_bind_address(&vhc->dev_manager, address, handle); 91 83 92 84 return EOK; … … 104 96 { 105 97 VHC_DATA(vhc, fun); 106 bool found = 107 usb_device_manager_find_by_address(&vhc->dev_manager, address, handle); 108 return found ? EOK : ENOENT; 98 return usb_device_manager_get_info_by_address( 99 &vhc->dev_manager, address, handle, NULL); 109 100 } 110 101 … … 119 110 VHC_DATA(vhc, fun); 120 111 usb_log_debug("Releasing address %d...\n", address); 121 usb_device_manager_release (&vhc->dev_manager, address);112 usb_device_manager_release_address(&vhc->dev_manager, address); 122 113 123 114 return ENOTSUP; … … 137 128 */ 138 129 static int register_endpoint(ddf_fun_t *fun, 139 usb_address_t address, usb_ speed_t speed, usb_endpoint_t endpoint,130 usb_address_t address, usb_endpoint_t endpoint, 140 131 usb_transfer_type_t transfer_type, usb_direction_t direction, 141 132 size_t max_packet_size, unsigned int interval) 142 133 { 143 /* TODO: Use usb_endpoint_manager_add_ep */ 144 VHC_DATA(vhc, fun); 145 146 endpoint_t *ep = endpoint_get( 147 address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1); 148 if (ep == NULL) { 149 return ENOMEM; 150 } 151 152 int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 153 if (rc != EOK) { 154 endpoint_destroy(ep); 155 return rc; 156 } 157 158 return EOK; 134 VHC_DATA(vhc, fun); 135 136 return usb_endpoint_manager_add_ep(&vhc->ep_manager, 137 address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1, 0, 138 NULL, NULL); 139 159 140 } 160 141 … … 172 153 VHC_DATA(vhc, fun); 173 154 174 int rc = usb_endpoint_manager_ unregister_ep(&vhc->ep_manager,175 address, endpoint, direction );155 int rc = usb_endpoint_manager_remove_ep(&vhc->ep_manager, 156 address, endpoint, direction, NULL, NULL); 176 157 177 158 return rc; … … 414 395 VHC_DATA(vhc, fun); 415 396 416 endpoint_t *ep = usb_endpoint_manager_ get_ep(&vhc->ep_manager,417 target.address, target.endpoint, USB_DIRECTION_IN , NULL);397 endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager, 398 target.address, target.endpoint, USB_DIRECTION_IN); 418 399 if (ep == NULL) { 419 400 return ENOENT; … … 456 437 VHC_DATA(vhc, fun); 457 438 458 endpoint_t *ep = usb_endpoint_manager_ get_ep(&vhc->ep_manager,459 target.address, target.endpoint, USB_DIRECTION_OUT , NULL);439 endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager, 440 target.address, target.endpoint, USB_DIRECTION_OUT); 460 441 if (ep == NULL) { 461 442 return ENOENT; … … 490 471 } 491 472 492 static int tell_address(ddf_fun_t *fun, devman_handle_t handle, 493 usb_address_t *address) 473 static int tell_address(ddf_fun_t *fun, usb_address_t *address) 494 474 { 495 475 UNSUPPORTED("tell_address"); … … 508 488 } 509 489 510 static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle, 511 usb_address_t *address) 490 static int tell_address_rh(ddf_fun_t *root_hub_fun, usb_address_t *address) 512 491 { 513 492 VHC_DATA(vhc, root_hub_fun); 514 493 515 if (handle == 0) { 516 handle = root_hub_fun->handle; 517 } 494 devman_handle_t handle = root_hub_fun->handle; 518 495 519 496 usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle); 520 usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle); 497 const usb_address_t addr = 498 usb_device_manager_find_address(&vhc->dev_manager, handle); 521 499 if (addr < 0) { 522 500 return addr; … … 530 508 .request_address = request_address, 531 509 .bind_address = bind_address, 532 . find_by_address= find_by_address,510 .get_handle = find_by_address, 533 511 .release_address = release_address, 534 512 … … 542 520 usb_iface_t vhc_usb_iface = { 543 521 .get_hc_handle = usb_iface_get_hc_handle_hc_impl, 544 .get_ address = tell_address522 .get_my_address = tell_address 545 523 }; 546 524 547 525 usb_iface_t rh_usb_iface = { 548 526 .get_hc_handle = usb_iface_get_hc_handle_rh_impl, 549 .get_ address = tell_address_rh527 .get_my_address = tell_address_rh 550 528 }; 551 529 -
uspace/drv/bus/usb/vhc/hub.c
rba72f2b r6843a9c 107 107 108 108 usb_hc_connection_t hc_conn; 109 rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle); 110 assert(rc == EOK); 109 usb_hc_connection_initialize(&hc_conn, hc_dev->handle); 111 110 112 111 rc = usb_hc_connection_open(&hc_conn); -
uspace/drv/bus/usb/vhc/main.c
rba72f2b r6843a9c 58 58 }; 59 59 60 static int vhc_ add_device(ddf_dev_t *dev)60 static int vhc_dev_add(ddf_dev_t *dev) 61 61 { 62 62 static int vhc_count = 0; … … 80 80 return rc; 81 81 } 82 usb_device_manager_init(&data->dev_manager );82 usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX); 83 83 84 84 ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc"); … … 131 131 132 132 static driver_ops_t vhc_driver_ops = { 133 . add_device = vhc_add_device,133 .dev_add = vhc_dev_add, 134 134 }; 135 135 -
uspace/drv/bus/usb/vhc/vhc.ma
rba72f2b r6843a9c 1 1 10 usb&hc=vhc 2
Note:
See TracChangeset
for help on using the changeset viewer.