Changeset b4b534ac in mainline for uspace/drv/bus
- Timestamp:
- 2016-07-22T08:24:47Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/fix-logger-deadlock, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f76d2c2
- Parents:
- 5b18137 (diff), 8351f9a4 (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/usb
- Files:
-
- 17 added
- 16 deleted
- 68 edited
- 7 moved
-
ehci/Makefile (modified) (3 diffs)
-
ehci/ehci_batch.c (added)
-
ehci/ehci_batch.h (added)
-
ehci/ehci_endpoint.c (added)
-
ehci/ehci_endpoint.h (moved) (moved from uspace/drv/bus/usb/uhcirh/root_hub.h ) (1 diff)
-
ehci/ehci_regs.h (added)
-
ehci/ehci_rh.c (added)
-
ehci/ehci_rh.h (moved) (moved from uspace/drv/bus/usb/uhci/root_hub.c ) (2 diffs)
-
ehci/endpoint_list.c (added)
-
ehci/endpoint_list.h (added)
-
ehci/hc.c (added)
-
ehci/hc.h (added)
-
ehci/hw_struct/fstn.h (moved) (moved from uspace/drv/bus/usb/uhci/uhci.h ) (2 diffs)
-
ehci/hw_struct/iso_transfer_descriptor.h (added)
-
ehci/hw_struct/link_pointer.h (moved) (moved from uspace/lib/usb/include/usb/ddfiface.h ) (2 diffs)
-
ehci/hw_struct/mem_access.h (moved) (moved from uspace/drv/bus/usb/uhci/res.h ) (2 diffs)
-
ehci/hw_struct/queue_head.c (added)
-
ehci/hw_struct/queue_head.h (added)
-
ehci/hw_struct/split_iso_transfer_descriptor.h (added)
-
ehci/hw_struct/transfer_descriptor.c (added)
-
ehci/hw_struct/transfer_descriptor.h (added)
-
ehci/main.c (modified) (3 diffs)
-
ehci/res.c (modified) (8 diffs)
-
ehci/res.h (modified) (1 diff)
-
ohci/Makefile (modified) (3 diffs)
-
ohci/endpoint_list.c (modified) (1 diff)
-
ohci/endpoint_list.h (modified) (2 diffs)
-
ohci/hc.c (modified) (12 diffs)
-
ohci/hc.h (modified) (3 diffs)
-
ohci/hw_struct/completion_codes.h (modified) (1 diff)
-
ohci/hw_struct/endpoint_descriptor.c (modified) (4 diffs)
-
ohci/hw_struct/endpoint_descriptor.h (modified) (1 diff)
-
ohci/hw_struct/hcca.h (modified) (4 diffs)
-
ohci/hw_struct/iso_transfer_descriptor.h (modified) (1 diff)
-
ohci/hw_struct/mem_access.h (modified) (1 diff)
-
ohci/hw_struct/transfer_descriptor.c (modified) (2 diffs)
-
ohci/hw_struct/transfer_descriptor.h (modified) (1 diff)
-
ohci/main.c (modified) (2 diffs)
-
ohci/ohci.c (deleted)
-
ohci/ohci.h (deleted)
-
ohci/ohci_batch.c (modified) (6 diffs)
-
ohci/ohci_batch.h (modified) (1 diff)
-
ohci/ohci_endpoint.c (modified) (4 diffs)
-
ohci/ohci_regs.h (modified) (3 diffs)
-
ohci/ohci_rh.c (added)
-
ohci/ohci_rh.h (moved) (moved from uspace/drv/bus/usb/ohci/root_hub.h ) (2 diffs)
-
ohci/res.c (deleted)
-
ohci/root_hub.c (deleted)
-
uhci/Makefile (modified) (3 diffs)
-
uhci/hc.c (modified) (10 diffs)
-
uhci/hc.h (modified) (4 diffs)
-
uhci/hw_struct/link_pointer.h (modified) (1 diff)
-
uhci/hw_struct/queue_head.h (modified) (1 diff)
-
uhci/hw_struct/transfer_descriptor.c (modified) (1 diff)
-
uhci/hw_struct/transfer_descriptor.h (modified) (1 diff)
-
uhci/main.c (modified) (4 diffs)
-
uhci/res.c (deleted)
-
uhci/transfer_list.c (modified) (1 diff)
-
uhci/transfer_list.h (modified) (1 diff)
-
uhci/uhci.c (deleted)
-
uhci/uhci_batch.c (modified) (2 diffs)
-
uhci/uhci_batch.h (modified) (1 diff)
-
uhci/uhci_rh.c (added)
-
uhci/uhci_rh.h (moved) (moved from uspace/drv/bus/usb/uhci/root_hub.h ) (2 diffs)
-
uhci/utils/malloc32.h (deleted)
-
uhcirh/Makefile (deleted)
-
uhcirh/main.c (deleted)
-
uhcirh/port.c (deleted)
-
uhcirh/port.h (deleted)
-
uhcirh/root_hub.c (deleted)
-
uhcirh/uhcirh.ma (deleted)
-
usbflbk/main.c (modified) (2 diffs)
-
usbhid/blink1/blink1.c (modified) (3 diffs)
-
usbhid/generic/hiddev.c (modified) (1 diff)
-
usbhid/kbd/kbddev.c (modified) (14 diffs)
-
usbhid/main.c (modified) (6 diffs)
-
usbhid/mouse/mousedev.c (modified) (5 diffs)
-
usbhid/multimedia/multimedia.c (modified) (1 diff)
-
usbhid/usbhid.c (modified) (9 diffs)
-
usbhid/usbhid.h (modified) (2 diffs)
-
usbhub/main.c (modified) (3 diffs)
-
usbhub/port.c (modified) (21 diffs)
-
usbhub/port.h (modified) (4 diffs)
-
usbhub/status.h (modified) (1 diff)
-
usbhub/usbhub.c (modified) (26 diffs)
-
usbhub/usbhub.h (modified) (2 diffs)
-
usbmast/bo_trans.c (modified) (10 diffs)
-
usbmast/bo_trans.h (modified) (2 diffs)
-
usbmast/main.c (modified) (11 diffs)
-
usbmast/scsi_ms.c (modified) (16 diffs)
-
usbmast/usbmast.h (modified) (2 diffs)
-
usbmid/explore.c (modified) (10 diffs)
-
usbmid/main.c (modified) (6 diffs)
-
usbmid/usbmid.c (modified) (6 diffs)
-
usbmid/usbmid.h (modified) (2 diffs)
-
usbmid/usbmid.ma (modified) (1 diff)
-
vhc/Makefile (modified) (1 diff)
-
vhc/conn.h (deleted)
-
vhc/conndev.c (modified) (3 diffs)
-
vhc/connhost.c (deleted)
-
vhc/devconn.c (modified) (5 diffs)
-
vhc/hub.c (deleted)
-
vhc/hub/virthub.c (modified) (5 diffs)
-
vhc/hub/virthub.h (modified) (1 diff)
-
vhc/hub/virthubops.c (modified) (2 diffs)
-
vhc/main.c (modified) (4 diffs)
-
vhc/transfer.c (modified) (6 diffs)
-
vhc/vhcd.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/Makefile
r5b18137 rb4b534ac 31 31 LIBS = \ 32 32 $(LIBUSBHOST_PREFIX)/libusbhost.a \ 33 $(LIBUSBVIRT_PREFIX)/libusbvirt.a \ 33 34 $(LIBUSB_PREFIX)/libusb.a \ 34 35 $(LIBDRV_PREFIX)/libdrv.a … … 36 37 EXTRA_CFLAGS += \ 37 38 -I$(LIBUSB_PREFIX)/include \ 39 -I$(LIBUSBDEV_PREFIX)/include \ 38 40 -I$(LIBUSBHOST_PREFIX)/include \ 41 -I$(LIBUSBVIRT_PREFIX)/include \ 39 42 -I$(LIBDRV_PREFIX)/include 40 43 … … 42 45 43 46 SOURCES = \ 47 ehci_batch.c \ 48 ehci_endpoint.c \ 49 ehci_rh.c \ 50 endpoint_list.c \ 51 hc.c \ 52 hw_struct/queue_head.c \ 53 hw_struct/transfer_descriptor.c \ 44 54 main.c \ 45 55 res.c -
uspace/drv/bus/usb/ehci/ehci_endpoint.h
r5b18137 rb4b534ac 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusb uhcirh28 /** @addtogroup drvusbehci 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver32 * @brief EHCI driver 33 33 */ 34 #ifndef DRV_ UHCI_ROOT_HUB_H35 #define DRV_ UHCI_ROOT_HUB_H34 #ifndef DRV_EHCI_HCD_ENDPOINT_H 35 #define DRV_EHCI_HCD_ENDPOINT_H 36 36 37 #include <ddf/driver.h> 38 #include <device/hw_res_parsed.h> 37 #include <assert.h> 38 #include <adt/list.h> 39 #include <usb/host/endpoint.h> 40 #include <usb/host/hcd.h> 39 41 40 #include "port.h" 42 #include "hw_struct/queue_head.h" 43 #include "hw_struct/transfer_descriptor.h" 41 44 42 #define UHCI_ROOT_HUB_PORT_COUNT 2 43 #define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */ 45 /** Connector structure linking ED to to prepared TD. */ 46 typedef struct ehci_endpoint { 47 /** EHCI endpoint descriptor */ 48 qh_t *qh; 49 /** Linked list used by driver software */ 50 link_t link; 51 } ehci_endpoint_t; 44 52 45 /** UHCI root hub drvier structure */ 46 typedef struct root_hub { 47 /** Ports provided by the hub */ 48 uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT]; 49 } uhci_root_hub_t; 53 int ehci_endpoint_init(hcd_t *hcd, endpoint_t *ep); 54 void ehci_endpoint_fini(hcd_t *hcd, endpoint_t *ep); 50 55 51 int uhci_root_hub_init(uhci_root_hub_t *instance, addr_range_t *regs, 52 ddf_dev_t *rh); 56 /** Get and convert assigned ehci_endpoint_t structure 57 * @param[in] ep USBD endpoint structure. 58 * @return Pointer to assigned hcd endpoint structure 59 */ 60 static inline ehci_endpoint_t * ehci_endpoint_get(const endpoint_t *ep) 61 { 62 assert(ep); 63 return ep->hc_data.data; 64 } 53 65 54 void uhci_root_hub_fini(uhci_root_hub_t *instance); 66 static inline ehci_endpoint_t * ehci_endpoint_list_instance(link_t *l) 67 { 68 return list_get_instance(l, ehci_endpoint_t, link); 69 } 70 55 71 #endif 56 72 /** 57 73 * @} 58 74 */ 75 -
uspace/drv/bus/usb/ehci/ehci_rh.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusb uhci28 /** @addtogroup drvusbehci 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver32 * @brief EHCI driver 33 33 */ 34 #ifndef DRV_EHCI_EHCI_RH_H 35 #define DRV_EHCI_EHCI_RH_H 36 34 37 #include <assert.h> 35 #include <errno.h> 36 #include <str_error.h> 37 #include <stdio.h> 38 #include <device/hw_res_parsed.h> 38 #include <sys/types.h> 39 39 40 #include <usb/debug.h> 40 #include <usb/usb.h> 41 #include <usb/classes/hub.h> 42 #include <usb/host/usb_transfer_batch.h> 43 #include <usbvirt/virthub_base.h> 41 44 42 #include " root_hub.h"45 #include "ehci_regs.h" 43 46 44 /** Root hub initialization 45 * @param[in] instance RH structure to initialize 46 * @param[in] fun DDF function representing UHCI root hub 47 * @param[in] reg_addr Address of root hub status and control registers. 48 * @param[in] reg_size Size of accessible address space. 49 * @return Error code. 47 enum { 48 EHCI_MAX_PORTS = 15, 49 }; 50 51 typedef struct { 52 /** Virtual hub instance */ 53 virthub_base_t base; 54 /** EHCI device registers */ 55 ehci_regs_t *registers; 56 /** Number of downstream ports, EHCI limits this to 15 */ 57 unsigned port_count; 58 /** USB hub descriptor describing the EHCI root hub */ 59 struct { 60 usb_hub_descriptor_header_t header; 61 uint8_t rempow[STATUS_BYTES(EHCI_MAX_PORTS) * 2]; 62 } __attribute__((packed)) hub_descriptor; 63 /** interrupt transfer waiting for an actual interrupt to occur */ 64 usb_transfer_batch_t *unfinished_interrupt_transfer; 65 bool reset_flag[EHCI_MAX_PORTS]; 66 bool resume_flag[EHCI_MAX_PORTS]; 67 } ehci_rh_t; 68 69 int ehci_rh_init(ehci_rh_t *instance, ehci_caps_regs_t *caps, ehci_regs_t *regs, 70 const char *name); 71 int ehci_rh_schedule(ehci_rh_t *instance, usb_transfer_batch_t *batch); 72 int ehci_rh_interrupt(ehci_rh_t *instance); 73 74 /** Get EHCI rh address. 75 * 76 * @param instance UHCI rh instance. 77 * @return USB address assigned to the hub. 78 * Wrapper for virtual hub address 50 79 */ 51 int 52 rh_init(rh_t *instance, ddf_fun_t *fun, addr_range_t *regs, uintptr_t reg_addr, 53 size_t reg_size) 80 static inline usb_address_t ehci_rh_get_address(ehci_rh_t *instance) 54 81 { 55 82 assert(instance); 56 assert(fun); 57 58 /* Crop the PIO window to the absolute address range of UHCI I/O. */ 59 instance->pio_window.mem.base = 0; 60 instance->pio_window.mem.size = 0; 61 instance->pio_window.io.base = RNGABS(*regs); 62 instance->pio_window.io.size = RNGSZ(*regs); 63 64 /* Initialize resource structure */ 65 instance->resource_list.count = 1; 66 instance->resource_list.resources = &instance->io_regs; 67 68 instance->io_regs.type = IO_RANGE; 69 instance->io_regs.res.io_range.address = reg_addr; 70 instance->io_regs.res.io_range.size = reg_size; 71 instance->io_regs.res.io_range.relative = true; 72 instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN; 73 74 const int ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100); 75 if (ret != EOK) { 76 usb_log_error("Failed to add root hub match id: %s\n", 77 str_error(ret)); 78 } 79 return ret; 83 return virthub_base_get_address(&instance->base); 80 84 } 85 #endif 81 86 /** 82 87 * @} -
uspace/drv/bus/usb/ehci/hw_struct/fstn.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 /** @addtogroup drvusbuhci 28 /** @addtogroup drvusbehci 30 29 * @{ 31 30 */ 32 31 /** @file 33 * @brief UHCI driver main structure for both host controller and root-hub.32 * @brief EHCI driver 34 33 */ 35 #ifndef DRV_UHCI_UHCI_H 36 #define DRV_UHCI_UHCI_H 37 #include <ddf/driver.h> 34 #ifndef DRV_EHCI_HW_STRUCT_FSTN_H 35 #define DRV_EHCI_HW_STRUCT_FSTN_H 38 36 39 int device_setup_uhci(ddf_dev_t *device); 37 #include "link_pointer.h" 38 39 typedef struct fstn { 40 link_pointer_t normal_path; 41 link_pointer_t back_path; 42 } fstn_t; 43 40 44 #endif 41 45 /** 42 46 * @} 43 47 */ 48 -
uspace/drv/bus/usb/ehci/hw_struct/link_pointer.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 1 Vojtech Horky2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 /** @addtogroup libusb 28 /** @addtogroup drvusbehci 30 29 * @{ 31 30 */ 32 31 /** @file 33 * Implementations of DDF interfaces functions.32 * @brief EHCI driver 34 33 */ 35 36 #ifndef LIBUSB_DDFIFACE_H_ 37 #define LIBUSB_DDFIFACE_H_ 34 #ifndef DRV_EHCI_HW_STRUCT_LINK_POINTER_H 35 #define DRV_EHCI_HW_STRUCT_LINK_POINTER_H 38 36 39 37 #include <sys/types.h> 40 #include <usb_iface.h>41 38 42 extern int usb_iface_get_hc_handle_device_impl(ddf_fun_t *, devman_handle_t *); 43 extern int usb_iface_get_my_address_forward_impl(ddf_fun_t *, usb_address_t *); 44 extern usb_iface_t usb_iface_hub_impl; 39 /** EHCI link pointer, used by many data structures */ 40 typedef volatile uint32_t link_pointer_t; 45 41 46 extern int usb_iface_get_my_address_from_device_data(ddf_fun_t *, usb_address_t *); 47 extern usb_iface_t usb_iface_hub_child_impl; 42 #define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */ 48 43 49 extern int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *); 44 #define LINK_POINTER_TERMINATE_FLAG (1 << 0) 45 46 enum { 47 LINK_POINTER_TYPE_iTD = 0x0 << 1, 48 LINK_POINTER_TYPE_QH = 0x1 << 1, 49 LINK_POINTER_TYPE_siTD = 0x2 << 1, 50 LINK_POINTER_TYPE_FSTN = 0x3 << 1, 51 LINK_POINTER_TYPE_MASK = 0x3 << 1, 52 }; 53 54 #define LINK_POINTER_QH(address) \ 55 ((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_TYPE_QH) 56 57 #define LINK_POINTER_TD(address) \ 58 (address & LINK_POINTER_ADDRESS_MASK) 59 60 #define LINK_POINTER_TERM \ 61 ((link_pointer_t)LINK_POINTER_TERMINATE_FLAG) 50 62 51 63 #endif 52 53 64 /** 54 65 * @} -
uspace/drv/bus/usb/ehci/hw_struct/mem_access.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 0 Vojtech Horky2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 /** @addtogroup drvusbuhcihc 28 /** @addtogroup drvusbehci 30 29 * @{ 31 30 */ 32 31 /** @file 33 * @brief UHCI driver PCI helper functions32 * @brief EHCI driver 34 33 */ 35 #ifndef DRV_ UHCI_PCI_H36 #define DRV_ UHCI_PCI_H34 #ifndef DRV_EHCI_HW_MEM_ACCESS_H 35 #define DRV_EHCI_HW_MEM_ACCESS_H 37 36 38 #include < ddf/driver.h>39 #include < device/hw_res_parsed.h>37 #include <byteorder.h> 38 #include <libarch/barrier.h> 40 39 41 int get_my_registers(ddf_dev_t *, addr_range_t *, int *); 42 int enable_interrupts(ddf_dev_t *); 43 int disable_legacy(ddf_dev_t *); 40 #define EHCI_MEM32_WR(reg, val) reg = host2uint32_t_le(val) 41 #define EHCI_MEM32_RD(reg) uint32_t_le2host(reg) 42 #define EHCI_MEM32_SET(reg, val) reg |= host2uint32_t_le(val) 43 #define EHCI_MEM32_CLR(reg, val) reg &= host2uint32_t_le(~val) 44 44 45 45 #endif 46 /** 46 47 /* 47 48 * @} 48 49 */ -
uspace/drv/bus/usb/ehci/main.c
r5b18137 rb4b534ac 33 33 * Main routines of EHCI driver. 34 34 */ 35 36 35 #include <ddf/driver.h> 37 36 #include <ddf/interrupt.h> 38 37 #include <device/hw_res.h> 39 38 #include <errno.h> 40 #include <stdbool.h>41 39 #include <str_error.h> 40 #include <io/logctl.h> 42 41 43 42 #include <usb_iface.h> 44 #include <usb/ddfiface.h>45 43 #include <usb/debug.h> 46 #include <usb/host/ hcd.h>44 #include <usb/host/ddf_helpers.h> 47 45 48 46 #include "res.h" 47 #include "hc.h" 48 #include "ehci_endpoint.h" 49 49 50 50 #define NAME "ehci" 51 51 52 static int ehci_dev_add(ddf_dev_t *device); 52 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 53 static void ehci_driver_fini(hcd_t *); 53 54 54 static driver_ops_t ehci_driver_ops = { 55 .dev_add = ehci_dev_add, 55 static const ddf_hc_driver_t ehci_hc_driver = { 56 .claim = disable_legacy, 57 .hc_speed = USB_SPEED_HIGH, 58 .irq_code_gen = ehci_hc_gen_irq_code, 59 .init = ehci_driver_init, 60 .fini = ehci_driver_fini, 61 .name = "EHCI-PCI", 62 .ops = { 63 .schedule = ehci_hc_schedule, 64 .ep_add_hook = ehci_endpoint_init, 65 .ep_remove_hook = ehci_endpoint_fini, 66 .irq_hook = ehci_hc_interrupt, 67 .status_hook = ehci_hc_status, 68 } 56 69 }; 57 70 58 static driver_t ehci_driver = {59 .name = NAME,60 .driver_ops = &ehci_driver_ops61 };62 static ddf_dev_ops_t hc_ops = {63 .interfaces[USBHC_DEV_IFACE] = &hcd_iface,64 };65 71 72 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq) 73 { 74 assert(hcd); 75 assert(hcd_get_driver_data(hcd) == NULL); 76 77 hc_t *instance = malloc(sizeof(hc_t)); 78 if (!instance) 79 return ENOMEM; 80 81 const int ret = hc_init(instance, res, irq); 82 if (ret == EOK) { 83 hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops); 84 } else { 85 free(instance); 86 } 87 return ret; 88 } 89 90 static void ehci_driver_fini(hcd_t *hcd) 91 { 92 assert(hcd); 93 hc_t *hc = hcd_get_driver_data(hcd); 94 if (hc) 95 hc_fini(hc); 96 97 free(hc); 98 hcd_set_implementation(hcd, NULL, NULL); 99 } 66 100 67 101 /** Initializes a new ddf driver instance of EHCI hcd. … … 72 106 static int ehci_dev_add(ddf_dev_t *device) 73 107 { 74 ddf_fun_t *hc_fun = NULL; 75 bool fun_bound = false; 76 108 usb_log_debug("ehci_dev_add() called\n"); 77 109 assert(device); 78 110 79 addr_range_t reg_range; 80 int irq = 0; 111 return hcd_ddf_add_hc(device, &ehci_hc_driver); 81 112 82 int rc = get_my_registers(device, ®_range, &irq); 83 if (rc != EOK) { 84 usb_log_error("Failed to get memory addresses for %" PRIun 85 ": %s.\n", ddf_dev_get_handle(device), str_error(rc)); 86 goto error; 87 } 113 } 88 114 89 usb_log_info("Memory mapped regs at %p (size %zu), IRQ %d.\n",90 RNGABSPTR(reg_range), RNGSZ(reg_range), irq);91 115 92 rc = disable_legacy(device, ®_range); 93 if (rc != EOK) { 94 usb_log_error("Failed to disable legacy USB: %s.\n", 95 str_error(rc)); 96 goto error; 97 } 116 static const driver_ops_t ehci_driver_ops = { 117 .dev_add = ehci_dev_add, 118 }; 98 119 99 hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc"); 100 if (hc_fun == NULL) { 101 usb_log_error("Failed to create EHCI function.\n"); 102 rc = ENOMEM; 103 goto error; 104 } 120 static const driver_t ehci_driver = { 121 .name = NAME, 122 .driver_ops = &ehci_driver_ops 123 }; 105 124 106 hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t));107 if (ehci_hc == NULL) {108 usb_log_error("Failed to alloc generic HC driver.\n");109 rc = ENOMEM;110 goto error;111 }112 113 /* High Speed, no bandwidth */114 hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL);115 ddf_fun_set_ops(hc_fun, &hc_ops);116 117 rc = ddf_fun_bind(hc_fun);118 if (rc != EOK) {119 usb_log_error("Failed to bind EHCI function: %s.\n",120 str_error(rc));121 goto error;122 }123 124 fun_bound = true;125 126 rc = ddf_fun_add_to_category(hc_fun, USB_HC_CATEGORY);127 if (rc != EOK) {128 usb_log_error("Failed to add EHCI to HC class: %s.\n",129 str_error(rc));130 goto error;131 }132 133 usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",134 ddf_dev_get_name(device), ddf_dev_get_handle(device));135 136 return EOK;137 error:138 if (fun_bound)139 ddf_fun_unbind(hc_fun);140 if (hc_fun != NULL)141 ddf_fun_destroy(hc_fun);142 return rc;143 }144 125 145 126 /** Initializes global driver structures (NONE). … … 154 135 { 155 136 log_init(NAME); 137 logctl_set_log_level(NAME, LVL_NOTE); 156 138 return ddf_driver_main(&ehci_driver); 157 139 } -
uspace/drv/bus/usb/ehci/res.c
r5b18137 rb4b534ac 46 46 47 47 #include "res.h" 48 49 #define HCC_PARAMS_OFFSET 0x8 50 #define HCC_PARAMS_EECP_MASK 0xff 51 #define HCC_PARAMS_EECP_OFFSET 8 52 53 #define CMD_OFFSET 0x0 54 #define STS_OFFSET 0x4 55 #define INT_OFFSET 0x8 56 #define CFG_OFFSET 0x40 57 58 #define USBCMD_RUN 1 59 #define USBSTS_HALTED (1 << 12) 48 #include "ehci_regs.h" 60 49 61 50 #define USBLEGSUP_OFFSET 0 … … 67 56 #define WAIT_STEP 10 68 57 69 70 /** Get address of registers and IRQ for given device.71 *72 * @param[in] dev Device asking for the addresses.73 * @param[out] mem_regs_p Pointer to the register range.74 * @param[out] irq_no IRQ assigned to the device.75 * @return Error code.76 */77 int get_my_registers(ddf_dev_t *dev,78 addr_range_t *mem_regs_p, int *irq_no)79 {80 assert(dev);81 82 async_sess_t *parent_sess = devman_parent_device_connect(83 ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);84 if (!parent_sess)85 return ENOMEM;86 87 hw_res_list_parsed_t hw_res;88 hw_res_list_parsed_init(&hw_res);89 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0);90 async_hangup(parent_sess);91 if (ret != EOK) {92 return ret;93 }94 95 if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) {96 hw_res_list_parsed_clean(&hw_res);97 return ENOENT;98 }99 100 if (mem_regs_p)101 *mem_regs_p = hw_res.mem_ranges.ranges[0];102 if (irq_no)103 *irq_no = hw_res.irqs.irqs[0];104 105 hw_res_list_parsed_clean(&hw_res);106 return EOK;107 }108 109 /** Calls the PCI driver with a request to enable interrupts110 *111 * @param[in] device Device asking for interrupts112 * @return Error code.113 */114 int enable_interrupts(ddf_dev_t *device)115 {116 async_sess_t *parent_sess = devman_parent_device_connect(117 ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);118 if (!parent_sess)119 return ENOMEM;120 121 const bool enabled = hw_res_enable_interrupt(parent_sess);122 async_hangup(parent_sess);123 124 return enabled ? EOK : EIO;125 }126 127 58 /** Implements BIOS hands-off routine as described in EHCI spec 128 59 * … … 131 62 * @return Error code. 132 63 */ 133 static int disable_extended_caps( ddf_dev_t *device, unsigned eecp)64 static int disable_extended_caps(async_sess_t *parent_sess, unsigned eecp) 134 65 { 135 66 /* nothing to do */ … … 137 68 return EOK; 138 69 139 async_sess_t *parent_sess = devman_parent_device_connect(140 ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);141 if (!parent_sess)142 return ENOMEM;143 144 70 /* Read the first EEC. i.e. Legacy Support register */ 145 71 uint32_t usblegsup; 146 int r c= pci_config_space_read_32(parent_sess,72 int ret = pci_config_space_read_32(parent_sess, 147 73 eecp + USBLEGSUP_OFFSET, &usblegsup); 148 if (rc != EOK) { 149 usb_log_error("Failed to read USBLEGSUP: %s.\n", 150 str_error(rc)); 151 goto error; 152 } 153 154 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 74 if (ret != EOK) { 75 usb_log_error("Failed to read USBLEGSUP: %s.\n", str_error(ret)); 76 return ret; 77 } 78 usb_log_debug2("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 155 79 156 80 /* Request control from firmware/BIOS by writing 1 to highest 157 81 * byte. (OS Control semaphore)*/ 158 82 usb_log_debug("Requesting OS control.\n"); 159 r c= pci_config_space_write_8(parent_sess,83 ret = pci_config_space_write_8(parent_sess, 160 84 eecp + USBLEGSUP_OFFSET + 3, 1); 161 if (r c!= EOK) {85 if (ret != EOK) { 162 86 usb_log_error("Failed to request OS EHCI control: %s.\n", 163 str_error(r c));164 goto error;87 str_error(ret)); 88 return ret; 165 89 } 166 90 167 91 size_t wait = 0; 168 92 /* Wait for BIOS to release control. */ 169 r c= pci_config_space_read_32(93 ret = pci_config_space_read_32( 170 94 parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup); 171 if (rc != EOK) { 172 usb_log_error("Failed reading PCI config space: %s.\n", 173 str_error(rc)); 174 goto error; 175 } 176 177 while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) { 95 while ((ret == EOK) && (wait < DEFAULT_WAIT) 96 && (usblegsup & USBLEGSUP_BIOS_CONTROL)) { 178 97 async_usleep(WAIT_STEP); 179 r c= pci_config_space_read_32(parent_sess,98 ret = pci_config_space_read_32(parent_sess, 180 99 eecp + USBLEGSUP_OFFSET, &usblegsup); 181 if (rc != EOK) {182 usb_log_error("Failed reading PCI config space: %s.\n",183 str_error(rc));184 goto error;185 }186 100 wait += WAIT_STEP; 187 101 } … … 189 103 if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) { 190 104 usb_log_info("BIOS released control after %zu usec.\n", wait); 191 async_hangup(parent_sess);192 105 return EOK; 193 106 } … … 196 109 usb_log_warning( "BIOS failed to release control after " 197 110 "%zu usecs, force it.\n", wait); 198 r c= pci_config_space_write_32(parent_sess,111 ret = pci_config_space_write_32(parent_sess, 199 112 eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL); 200 if (r c!= EOK) {201 usb_log_error("Failed to force OS control: "202 "%s.\n", str_error(rc));203 goto error;113 if (ret != EOK) { 114 usb_log_error("Failed to force OS control: %s.\n", 115 str_error(ret)); 116 return ret; 204 117 } 205 118 … … 213 126 /* Read the second EEC Legacy Support and Control register */ 214 127 uint32_t usblegctlsts; 215 r c= pci_config_space_read_32(parent_sess,128 ret = pci_config_space_read_32(parent_sess, 216 129 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 217 if (r c!= EOK) {130 if (ret != EOK) { 218 131 usb_log_error("Failed to get USBLEGCTLSTS: %s.\n", 219 str_error(r c));220 goto error;132 str_error(ret)); 133 return ret; 221 134 } 222 223 usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts); 135 usb_log_debug2("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts); 224 136 /* 225 137 * Zero SMI enables in legacy control register. … … 227 139 * interfering. NOTE: Three upper bits are WC 228 140 */ 229 r c= pci_config_space_write_32(parent_sess,141 ret = pci_config_space_write_32(parent_sess, 230 142 eecp + USBLEGCTLSTS_OFFSET, 0xe0000000); 231 if (rc != EOK) { 232 usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", rc); 233 goto error; 143 if (ret != EOK) { 144 usb_log_error("Failed to zero USBLEGCTLSTS: %s\n", 145 str_error(ret)); 146 return ret; 234 147 } 235 148 236 149 udelay(10); 237 rc = pci_config_space_read_32(parent_sess, 150 /* read again to amke sure it's zeroed */ 151 ret = pci_config_space_read_32(parent_sess, 238 152 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 239 if (r c!= EOK) {153 if (ret != EOK) { 240 154 usb_log_error("Failed to get USBLEGCTLSTS 2: %s.\n", 241 str_error(r c));242 goto error;155 str_error(ret)); 156 return ret; 243 157 } 244 245 usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n", 158 usb_log_debug2("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n", 246 159 usblegctlsts); 247 160 } 248 161 249 162 /* Read again Legacy Support register */ 250 r c= pci_config_space_read_32(parent_sess,163 ret = pci_config_space_read_32(parent_sess, 251 164 eecp + USBLEGSUP_OFFSET, &usblegsup); 252 if (r c!= EOK) {165 if (ret != EOK) { 253 166 usb_log_error("Failed to read USBLEGSUP: %s.\n", 254 str_error(rc)); 255 goto error; 256 } 257 258 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 259 async_hangup(parent_sess); 260 return EOK; 261 error: 262 async_hangup(parent_sess); 263 return rc; 167 str_error(ret)); 168 return ret; 169 } 170 usb_log_debug2("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 171 return ret; 264 172 } 265 173 266 int disable_legacy(ddf_dev_t *device , addr_range_t *reg_range)174 int disable_legacy(ddf_dev_t *device) 267 175 { 268 176 assert(device); 177 178 async_sess_t *parent_sess = devman_parent_device_connect( 179 ddf_dev_get_handle(device), IPC_FLAG_BLOCKING); 180 if (!parent_sess) 181 return ENOMEM; 182 269 183 usb_log_debug("Disabling EHCI legacy support.\n"); 184 185 hw_res_list_parsed_t res; 186 hw_res_list_parsed_init(&res); 187 int ret = hw_res_get_list_parsed(parent_sess, &res, 0); 188 if (ret != EOK) { 189 usb_log_error("Failed to get resource list: %s\n", 190 str_error(ret)); 191 goto clean; 192 } 193 194 if (res.mem_ranges.count < 1) { 195 usb_log_error("Incorrect mem range count: %zu", 196 res.mem_ranges.count); 197 ret = EINVAL; 198 goto clean; 199 } 270 200 271 201 /* Map EHCI registers */ 272 202 void *regs = NULL; 273 int rc = pio_enable_range(reg_range, ®s);274 if (r c!= EOK) {203 ret = pio_enable_range(&res.mem_ranges.ranges[0], ®s); 204 if (ret != EOK) { 275 205 usb_log_error("Failed to map registers %p: %s.\n", 276 RNGABSPTR(*reg_range), str_error(rc)); 277 return rc; 278 } 279 280 usb_log_debug2("Registers mapped at: %p.\n", regs); 281 282 const uint32_t hcc_params = 283 *(uint32_t*)(regs + HCC_PARAMS_OFFSET); 284 usb_log_debug("Value of hcc params register: %x.\n", hcc_params); 206 RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret)); 207 goto clean; 208 } 209 210 usb_log_debug("Registers mapped at: %p.\n", regs); 211 212 ehci_caps_regs_t *ehci_caps = regs; 213 214 const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams); 215 usb_log_debug2("Value of hcc params register: %x.\n", hcc_params); 285 216 286 217 /* Read value of EHCI Extended Capabilities Pointer 287 218 * position of EEC registers (points to PCI config space) */ 288 219 const uint32_t eecp = 289 (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;290 usb_log_debug ("Value of EECP: %x.\n", eecp);291 292 r c = disable_extended_caps(device, eecp);293 if (r c!= EOK) {220 (hcc_params >> EHCI_CAPS_HCC_EECP_SHIFT) & EHCI_CAPS_HCC_EECP_MASK; 221 usb_log_debug2("Value of EECP: %x.\n", eecp); 222 223 ret = disable_extended_caps(parent_sess, eecp); 224 if (ret != EOK) { 294 225 usb_log_error("Failed to disable extended capabilities: %s.\n", 295 str_error(rc)); 296 return rc; 297 } 298 299 /* 300 * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT IF NEEDED 301 */ 302 303 /* Get size of capability registers in memory space. */ 304 const unsigned operation_offset = *(uint8_t*)regs; 305 usb_log_debug("USBCMD offset: %d.\n", operation_offset); 306 307 /* Zero USBCMD register. */ 308 volatile uint32_t *usbcmd = 309 (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET); 310 volatile uint32_t *usbsts = 311 (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET); 312 volatile uint32_t *usbconf = 313 (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET); 314 volatile uint32_t *usbint = 315 (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET); 316 usb_log_debug("USBCMD value: %x.\n", *usbcmd); 317 if (*usbcmd & USBCMD_RUN) { 318 *usbsts = 0x3f; /* ack all interrupts */ 319 *usbint = 0; /* disable all interrupts */ 320 *usbconf = 0; /* release control of RH ports */ 321 322 *usbcmd = 0; 323 /* Wait until hc is halted */ 324 while ((*usbsts & USBSTS_HALTED) == 0); 325 usb_log_info("EHCI turned off.\n"); 326 } else { 327 usb_log_info("EHCI was not running.\n"); 328 } 329 usb_log_debug("Registers: \n" 330 "\t USBCMD(%p): %x(0x00080000 = at least 1ms between interrupts)\n" 331 "\t USBSTS(%p): %x(0x00001000 = HC halted)\n" 332 "\t USBINT(%p): %x(0x0 = no interrupts).\n" 333 "\t CONFIG(%p): %x(0x0 = ports controlled by companion hc).\n", 334 usbcmd, *usbcmd, usbsts, *usbsts, usbint, *usbint, usbconf,*usbconf); 335 336 return rc; 226 str_error(ret)); 227 goto clean; 228 } 229 clean: 230 //TODO unmap registers 231 hw_res_list_parsed_clean(&res); 232 async_hangup(parent_sess); 233 return ret; 337 234 } 338 235 -
uspace/drv/bus/usb/ehci/res.h
r5b18137 rb4b534ac 39 39 #include <device/hw_res_parsed.h> 40 40 41 int get_my_registers(ddf_dev_t *, addr_range_t *, int *); 42 int enable_interrupts(ddf_dev_t *); 43 int disable_legacy(ddf_dev_t *, addr_range_t *); 41 int disable_legacy(ddf_dev_t *); 44 42 45 43 #endif -
uspace/drv/bus/usb/ohci/Makefile
r5b18137 rb4b534ac 31 31 LIBS = \ 32 32 $(LIBUSBHOST_PREFIX)/libusbhost.a \ 33 $(LIBUSB DEV_PREFIX)/libusbdev.a \33 $(LIBUSBVIRT_PREFIX)/libusbvirt.a \ 34 34 $(LIBUSB_PREFIX)/libusb.a \ 35 35 $(LIBDRV_PREFIX)/libdrv.a … … 39 39 -I$(LIBUSBDEV_PREFIX)/include \ 40 40 -I$(LIBUSBHOST_PREFIX)/include \ 41 -I$(LIBUSBVIRT_PREFIX)/include \ 41 42 -I$(LIBDRV_PREFIX)/include 42 43 … … 47 48 hc.c \ 48 49 main.c \ 49 ohci.c \50 50 ohci_batch.c \ 51 51 ohci_endpoint.c \ 52 res.c \ 53 root_hub.c \ 52 ohci_rh.c \ 54 53 hw_struct/endpoint_descriptor.c \ 55 54 hw_struct/transfer_descriptor.c -
uspace/drv/bus/usb/ohci/endpoint_list.c
r5b18137 rb4b534ac 34 34 */ 35 35 36 #include <assert.h> 36 37 #include <errno.h> 38 #include <libarch/barrier.h> 39 37 40 #include <usb/debug.h> 38 #include <libarch/barrier.h> 41 #include <usb/host/utils/malloc32.h> 42 39 43 #include "endpoint_list.h" 40 44 -
uspace/drv/bus/usb/ohci/endpoint_list.h
r5b18137 rb4b534ac 35 35 #define DRV_OHCI_ENDPOINT_LIST_H 36 36 37 #include <adt/list.h> 38 #include <assert.h> 37 39 #include <fibril_synch.h> 40 #include <sys/types.h> 41 #include <usb/host/utils/malloc32.h> 38 42 39 43 #include "ohci_endpoint.h" 40 44 #include "hw_struct/endpoint_descriptor.h" 41 #include "utils/malloc32.h"42 45 43 46 /** Structure maintains both OHCI queue and software list of active endpoints.*/ … … 65 68 assert(instance); 66 69 free32(instance->list_head); 70 instance->list_head = NULL; 67 71 } 68 72 -
uspace/drv/bus/usb/ohci/hc.c
r5b18137 rb4b534ac 34 34 */ 35 35 36 #include <assert.h> 37 #include <async.h> 36 38 #include <errno.h> 37 #include <stdbool.h> 39 #include <macros.h> 40 #include <mem.h> 41 #include <stdlib.h> 38 42 #include <str_error.h> 39 #include <adt/list.h> 40 #include <libarch/ddi.h> 43 #include <sys/types.h> 41 44 42 45 #include <usb/debug.h> 43 46 #include <usb/usb.h> 44 #include <usb/ddfiface.h> 47 48 #include "ohci_endpoint.h" 49 #include "ohci_batch.h" 45 50 46 51 #include "hc.h" 47 #include "ohci_endpoint.h"48 52 49 53 #define OHCI_USED_INTERRUPTS \ … … 84 88 }; 85 89 86 enum {87 /** Number of PIO ranges used in IRQ code */88 hc_irq_pio_range_count =89 sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t),90 91 /** Number of commands used in IRQ code */92 hc_irq_cmd_count =93 sizeof(ohci_irq_commands) / sizeof(irq_cmd_t)94 };95 96 90 static void hc_gain_control(hc_t *instance); 97 91 static void hc_start(hc_t *instance); 98 92 static int hc_init_transfer_lists(hc_t *instance); 99 93 static int hc_init_memory(hc_t *instance); 100 static int interrupt_emulator(hc_t *instance);101 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);102 94 103 95 /** Generate IRQ code. … … 106 98 * @param[out] cmds Commands buffer. 107 99 * @param[in] cmds_size Size of the commands buffer (bytes). 108 * @param[in] regs Device's register range.100 * @param[in] hw_res Device's resources. 109 101 * 110 102 * @return Error code. 111 103 */ 112 int 113 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[], 114 size_t cmds_size, addr_range_t *regs) 115 { 116 if ((ranges_size < sizeof(ohci_pio_ranges)) || 117 (cmds_size < sizeof(ohci_irq_commands)) || 118 (RNGSZ(*regs) < sizeof(ohci_regs_t))) 104 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res) 105 { 106 assert(code); 107 assert(hw_res); 108 109 if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) 110 return EINVAL; 111 112 const addr_range_t regs = hw_res->mem_ranges.ranges[0]; 113 114 if (RNGSZ(regs) < sizeof(ohci_regs_t)) 119 115 return EOVERFLOW; 120 116 121 memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges)); 122 ranges[0].base = RNGABS(*regs); 123 124 memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 125 ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(*regs); 126 cmds[0].addr = (void *) ®isters->interrupt_status; 127 cmds[3].addr = (void *) ®isters->interrupt_status; 128 OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS); 129 130 return EOK; 131 } 132 133 /** Register interrupt handler. 134 * 135 * @param[in] device Host controller DDF device 136 * @param[in] regs Register range 137 * @param[in] irq Interrupt number 138 * @paran[in] handler Interrupt handler 139 * 140 * @return EOK on success or negative error code 141 */ 142 int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq, 143 interrupt_handler_t handler) 144 { 145 int rc; 146 147 irq_pio_range_t irq_ranges[hc_irq_pio_range_count]; 148 irq_cmd_t irq_cmds[hc_irq_cmd_count]; 149 150 irq_code_t irq_code = { 151 .rangecount = hc_irq_pio_range_count, 152 .ranges = irq_ranges, 153 .cmdcount = hc_irq_cmd_count, 154 .cmds = irq_cmds 155 }; 156 157 rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 158 sizeof(irq_cmds), regs); 159 if (rc != EOK) { 160 usb_log_error("Failed to generate IRQ code: %s.\n", 161 str_error(rc)); 162 return rc; 163 } 164 165 /* Register handler to avoid interrupt lockup */ 166 rc = register_interrupt_handler(device, irq, handler, &irq_code); 167 if (rc != EOK) { 168 usb_log_error("Failed to register interrupt handler: %s.\n", 169 str_error(rc)); 170 return rc; 171 } 172 173 return EOK; 174 } 175 176 /** Announce OHCI root hub to the DDF 177 * 178 * @param[in] instance OHCI driver intance 179 * @param[in] hub_fun DDF fuction representing OHCI root hub 180 * @return Error code 181 */ 182 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun) 183 { 184 bool addr_reqd = false; 185 bool ep_added = false; 186 bool fun_bound = false; 187 int rc; 188 189 assert(instance); 190 assert(hub_fun); 191 192 /* Try to get address 1 for root hub. */ 193 instance->rh.address = 1; 194 rc = usb_device_manager_request_address( 195 &instance->generic->dev_manager, &instance->rh.address, false, 196 USB_SPEED_FULL); 197 if (rc != EOK) { 198 usb_log_error("Failed to get OHCI root hub address: %s\n", 199 str_error(rc)); 200 goto error; 201 } 202 203 addr_reqd = true; 204 205 rc = usb_endpoint_manager_add_ep( 206 &instance->generic->ep_manager, instance->rh.address, 0, 207 USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 208 0, NULL, NULL); 209 if (rc != EOK) { 210 usb_log_error("Failed to register root hub control endpoint: %s.\n", 211 str_error(rc)); 212 goto error; 213 } 214 215 ep_added = true; 216 217 rc = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100); 218 if (rc != EOK) { 219 usb_log_error("Failed to add root hub match-id: %s.\n", 220 str_error(rc)); 221 goto error; 222 } 223 224 rc = ddf_fun_bind(hub_fun); 225 if (rc != EOK) { 226 usb_log_error("Failed to bind root hub function: %s.\n", 227 str_error(rc)); 228 goto error; 229 } 230 231 fun_bound = true; 232 233 rc = usb_device_manager_bind_address(&instance->generic->dev_manager, 234 instance->rh.address, ddf_fun_get_handle(hub_fun)); 235 if (rc != EOK) { 236 usb_log_warning("Failed to bind root hub address: %s.\n", 237 str_error(rc)); 238 } 239 240 return EOK; 241 error: 242 if (fun_bound) 243 ddf_fun_unbind(hub_fun); 244 if (ep_added) { 245 usb_endpoint_manager_remove_ep( 246 &instance->generic->ep_manager, instance->rh.address, 0, 247 USB_DIRECTION_BOTH, NULL, NULL); 248 } 249 if (addr_reqd) { 250 usb_device_manager_release_address( 251 &instance->generic->dev_manager, instance->rh.address); 252 } 253 return rc; 117 code->ranges = malloc(sizeof(ohci_pio_ranges)); 118 if (code->ranges == NULL) 119 return ENOMEM; 120 121 code->cmds = malloc(sizeof(ohci_irq_commands)); 122 if (code->cmds == NULL) { 123 free(code->ranges); 124 return ENOMEM; 125 } 126 127 code->rangecount = ARRAY_SIZE(ohci_pio_ranges); 128 code->cmdcount = ARRAY_SIZE(ohci_irq_commands); 129 130 memcpy(code->ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges)); 131 code->ranges[0].base = RNGABS(regs); 132 133 memcpy(code->cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 134 ohci_regs_t *registers = (ohci_regs_t *) RNGABSPTR(regs); 135 code->cmds[0].addr = (void *) ®isters->interrupt_status; 136 code->cmds[3].addr = (void *) ®isters->interrupt_status; 137 OHCI_WR(code->cmds[1].value, OHCI_USED_INTERRUPTS); 138 139 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 140 RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]); 141 142 return hw_res->irqs.irqs[0]; 254 143 } 255 144 … … 257 146 * 258 147 * @param[in] instance Memory place for the structure. 259 * @param[in] HC function node 260 * @param[in] regs Device's I/O registers range. 148 * @param[in] regs Device's resources 261 149 * @param[in] interrupts True if w interrupts should be used 262 150 * @return Error code 263 151 */ 264 int hc_init(hc_t *instance, ddf_fun_t *fun, addr_range_t *regs, bool interrupts) 265 { 266 assert(instance); 267 268 int rc = pio_enable_range(regs, (void **) &instance->registers); 269 if (rc != EOK) { 270 usb_log_error("Failed to gain access to device registers: %s.\n", 271 str_error(rc)); 272 return rc; 273 } 152 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts) 153 { 154 assert(instance); 155 assert(hw_res); 156 if (hw_res->mem_ranges.count != 1 || 157 hw_res->mem_ranges.ranges[0].size < sizeof(ohci_regs_t)) 158 return EINVAL; 159 160 int ret = pio_enable_range(&hw_res->mem_ranges.ranges[0], 161 (void **) &instance->registers); 162 if (ret != EOK) { 163 usb_log_error("Failed to gain access to registers: %s.\n", 164 str_error(ret)); 165 return ret; 166 } 167 usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.\n", 168 hw_res->mem_ranges.ranges[0].address.absolute, 169 hw_res->mem_ranges.ranges[0].size); 274 170 275 171 list_initialize(&instance->pending_batches); 276 277 instance->generic = ddf_fun_data_alloc(fun, sizeof(hcd_t)); 278 if (instance->generic == NULL) { 279 usb_log_error("Out of memory.\n"); 280 return ENOMEM; 281 } 282 283 hcd_init(instance->generic, USB_SPEED_FULL, 284 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 285 instance->generic->private_data = instance; 286 instance->generic->schedule = hc_schedule; 287 instance->generic->ep_add_hook = ohci_endpoint_init; 288 instance->generic->ep_remove_hook = ohci_endpoint_fini; 289 290 rc = hc_init_memory(instance); 291 if (rc != EOK) { 172 fibril_mutex_initialize(&instance->guard); 173 instance->hw_interrupts = interrupts; 174 175 ret = hc_init_memory(instance); 176 if (ret != EOK) { 292 177 usb_log_error("Failed to create OHCI memory structures: %s.\n", 293 str_error(rc)); 294 return rc; 295 } 296 297 fibril_mutex_initialize(&instance->guard); 178 str_error(ret)); 179 //TODO: We should disable pio access here 180 return ret; 181 } 298 182 299 183 hc_gain_control(instance); 300 184 301 if (!interrupts) { 302 instance->interrupt_emulator = 303 fibril_create((int(*)(void*))interrupt_emulator, instance); 304 fibril_add_ready(instance->interrupt_emulator); 305 } 306 307 rh_init(&instance->rh, instance->registers); 185 ohci_rh_init(&instance->rh, instance->registers, "ohci rh"); 308 186 hc_start(instance); 309 187 310 188 return EOK; 311 189 } 190 191 /** Safely dispose host controller internal structures 192 * 193 * @param[in] instance Host controller structure to use. 194 */ 195 void hc_fini(hc_t *instance) 196 { 197 assert(instance); 198 /* TODO: implement*/ 199 }; 312 200 313 201 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) … … 379 267 } 380 268 269 int ohci_hc_status(hcd_t *hcd, uint32_t *status) 270 { 271 assert(hcd); 272 assert(status); 273 hc_t *instance = hcd_get_driver_data(hcd); 274 assert(instance); 275 276 if (instance->registers){ 277 *status = OHCI_RD(instance->registers->interrupt_status); 278 OHCI_WR(instance->registers->interrupt_status, *status); 279 } 280 return EOK; 281 } 282 381 283 /** Add USB transfer to the schedule. 382 284 * 383 * @param[in] instance OHCI hcdriver structure.285 * @param[in] hcd HCD driver structure. 384 286 * @param[in] batch Batch representing the transfer. 385 287 * @return Error code. 386 288 */ 387 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)289 int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 388 290 { 389 291 assert(hcd); 390 hc_t *instance = hcd ->private_data;292 hc_t *instance = hcd_get_driver_data(hcd); 391 293 assert(instance); 392 294 393 295 /* Check for root hub communication */ 394 if (batch->ep->address == instance->rh.address) {296 if (batch->ep->address == ohci_rh_get_address(&instance->rh)) { 395 297 usb_log_debug("OHCI root hub request.\n"); 396 rh_request(&instance->rh, batch); 397 return EOK; 298 return ohci_rh_schedule(&instance->rh, batch); 398 299 } 399 300 ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch); … … 423 324 /** Interrupt handling routine 424 325 * 425 * @param[in] instance OHCI hcdriver structure.326 * @param[in] hcd HCD driver structure. 426 327 * @param[in] status Value of the status register at the time of interrupt. 427 328 */ 428 void hc_interrupt(hc_t *instance, uint32_t status) 429 { 329 void ohci_hc_interrupt(hcd_t *hcd, uint32_t status) 330 { 331 assert(hcd); 332 hc_t *instance = hcd_get_driver_data(hcd); 430 333 status = OHCI_RD(status); 431 334 assert(instance); … … 434 337 usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status); 435 338 if (status & I_RHSC) 436 rh_interrupt(&instance->rh);339 ohci_rh_interrupt(&instance->rh); 437 340 438 341 if (status & I_WDH) { … … 465 368 } 466 369 467 }468 469 /** Check status register regularly470 *471 * @param[in] instance OHCI hc driver structure.472 * @return Error code473 */474 int interrupt_emulator(hc_t *instance)475 {476 assert(instance);477 usb_log_info("Started interrupt emulator.\n");478 while (1) {479 const uint32_t status = instance->registers->interrupt_status;480 instance->registers->interrupt_status = status;481 hc_interrupt(instance, status);482 async_usleep(10000);483 }484 return EOK;485 370 } 486 371 … … 508 393 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg)); 509 394 /* Zero everything but A20State */ 395 //TODO: should we ack interrupts before doing this? 510 396 OHCI_CLR(*ohci_emulation_reg, ~0x100); 511 397 usb_log_debug( … … 517 403 if (OHCI_RD(instance->registers->control) & C_IR) { 518 404 usb_log_debug("SMM driver: request ownership change.\n"); 405 //TODO: should we ack interrupts before doing this? 519 406 OHCI_SET(instance->registers->command_status, CS_OCR); 520 407 /* Hope that SMM actually knows its stuff or we can hang here */ 521 while (OHCI_RD(instance->registers->control & C_IR)) {408 while (OHCI_RD(instance->registers->control) & C_IR) { 522 409 async_usleep(1000); 523 410 } … … 603 490 604 491 /* Enable interrupts */ 605 OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS); 606 usb_log_debug("Enabled interrupts: %x.\n", 607 OHCI_RD(instance->registers->interrupt_enable)); 608 OHCI_WR(instance->registers->interrupt_enable, I_MI); 492 if (instance->hw_interrupts) { 493 OHCI_WR(instance->registers->interrupt_enable, 494 OHCI_USED_INTERRUPTS); 495 usb_log_debug("Enabled interrupts: %x.\n", 496 OHCI_RD(instance->registers->interrupt_enable)); 497 OHCI_WR(instance->registers->interrupt_enable, I_MI); 498 } 609 499 610 500 /* Set periodic start to 90% */ … … 632 522 do { \ 633 523 const char *name = usb_str_transfer_type(type); \ 634 int ret = endpoint_list_init(&instance->lists[type], name); \524 const int ret = endpoint_list_init(&instance->lists[type], name); \ 635 525 if (ret != EOK) { \ 636 526 usb_log_error("Failed to setup %s endpoint list: %s.\n", \ -
uspace/drv/bus/usb/ohci/hc.h
r5b18137 rb4b534ac 35 35 #define DRV_OHCI_HC_H 36 36 37 #include <adt/list.h> 38 #include <ddi.h> 37 39 #include <ddf/driver.h> 38 #include <d df/interrupt.h>40 #include <device/hw_res_parsed.h> 39 41 #include <fibril.h> 40 42 #include <fibril_synch.h> 41 #include < adt/list.h>42 #include < ddi.h>43 #include <stdbool.h> 44 #include <sys/types.h> 43 45 44 #include <usb/usb.h>45 46 #include <usb/host/hcd.h> 47 #include <usb/host/endpoint.h> 48 #include <usb/host/usb_transfer_batch.h> 46 49 47 #include "ohci_batch.h"48 50 #include "ohci_regs.h" 49 #include " root_hub.h"51 #include "ohci_rh.h" 50 52 #include "endpoint_list.h" 51 53 #include "hw_struct/hcca.h" … … 53 55 /** Main OHCI driver structure */ 54 56 typedef struct hc { 55 /** Generic USB hc driver */56 hcd_t *generic;57 58 57 /** Memory mapped I/O registers area */ 59 58 ohci_regs_t *registers; … … 72 71 fibril_mutex_t guard; 73 72 73 /** interrupts available */ 74 bool hw_interrupts; 75 74 76 /** USB hub emulation structure */ 75 rh_t rh;77 ohci_rh_t rh; 76 78 } hc_t; 77 79 78 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, 79 addr_range_t *); 80 int hc_register_irq_handler(ddf_dev_t *, addr_range_t *, int, 81 interrupt_handler_t); 82 int hc_register_hub(hc_t *, ddf_fun_t *); 83 int hc_init(hc_t *, ddf_fun_t *, addr_range_t *, bool); 84 85 /** Safely dispose host controller internal structures 86 * 87 * @param[in] instance Host controller structure to use. 88 */ 89 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 80 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts); 81 void hc_fini(hc_t *instance); 90 82 91 83 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep); 92 84 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep); 93 85 94 void hc_interrupt(hc_t *instance, uint32_t status); 86 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res); 87 88 void ohci_hc_interrupt(hcd_t *hcd, uint32_t status); 89 int ohci_hc_status(hcd_t *hcd, uint32_t *status); 90 int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 95 91 #endif 96 92 /** -
uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h
r5b18137 rb4b534ac 37 37 #include <errno.h> 38 38 39 #define CC_NOERROR (0x0) 40 #define CC_CRC (0x1) 41 #define CC_BITSTUFF (0x2) 42 #define CC_TOGGLE (0x3) 43 #define CC_STALL (0x4) 44 #define CC_NORESPONSE (0x5) 45 #define CC_PIDFAIL (0x6) 46 #define CC_PIDUNEXPECTED (0x7) 47 #define CC_DATAOVERRRUN (0x8) 48 #define CC_DATAUNDERRRUN (0x9) 49 #define CC_BUFFEROVERRRUN (0xc) 50 #define CC_BUFFERUNDERRUN (0xd) 51 #define CC_NOACCESS1 (0xe) 52 #define CC_NOACCESS2 (0xf) 39 enum { 40 CC_NOERROR = 0x0, 41 CC_CRC = 0x1, 42 CC_BITSTUFF = 0x2, 43 CC_TOGGLE = 0x3, 44 CC_STALL = 0x4, 45 CC_NORESPONSE = 0x5, 46 CC_PIDFAIL = 0x6, 47 CC_PIDUNEXPECTED = 0x7, 48 CC_DATAOVERRRUN = 0x8, 49 CC_DATAUNDERRRUN = 0x9, 50 CC_BUFFEROVERRRUN = 0xc, 51 CC_BUFFERUNDERRUN = 0xd, 52 CC_NOACCESS1 = 0xe, 53 CC_NOACCESS2 = 0xf, 54 }; 53 55 54 inline static int cc_to_rc(intcc)56 inline static unsigned cc_to_rc(unsigned cc) 55 57 { 56 58 switch (cc) { -
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
r5b18137 rb4b534ac 32 32 * @brief OHCI driver 33 33 */ 34 35 #include <assert.h> 36 #include <macros.h> 37 #include <mem.h> 38 39 #include <usb/usb.h> 40 #include <usb/host/utils/malloc32.h> 41 42 #include "mem_access.h" 43 34 44 #include "endpoint_descriptor.h" 35 45 … … 48 58 * @param td TD to put in the list. 49 59 * 50 * If @param ep is NULL, dummy ED is init alized with only skip flag set.60 * If @param ep is NULL, dummy ED is initialized with only skip flag set. 51 61 */ 52 62 void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td) 53 63 { 54 64 assert(instance); 55 memset(instance, 0, sizeof( ed_t));65 memset(instance, 0, sizeof(*instance)); 56 66 57 67 if (ep == NULL) { … … 61 71 return; 62 72 } 63 /* Non-dummy ED must have TD assigned */73 /* Non-dummy ED must have corresponding EP and TD assigned */ 64 74 assert(td); 75 assert(ep); 76 assert(ep->direction < ARRAY_SIZE(dir)); 65 77 66 78 /* Status: address, endpoint nr, direction mask and max packet size. */ … … 77 89 78 90 /* Isochronous format flag */ 91 // TODO: We need iTD instead of TD for iso transfers 79 92 if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS) 80 93 OHCI_MEM32_SET(instance->status, ED_STATUS_F_FLAG); -
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h
r5b18137 rb4b534ac 36 36 37 37 #include <assert.h> 38 #include <stdint.h> 38 #include <stdbool.h> 39 #include <sys/types.h> 39 40 40 41 #include <usb/host/endpoint.h> 41 42 #include "../utils/malloc32.h" 42 #include <usb/host/utils/malloc32.h> 43 43 44 #include "transfer_descriptor.h" 44 45 -
uspace/drv/bus/usb/ohci/hw_struct/hcca.h
r5b18137 rb4b534ac 35 35 #define DRV_OHCI_HW_STRUCT_HCCA_H 36 36 37 #include <stdint.h>38 37 #include <malloc.h> 38 #include <sys/types.h> 39 #include <macros.h> 39 40 40 41 #include "mem_access.h" … … 50 51 /** Frame number. */ 51 52 uint16_t frame_number; 52 uint16_t pad1;53 PADD16; 53 54 /** Pointer to the last completed TD. (useless) */ 54 55 uint32_t done_head; 55 56 /** Padding to make the size 256B */ 56 uint32_t reserved[30];57 PADD32[30]; 57 58 } hcca_t; 59 60 STATIC_ASSERT(sizeof(hcca_t) == 256); 58 61 59 62 /** Allocate properly aligned structure. … … 65 68 static inline hcca_t * hcca_get(void) 66 69 { 67 static_assert(sizeof(hcca_t) == 256); 68 hcca_t *hcca = memalign(256, sizeof(hcca_t)); 70 hcca_t *hcca = memalign(sizeof(hcca_t), sizeof(hcca_t)); 69 71 if (hcca) 70 72 memset(hcca, 0, sizeof(hcca_t)); … … 80 82 { 81 83 assert(hcca); 82 assert(index < HCCA_INT_EP_COUNT);84 assert(index < ARRAY_SIZE(hcca->int_ep)); 83 85 OHCI_MEM32_WR(hcca->int_ep[index], pa); 84 85 86 } 86 87 #endif -
uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h
r5b18137 rb4b534ac 35 35 #define DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H 36 36 37 #include <s tdint.h>37 #include <sys/types.h> 38 38 39 39 #include "completion_codes.h" -
uspace/drv/bus/usb/ohci/hw_struct/mem_access.h
r5b18137 rb4b534ac 47 47 * @} 48 48 */ 49 -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
r5b18137 rb4b534ac 32 32 * @brief OHCI driver 33 33 */ 34 35 #include <assert.h> 36 #include <mem.h> 37 34 38 #include <usb/usb.h> 35 #include <mem.h> 36 #include "../utils/malloc32.h" 39 #include <usb/host/utils/malloc32.h> 40 41 #include "completion_codes.h" 42 #include "mem_access.h" 37 43 #include "transfer_descriptor.h" 38 44 … … 70 76 } 71 77 72 /* Al ow less data on input. */78 /* Allow less data on input. */ 73 79 if (dir == USB_DIRECTION_IN) { 74 80 OHCI_MEM32_SET(instance->status, TD_STATUS_ROUND_FLAG); -
uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
r5b18137 rb4b534ac 35 35 #define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H 36 36 37 #include <assert.h> 37 38 #include <stdbool.h> 38 39 #include <stdint.h> -
uspace/drv/bus/usb/ohci/main.c
r5b18137 rb4b534ac 33 33 * Main routines of OHCI driver. 34 34 */ 35 36 #include <assert.h> 35 37 #include <ddf/driver.h> 36 38 #include <errno.h> 39 #include <io/log.h> 37 40 #include <str_error.h> 38 41 39 42 #include <usb/debug.h> 43 #include <usb/host/ddf_helpers.h> 40 44 41 #include " ohci.h"45 #include "hc.h" 42 46 43 47 #define NAME "ohci" 48 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 49 static void ohci_driver_fini(hcd_t *); 50 51 static const ddf_hc_driver_t ohci_hc_driver = { 52 .hc_speed = USB_SPEED_FULL, 53 .irq_code_gen = ohci_hc_gen_irq_code, 54 .init = ohci_driver_init, 55 .fini = ohci_driver_fini, 56 .name = "OHCI", 57 .ops = { 58 .schedule = ohci_hc_schedule, 59 .ep_add_hook = ohci_endpoint_init, 60 .ep_remove_hook = ohci_endpoint_fini, 61 .irq_hook = ohci_hc_interrupt, 62 .status_hook = ohci_hc_status, 63 }, 64 }; 65 66 67 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq) 68 { 69 assert(hcd); 70 assert(hcd_get_driver_data(hcd) == NULL); 71 72 hc_t *instance = malloc(sizeof(hc_t)); 73 if (!instance) 74 return ENOMEM; 75 76 const int ret = hc_init(instance, res, irq); 77 if (ret == EOK) { 78 hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops); 79 } else { 80 free(instance); 81 } 82 return ret; 83 } 84 85 static void ohci_driver_fini(hcd_t *hcd) 86 { 87 assert(hcd); 88 hc_t *hc = hcd_get_driver_data(hcd); 89 if (hc) 90 hc_fini(hc); 91 92 hcd_set_implementation(hcd, NULL, NULL); 93 free(hc); 94 } 44 95 45 96 /** Initializes a new ddf driver instance of OHCI hcd. … … 52 103 usb_log_debug("ohci_dev_add() called\n"); 53 104 assert(device); 54 55 int ret = device_setup_ohci(device); 56 if (ret != EOK) { 57 usb_log_error("Failed to initialize OHCI driver: %s.\n", 58 str_error(ret)); 59 return ret; 60 } 61 usb_log_info("Controlling new OHCI device '%s'.\n", ddf_dev_get_name(device)); 62 63 return EOK; 105 return hcd_ddf_add_hc(device, &ohci_hc_driver); 64 106 } 65 107 66 static driver_ops_t ohci_driver_ops = {108 static const driver_ops_t ohci_driver_ops = { 67 109 .dev_add = ohci_dev_add, 68 110 }; 69 111 70 static driver_t ohci_driver = {112 static const driver_t ohci_driver = { 71 113 .name = NAME, 72 114 .driver_ops = &ohci_driver_ops -
uspace/drv/bus/usb/ohci/ohci_batch.c
r5b18137 rb4b534ac 32 32 * @brief OHCI driver USB transaction structure 33 33 */ 34 35 #include <assert.h> 34 36 #include <errno.h> 35 #include <str_error.h>36 37 #include <macros.h> 38 #include <mem.h> 39 #include <stdbool.h> 37 40 38 41 #include <usb/usb.h> 39 42 #include <usb/debug.h> 43 #include <usb/host/utils/malloc32.h> 40 44 41 45 #include "ohci_batch.h" 42 46 #include "ohci_endpoint.h" 43 #include "utils/malloc32.h"44 47 45 48 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t); … … 94 97 { 95 98 assert(usb_batch); 96 #define CHECK_NULL_DISPOSE_RET(ptr, message...) \97 if (ptr == NULL) { \98 usb_log_error(message); \99 ohci_transfer_batch_dispose(ohci_batch); \100 return NULL; \101 } else (void)0102 99 103 100 ohci_transfer_batch_t *ohci_batch = 104 101 calloc(1, sizeof(ohci_transfer_batch_t)); 105 CHECK_NULL_DISPOSE_RET(ohci_batch, 106 "Failed to allocate OHCI batch data.\n"); 102 if (!ohci_batch) { 103 usb_log_error("Failed to allocate OHCI batch data."); 104 goto dispose; 105 } 107 106 link_initialize(&ohci_batch->link); 108 107 ohci_batch->td_count = … … 116 115 /* We need an extra place for TD that was left at ED */ 117 116 ohci_batch->tds = calloc(ohci_batch->td_count + 1, sizeof(td_t*)); 118 CHECK_NULL_DISPOSE_RET(ohci_batch->tds, 119 "Failed to allocate OHCI transfer descriptors.\n"); 117 if (!ohci_batch->tds) { 118 usb_log_error("Failed to allocate OHCI transfer descriptors."); 119 goto dispose; 120 } 120 121 121 122 /* Add TD left over by the previous transfer */ … … 125 126 for (unsigned i = 1; i <= ohci_batch->td_count; ++i) { 126 127 ohci_batch->tds[i] = malloc32(sizeof(td_t)); 127 CHECK_NULL_DISPOSE_RET(ohci_batch->tds[i], 128 "Failed to allocate TD %d.\n", i ); 128 if (!ohci_batch->tds[i]) { 129 usb_log_error("Failed to allocate TD %d.", i); 130 goto dispose; 131 } 129 132 } 130 133 … … 138 141 ohci_batch->device_buffer = 139 142 malloc32(usb_batch->setup_size + usb_batch->buffer_size); 140 CHECK_NULL_DISPOSE_RET(ohci_batch->device_buffer, 141 "Failed to allocate device accessible buffer.\n"); 143 if (!ohci_batch->device_buffer) { 144 usb_log_error("Failed to allocate device buffer"); 145 goto dispose; 146 } 142 147 /* Copy setup data */ 143 148 memcpy(ohci_batch->device_buffer, usb_batch->setup_buffer, … … 156 161 157 162 return ohci_batch; 158 #undef CHECK_NULL_DISPOSE_RET 163 dispose: 164 ohci_transfer_batch_dispose(ohci_batch); 165 return NULL; 159 166 } 160 167 -
uspace/drv/bus/usb/ohci/ohci_batch.h
r5b18137 rb4b534ac 36 36 37 37 #include <adt/list.h> 38 #include < usbhc_iface.h>39 #include < usb/usb.h>38 #include <assert.h> 39 #include <stdbool.h> 40 40 #include <usb/host/usb_transfer_batch.h> 41 41 -
uspace/drv/bus/usb/ohci/ohci_endpoint.c
r5b18137 rb4b534ac 32 32 * @brief OHCI driver 33 33 */ 34 #include "utils/malloc32.h" 34 35 #include <assert.h> 36 #include <stdlib.h> 37 #include <usb/host/utils/malloc32.h> 38 35 39 #include "ohci_endpoint.h" 36 40 #include "hc.h" … … 87 91 } 88 92 93 link_initialize(&ohci_ep->link); 89 94 ed_init(ohci_ep->ed, ep, ohci_ep->td); 90 95 endpoint_set_hc_data( 91 96 ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set); 92 hc_enqueue_endpoint(hcd ->private_data, ep);97 hc_enqueue_endpoint(hcd_get_driver_data(hcd), ep); 93 98 return EOK; 94 99 } … … 104 109 assert(ep); 105 110 ohci_endpoint_t *instance = ohci_endpoint_get(ep); 106 hc_dequeue_endpoint(hcd->private_data, ep); 111 hc_dequeue_endpoint(hcd_get_driver_data(hcd), ep); 112 endpoint_clear_hc_data(ep); 107 113 if (instance) { 108 114 free32(instance->ed); … … 110 116 free(instance); 111 117 } 112 endpoint_clear_hc_data(ep);113 118 } 114 119 /** -
uspace/drv/bus/usb/ohci/ohci_regs.h
r5b18137 rb4b534ac 34 34 #ifndef DRV_OHCI_OHCI_REGS_H 35 35 #define DRV_OHCI_OHCI_REGS_H 36 #include <ddi.h> 36 37 #include <sys/types.h> 37 38 #include <byteorder.h> 38 39 39 #define OHCI_WR(reg, val) reg = host2uint32_t_le(val) 40 #define OHCI_RD(reg) uint32_t_le2host(reg) 41 #define OHCI_SET(reg, val) reg |= host2uint32_t_le(val) 42 #define OHCI_CLR(reg, val) reg &= host2uint32_t_le(~val) 43 40 #define OHCI_WR(reg, val) pio_write_32(&(reg), host2uint32_t_le(val)) 41 #define OHCI_RD(reg) uint32_t_le2host(pio_read_32(&(reg))) 42 #define OHCI_SET(reg, val) pio_set_32(&(reg), host2uint32_t_le(val), 1) 43 #define OHCI_CLR(reg, val) pio_clear_32(&(reg), host2uint32_t_le(val), 1) 44 44 45 45 #define LEGACY_REGS_OFFSET 0x100 … … 215 215 /** Root hub per port status */ 216 216 ioport32_t rh_port_status[]; 217 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,217 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status, 218 218 * w: 1-clear port enable, 0-N/S*/ 219 219 #define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG 220 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status220 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status 221 221 * w: 1-set port enable, 0-N/S */ 222 222 #define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG 223 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status223 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status 224 224 * w: 1-set port suspend, 0-N/S */ 225 225 #define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG 226 #define RHPS_POCI_FLAG (1 << 3) /* r: port over-current226 #define RHPS_POCI_FLAG (1 << 3) /* r: port over-current 227 227 * (if reports are per-port 228 228 * w: 1-clear port suspend … … 230 230 * 0-nothing */ 231 231 #define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG 232 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status232 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status 233 233 * w: 1-set port reset, 0-N/S */ 234 234 #define RHPS_SET_PORT_RESET RHPS_PRS_FLAG 235 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status235 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status 236 236 * w: 1-set port power, 0-N/S */ 237 237 #define RHPS_SET_PORT_POWER RHPS_PPS_FLAG 238 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached238 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached 239 239 * w: 1-clear port power, 0-N/S*/ 240 240 #define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG -
uspace/drv/bus/usb/ohci/ohci_rh.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 32 32 * @brief OHCI driver 33 33 */ 34 #ifndef DRV_OHCI_ROOT_HUB_H 35 #define DRV_OHCI_ROOT_HUB_H 34 #ifndef DRV_OHCI_OHCI_RH_H 35 #define DRV_OHCI_OHCI_RH_H 36 37 #include <assert.h> 38 #include <sys/types.h> 36 39 37 40 #include <usb/usb.h> 38 #include <usb/ dev/driver.h>41 #include <usb/classes/hub.h> 39 42 #include <usb/host/usb_transfer_batch.h> 43 #include <usbvirt/virthub_base.h> 40 44 41 45 #include "ohci_regs.h" 42 46 43 #define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2) 47 enum { 48 OHCI_MAX_PORTS = 15, 49 }; 44 50 45 /** 46 * ohci root hub representation 47 */ 48 typedef struct rh { 49 fibril_mutex_t guard; 50 /** pointer to ohci driver registers */ 51 typedef struct { 52 /** Virtual hub instance */ 53 virthub_base_t base; 54 /** OHCI device registers */ 51 55 ohci_regs_t *registers; 52 /** usb address of the root hub */ 53 usb_address_t address; 54 /** hub port count */ 55 size_t port_count; 56 /** Number of downstream ports, OHCI limits this to 15 */ 57 unsigned port_count; 58 /** USB hub descriptor describing the OHCI root hub */ 59 struct { 60 usb_hub_descriptor_header_t header; 61 uint8_t rempow[STATUS_BYTES(OHCI_MAX_PORTS) * 2]; 62 } __attribute__((packed)) hub_descriptor; 56 63 /** interrupt transfer waiting for an actual interrupt to occur */ 57 64 usb_transfer_batch_t *unfinished_interrupt_transfer; 58 /** size of interrupt buffer */ 59 size_t interrupt_mask_size; 60 /** Descriptors */ 61 struct { 62 usb_standard_configuration_descriptor_t configuration; 63 usb_standard_interface_descriptor_t interface; 64 usb_standard_endpoint_descriptor_t endpoint; 65 uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE]; 66 } __attribute__ ((packed)) descriptors; 67 /** size of hub descriptor */ 68 size_t hub_descriptor_size; 69 } rh_t; 65 } ohci_rh_t; 70 66 71 void rh_init(rh_t *instance, ohci_regs_t *regs); 67 int ohci_rh_init(ohci_rh_t *instance, ohci_regs_t *regs, const char *name); 68 int ohci_rh_schedule(ohci_rh_t *instance, usb_transfer_batch_t *batch); 69 int ohci_rh_interrupt(ohci_rh_t *instance); 72 70 73 void rh_request(rh_t *instance, usb_transfer_batch_t *request); 74 75 void rh_interrupt(rh_t *instance); 71 /** Get OHCI rh address. 72 * 73 * @param instance UHCI rh instance. 74 * @return USB address assigned to the hub. 75 * Wrapper for virtual hub address 76 */ 77 static inline usb_address_t ohci_rh_get_address(ohci_rh_t *instance) 78 { 79 assert(instance); 80 return virthub_base_get_address(&instance->base); 81 } 76 82 #endif 77 83 /** -
uspace/drv/bus/usb/uhci/Makefile
r5b18137 rb4b534ac 31 31 LIBS = \ 32 32 $(LIBUSBHOST_PREFIX)/libusbhost.a \ 33 $(LIBUSBVIRT_PREFIX)/libusbvirt.a \ 33 34 $(LIBUSB_PREFIX)/libusb.a \ 34 35 $(LIBDRV_PREFIX)/libdrv.a … … 36 37 EXTRA_CFLAGS += \ 37 38 -I$(LIBUSB_PREFIX)/include \ 39 -I$(LIBUSBDEV_PREFIX)/include \ 38 40 -I$(LIBUSBHOST_PREFIX)/include \ 41 -I$(LIBUSBVIRT_PREFIX)/include \ 39 42 -I$(LIBDRV_PREFIX)/include 40 43 … … 44 47 hc.c \ 45 48 main.c \ 46 res.c \47 root_hub.c \48 49 transfer_list.c \ 49 uhci.c \50 50 uhci_batch.c \ 51 uhci_rh.c \ 51 52 hw_struct/transfer_descriptor.c 52 53 -
uspace/drv/bus/usb/uhci/hc.c
r5b18137 rb4b534ac 32 32 * @brief UHCI Host controller driver routines 33 33 */ 34 35 #include <adt/list.h> 36 #include <assert.h> 37 #include <async.h> 38 #include <ddi.h> 39 #include <device/hw_res_parsed.h> 40 #include <fibril.h> 34 41 #include <errno.h> 42 #include <macros.h> 43 #include <mem.h> 44 #include <stdlib.h> 35 45 #include <str_error.h> 36 #include <adt/list.h> 37 #include <ddi.h> 46 #include <sys/types.h> 38 47 39 48 #include <usb/debug.h> 40 49 #include <usb/usb.h> 41 50 #include <usb/host/utils/malloc32.h> 51 52 #include "uhci_batch.h" 42 53 #include "hc.h" 43 #include "uhci_batch.h"44 54 45 55 #define UHCI_INTR_ALLOW_INTERRUPTS \ … … 85 95 static int hc_init_mem_structures(hc_t *instance); 86 96 static int hc_init_transfer_lists(hc_t *instance); 87 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 88 89 static int hc_interrupt_emulator(void *arg); 97 90 98 static int hc_debug_checker(void *arg); 91 99 92 enum {93 /** Number of PIO ranges used in IRQ code */94 hc_irq_pio_range_count =95 sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t),96 97 /* Number of commands used in IRQ code */98 hc_irq_cmd_count =99 sizeof(uhci_irq_commands) / sizeof(irq_cmd_t)100 };101 100 102 101 /** Generate IRQ code. 103 * @param[out] ranges PIO ranges buffer. 104 * @param[in] ranges_size Size of the ranges buffer (bytes). 105 * @param[out] cmds Commands buffer. 106 * @param[in] cmds_size Size of the commands buffer (bytes). 107 * @param[in] regs Device's register range. 102 * @param[out] code IRQ code structure. 103 * @param[in] hw_res Device's resources. 108 104 * 109 105 * @return Error code. 110 106 */ 111 int 112 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[], 113 size_t cmds_size, addr_range_t *regs) 114 { 115 if ((ranges_size < sizeof(uhci_irq_pio_ranges)) || 116 (cmds_size < sizeof(uhci_irq_commands)) || 117 (RNGSZ(*regs) < sizeof(uhci_regs_t))) 107 int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res) 108 { 109 assert(code); 110 assert(hw_res); 111 112 if (hw_res->irqs.count != 1 || hw_res->io_ranges.count != 1) 113 return EINVAL; 114 const addr_range_t regs = hw_res->io_ranges.ranges[0]; 115 116 if (RNGSZ(regs) < sizeof(uhci_regs_t)) 118 117 return EOVERFLOW; 119 118 120 memcpy(ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges)); 121 ranges[0].base = RNGABS(*regs); 122 123 memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands)); 124 uhci_regs_t *registers = (uhci_regs_t *) RNGABSPTR(*regs); 125 cmds[0].addr = (void *) ®isters->usbsts; 126 cmds[3].addr = (void *) ®isters->usbsts; 127 128 return EOK; 129 } 130 131 /** Register interrupt handler. 132 * 133 * @param[in] device Host controller DDF device 134 * @param[in] regs Register range 135 * @param[in] irq Interrupt number 136 * @paran[in] handler Interrupt handler 137 * 138 * @return EOK on success or negative error code 139 */ 140 int hc_register_irq_handler(ddf_dev_t *device, addr_range_t *regs, int irq, 141 interrupt_handler_t handler) 142 { 143 int rc; 144 irq_pio_range_t irq_ranges[hc_irq_pio_range_count]; 145 irq_cmd_t irq_cmds[hc_irq_cmd_count]; 146 rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 147 sizeof(irq_cmds), regs); 148 if (rc != EOK) { 149 usb_log_error("Failed to generate IRQ commands: %s.\n", 150 str_error(rc)); 151 return rc; 152 } 153 154 irq_code_t irq_code = { 155 .rangecount = hc_irq_pio_range_count, 156 .ranges = irq_ranges, 157 .cmdcount = hc_irq_cmd_count, 158 .cmds = irq_cmds 159 }; 160 161 /* Register handler to avoid interrupt lockup */ 162 rc = register_interrupt_handler(device, irq, handler, &irq_code); 163 if (rc != EOK) { 164 usb_log_error("Failed to register interrupt handler: %s.\n", 165 str_error(rc)); 166 return rc; 167 } 168 169 return EOK; 119 code->ranges = malloc(sizeof(uhci_irq_pio_ranges)); 120 if (code->ranges == NULL) 121 return ENOMEM; 122 123 code->cmds = malloc(sizeof(uhci_irq_commands)); 124 if (code->cmds == NULL) { 125 free(code->ranges); 126 return ENOMEM; 127 } 128 129 code->rangecount = ARRAY_SIZE(uhci_irq_pio_ranges); 130 code->cmdcount = ARRAY_SIZE(uhci_irq_commands); 131 132 memcpy(code->ranges, uhci_irq_pio_ranges, sizeof(uhci_irq_pio_ranges)); 133 code->ranges[0].base = RNGABS(regs); 134 135 memcpy(code->cmds, uhci_irq_commands, sizeof(uhci_irq_commands)); 136 uhci_regs_t *registers = (uhci_regs_t *) RNGABSPTR(regs); 137 code->cmds[0].addr = (void*)®isters->usbsts; 138 code->cmds[3].addr = (void*)®isters->usbsts; 139 140 usb_log_debug("I/O regs at %p (size %zu), IRQ %d.\n", 141 RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]); 142 143 return hw_res->irqs.irqs[0]; 170 144 } 171 145 172 146 /** Take action based on the interrupt cause. 173 147 * 174 * @param[in] instance UHCIstructure to use.148 * @param[in] hcd HCD structure to use. 175 149 * @param[in] status Value of the status register at the time of interrupt. 176 150 * … … 180 154 * - resume from suspend state (not implemented) 181 155 */ 182 void hc_interrupt(hc_t *instance, uint16_t status) 183 { 156 void uhci_hc_interrupt(hcd_t *hcd, uint32_t status) 157 { 158 assert(hcd); 159 hc_t *instance = hcd_get_driver_data(hcd); 184 160 assert(instance); 185 161 /* Lower 2 bits are transaction error and transaction complete */ … … 195 171 &instance->transfers_bulk_full, &done); 196 172 197 while (!list_empty(&done)) { 198 link_t *item = list_first(&done); 199 list_remove(item); 173 list_foreach_safe(done, current, next) { 174 list_remove(current); 200 175 uhci_transfer_batch_t *batch = 201 uhci_transfer_batch_from_link( item);176 uhci_transfer_batch_from_link(current); 202 177 uhci_transfer_batch_finish_dispose(batch); 203 178 } … … 230 205 * 231 206 * @param[in] instance Memory place to initialize. 232 * @param[in] HC function node233 207 * @param[in] regs Range of device's I/O control registers. 234 208 * @param[in] interrupts True if hw interrupts should be used. … … 239 213 * interrupt fibrils. 240 214 */ 241 int hc_init(hc_t *instance, ddf_fun_t *fun, addr_range_t *regs, bool interrupts) 242 { 243 assert(regs->size >= sizeof(uhci_regs_t)); 244 int rc; 215 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts) 216 { 217 assert(instance); 218 assert(hw_res); 219 if (hw_res->io_ranges.count != 1 || 220 hw_res->io_ranges.ranges[0].size < sizeof(uhci_regs_t)) 221 return EINVAL; 245 222 246 223 instance->hw_interrupts = interrupts; … … 248 225 249 226 /* allow access to hc control registers */ 250 uhci_regs_t *io; 251 rc = pio_enable_range(regs, (void **) &io); 252 if (rc != EOK) { 253 usb_log_error("Failed to gain access to registers at %p: %s.\n", 254 io, str_error(rc)); 255 return rc; 256 } 257 258 instance->registers = io; 259 usb_log_debug( 260 "Device registers at %p (%zuB) accessible.\n", io, regs->size); 261 262 rc = hc_init_mem_structures(instance); 263 if (rc != EOK) { 264 usb_log_error("Failed to initialize UHCI memory structures: %s.\n", 265 str_error(rc)); 266 return rc; 267 } 268 269 instance->generic = ddf_fun_data_alloc(fun, sizeof(hcd_t)); 270 if (instance->generic == NULL) { 271 usb_log_error("Out of memory.\n"); 272 return ENOMEM; 273 } 274 275 hcd_init(instance->generic, USB_SPEED_FULL, 276 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 277 278 instance->generic->private_data = instance; 279 instance->generic->schedule = hc_schedule; 280 instance->generic->ep_add_hook = NULL; 227 int ret = pio_enable_range(&hw_res->io_ranges.ranges[0], 228 (void **) &instance->registers); 229 if (ret != EOK) { 230 usb_log_error("Failed to gain access to registers: %s.\n", 231 str_error(ret)); 232 return ret; 233 } 234 235 usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.\n", 236 hw_res->io_ranges.ranges[0].address.absolute, 237 hw_res->io_ranges.ranges[0].size); 238 239 ret = hc_init_mem_structures(instance); 240 if (ret != EOK) { 241 usb_log_error("Failed to init UHCI memory structures: %s.\n", 242 str_error(ret)); 243 // TODO: we should disable pio here 244 return ret; 245 } 281 246 282 247 hc_init_hw(instance); 283 if (!interrupts) {284 instance->interrupt_emulator =285 fibril_create(hc_interrupt_emulator, instance);286 fibril_add_ready(instance->interrupt_emulator);287 }288 248 (void)hc_debug_checker; 289 249 250 uhci_rh_init(&instance->rh, instance->registers->ports, "uhci"); 251 290 252 return EOK; 253 } 254 255 /** Safely dispose host controller internal structures 256 * 257 * @param[in] instance Host controller structure to use. 258 */ 259 void hc_fini(hc_t *instance) 260 { 261 assert(instance); 262 //TODO Implement 291 263 } 292 264 … … 432 404 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] = 433 405 &instance->transfers_bulk_full; 434 instance->transfers[USB_SPEED_LOW][USB_TRANSFER_BULK] = 435 &instance->transfers_bulk_full; 436 406 407 return EOK; 408 } 409 410 int uhci_hc_status(hcd_t *hcd, uint32_t *status) 411 { 412 assert(hcd); 413 assert(status); 414 hc_t *instance = hcd_get_driver_data(hcd); 415 assert(instance); 416 417 *status = 0; 418 if (instance->registers) { 419 uint16_t s = pio_read_16(&instance->registers->usbsts); 420 pio_write_16(&instance->registers->usbsts, s); 421 *status = s; 422 } 437 423 return EOK; 438 424 } … … 446 432 * Checks for bandwidth availability and appends the batch to the proper queue. 447 433 */ 448 int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)434 int uhci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 449 435 { 450 436 assert(hcd); 451 hc_t *instance = hcd ->private_data;437 hc_t *instance = hcd_get_driver_data(hcd); 452 438 assert(instance); 453 439 assert(batch); 440 441 if (batch->ep->address == uhci_rh_get_address(&instance->rh)) 442 return uhci_rh_schedule(&instance->rh, batch); 443 454 444 uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch); 455 445 if (!uhci_batch) { … … 463 453 transfer_list_add_batch(list, uhci_batch); 464 454 465 return EOK;466 }467 468 /** Polling function, emulates interrupts.469 *470 * @param[in] arg UHCI hc structure to use.471 * @return EOK (should never return)472 */473 int hc_interrupt_emulator(void* arg)474 {475 usb_log_debug("Started interrupt emulator.\n");476 hc_t *instance = arg;477 assert(instance);478 479 while (1) {480 /* Read and clear status register */481 uint16_t status = pio_read_16(&instance->registers->usbsts);482 pio_write_16(&instance->registers->usbsts, status);483 if (status != 0)484 usb_log_debug2("UHCI status: %x.\n", status);485 hc_interrupt(instance, status);486 async_usleep(UHCI_INT_EMULATOR_TIMEOUT);487 }488 455 return EOK; 489 456 } -
uspace/drv/bus/usb/uhci/hc.h
r5b18137 rb4b534ac 36 36 #define DRV_UHCI_HC_H 37 37 38 #include <ddf/driver.h>39 #include <ddf/interrupt.h>40 38 #include <device/hw_res_parsed.h> 41 39 #include <fibril.h> 40 #include <macros.h> 41 #include <stdbool.h> 42 #include <sys/types.h> 42 43 #include <usb/host/hcd.h> 44 #include <usb/host/usb_transfer_batch.h> 43 45 46 #include "uhci_rh.h" 44 47 #include "transfer_list.h" 48 #include "hw_struct/link_pointer.h" 45 49 46 50 /** UHCI I/O registers layout */ … … 83 87 /** SOF modification to match external timers */ 84 88 ioport8_t sofmod; 89 90 PADD8[3]; 91 ioport16_t ports[]; 85 92 } uhci_regs_t; 86 93 87 94 #define UHCI_FRAME_LIST_COUNT 1024 88 #define UHCI_INT_EMULATOR_TIMEOUT 1000089 95 #define UHCI_DEBUGER_TIMEOUT 5000000 90 96 #define UHCI_ALLOWED_HW_FAIL 5 91 #define UHCI_NEEDED_IRQ_COMMANDS 592 97 93 98 /** Main UHCI driver structure */ 94 99 typedef struct hc { 95 /** Generic HCD driver structure */ 96 hcd_t *generic; 97 100 uhci_rh_t rh; 98 101 /** Addresses of I/O registers */ 99 102 uhci_regs_t *registers; … … 113 116 /** Pointer table to the above lists, helps during scheduling */ 114 117 transfer_list_t *transfers[2][4]; 115 /** Fibril periodically checking status register*/116 fid_t interrupt_emulator;117 118 /** Indicator of hw interrupts availability */ 118 119 bool hw_interrupts; … … 122 123 } hc_t; 123 124 124 int hc_register_irq_handler(ddf_dev_t *, addr_range_t *, int, 125 interrupt_handler_t); 126 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, 127 addr_range_t *); 128 void hc_interrupt(hc_t *instance, uint16_t status); 129 int hc_init(hc_t *, ddf_fun_t *, addr_range_t *, bool); 125 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interupts); 126 void hc_fini(hc_t *instance); 130 127 131 /** Safely dispose host controller internal structures 132 * 133 * @param[in] instance Host controller structure to use. 134 */ 135 static inline void hc_fini(hc_t *instance) {} /* TODO: implement*/ 128 int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res); 129 130 void uhci_hc_interrupt(hcd_t *hcd, uint32_t status); 131 int uhci_hc_status(hcd_t *hcd, uint32_t *status); 132 int uhci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 133 136 134 #endif 137 135 -
uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h
r5b18137 rb4b534ac 35 35 #define DRV_UHCI_HW_STRUCT_LINK_POINTER_H 36 36 37 #include <sys/types.h> 38 37 39 /** UHCI link pointer, used by many data structures */ 38 40 typedef uint32_t link_pointer_t; -
uspace/drv/bus/usb/uhci/hw_struct/queue_head.h
r5b18137 rb4b534ac 34 34 #ifndef DRV_UHCI_HW_STRUCT_QH_H 35 35 #define DRV_UHCI_HW_STRUCT_QH_H 36 36 37 #include <assert.h> 38 #include <sys/types.h> 39 #include <usb/host/utils/malloc32.h> 37 40 38 41 #include "link_pointer.h" 39 42 #include "transfer_descriptor.h" 40 #include "../utils/malloc32.h"41 43 42 44 /** This structure is defined in UHCI design guide p. 31 */ -
uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c
r5b18137 rb4b534ac 32 32 * @brief UHCI driver 33 33 */ 34 35 #include <assert.h> 34 36 #include <errno.h> 37 35 38 #include <usb/debug.h> 39 #include <usb/usb.h> 40 #include <usb/host/utils/malloc32.h> 36 41 42 #include "link_pointer.h" 37 43 #include "transfer_descriptor.h" 38 #include "../utils/malloc32.h"39 44 40 45 /** Initialize Transfer Descriptor -
uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h
r5b18137 rb4b534ac 35 35 #define DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H 36 36 37 #include < mem.h>37 #include <assert.h> 38 38 #include <usb/usb.h> 39 #include <stdbool.h> 40 #include <sys/types.h> 39 41 40 42 #include "link_pointer.h" -
uspace/drv/bus/usb/uhci/main.c
r5b18137 rb4b534ac 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhci hc28 /** @addtogroup drvusbuhci 29 29 * @{ 30 30 */ … … 32 32 * @brief UHCI driver initialization 33 33 */ 34 35 #include <assert.h> 34 36 #include <ddf/driver.h> 37 #include <devman.h> 35 38 #include <errno.h> 39 #include <io/log.h> 40 #include <io/logctl.h> 41 #include <pci_dev_iface.h> 42 #include <stdio.h> 36 43 #include <str_error.h> 44 #include <usb/debug.h> 45 #include <usb/host/ddf_helpers.h> 37 46 38 #include <usb/ddfiface.h> 39 #include <usb/debug.h> 40 41 #include "uhci.h" 47 #include "hc.h" 42 48 43 49 #define NAME "uhci" 44 50 45 static int uhci_dev_add(ddf_dev_t *device); 51 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 52 static void uhci_driver_fini(hcd_t *); 53 static int disable_legacy(ddf_dev_t *); 46 54 47 static driver_ops_t uhci_driver_ops = { 48 .dev_add = uhci_dev_add, 55 static const ddf_hc_driver_t uhci_hc_driver = { 56 .claim = disable_legacy, 57 .hc_speed = USB_SPEED_FULL, 58 .irq_code_gen = uhci_hc_gen_irq_code, 59 .init = uhci_driver_init, 60 .fini = uhci_driver_fini, 61 .name = "UHCI", 62 .ops = { 63 .schedule = uhci_hc_schedule, 64 .irq_hook = uhci_hc_interrupt, 65 .status_hook = uhci_hc_status, 66 }, 49 67 }; 50 68 51 static driver_t uhci_driver = { 52 .name = NAME, 53 .driver_ops = &uhci_driver_ops 54 }; 69 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq) 70 { 71 assert(hcd); 72 assert(hcd_get_driver_data(hcd) == NULL); 73 74 hc_t *instance = malloc(sizeof(hc_t)); 75 if (!instance) 76 return ENOMEM; 77 78 const int ret = hc_init(instance, res, irq); 79 if (ret == EOK) { 80 hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops); 81 } else { 82 free(instance); 83 } 84 return ret; 85 } 86 87 static void uhci_driver_fini(hcd_t *hcd) 88 { 89 assert(hcd); 90 hc_t *hc = hcd_get_driver_data(hcd); 91 if (hc) 92 hc_fini(hc); 93 94 hcd_set_implementation(hcd, NULL, NULL); 95 free(hc); 96 } 97 98 /** Call the PCI driver with a request to clear legacy support register 99 * 100 * @param[in] device Device asking to disable interrupts 101 * @return Error code. 102 */ 103 static int disable_legacy(ddf_dev_t *device) 104 { 105 assert(device); 106 107 async_sess_t *parent_sess = devman_parent_device_connect( 108 ddf_dev_get_handle(device), IPC_FLAG_BLOCKING); 109 if (!parent_sess) 110 return ENOMEM; 111 112 /* See UHCI design guide page 45 for these values. 113 * Write all WC bits in USB legacy register */ 114 const int rc = pci_config_space_write_16(parent_sess, 0xc0, 0xaf00); 115 116 async_hangup(parent_sess); 117 return rc; 118 } 55 119 56 120 /** Initialize a new ddf driver instance for uhci hc and hub. … … 59 123 * @return Error code. 60 124 */ 61 int uhci_dev_add(ddf_dev_t *device)125 static int uhci_dev_add(ddf_dev_t *device) 62 126 { 63 127 usb_log_debug2("uhci_dev_add() called\n"); 64 128 assert(device); 129 return hcd_ddf_add_hc(device, &uhci_hc_driver); 130 } 65 131 66 const int ret = device_setup_uhci(device); 67 if (ret != EOK) { 68 usb_log_error("Failed to initialize UHCI driver: %s.\n", 69 str_error(ret)); 70 } else { 71 usb_log_info("Controlling new UHCI device '%s'.\n", 72 ddf_dev_get_name(device)); 73 } 132 static const driver_ops_t uhci_driver_ops = { 133 .dev_add = uhci_dev_add, 134 }; 74 135 75 return ret; 76 } 136 static const driver_t uhci_driver = { 137 .name = NAME, 138 .driver_ops = &uhci_driver_ops 139 }; 140 77 141 78 142 /** Initialize global driver structures (NONE). … … 88 152 printf(NAME ": HelenOS UHCI driver.\n"); 89 153 log_init(NAME); 90 154 logctl_set_log_level(NAME, LVL_NOTE); 91 155 return ddf_driver_main(&uhci_driver); 92 156 } -
uspace/drv/bus/usb/uhci/transfer_list.c
r5b18137 rb4b534ac 34 34 */ 35 35 36 #include <assert.h> 36 37 #include <errno.h> 38 #include <libarch/barrier.h> 39 #include <sys/types.h> 37 40 #include <usb/debug.h> 38 #include <libarch/barrier.h> 39 41 #include <usb/host/usb_transfer_batch.h> 42 #include <usb/host/utils/malloc32.h> 43 44 #include "hw_struct/link_pointer.h" 40 45 #include "transfer_list.h" 41 46 -
uspace/drv/bus/usb/uhci/transfer_list.h
r5b18137 rb4b534ac 35 35 #define DRV_UHCI_TRANSFER_LIST_H 36 36 37 #include <adt/list.h> 37 38 #include <fibril_synch.h> 38 39 -
uspace/drv/bus/usb/uhci/uhci_batch.c
r5b18137 rb4b534ac 32 32 * @brief UHCI driver USB transfer structure 33 33 */ 34 35 #include <assert.h> 34 36 #include <errno.h> 35 #include <str_error.h>36 37 #include <macros.h> 38 #include <mem.h> 39 #include <stdlib.h> 37 40 38 41 #include <usb/usb.h> 39 42 #include <usb/debug.h> 43 #include <usb/host/endpoint.h> 44 #include <usb/host/utils/malloc32.h> 40 45 41 46 #include "uhci_batch.h" 42 #include "transfer_list.h"43 47 #include "hw_struct/transfer_descriptor.h" 44 #include "utils/malloc32.h"45 48 46 49 #define DEFAULT_ERROR_COUNT 3 … … 67 70 assert(uhci_batch); 68 71 assert(uhci_batch->usb_batch); 72 assert(!link_in_use(&uhci_batch->link)); 69 73 usb_transfer_batch_finish(uhci_batch->usb_batch, 70 74 uhci_transfer_batch_data_buffer(uhci_batch)); -
uspace/drv/bus/usb/uhci/uhci_batch.h
r5b18137 rb4b534ac 35 35 #define DRV_UHCI_BATCH_H 36 36 37 #include <adt/list.h> 38 #include <assert.h> 39 #include <errno.h> 40 #include <stdbool.h> 41 #include <sys/types.h> 37 42 #include <usb/host/usb_transfer_batch.h> 38 #include <adt/list.h>39 43 40 44 #include "hw_struct/queue_head.h" -
uspace/drv/bus/usb/uhci/uhci_rh.h
r5b18137 rb4b534ac 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2013 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief UHCI driver33 * @brief UHCI host controller driver structure 34 34 */ 35 #ifndef DRV_UHCI_ RH_H36 #define DRV_UHCI_ RH_H35 #ifndef DRV_UHCI_UHCI_RH_H 36 #define DRV_UHCI_UHCI_RH_H 37 37 38 #include < ddf/driver.h>39 #include < ops/hw_res.h>40 #include < ops/pio_window.h>38 #include <usbvirt/virthub_base.h> 39 #include <usb/host/usb_transfer_batch.h> 40 #include <usb/usb.h> 41 41 42 /** DDF support structure for uhci_rhd driver, provides I/O resources */ 43 typedef struct rh { 44 /** List of resources available to the root hub. */ 45 hw_resource_list_t resource_list; 46 /** The only resource in the RH resource list */ 47 hw_resource_t io_regs; 48 /** PIO window in which the RH will operate. */ 49 pio_window_t pio_window; 50 } rh_t; 42 #include <stdbool.h> 43 #include <sys/types.h> 51 44 52 extern int rh_init(rh_t *, ddf_fun_t *, addr_range_t *, uintptr_t, size_t); 45 /** Endpoint number for status change pipe. */ 46 #define HUB_STATUS_CHANGE_PIPE 1 47 48 /** Virtual to UHCI hub connector */ 49 typedef struct { 50 /** Virtual hub software implementation */ 51 virthub_base_t base; 52 /** UHCI root hub port io registers */ 53 ioport16_t *ports[2]; 54 /** Reset change indicator, it is not reported by regs */ 55 bool reset_changed[2]; 56 } uhci_rh_t; 57 58 int uhci_rh_init(uhci_rh_t *instance, ioport16_t *ports, const char *name); 59 int uhci_rh_schedule(uhci_rh_t *instance, usb_transfer_batch_t *batch); 60 61 /** Get UHCI rh address. 62 * 63 * @param instance UHCI rh instance. 64 * @return USB address assigned to the hub. 65 * Wrapper for virtual hub address 66 */ 67 static inline usb_address_t uhci_rh_get_address(uhci_rh_t *instance) 68 { 69 return virthub_base_get_address(&instance->base); 70 } 53 71 54 72 #endif -
uspace/drv/bus/usb/usbflbk/main.c
r5b18137 rb4b534ac 48 48 static int usbfallback_device_add(usb_device_t *dev) 49 49 { 50 int rc; 51 const char *fun_name = "ctl"; 52 53 ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 54 fun_name); 55 if (ctl_fun == NULL) { 56 usb_log_error("Failed to create control function.\n"); 57 return ENOMEM; 58 } 59 rc = ddf_fun_bind(ctl_fun); 60 if (rc != EOK) { 61 usb_log_error("Failed to bind control function: %s.\n", 62 str_error(rc)); 63 return rc; 64 } 65 66 dev->driver_data = ctl_fun; 67 68 usb_log_info("Pretending to control %s `%s'" \ 69 " (node `%s', handle %" PRIun ").\n", 70 dev->interface_no < 0 ? "device" : "interface", 71 ddf_dev_get_name(dev->ddf_dev), fun_name, ddf_dev_get_handle(dev->ddf_dev)); 72 50 usb_log_info("Pretending to control %s `%s'.\n", 51 usb_device_get_iface_number(dev) < 0 ? "device" : "interface", 52 usb_device_get_name(dev)); 73 53 return EOK; 74 54 } … … 82 62 { 83 63 assert(dev); 84 ddf_fun_t *ctl_fun = dev->driver_data;85 const int ret = ddf_fun_unbind(ctl_fun);86 if (ret != EOK) {87 usb_log_error("Failed to unbind %s.\n", ddf_fun_get_name(ctl_fun));88 return ret;89 }90 ddf_fun_destroy(ctl_fun);91 dev->driver_data = NULL;92 93 64 return EOK; 94 65 } -
uspace/drv/bus/usb/usbhid/blink1/blink1.c
r5b18137 rb4b534ac 35 35 */ 36 36 37 #include <errno.h> 37 38 #include <str_error.h> 38 39 #include <usb/debug.h> … … 78 79 report.arg5 = 0; 79 80 80 return usbhid_req_set_report(&blink1_dev->hid_dev->usb_dev->ctrl_pipe, 81 blink1_dev->hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_FEATURE, 82 (uint8_t *) &report, sizeof(report)); 81 return usbhid_req_set_report( 82 usb_device_get_default_pipe(blink1_dev->hid_dev->usb_dev), 83 usb_device_get_iface_number(blink1_dev->hid_dev->usb_dev), 84 USB_HID_REPORT_TYPE_FEATURE, (uint8_t *) &report, sizeof(report)); 83 85 } 84 86 … … 100 102 101 103 /* Create the exposed function. */ 102 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,103 HID_BLINK1_FUN_NAME);104 ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev, 105 fun_exposed, HID_BLINK1_FUN_NAME); 104 106 if (fun == NULL) { 105 107 usb_log_error("Could not create DDF function node `%s'.\n", -
uspace/drv/bus/usb/usbhid/generic/hiddev.c
r5b18137 rb4b534ac 190 190 /* Create the exposed function. */ 191 191 usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME); 192 ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,193 HID_GENERIC_FUN_NAME);192 ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev, 193 fun_exposed, HID_GENERIC_FUN_NAME); 194 194 if (fun == NULL) { 195 195 usb_log_error("Could not create DDF function node.\n"); -
uspace/drv/bus/usb/usbhid/kbd/kbddev.c
r5b18137 rb4b534ac 100 100 101 101 const char *HID_KBD_FUN_NAME = "keyboard"; 102 const char *HID_KBD_CATEGORY = "keyboard";102 const char *HID_KBD_CATEGORY_NAME = "keyboard"; 103 103 104 104 static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev); … … 261 261 262 262 if (rc != EOK) { 263 usb_log_warning(" Error translating LED output to output report"264 " .\n");263 usb_log_warning("Could not translate LED output to output" 264 "report.\n"); 265 265 return; 266 266 } … … 270 270 0)); 271 271 272 rc = usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe, 273 hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 272 rc = usbhid_req_set_report( 273 usb_device_get_default_pipe(hid_dev->usb_dev), 274 usb_device_get_iface_number(hid_dev->usb_dev), 275 USB_HID_REPORT_TYPE_OUTPUT, 274 276 kbd_dev->output_buffer, kbd_dev->output_size); 275 277 if (rc != EOK) { … … 476 478 } 477 479 478 /* API functions */ 479 480 /** 481 * Initialization of the USB/HID keyboard structure. 482 * 483 * This functions initializes required structures from the device's descriptors. 484 * 485 * During initialization, the keyboard is switched into boot protocol, the idle 486 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 487 * when a key is pressed or released. Finally, the LED lights are turned on 488 * according to the default setup of lock keys. 489 * 490 * @note By default, the keyboards is initialized with Num Lock turned on and 491 * other locks turned off. 492 * 493 * @param kbd_dev Keyboard device structure to be initialized. 494 * @param dev DDF device structure of the keyboard. 495 * 496 * @retval EOK if successful. 497 * @retval EINVAL if some parameter is not given. 498 * @return Other value inherited from function usbhid_dev_init(). 499 */ 500 int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data) 501 { 502 ddf_fun_t *fun = NULL; 503 usb_kbd_t *kbd_dev = NULL; 504 usb_hid_report_path_t *path = NULL; 505 bool bound = false; 506 fid_t fid = 0; 507 int rc; 508 509 usb_log_debug("Initializing HID/KBD structure...\n"); 510 511 if (hid_dev == NULL) { 512 usb_log_error( 513 "Failed to init keyboard structure: no structure given.\n"); 514 rc = EINVAL; 515 goto error; 516 } 517 518 /* Create the exposed function. */ 519 usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME); 520 fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 521 HID_KBD_FUN_NAME); 522 if (fun == NULL) { 523 usb_log_error("Could not create DDF function node.\n"); 524 rc = ENOMEM; 525 goto error; 526 } 527 528 /* Store the initialized HID device and HID ops 529 * to the DDF function. */ 530 ddf_fun_set_ops(fun, &kbdops); 531 532 kbd_dev = ddf_fun_data_alloc(fun, sizeof(usb_kbd_t)); 533 if (kbd_dev == NULL) { 534 usb_log_error("Failed to allocate KBD device structure.\n"); 535 rc = ENOMEM; 536 goto error; 537 } 538 539 kbd_dev->fun = fun; 480 /* HID/KBD structure manipulation */ 481 482 static int kbd_dev_init(usb_kbd_t *kbd_dev, usb_hid_dev_t *hid_dev) 483 { 484 assert(kbd_dev); 485 assert(hid_dev); 540 486 541 487 /* Default values */ … … 554 500 555 501 // TODO: make more general 556 path = usb_hid_report_path();502 usb_hid_report_path_t *path = usb_hid_report_path(); 557 503 if (path == NULL) { 558 504 usb_log_error("Failed to create kbd report path.\n"); 559 rc = ENOMEM; 560 goto error; 561 } 562 563 rc = usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 564 if (rc != EOK) { 505 usb_kbd_destroy(kbd_dev); 506 return ENOMEM; 507 } 508 509 int ret = 510 usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0); 511 if (ret != EOK) { 565 512 usb_log_error("Failed to append item to kbd report path.\n"); 566 goto error; 513 usb_hid_report_path_free(path); 514 usb_kbd_destroy(kbd_dev); 515 return ret; 567 516 } 568 517 … … 573 522 574 523 usb_hid_report_path_free(path); 575 path = NULL;576 524 577 525 usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count); … … 580 528 if (kbd_dev->keys == NULL) { 581 529 usb_log_error("Failed to allocate key buffer.\n"); 582 rc = ENOMEM;583 goto error;530 usb_kbd_destroy(kbd_dev); 531 return ENOMEM; 584 532 } 585 533 … … 587 535 if (kbd_dev->keys_old == NULL) { 588 536 usb_log_error("Failed to allocate old_key buffer.\n"); 589 rc = ENOMEM;590 goto error;537 usb_kbd_destroy(kbd_dev); 538 return ENOMEM; 591 539 } 592 540 … … 597 545 if (kbd_dev->output_buffer == NULL) { 598 546 usb_log_error("Error creating output report buffer.\n"); 599 rc = ENOMEM;600 goto error;547 usb_kbd_destroy(kbd_dev); 548 return ENOMEM; 601 549 } 602 550 … … 606 554 if (kbd_dev->led_path == NULL) { 607 555 usb_log_error("Failed to create kbd led report path.\n"); 608 rc = ENOMEM;609 goto error;610 } 611 612 r c= usb_hid_report_path_append_item(556 usb_kbd_destroy(kbd_dev); 557 return ENOMEM; 558 } 559 560 ret = usb_hid_report_path_append_item( 613 561 kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0); 614 if (r c!= EOK) {562 if (ret != EOK) { 615 563 usb_log_error("Failed to append to kbd/led report path.\n"); 616 goto error; 564 usb_kbd_destroy(kbd_dev); 565 return ret; 617 566 } 618 567 … … 626 575 if (kbd_dev->led_data == NULL) { 627 576 usb_log_error("Error creating buffer for LED output report.\n"); 628 rc = ENOMEM;629 goto error;577 usb_kbd_destroy(kbd_dev); 578 return ENOMEM; 630 579 } 631 580 … … 634 583 usb_kbd_set_led(hid_dev, kbd_dev); 635 584 636 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 637 hid_dev->usb_dev->interface_no, IDLE_RATE); 585 usbhid_req_set_idle(usb_device_get_default_pipe(hid_dev->usb_dev), 586 usb_device_get_iface_number(hid_dev->usb_dev), IDLE_RATE); 587 588 589 kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED; 590 usb_log_debug("HID/KBD device structure initialized.\n"); 591 592 return EOK; 593 } 594 595 596 /* API functions */ 597 598 /** 599 * Initialization of the USB/HID keyboard structure. 600 * 601 * This functions initializes required structures from the device's descriptors. 602 * 603 * During initialization, the keyboard is switched into boot protocol, the idle 604 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 605 * when a key is pressed or released. Finally, the LED lights are turned on 606 * according to the default setup of lock keys. 607 * 608 * @note By default, the keyboards is initialized with Num Lock turned on and 609 * other locks turned off. 610 * 611 * @param kbd_dev Keyboard device structure to be initialized. 612 * @param dev DDF device structure of the keyboard. 613 * 614 * @retval EOK if successful. 615 * @retval EINVAL if some parameter is not given. 616 * @return Other value inherited from function usbhid_dev_init(). 617 */ 618 int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data) 619 { 620 usb_log_debug("Initializing HID/KBD structure...\n"); 621 622 if (hid_dev == NULL) { 623 usb_log_error( 624 "Failed to init keyboard structure: no structure given.\n"); 625 return EINVAL; 626 } 627 628 /* Create the exposed function. */ 629 usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME); 630 ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev, 631 fun_exposed, HID_KBD_FUN_NAME); 632 if (fun == NULL) { 633 usb_log_error("Could not create DDF function node.\n"); 634 return ENOMEM; 635 } 636 637 usb_kbd_t *kbd_dev = ddf_fun_data_alloc(fun, sizeof(usb_kbd_t)); 638 if (kbd_dev == NULL) { 639 usb_log_error("Failed to allocate KBD device structure.\n"); 640 ddf_fun_destroy(fun); 641 return ENOMEM; 642 } 643 644 int ret = kbd_dev_init(kbd_dev, hid_dev); 645 if (ret != EOK) { 646 usb_log_error("Failed to initialize KBD device structure.\n"); 647 ddf_fun_destroy(fun); 648 return ret; 649 } 650 651 /* Store the initialized HID device and HID ops 652 * to the DDF function. */ 653 ddf_fun_set_ops(fun, &kbdops); 654 655 ret = ddf_fun_bind(fun); 656 if (ret != EOK) { 657 usb_log_error("Could not bind DDF function: %s.\n", 658 str_error(ret)); 659 usb_kbd_destroy(kbd_dev); 660 ddf_fun_destroy(fun); 661 return ret; 662 } 663 664 usb_log_debug("%s function created. Handle: %" PRIun "\n", 665 HID_KBD_FUN_NAME, ddf_fun_get_handle(fun)); 666 667 usb_log_debug("Adding DDF function to category %s...\n", 668 HID_KBD_CATEGORY_NAME); 669 ret = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME); 670 if (ret != EOK) { 671 usb_log_error( 672 "Could not add DDF function to category %s: %s.\n", 673 HID_KBD_CATEGORY_NAME, str_error(ret)); 674 usb_kbd_destroy(kbd_dev); 675 if (ddf_fun_unbind(fun) == EOK) { 676 ddf_fun_destroy(fun); 677 } else { 678 usb_log_error( 679 "Failed to unbind `%s', will not destroy.\n", 680 ddf_fun_get_name(fun)); 681 } 682 return ret; 683 } 638 684 639 685 /* Create new fibril for auto-repeat. */ 640 fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);686 fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev); 641 687 if (fid == 0) { 642 688 usb_log_error("Failed to start fibril for KBD auto-repeat"); 643 rc = ENOMEM; 644 goto error; 645 } 646 647 kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED; 648 usb_log_debug("HID/KBD device structure initialized.\n"); 649 650 rc = ddf_fun_bind(fun); 651 if (rc != EOK) { 652 usb_log_error("Could not bind DDF function: %s.\n", 653 str_error(rc)); 654 goto error; 655 } 656 657 bound = true; 658 659 usb_log_debug("%s function created. Handle: %" PRIun "\n", 660 HID_KBD_FUN_NAME, ddf_fun_get_handle(fun)); 661 662 usb_log_debug("Adding DDF function to category %s...\n", 663 HID_KBD_CATEGORY); 664 rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY); 665 if (rc != EOK) { 666 usb_log_error( 667 "Could not add DDF function to category %s: %s.\n", 668 HID_KBD_CATEGORY, str_error(rc)); 669 goto error; 670 } 671 689 usb_kbd_destroy(kbd_dev); 690 return ENOMEM; 691 } 672 692 fibril_add_ready(fid); 673 693 kbd_dev->fun = fun; 674 694 /* Save the KBD device structure into the HID device structure. */ 675 695 *data = kbd_dev; 676 696 677 697 return EOK; 678 error:679 if (bound)680 ddf_fun_unbind(fun);681 if (fid != 0)682 fibril_destroy(fid);683 if (kbd_dev != NULL) {684 free(kbd_dev->led_data);685 if (kbd_dev->led_path != NULL)686 usb_hid_report_path_free(kbd_dev->led_path);687 if (kbd_dev->output_buffer != NULL)688 usb_hid_report_output_free(kbd_dev->output_buffer);689 free(kbd_dev->keys_old);690 free(kbd_dev->keys);691 }692 if (path != NULL)693 usb_hid_report_path_free(path);694 if (fun != NULL)695 ddf_fun_destroy(fun);696 return rc;697 698 } 698 699 … … 749 750 usb_hid_report_output_free(kbd_dev->output_buffer); 750 751 751 ddf_fun_unbind(kbd_dev->fun); 752 ddf_fun_destroy(kbd_dev->fun); 752 if (kbd_dev->fun) { 753 if (ddf_fun_unbind(kbd_dev->fun) != EOK) { 754 usb_log_warning("Failed to unbind %s.\n", 755 ddf_fun_get_name(kbd_dev->fun)); 756 } else { 757 usb_log_debug2("%s unbound.\n", 758 ddf_fun_get_name(kbd_dev->fun)); 759 ddf_fun_destroy(kbd_dev->fun); 760 } 761 } 753 762 } 754 763 … … 779 788 } 780 789 781 rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 782 hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT); 790 rc = usbhid_req_set_protocol( 791 usb_device_get_default_pipe(hid_dev->usb_dev), 792 usb_device_get_iface_number(hid_dev->usb_dev), 793 USB_HID_PROTOCOL_BOOT); 783 794 784 795 if (rc != EOK) { -
uspace/drv/bus/usb/usbhid/main.c
r5b18137 rb4b534ac 65 65 } 66 66 67 if ( dev->interface_no< 0) {67 if (usb_device_get_iface_number(dev) < 0) { 68 68 usb_log_error("Failed to add HID device: endpoints not found." 69 69 "\n"); … … 89 89 * This will create a separate fibril that will query the device 90 90 * for the data continuously. */ 91 rc = usb_device_auto_poll(dev,91 rc = usb_device_auto_poll_desc(dev, 92 92 /* Index of the polling pipe. */ 93 hid_dev->poll_pipe_ index,93 hid_dev->poll_pipe_mapping->description, 94 94 /* Callback when data arrives. */ 95 95 usb_hid_polling_callback, 96 96 /* How much data to request. */ 97 dev->pipes[hid_dev->poll_pipe_index].pipe.max_packet_size, 97 hid_dev->poll_pipe_mapping->pipe.max_packet_size, 98 /* Delay */ 99 -1, 98 100 /* Callback when the polling ends. */ 99 101 usb_hid_polling_ended_callback, … … 103 105 if (rc != EOK) { 104 106 usb_log_error("Failed to start polling fibril for `%s'.\n", 105 ddf_dev_get_name(dev->ddf_dev));107 usb_device_get_name(dev)); 106 108 usb_hid_deinit(hid_dev); 107 109 return rc; … … 109 111 hid_dev->running = true; 110 112 111 usb_log_info("HID device `%s' ready to use.\n", 112 ddf_dev_get_name(dev->ddf_dev)); 113 usb_log_info("HID device `%s' ready.\n", usb_device_get_name(dev)); 113 114 114 115 return EOK; … … 137 138 { 138 139 assert(dev); 139 assert(dev->driver_data);140 usb_hid_dev_t *hid_dev = dev->driver_data;140 usb_hid_dev_t *hid_dev = usb_device_data_get(dev); 141 assert(hid_dev); 141 142 unsigned tries = 100; 142 143 /* Wait for fail. */ … … 150 151 151 152 usb_hid_deinit(hid_dev); 152 usb_log_debug2("%s destruction complete.\n", ddf_dev_get_name(dev->ddf_dev));153 usb_log_debug2("%s destruction complete.\n", usb_device_get_name(dev)); 153 154 return EOK; 154 155 } -
uspace/drv/bus/usb/usbhid/mouse/mousedev.c
r5b18137 rb4b534ac 246 246 } 247 247 248 #define FUN_UNBIND_DESTROY(fun) \ 249 if (fun) { \ 250 if (ddf_fun_unbind((fun)) == EOK) { \ 251 ddf_fun_destroy((fun)); \ 252 } else { \ 253 usb_log_error("Could not unbind function `%s', it " \ 254 "will not be destroyed.\n", ddf_fun_get_name(fun)); \ 255 } \ 256 } else (void)0 257 248 258 /** Get highest index of a button mentioned in given report. 249 259 * … … 286 296 } 287 297 288 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data) 289 { 290 ddf_fun_t *fun = NULL; 291 usb_mouse_t *mouse_dev = NULL; 292 bool bound = false; 293 int rc; 294 295 usb_log_debug("Initializing HID/Mouse structure...\n"); 296 297 if (hid_dev == NULL) { 298 usb_log_error("Failed to init mouse structure: no structure" 299 " given.\n"); 300 rc = EINVAL; 301 goto error; 302 } 303 304 /* Create the exposed function. */ 305 usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME); 306 fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 307 HID_MOUSE_FUN_NAME); 308 if (fun == NULL) { 309 usb_log_error("Could not create DDF function node `%s'.\n", 310 HID_MOUSE_FUN_NAME); 311 rc = ENOMEM; 312 goto error; 313 } 314 315 ddf_fun_set_ops(fun, &ops); 316 317 mouse_dev = ddf_fun_data_alloc(fun, sizeof(usb_mouse_t)); 318 if (mouse_dev == NULL) { 319 usb_log_error("Error while creating USB/HID Mouse device " 320 "structure.\n"); 321 rc = ENOMEM; 322 goto error; 323 } 324 298 static int mouse_dev_init(usb_mouse_t *mouse_dev, usb_hid_dev_t *hid_dev) 299 { 325 300 // FIXME: This may not be optimal since stupid hardware vendor may 326 301 // use buttons 1, 2, 3 and 6000 and we would allocate array of … … 335 310 if (mouse_dev->buttons == NULL) { 336 311 usb_log_error(NAME ": out of memory, giving up on device!\n"); 337 rc = ENOMEM;338 goto error;312 free(mouse_dev); 313 return ENOMEM; 339 314 } 340 315 341 316 // TODO: how to know if the device supports the request??? 342 usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 343 hid_dev->usb_dev->interface_no, IDLE_RATE); 344 345 rc = ddf_fun_bind(fun); 346 if (rc != EOK) { 317 usbhid_req_set_idle(usb_device_get_default_pipe(hid_dev->usb_dev), 318 usb_device_get_iface_number(hid_dev->usb_dev), IDLE_RATE); 319 return EOK; 320 } 321 322 int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data) 323 { 324 usb_log_debug("Initializing HID/Mouse structure...\n"); 325 326 if (hid_dev == NULL) { 327 usb_log_error("Failed to init keyboard structure: no structure" 328 " given.\n"); 329 return EINVAL; 330 } 331 332 /* Create the exposed function. */ 333 usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME); 334 ddf_fun_t *fun = usb_device_ddf_fun_create(hid_dev->usb_dev, 335 fun_exposed, HID_MOUSE_FUN_NAME); 336 if (fun == NULL) { 337 usb_log_error("Could not create DDF function node `%s'.\n", 338 HID_MOUSE_FUN_NAME); 339 return ENOMEM; 340 } 341 342 usb_mouse_t *mouse_dev = ddf_fun_data_alloc(fun, sizeof(usb_mouse_t)); 343 if (mouse_dev == NULL) { 344 usb_log_error("Failed to alloc HID mouse device structure.\n"); 345 ddf_fun_destroy(fun); 346 return ENOMEM; 347 } 348 349 int ret = mouse_dev_init(mouse_dev, hid_dev); 350 if (ret != EOK) { 351 usb_log_error("Failed to init HID mouse device structure.\n"); 352 return ret; 353 } 354 355 ddf_fun_set_ops(fun, &ops); 356 357 ret = ddf_fun_bind(fun); 358 if (ret != EOK) { 347 359 usb_log_error("Could not bind DDF function `%s': %s.\n", 348 ddf_fun_get_name(fun), str_error(rc)); 349 goto error; 350 } 351 352 bound = true; 360 ddf_fun_get_name(fun), str_error(ret)); 361 ddf_fun_destroy(fun); 362 return ret; 363 } 353 364 354 365 usb_log_debug("Adding DDF function `%s' to category %s...\n", 355 366 ddf_fun_get_name(fun), HID_MOUSE_CATEGORY); 356 rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY); 357 if (rc != EOK) { 358 usb_log_error("Could not add DDF function to category %s: " 359 "%s.\n", HID_MOUSE_CATEGORY, str_error(rc)); 360 goto error; 361 } 362 367 ret = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY); 368 if (ret != EOK) { 369 usb_log_error( 370 "Could not add DDF function to category %s: %s.\n", 371 HID_MOUSE_CATEGORY, str_error(ret)); 372 FUN_UNBIND_DESTROY(fun); 373 return ret; 374 } 363 375 mouse_dev->mouse_fun = fun; 364 376 365 377 /* Save the Mouse device structure into the HID device structure. */ 366 378 *data = mouse_dev; 379 367 380 return EOK; 368 error:369 if (bound)370 ddf_fun_unbind(fun);371 if (mouse_dev != NULL)372 free(mouse_dev->buttons);373 if (fun != NULL)374 ddf_fun_destroy(fun);375 return rc;376 381 } 377 382 … … 404 409 } 405 410 406 ddf_fun_unbind(mouse_dev->mouse_fun);407 411 free(mouse_dev->buttons); 408 ddf_fun_destroy(mouse_dev->mouse_fun);412 FUN_UNBIND_DESTROY(mouse_dev->mouse_fun); 409 413 } 410 414 … … 421 425 } 422 426 423 rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 424 hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT); 427 rc = usbhid_req_set_protocol( 428 usb_device_get_default_pipe(hid_dev->usb_dev), 429 usb_device_get_iface_number(hid_dev->usb_dev), 430 USB_HID_PROTOCOL_BOOT); 425 431 426 432 if (rc != EOK) { -
uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
r5b18137 rb4b534ac 162 162 163 163 /* Create the exposed function. */ 164 ddf_fun_t *fun = ddf_fun_create(165 hid_dev->usb_dev ->ddf_dev, fun_exposed, NAME);164 ddf_fun_t *fun = usb_device_ddf_fun_create( 165 hid_dev->usb_dev, fun_exposed, NAME); 166 166 if (fun == NULL) { 167 167 usb_log_error("Could not create DDF function node.\n"); -
uspace/drv/bus/usb/usbhid/usbhid.c
r5b18137 rb4b534ac 41 41 #include <usb/hid/hidreport.h> 42 42 #include <usb/hid/request.h> 43 43 44 #include <errno.h> 45 #include <macros.h> 44 46 #include <str_error.h> 45 47 … … 114 116 const usb_hid_subdriver_mapping_t *mapping) 115 117 { 116 assert(hid_dev != NULL); 117 assert(hid_dev->usb_dev != NULL); 118 119 return (hid_dev->usb_dev->descriptors.device.vendor_id 120 == mapping->vendor_id 121 && hid_dev->usb_dev->descriptors.device.product_id 122 == mapping->product_id); 118 assert(hid_dev); 119 assert(hid_dev->usb_dev); 120 assert(mapping); 121 const usb_standard_device_descriptor_t *d = 122 &usb_device_descriptors(hid_dev->usb_dev)->device; 123 124 return (d->vendor_id == mapping->vendor_id) 125 && (d->product_id == mapping->product_id); 123 126 } 124 127 … … 264 267 } 265 268 266 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, constusb_device_t *dev)269 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev) 267 270 { 268 271 assert(hid_dev); … … 270 273 271 274 static const struct { 272 unsigned ep_number;275 const usb_endpoint_description_t *desc; 273 276 const char* description; 274 277 } 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 {&usb_hid_kbd_poll_endpoint_description, "Keyboard endpoint"}, 279 {&usb_hid_mouse_poll_endpoint_description, "Mouse endpoint"}, 280 {&usb_hid_generic_poll_endpoint_description, "Generic HID endpoint"}, 278 281 }; 279 282 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) { 283 for (unsigned i = 0; i < ARRAY_SIZE(endpoints); ++i) { 284 usb_endpoint_mapping_t *epm = 285 usb_device_get_mapped_ep_desc(dev, endpoints[i].desc); 286 if (epm && epm->present) { 285 287 usb_log_debug("Found: %s.\n", endpoints[i].description); 286 hid_dev->poll_pipe_ index = endpoints[i].ep_number;288 hid_dev->poll_pipe_mapping = epm; 287 289 return EOK; 288 290 } … … 351 353 /* The USB device should already be initialized, save it in structure */ 352 354 hid_dev->usb_dev = dev; 353 hid_dev->poll_pipe_ index = -1;355 hid_dev->poll_pipe_mapping = NULL; 354 356 355 357 int rc = usb_hid_check_pipes(hid_dev, dev); … … 381 383 "boot protocol.\n"); 382 384 383 switch (hid_dev->poll_pipe_ index) {384 case USB_HID_ KBD_POLL_EP_NO:385 switch (hid_dev->poll_pipe_mapping->interface->interface_protocol) { 386 case USB_HID_PROTOCOL_KEYBOARD: 385 387 usb_log_info("Falling back to kbd boot protocol.\n"); 386 388 rc = usb_kbd_set_boot_protocol(hid_dev); … … 389 391 } 390 392 break; 391 case USB_HID_ MOUSE_POLL_EP_NO:393 case USB_HID_PROTOCOL_MOUSE: 392 394 usb_log_info("Falling back to mouse boot protocol.\n"); 393 395 rc = usb_mouse_set_boot_protocol(hid_dev); … … 397 399 break; 398 400 default: 399 assert(hid_dev->poll_pipe_index400 == USB_HID_GENERIC_POLL_EP_NO);401 401 usb_log_info("Falling back to generic HID driver.\n"); 402 402 usb_hid_set_generic_hid_subdriver(hid_dev); … … 476 476 &hid_dev->report, buffer, buffer_size, &hid_dev->report_id); 477 477 if (rc != EOK) { 478 usb_log_warning(" Errorin usb_hid_parse_report():"478 usb_log_warning("Failure in usb_hid_parse_report():" 479 479 "%s\n", str_error(rc)); 480 480 } -
uspace/drv/bus/usb/usbhid/usbhid.h
r5b18137 rb4b534ac 103 103 usb_device_t *usb_dev; 104 104 105 /** Index of the polling pipe in usb_hid_endpoints array. */106 u nsigned poll_pipe_index;105 /** Endpont mapping of the polling pipe. */ 106 usb_endpoint_mapping_t *poll_pipe_mapping; 107 107 108 108 /** Subdrivers. */ … … 132 132 }; 133 133 134 135 136 enum {137 USB_HID_KBD_POLL_EP_NO = 0,138 USB_HID_MOUSE_POLL_EP_NO = 1,139 USB_HID_GENERIC_POLL_EP_NO = 2,140 USB_HID_POLL_EP_COUNT = 3141 };142 143 134 extern const usb_endpoint_description_t *usb_hid_endpoints[]; 144 145 146 135 147 136 int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev); -
uspace/drv/bus/usb/usbhub/main.c
r5b18137 rb4b534ac 36 36 #include <async.h> 37 37 #include <stdio.h> 38 #include <io/logctl.h> 38 39 39 40 #include <usb/dev/driver.h> … … 43 44 #include "usbhub.h" 44 45 45 /** Hub status-change endpoint description.46 *47 * For more information see section 11.15.1 of USB 1.1 specification.48 */49 static const usb_endpoint_description_t hub_status_change_endpoint_description =50 {51 .transfer_type = USB_TRANSFER_INTERRUPT,52 .direction = USB_DIRECTION_IN,53 .interface_class = USB_CLASS_HUB,54 .interface_subclass = 0,55 .interface_protocol = 0,56 .flags = 057 };58 46 59 47 /** USB hub driver operations. */ … … 80 68 printf(NAME ": HelenOS USB hub driver.\n"); 81 69 log_init(NAME); 82 70 logctl_set_log_level(NAME, LVL_NOTE); 83 71 return usb_driver_main(&usb_hub_driver); 84 72 } -
uspace/drv/bus/usb/usbhub/port.c
r5b18137 rb4b534ac 41 41 42 42 #include <usb/debug.h> 43 #include <usb/dev/hub.h>44 43 45 44 #include "port.h" … … 56 55 static int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub); 57 56 static void usb_hub_port_reset_completed(usb_hub_port_t *port, 58 usb_ port_status_t status);57 usb_hub_dev_t *hub, usb_port_status_t status); 59 58 static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status); 60 static int enable_port_callback(void *arg);61 59 static int add_device_phase1_worker_fibril(void *arg); 62 60 static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub, … … 66 64 { 67 65 assert(port); 68 if (port-> attached_device.fun)66 if (port->device_attached) 69 67 return usb_hub_port_device_gone(port, hub); 70 68 return EOK; … … 124 122 assert(port); 125 123 fibril_mutex_lock(&port->mutex); 126 port->reset_completed = true;127 port->reset_okay = false;124 if (port->reset_status == IN_RESET) 125 port->reset_status = RESET_FAIL; 128 126 fibril_condvar_broadcast(&port->reset_cv); 129 127 fibril_mutex_unlock(&port->mutex); … … 141 139 assert(port); 142 140 assert(hub); 143 usb_log_debug ("Interrupt at port %zu\n", port->port_number);141 usb_log_debug2("(%p-%u): Interrupt.\n", hub, port->port_number); 144 142 145 143 usb_port_status_t status = 0; 146 144 const int opResult = get_port_status(port, &status); 147 145 if (opResult != EOK) { 148 usb_log_error(" Failed to get port %zu status: %s.\n",146 usb_log_error("(%p-%u): Failed to get port status: %s.\n", hub, 149 147 port->port_number, str_error(opResult)); 150 148 return; … … 155 153 const bool connected = 156 154 (status & USB_HUB_PORT_STATUS_CONNECTION) != 0; 157 usb_log_debug(" Connection change on port %zu: device %s.\n",155 usb_log_debug("(%p-%u): Connection change: device %s.\n", hub, 158 156 port->port_number, connected ? "attached" : "removed"); 159 157 … … 162 160 USB_HUB_FEATURE_C_PORT_CONNECTION); 163 161 if (opResult != EOK) { 164 usb_log_warning("Failed to clear port-change-connection" 165 " flag: %s.\n", str_error(opResult)); 162 usb_log_warning("(%p-%u): Failed to clear " 163 "port-change-connection flag: %s.\n", hub, 164 port->port_number, str_error(opResult)); 166 165 } 167 166 … … 170 169 usb_port_speed(status)); 171 170 if (opResult != EOK) { 172 usb_log_error( 173 "Cannot handle change on port %zu: %s.\n",174 port->port_number,str_error(opResult));171 usb_log_error("(%p-%u): Cannot handle change on" 172 " port: %s.\n", hub, port->port_number, 173 str_error(opResult)); 175 174 } 176 175 } else { 176 /* Handle the case we were in reset */ 177 //usb_hub_port_reset_fail(port); 177 178 /* If enabled change was reported leave the removal 178 179 * to that handler, it shall ACK the change too. */ … … 185 186 /* Enable change, ports are automatically disabled on errors. */ 186 187 if (status & USB_HUB_PORT_C_STATUS_ENABLED) { 187 usb_log_info("Port %zu, disabled because of errors.\n", 188 //TODO: maybe HS reset failed? 189 usb_log_info("(%p-%u): Port disabled because of errors.\n", hub, 188 190 port->port_number); 189 191 usb_hub_port_device_gone(port, hub); … … 191 193 USB_HUB_FEATURE_C_PORT_ENABLE); 192 194 if (rc != EOK) { 193 usb_log_error( 194 " Failed to clear port %zu enable change feature: "195 "%s.\n", port->port_number,str_error(rc));195 usb_log_error("(%p-%u): Failed to clear port enable " 196 "change feature: %s.", hub, port->port_number, 197 str_error(rc)); 196 198 } 197 199 … … 200 202 /* Suspend change */ 201 203 if (status & USB_HUB_PORT_C_STATUS_SUSPEND) { 202 usb_log_error(" Port %zuwent to suspend state, this should"203 " NOT happen as we do not support suspend state!",204 usb_log_error("(%p-%u): Port went to suspend state, this should" 205 " NOT happen as we do not support suspend state!", hub, 204 206 port->port_number); 205 207 const int rc = usb_hub_port_clear_feature(port, 206 208 USB_HUB_FEATURE_C_PORT_SUSPEND); 207 209 if (rc != EOK) { 208 usb_log_error( 209 " Failed to clear port %zu suspend change feature: "210 "%s.\n", port->port_number,str_error(rc));210 usb_log_error("(%p-%u): Failed to clear port suspend " 211 "change feature: %s.", hub, port->port_number, 212 str_error(rc)); 211 213 } 212 214 } … … 214 216 /* Over current */ 215 217 if (status & USB_HUB_PORT_C_STATUS_OC) { 218 usb_log_debug("(%p-%u): Port OC reported!.", hub, 219 port->port_number); 216 220 /* According to the USB specs: 217 221 * 11.13.5 Over-current Reporting and Recovery … … 222 226 USB_HUB_FEATURE_C_PORT_OVER_CURRENT); 223 227 if (rc != EOK) { 224 usb_log_error( 225 " Failed to clear port %zu OC change feature: %s.\n",226 port->port_number,str_error(rc));228 usb_log_error("(%p-%u): Failed to clear port OC change " 229 "feature: %s.\n", hub, port->port_number, 230 str_error(rc)); 227 231 } 228 232 if (!(status & ~USB_HUB_PORT_STATUS_OC)) { … … 230 234 port, USB_HUB_FEATURE_PORT_POWER); 231 235 if (rc != EOK) { 232 usb_log_error( 233 " Failed to set port %zu power after OC:"234 " %s.\n",port->port_number, str_error(rc));236 usb_log_error("(%p-%u): Failed to set port " 237 "power after OC: %s.", hub, 238 port->port_number, str_error(rc)); 235 239 } 236 240 } … … 239 243 /* Port reset, set on port reset complete. */ 240 244 if (status & USB_HUB_PORT_C_STATUS_RESET) { 241 usb_hub_port_reset_completed(port, status);242 } 243 244 usb_log_debug ("Port %zu status 0x%08" PRIx32 "\n",245 usb_hub_port_reset_completed(port, hub, status); 246 } 247 248 usb_log_debug2("(%p-%u): Port status %#08" PRIx32, hub, 245 249 port->port_number, status); 246 250 } … … 259 263 assert(port); 260 264 assert(hub); 261 if (port->attached_device.address < 0) { 262 usb_log_warning( 263 "Device on port %zu removed before being registered.\n", 264 port->port_number); 265 266 /* 267 * Device was removed before port reset completed. 268 * We will announce a failed port reset to unblock the 269 * port reset callback from new device wrapper. 270 */ 271 usb_hub_port_reset_fail(port); 272 return EOK; 273 } 274 275 fibril_mutex_lock(&port->mutex); 276 assert(port->attached_device.fun); 277 usb_log_debug("Removing device on port %zu.\n", port->port_number); 278 int ret = ddf_fun_unbind(port->attached_device.fun); 279 if (ret != EOK) { 280 usb_log_error("Failed to unbind child function on port" 281 " %zu: %s.\n", port->port_number, str_error(ret)); 282 fibril_mutex_unlock(&port->mutex); 283 return ret; 284 } 285 286 ddf_fun_destroy(port->attached_device.fun); 287 port->attached_device.fun = NULL; 288 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)); 294 } 295 296 port->attached_device.address = -1; 297 fibril_mutex_unlock(&port->mutex); 298 usb_log_info("Removed device on port %zu.\n", port->port_number); 299 return EOK; 265 async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device); 266 if (!exch) 267 return ENOMEM; 268 const int rc = usb_device_remove(exch, port->port_number); 269 usb_device_bus_exchange_end(exch); 270 if (rc == EOK) 271 port->device_attached = false; 272 return rc; 273 300 274 } 301 275 … … 308 282 * @param status Port status mask 309 283 */ 310 void usb_hub_port_reset_completed(usb_hub_port_t *port, 284 void usb_hub_port_reset_completed(usb_hub_port_t *port, usb_hub_dev_t *hub, 311 285 usb_port_status_t status) 312 286 { 313 287 assert(port); 314 288 fibril_mutex_lock(&port->mutex); 289 const bool enabled = (status & USB_HUB_PORT_STATUS_ENABLED) != 0; 315 290 /* Finalize device adding. */ 316 port->reset_completed = true; 317 port->reset_okay = (status & USB_HUB_PORT_STATUS_ENABLED) != 0;318 319 if (port->reset_okay) {320 usb_log_debug("Port %zu reset complete.\n",port->port_number);291 292 if (enabled) { 293 port->reset_status = RESET_OK; 294 usb_log_debug("(%p-%u): Port reset complete.\n", hub, 295 port->port_number); 321 296 } else { 322 usb_log_warning(323 "Port %zu reset complete but port not enabled.\n",324 port->port_number);297 port->reset_status = RESET_FAIL; 298 usb_log_warning("(%p-%u): Port reset complete but port not " 299 "enabled.", hub, port->port_number); 325 300 } 326 301 fibril_condvar_broadcast(&port->reset_cv); … … 330 305 int rc = usb_hub_port_clear_feature(port, USB_HUB_FEATURE_C_PORT_RESET); 331 306 if (rc != EOK) { 332 usb_log_error( 333 "Failed to clear port %zu reset change feature: %s.\n", 334 port->port_number, str_error(rc)); 307 usb_log_error("(%p-%u): Failed to clear port reset change: %s.", 308 hub, port->port_number, str_error(rc)); 335 309 } 336 310 } … … 376 350 } 377 351 378 /** Callback for enabling a specific port. 379 * 380 * We wait on a CV until port is reseted. 381 * That is announced via change on interrupt pipe. 382 * 383 * @param port_no Port number (starting at 1). 384 * @param arg Custom argument, points to @c usb_hub_dev_t. 385 * @return Error code. 386 */ 387 static int enable_port_callback(void *arg) 388 { 389 usb_hub_port_t *port = arg;390 assert(port);391 const int rc =392 usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET);393 if (rc != EOK) {394 usb_log_warning("Port reset failed: %s.\n", str_error(rc));352 static int port_enable(usb_hub_port_t *port, usb_hub_dev_t *hub, bool enable) 353 { 354 if (enable) { 355 int rc = 356 usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET); 357 if (rc != EOK) { 358 usb_log_error("(%p-%u): Port reset request failed: %s.", 359 hub, port->port_number, str_error(rc)); 360 return rc; 361 } 362 /* Wait until reset completes. */ 363 fibril_mutex_lock(&port->mutex); 364 port->reset_status = IN_RESET; 365 while (port->reset_status == IN_RESET) 366 fibril_condvar_wait(&port->reset_cv, &port->mutex); 367 rc = port->reset_status == RESET_OK ? EOK : ESTALL; 368 fibril_mutex_unlock(&port->mutex); 395 369 return rc; 396 } 397 398 /* 399 * Wait until reset completes. 400 */ 401 fibril_mutex_lock(&port->mutex); 402 while (!port->reset_completed) { 403 fibril_condvar_wait(&port->reset_cv, &port->mutex); 404 } 405 fibril_mutex_unlock(&port->mutex); 406 407 return port->reset_okay ? EOK : ESTALL; 370 } else { 371 return usb_hub_port_clear_feature(port, 372 USB_HUB_FEATURE_PORT_ENABLE); 373 } 408 374 } 409 375 … … 418 384 int add_device_phase1_worker_fibril(void *arg) 419 385 { 420 struct add_device_phase1 *data = arg; 421 assert(data); 422 423 usb_address_t new_address; 424 ddf_fun_t *child_fun; 425 426 child_fun = ddf_fun_create(data->hub->usb_device->ddf_dev, 427 fun_inner, NULL); 428 if (child_fun == NULL) 429 return ENOMEM; 430 431 const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 432 child_fun, &data->hub->usb_device->hc_conn, data->speed, 433 enable_port_callback, data->port, &new_address, NULL); 434 435 if (rc == EOK) { 436 fibril_mutex_lock(&data->port->mutex); 437 data->port->attached_device.fun = child_fun; 438 data->port->attached_device.address = new_address; 439 fibril_mutex_unlock(&data->port->mutex); 440 441 usb_log_info("Detected new device on `%s' (port %zu), " 442 "address %d (handle %" PRIun ").\n", 443 ddf_dev_get_name(data->hub->usb_device->ddf_dev), 444 data->port->port_number, new_address, 445 ddf_fun_get_handle(child_fun)); 386 struct add_device_phase1 *params = arg; 387 assert(params); 388 389 int ret = EOK; 390 usb_hub_dev_t *hub = params->hub; 391 usb_hub_port_t *port = params->port; 392 const usb_speed_t speed = params->speed; 393 free(arg); 394 395 usb_log_debug("(%p-%u): New device sequence.", hub, port->port_number); 396 397 async_exch_t *exch = usb_device_bus_exchange_begin(hub->usb_device); 398 if (!exch) { 399 usb_log_error("(%p-%u): Failed to begin bus exchange.", hub, 400 port->port_number); 401 ret = ENOMEM; 402 goto out; 403 } 404 405 /* Reserve default address */ 406 while ((ret = usb_reserve_default_address(exch, speed)) == ENOENT) { 407 async_usleep(1000000); 408 } 409 if (ret != EOK) { 410 usb_log_error("(%p-%u): Failed to reserve default address: %s", 411 hub, port->port_number, str_error(ret)); 412 goto out; 413 } 414 415 usb_log_debug("(%p-%u): Got default address reseting port.", hub, 416 port->port_number); 417 /* Reset port */ 418 ret = port_enable(port, hub, true); 419 if (ret != EOK) { 420 usb_log_error("(%p-%u): Failed to reset port.", hub, 421 port->port_number); 422 if (usb_release_default_address(exch) != EOK) 423 usb_log_warning("(%p-%u): Failed to release default " 424 "address.", hub, port->port_number); 425 ret = EIO; 426 goto out; 427 } 428 usb_log_debug("(%p-%u): Port reset, enumerating device", hub, 429 port->port_number); 430 431 ret = usb_device_enumerate(exch, port->port_number); 432 if (ret != EOK) { 433 usb_log_error("(%p-%u): Failed to enumerate device: %s", hub, 434 port->port_number, str_error(ret)); 435 const int ret = port_enable(port, hub, false); 436 if (ret != EOK) { 437 usb_log_warning("(%p-%u)Failed to disable port (%s), " 438 "NOT releasing default address.", hub, 439 port->port_number, str_error(ret)); 440 } else { 441 const int ret = usb_release_default_address(exch); 442 if (ret != EOK) 443 usb_log_warning("(%p-%u): Failed to release " 444 "default address: %s", hub, 445 port->port_number, str_error(ret)); 446 } 446 447 } else { 447 ddf_fun_destroy(child_fun); 448 usb_log_error("Failed registering device on port %zu: %s.\n", 449 data->port->port_number, str_error(rc)); 450 } 451 452 453 fibril_mutex_lock(&data->hub->pending_ops_mutex); 454 assert(data->hub->pending_ops_count > 0); 455 --data->hub->pending_ops_count; 456 fibril_condvar_signal(&data->hub->pending_ops_cv); 457 fibril_mutex_unlock(&data->hub->pending_ops_mutex); 458 459 free(arg); 460 461 return rc; 448 usb_log_debug("(%p-%u): Device enumerated", hub, 449 port->port_number); 450 port->device_attached = true; 451 if (usb_release_default_address(exch) != EOK) 452 usb_log_warning("(%p-%u): Failed to release default " 453 "address", hub, port->port_number); 454 } 455 out: 456 usb_device_bus_exchange_end(exch); 457 458 fibril_mutex_lock(&hub->pending_ops_mutex); 459 assert(hub->pending_ops_count > 0); 460 --hub->pending_ops_count; 461 fibril_condvar_signal(&hub->pending_ops_cv); 462 fibril_mutex_unlock(&hub->pending_ops_mutex); 463 464 return ret; 462 465 } 463 466 … … 485 488 data->speed = speed; 486 489 487 fibril_mutex_lock(&port->mutex);488 port->reset_completed = false;489 fibril_mutex_unlock(&port->mutex);490 491 490 fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data); 492 491 if (fibril == 0) { -
uspace/drv/bus/usb/usbhub/port.h
r5b18137 rb4b534ac 37 37 38 38 #include <usb/dev/driver.h> 39 #include <usb/dev/hub.h>40 39 #include <usb/classes/hub.h> 40 #include <usb_iface.h> 41 41 42 42 typedef struct usb_hub_dev usb_hub_dev_t; … … 44 44 /** Information about single port on a hub. */ 45 45 typedef struct { 46 /* Port number as reported in descriptors. */47 size_tport_number;46 /** Port number as reported in descriptors. */ 47 unsigned port_number; 48 48 /** Device communication pipe. */ 49 49 usb_pipe_t *control_pipe; … … 52 52 /** CV for waiting to port reset completion. */ 53 53 fibril_condvar_t reset_cv; 54 /** Whether port reset is completed.54 /** Port reset status. 55 55 * Guarded by @c reset_mutex. 56 56 */ 57 bool reset_completed; 58 /** Whether to announce the port reset as successful. */ 59 bool reset_okay; 60 61 /** Information about attached device. */ 62 usb_hub_attached_device_t attached_device; 57 enum { 58 NO_RESET, 59 IN_RESET, 60 RESET_OK, 61 RESET_FAIL, 62 } reset_status; 63 /** Device reported to USB bus driver */ 64 bool device_attached; 63 65 } usb_hub_port_t; 64 66 … … 67 69 * @param port Port to be initialized. 68 70 */ 69 static inline void usb_hub_port_init(usb_hub_port_t *port, size_tport_number,71 static inline void usb_hub_port_init(usb_hub_port_t *port, unsigned port_number, 70 72 usb_pipe_t *control_pipe) 71 73 { 72 74 assert(port); 73 port->attached_device.address = -1;74 port->attached_device.fun = NULL;75 75 port->port_number = port_number; 76 76 port->control_pipe = control_pipe; 77 port->reset_status = NO_RESET; 78 port->device_attached = false; 77 79 fibril_mutex_initialize(&port->mutex); 78 80 fibril_condvar_initialize(&port->reset_cv); -
uspace/drv/bus/usb/usbhub/status.h
r5b18137 rb4b534ac 64 64 #define USB_HUB_PORT_STATUS_HIGH_SPEED \ 65 65 (uint32_usb2host(1 << 10)) 66 #define USB_HUB_PORT_STATUS_TEST_MODE \ 67 (uint32_usb2host(1 << 11)) 68 #define USB_HUB_PORT_INDICATOR_CONTROL \ 69 (uint32_usb2host(1 << 12)) 66 70 67 71 #define USB_HUB_PORT_C_STATUS_CONNECTION \ -
uspace/drv/bus/usb/usbhub/usbhub.c
r5b18137 rb4b534ac 45 45 #include <usb/dev/pipes.h> 46 46 #include <usb/classes/classes.h> 47 #include <usb/ddfiface.h>48 47 #include <usb/descriptor.h> 49 48 #include <usb/dev/recognise.h> … … 57 56 58 57 #define HUB_FNC_NAME "hub" 58 /** Hub status-change endpoint description. 59 * 60 * For more information see section 11.15.1 of USB 1.1 specification. 61 */ 62 const usb_endpoint_description_t hub_status_change_endpoint_description = 63 { 64 .transfer_type = USB_TRANSFER_INTERRUPT, 65 .direction = USB_DIRECTION_IN, 66 .interface_class = USB_CLASS_HUB, 67 .interface_subclass = 0, 68 .interface_protocol = 0, 69 .flags = 0 70 }; 59 71 60 72 /** Standard get hub global status request */ … … 99 111 fibril_condvar_initialize(&hub_dev->pending_ops_cv); 100 112 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 113 /* 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); 114 int opResult = usb_set_first_configuration(usb_dev); 115 if (opResult != EOK) { 113 116 usb_log_error("Could not set hub configuration: %s\n", 114 117 str_error(opResult)); … … 119 122 opResult = usb_hub_process_hub_specific_info(hub_dev); 120 123 if (opResult != EOK) { 121 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);122 124 usb_log_error("Could process hub specific info, %s\n", 123 125 str_error(opResult)); … … 127 129 /* Create hub control function. */ 128 130 usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n"); 129 hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,131 hub_dev->hub_fun = usb_device_ddf_fun_create(hub_dev->usb_device, 130 132 fun_exposed, HUB_FNC_NAME); 131 133 if (hub_dev->hub_fun == NULL) { 132 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);133 134 usb_log_error("Failed to create hub function.\n"); 134 135 return ENOMEM; … … 138 139 opResult = ddf_fun_bind(hub_dev->hub_fun); 139 140 if (opResult != EOK) { 140 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);141 141 usb_log_error("Failed to bind hub function: %s.\n", 142 142 str_error(opResult)); … … 146 146 147 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);148 opResult = usb_device_auto_poll_desc(hub_dev->usb_device, 149 &hub_status_change_endpoint_description, 150 hub_port_changes_callback, ((hub_dev->port_count + 1 + 7) / 8), 151 -1, usb_hub_polling_terminated_callback, hub_dev); 152 if (opResult != EOK) { 153 153 /* Function is already bound */ 154 154 ddf_fun_unbind(hub_dev->hub_fun); … … 159 159 } 160 160 hub_dev->running = true; 161 usb_log_info("Controlling hub '%s' (% zu ports).\n",162 ddf_dev_get_name(hub_dev->usb_device->ddf_dev), hub_dev->port_count);163 164 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 161 usb_log_info("Controlling hub '%s' (%p: %zu ports).\n", 162 usb_device_get_name(hub_dev->usb_device), hub_dev, 163 hub_dev->port_count); 164 165 165 return EOK; 166 166 } … … 185 185 { 186 186 assert(usb_dev); 187 usb_hub_dev_t *hub = usb_dev ->driver_data;187 usb_hub_dev_t *hub = usb_device_data_get(usb_dev); 188 188 assert(hub); 189 189 unsigned tries = 10; … … 191 191 async_usleep(100000); 192 192 if (!tries--) { 193 usb_log_error("Can't remove hub, still running.\n"); 193 usb_log_error("(%p): Can't remove hub, still running.", 194 hub); 194 195 return EBUSY; 195 196 } … … 199 200 200 201 for (size_t port = 0; port < hub->port_count; ++port) { 201 if (hub->ports[port].attached_device.fun) { 202 const int ret = 203 usb_hub_port_fini(&hub->ports[port], hub); 204 if (ret != EOK) 205 return ret; 206 } 202 const int ret = usb_hub_port_fini(&hub->ports[port], hub); 203 if (ret != EOK) 204 return ret; 207 205 } 208 206 free(hub->ports); … … 210 208 const int ret = ddf_fun_unbind(hub->hub_fun); 211 209 if (ret != EOK) { 212 usb_log_error(" Failed to unbind '%s' function: %s.\n",213 HUB_FNC_NAME, str_error(ret));210 usb_log_error("(%p) Failed to unbind '%s' function: %s.", 211 hub, HUB_FNC_NAME, str_error(ret)); 214 212 return ret; 215 213 } 216 214 ddf_fun_destroy(hub->hub_fun); 217 215 218 usb_log_info(" USB hub driver, stopped and cleaned.\n");216 usb_log_info("(%p) USB hub driver stopped and cleaned.", hub); 219 217 return EOK; 220 218 } … … 231 229 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) 232 230 { 233 usb_log_debug("hub_port_changes_callback\n");231 // usb_log_debug("hub_port_changes_callback\n"); 234 232 usb_hub_dev_t *hub = arg; 235 233 assert(hub); … … 247 245 248 246 /* N + 1 bit indicates change on port N */ 249 for (size_t port = 0; port < hub->port_count + 1; port++) {247 for (size_t port = 0; port < hub->port_count; ++port) { 250 248 const size_t bit = port + 1; 251 249 const bool change = (change_bitmap[bit / 8] >> (bit % 8)) & 1; … … 272 270 273 271 /* Get hub descriptor. */ 274 usb_log_debug("Retrieving descriptor\n"); 275 usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe; 272 usb_log_debug("(%p): Retrieving descriptor.", hub_dev); 273 usb_pipe_t *control_pipe = 274 usb_device_get_default_pipe(hub_dev->usb_device); 276 275 277 276 usb_hub_descriptor_header_t descriptor; … … 282 281 sizeof(usb_hub_descriptor_header_t), &received_size); 283 282 if (opResult != EOK) { 284 usb_log_error(" Failed to receive hub descriptor: %s.\n",285 str_error(opResult));283 usb_log_error("(%p): Failed to receive hub descriptor: %s.\n", 284 hub_dev, str_error(opResult)); 286 285 return opResult; 287 286 } 288 287 289 usb_log_debug("Setting port count to %d.\n", descriptor.port_count); 288 usb_log_debug("(%p): Setting port count to %d.\n", hub_dev, 289 descriptor.port_count); 290 290 hub_dev->port_count = descriptor.port_count; 291 291 … … 306 306 307 307 if (!hub_dev->power_switched) { 308 usb_log_info( 309 "Power switching not supported, ports always powered.\n");308 usb_log_info("(%p): Power switching not supported, " 309 "ports always powered.", hub_dev); 310 310 return EOK; 311 311 } 312 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); 313 usb_log_info("(%p): Hub port power switching enabled (%s).\n", hub_dev, 314 hub_dev->per_port_power ? "per port" : "ganged"); 315 316 for (unsigned port = 0; port < hub_dev->port_count; ++port) { 317 usb_log_debug("(%p): Powering port %u.", hub_dev, port); 317 318 const int ret = usb_hub_port_set_feature( 318 319 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 319 320 320 321 if (ret != EOK) { 321 usb_log_error("Cannot power on port %zu: %s.\n", 322 hub_dev->ports[port].port_number, str_error(ret)); 322 usb_log_error("(%p-%u): Cannot power on port: %s.\n", 323 hub_dev, hub_dev->ports[port].port_number, 324 str_error(ret)); 323 325 } else { 324 326 if (!hub_dev->per_port_power) { 325 usb_log_debug(" Ganged power switching, "326 "one port is enough. \n");327 usb_log_debug("(%p) Ganged power switching, " 328 "one port is enough.", hub_dev); 327 329 break; 328 330 } … … 345 347 /* Get number of possible configurations from device descriptor */ 346 348 const size_t configuration_count = 347 usb_device ->descriptors.device.configuration_count;349 usb_device_descriptors(usb_device)->device.configuration_count; 348 350 usb_log_debug("Hub has %zu configurations.\n", configuration_count); 349 351 … … 353 355 } 354 356 355 if (usb_device->descriptors.configuration_size 356 < sizeof(usb_standard_configuration_descriptor_t)) { 357 const size_t config_size = 358 usb_device_descriptors(usb_device)->full_config_size; 359 const usb_standard_configuration_descriptor_t *config_descriptor = 360 usb_device_descriptors(usb_device)->full_config; 361 362 if (config_size < sizeof(usb_standard_configuration_descriptor_t)) { 357 363 usb_log_error("Configuration descriptor is not big enough" 358 364 " to fit standard configuration descriptor.\n"); … … 360 366 } 361 367 362 // TODO: Make sure that the cast is correct363 usb_standard_configuration_descriptor_t *config_descriptor364 = (usb_standard_configuration_descriptor_t *)365 usb_device->descriptors.configuration;366 367 368 /* Set configuration. Use the configuration that was in 368 369 * usb_device->descriptors.configuration i.e. The first one. */ 369 370 const int opResult = usb_request_set_configuration( 370 &usb_device->ctrl_pipe, config_descriptor->configuration_number); 371 usb_device_get_default_pipe(usb_device), 372 config_descriptor->configuration_number); 371 373 if (opResult != EOK) { 372 374 usb_log_error("Failed to set hub configuration: %s.\n", … … 392 394 if (status & USB_HUB_STATUS_OVER_CURRENT) { 393 395 /* Hub should remove power from all ports if it detects OC */ 394 usb_log_warning(" Detected hub over-current condition, "395 "all ports should be powered off." );396 usb_log_warning("(%p) Detected hub over-current condition, " 397 "all ports should be powered off.", hub_dev); 396 398 return; 397 399 } … … 406 408 &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER); 407 409 if (ret != EOK) { 408 usb_log_warning(" HUB OVER-CURRENT GONE: Cannot power on"409 " po rt %zu: %s\n", hub_dev->ports[port].port_number,410 str_error(ret));410 usb_log_warning("(%p-%u): HUB OVER-CURRENT GONE: Cannot" 411 " power on port: %s\n", hub_dev, 412 hub_dev->ports[port].port_number, str_error(ret)); 411 413 } else { 412 414 if (!hub_dev->per_port_power) … … 427 429 assert(hub_dev); 428 430 assert(hub_dev->usb_device); 429 usb_log_debug("Global interrupt on a hub\n"); 430 usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe; 431 usb_log_debug("(%p): Global interrupt on th hub.", hub_dev); 432 usb_pipe_t *control_pipe = 433 usb_device_get_default_pipe(hub_dev->usb_device); 431 434 432 435 usb_hub_status_t status; … … 438 441 &status, sizeof(usb_hub_status_t), &rcvd_size); 439 442 if (opResult != EOK) { 440 usb_log_error(" Could not get hub status: %s\n",443 usb_log_error("(%p): Could not get hub status: %s.", hub_dev, 441 444 str_error(opResult)); 442 445 return; 443 446 } 444 447 if (rcvd_size != sizeof(usb_hub_status_t)) { 445 usb_log_error("Received status has incorrect size\n"); 448 usb_log_error("(%p): Received status has incorrect size: " 449 "%zu != %zu", hub_dev, rcvd_size, sizeof(usb_hub_status_t)); 446 450 return; 447 451 } … … 452 456 /* Ack change in hub OC flag */ 453 457 const int ret = usb_request_clear_feature( 454 &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,458 control_pipe, USB_REQUEST_TYPE_CLASS, 455 459 USB_REQUEST_RECIPIENT_DEVICE, 456 460 USB_HUB_FEATURE_C_HUB_OVER_CURRENT, 0); 457 461 if (ret != EOK) { 458 usb_log_error(" Failed to clear hub over-current "459 "change flag: %s.\n", str_error(opResult));462 usb_log_error("(%p): Failed to clear hub over-current " 463 "change flag: %s.\n", hub_dev, str_error(opResult)); 460 464 } 461 465 } … … 480 484 USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0); 481 485 if (opResult != EOK) { 482 usb_log_error(" Failed to clear hub power change "483 "flag: %s.\n", str_error(ret));486 usb_log_error("(%p): Failed to clear hub power change " 487 "flag: %s.\n", hub_dev, str_error(ret)); 484 488 } 485 489 } -
uspace/drv/bus/usb/usbhub/usbhub.h
r5b18137 rb4b534ac 39 39 #include <ddf/driver.h> 40 40 41 #include <usb/dev/hub.h>42 41 #include <usb/classes/hub.h> 43 42 … … 81 80 }; 82 81 82 extern const usb_endpoint_description_t hub_status_change_endpoint_description; 83 83 84 int usb_hub_device_add(usb_device_t *usb_dev); 84 85 int usb_hub_device_remove(usb_device_t *usb_dev); -
uspace/drv/bus/usb/usbmast/bo_trans.c
r5b18137 rb4b534ac 44 44 #include "usbmast.h" 45 45 46 bool usb_mast_verbose = false;47 46 48 47 #define MASTLOG(format, ...) \ 49 do { \ 50 if (usb_mast_verbose) { \ 51 usb_log_debug2("USB cl08: " format, ##__VA_ARGS__); \ 52 } \ 53 } while (false) 48 usb_log_debug2("USB cl08: " format, ##__VA_ARGS__) 54 49 55 50 /** Send command via bulk-only transport. … … 65 60 { 66 61 int rc; 67 int retval = EOK; 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; 71 usb_direction_t ddir; 72 void *dbuf; 73 size_t dbuf_size; 74 75 if (cmd->data_out != NULL && cmd->data_in == NULL) { 76 ddir = USB_DIRECTION_OUT; 77 dbuf = (void *)cmd->data_out; 78 dbuf_size = cmd->data_out_size; 79 } else if (cmd->data_out == NULL && cmd->data_in != NULL) { 62 63 if (cmd->data_in && cmd->data_out) 64 return EINVAL; 65 66 usb_pipe_t *bulk_in_pipe = mfun->mdev->bulk_in_pipe; 67 usb_pipe_t *bulk_out_pipe = mfun->mdev->bulk_out_pipe; 68 69 usb_pipe_t *dpipe = bulk_out_pipe; 70 usb_direction_t ddir = USB_DIRECTION_OUT; 71 size_t dbuf_size = cmd->data_out_size; 72 73 if (cmd->data_in) { 80 74 ddir = USB_DIRECTION_IN; 81 dbuf = cmd->data_in;82 75 dbuf_size = cmd->data_in_size; 83 } else { 84 assert(false); 76 dpipe = bulk_in_pipe; 85 77 } 86 78 … … 96 88 usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0), 97 89 str_error(rc)); 98 if (rc != EOK) 99 return EIO; 90 if (rc != EOK) { 91 usb_log_error("Bulk out write failed: %s\n", str_error(rc)); 92 return EIO; 93 } 100 94 101 95 MASTLOG("Transferring data.\n"); 102 if (ddir == USB_DIRECTION_IN) { 96 if (cmd->data_in) { 97 size_t act_size; 103 98 /* Recieve data from the device. */ 104 rc = usb_pipe_read(bulk_in_pipe, dbuf, dbuf_size, &act_size); 99 rc = usb_pipe_read(dpipe, cmd->data_in, cmd->data_in_size, 100 &act_size); 105 101 MASTLOG("Received %zu bytes (%s): %s.\n", act_size, 106 usb_debug_str_buffer( (uint8_t *) dbuf, act_size, 0),102 usb_debug_str_buffer(cmd->data_in, act_size, 0), 107 103 str_error(rc)); 108 } else { 104 } 105 if (cmd->data_out) { 109 106 /* Send data to the device. */ 110 rc = usb_pipe_write( bulk_out_pipe, dbuf, dbuf_size);111 MASTLOG("Sent %zu bytes (%s): %s.\n", act_size,112 usb_debug_str_buffer( (uint8_t *) dbuf, act_size, 0),107 rc = usb_pipe_write(dpipe, cmd->data_out, cmd->data_out_size); 108 MASTLOG("Sent %zu bytes (%s): %s.\n", cmd->data_out_size, 109 usb_debug_str_buffer(cmd->data_out, cmd->data_out_size, 0), 113 110 str_error(rc)); 114 111 } … … 116 113 if (rc == ESTALL) { 117 114 /* Clear stall condition and continue below to read CSW. */ 118 if (ddir == USB_DIRECTION_IN) { 119 usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe, 120 &mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe); 121 } else { 122 usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe, 123 &mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe); 124 } 115 usb_pipe_clear_halt( 116 usb_device_get_default_pipe(mfun->mdev->usb_dev), dpipe); 125 117 } else if (rc != EOK) { 118 usb_log_error("Failed to transfer data: %s", str_error(rc)); 126 119 return EIO; 127 120 } … … 136 129 str_error(rc)); 137 130 if (rc != EOK) { 138 MASTLOG("rc != EOK\n");131 usb_log_error("Failed to read CSW: %s", str_error(rc)); 139 132 return EIO; 140 133 } 141 134 142 135 if (csw_size != sizeof(csw)) { 143 MASTLOG("csw_size != sizeof(csw)\n");136 usb_log_error("Received CSW of incorrect size."); 144 137 return EIO; 145 138 } 146 139 147 140 if (csw.dCSWTag != tag) { 148 MASTLOG("csw.dCSWTag != tag\n"); 141 usb_log_error("Received CSW with incorrect tag. (expected: %" 142 PRIX32" received: %"PRIx32, tag, csw.dCSWTag); 149 143 return EIO; 150 144 } … … 158 152 break; 159 153 case cbs_failed: 160 MASTLOG("Command failed\n");161 154 cmd->status = CMDS_FAILED; 155 usb_log_error("CBS Failed.\n"); 162 156 break; 163 157 case cbs_phase_error: 164 MASTLOG("Phase error\n");165 r etval= EIO;158 usb_log_error("CBS phase error.\n"); 159 rc = EIO; 166 160 break; 167 161 default: 168 retval = EIO; 169 break; 170 } 171 172 size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue); 162 usb_log_error("CBS other error.\n"); 163 rc = EIO; 164 break; 165 } 166 167 const size_t residue = uint32_usb2host(csw.dCSWDataResidue); 173 168 if (residue > dbuf_size) { 174 MASTLOG("residue > dbuf_size\n"); 169 usb_log_error("Residue > buffer size (%zu > %zu).\n", 170 residue, dbuf_size); 175 171 return EIO; 176 172 } … … 184 180 */ 185 181 186 if ( ddir == USB_DIRECTION_IN)182 if (cmd->data_in) 187 183 cmd->rcvd_size = dbuf_size - residue; 188 184 189 return r etval;185 return rc; 190 186 } 191 187 … … 197 193 int usb_massstor_reset(usbmast_dev_t *mdev) 198 194 { 199 return usb_control_request_set(&mdev->usb_dev->ctrl_pipe, 195 return usb_control_request_set( 196 usb_device_get_default_pipe(mdev->usb_dev), 200 197 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 201 0xFF, 0, mdev->usb_dev->interface_no, NULL, 0);198 0xFF, 0, usb_device_get_iface_number(mdev->usb_dev), NULL, 0); 202 199 } 203 200 … … 215 212 */ 216 213 usb_massstor_reset(mdev); 217 usb_pipe_clear_halt( &mdev->usb_dev->ctrl_pipe,218 &mdev->usb_dev->pipes[BULK_IN_EP].pipe);219 usb_pipe_clear_halt( &mdev->usb_dev->ctrl_pipe,220 &mdev->usb_dev->pipes[BULK_OUT_EP].pipe);214 usb_pipe_clear_halt(usb_device_get_default_pipe(mdev->usb_dev), 215 mdev->bulk_in_pipe); 216 usb_pipe_clear_halt(usb_device_get_default_pipe(mdev->usb_dev), 217 mdev->bulk_out_pipe); 221 218 } 222 219 … … 236 233 uint8_t max_lun; 237 234 size_t data_recv_len; 238 int rc = usb_control_request_get(&mdev->usb_dev->ctrl_pipe, 235 int rc = usb_control_request_get( 236 usb_device_get_default_pipe(mdev->usb_dev), 239 237 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 240 0xFE, 0, mdev->usb_dev->interface_no, &max_lun, 1, &data_recv_len); 238 0xFE, 0, usb_device_get_iface_number(mdev->usb_dev), &max_lun, 1, 239 &data_recv_len); 241 240 if (rc != EOK) { 242 241 return rc; -
uspace/drv/bus/usb/usbmast/bo_trans.h
r5b18137 rb4b534ac 44 44 #include "usbmast.h" 45 45 46 #define BULK_IN_EP 047 #define BULK_OUT_EP 148 49 46 typedef enum cmd_status { 50 47 CMDS_GOOD, … … 63 60 64 61 /** Command Descriptor Block */ 65 void *cdb;62 const void *cdb; 66 63 /** CDB size in bytes */ 67 64 size_t cdb_size; -
uspace/drv/bus/usb/usbmast/main.c
r5b18137 rb4b534ac 44 44 #include <usb/classes/massstor.h> 45 45 #include <errno.h> 46 #include <io/logctl.h> 46 47 #include <str_error.h> 47 48 #include "cmdw.h" … … 51 52 52 53 #define NAME "usbmast" 53 54 #define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)55 #define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)56 54 57 55 static const usb_endpoint_description_t bulk_in_ep = { … … 112 110 static int usbmast_device_gone(usb_device_t *dev) 113 111 { 114 usbmast_dev_t *mdev = dev->driver_data;112 usbmast_dev_t *mdev = usb_device_data_get(dev); 115 113 assert(mdev); 116 114 … … 152 150 unsigned i; 153 151 152 usb_endpoint_mapping_t *epm_in = 153 usb_device_get_mapped_ep_desc(dev, &bulk_in_ep); 154 usb_endpoint_mapping_t *epm_out = 155 usb_device_get_mapped_ep_desc(dev, &bulk_out_ep); 156 if (!epm_in || !epm_out || !epm_in->present || !epm_out->present) { 157 usb_log_error("Required EPs were not mapped.\n"); 158 return ENOENT; 159 } 160 154 161 /* Allocate softstate */ 155 162 mdev = usb_device_data_alloc(dev, sizeof(usbmast_dev_t)); … … 159 166 } 160 167 161 mdev->ddf_dev = dev->ddf_dev;162 168 mdev->usb_dev = dev; 163 169 164 usb_log_info("Initializing mass storage `%s'.\n", ddf_dev_get_name(dev->ddf_dev)); 170 usb_log_info("Initializing mass storage `%s'.\n", 171 usb_device_get_name(dev)); 165 172 usb_log_debug("Bulk in endpoint: %d [%zuB].\n", 166 dev->pipes[BULK_IN_EP].pipe.endpoint_no, 167 dev->pipes[BULK_IN_EP].pipe.max_packet_size); 173 epm_in->pipe.endpoint_no, epm_in->pipe.max_packet_size); 168 174 usb_log_debug("Bulk out endpoint: %d [%zuB].\n", 169 dev->pipes[BULK_OUT_EP].pipe.endpoint_no, 170 dev->pipes[BULK_OUT_EP].pipe.max_packet_size); 175 epm_out->pipe.endpoint_no, epm_out->pipe.max_packet_size); 171 176 172 177 usb_log_debug("Get LUN count...\n"); … … 179 184 } 180 185 186 mdev->bulk_in_pipe = &epm_in->pipe; 187 mdev->bulk_out_pipe = &epm_out->pipe; 181 188 for (i = 0; i < mdev->lun_count; i++) { 182 189 rc = usbmast_fun_create(mdev, i); … … 223 230 } 224 231 225 fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name);232 fun = usb_device_ddf_fun_create(mdev->usb_dev, fun_exposed, fun_name); 226 233 if (fun == NULL) { 227 234 usb_log_error("Failed to create DDF function %s.\n", fun_name); … … 254 261 if (rc != EOK) { 255 262 usb_log_warning("Failed to inquire device `%s': %s.\n", 256 ddf_dev_get_name(mdev->ddf_dev), str_error(rc));263 usb_device_get_name(mdev->usb_dev), str_error(rc)); 257 264 rc = EIO; 258 265 goto error; … … 261 268 usb_log_info("Mass storage `%s' LUN %u: " \ 262 269 "%s by %s rev. %s is %s (%s).\n", 263 ddf_dev_get_name(mdev->ddf_dev),270 usb_device_get_name(mdev->usb_dev), 264 271 lun, 265 272 inquiry.product, … … 274 281 if (rc != EOK) { 275 282 usb_log_warning("Failed to read capacity, device `%s': %s.\n", 276 ddf_dev_get_name(mdev->ddf_dev), str_error(rc));283 usb_device_get_name(mdev->usb_dev), str_error(rc)); 277 284 rc = EIO; 278 285 goto error; … … 396 403 { 397 404 log_init(NAME); 398 405 logctl_set_log_level(NAME, LVL_NOTE); 399 406 return usb_driver_main(&usbmast_driver); 400 407 } -
uspace/drv/bus/usb/usbmast/scsi_ms.c
r5b18137 rb4b534ac 63 63 static void usbmast_dump_sense(scsi_sense_data_t *sense_buf) 64 64 { 65 unsigned sense_key; 66 67 sense_key = sense_buf->flags_key & 0x0f; 65 const unsigned sense_key = sense_buf->flags_key & 0x0f; 68 66 printf("Got sense data. Sense key: 0x%x (%s), ASC 0x%02x, " 69 67 "ASCQ 0x%02x.\n", sense_key, … … 73 71 } 74 72 73 static int usb_massstor_unit_ready(usbmast_fun_t *mfun) 74 { 75 scsi_cmd_t cmd; 76 scsi_cdb_test_unit_ready_t cdb; 77 int rc; 78 79 memset(&cdb, 0, sizeof(cdb)); 80 cdb.op_code = SCSI_CMD_TEST_UNIT_READY; 81 82 memset(&cmd, 0, sizeof(cmd)); 83 cmd.cdb = &cdb; 84 cmd.cdb_size = sizeof(cdb); 85 86 rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd); 87 88 if (rc != EOK) { 89 usb_log_error("Test Unit Ready failed on device %s: %s.", 90 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 91 return rc; 92 } 93 /* Ignore command error here. If there's something wrong 94 * with the device the following commands will fail too. 95 */ 96 if (cmd.status != CMDS_GOOD) 97 usb_log_warning("Test Unit Ready command failed on device %s.", 98 usb_device_get_name(mfun->mdev->usb_dev)); 99 100 return EOK; 101 } 102 75 103 /** Run SCSI command. 76 104 * … … 85 113 86 114 do { 115 rc = usb_massstor_unit_ready(mfun); 116 if (rc != EOK) { 117 usb_log_error("Inquiry transport failed, device %s: %s.\n", 118 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 119 return rc; 120 } 121 87 122 rc = usb_massstor_cmd(mfun, 0xDEADBEEF, cmd); 88 123 if (rc != EOK) { 89 124 usb_log_error("Inquiry transport failed, device %s: %s.\n", 90 ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));125 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 91 126 return rc; 92 127 } … … 96 131 97 132 usb_log_error("SCSI command failed, device %s.\n", 98 ddf_dev_get_name(mfun->mdev->ddf_dev));133 usb_device_get_name(mfun->mdev->usb_dev)); 99 134 100 135 rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf)); … … 147 182 if (rc != EOK) { 148 183 usb_log_error("Inquiry transport failed, device %s: %s.\n", 149 ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));184 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 150 185 return rc; 151 186 } … … 153 188 if (cmd.status != CMDS_GOOD) { 154 189 usb_log_error("Inquiry command failed, device %s.\n", 155 ddf_dev_get_name(mfun->mdev->ddf_dev));190 usb_device_get_name(mfun->mdev->usb_dev)); 156 191 return EIO; 157 192 } … … 215 250 if (rc != EOK || cmd.status != CMDS_GOOD) { 216 251 usb_log_error("Request Sense failed, device %s: %s.\n", 217 ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));252 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 218 253 return rc; 219 254 } … … 257 292 if (rc != EOK) { 258 293 usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n", 259 ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));294 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 260 295 return rc; 261 296 } … … 263 298 if (cmd.status != CMDS_GOOD) { 264 299 usb_log_error("Read Capacity (10) command failed, device %s.\n", 265 ddf_dev_get_name(mfun->mdev->ddf_dev));300 usb_device_get_name(mfun->mdev->usb_dev)); 266 301 return EIO; 267 302 } … … 314 349 if (rc != EOK) { 315 350 usb_log_error("Read (10) transport failed, device %s: %s.\n", 316 ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));351 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 317 352 return rc; 318 353 } … … 320 355 if (cmd.status != CMDS_GOOD) { 321 356 usb_log_error("Read (10) command failed, device %s.\n", 322 ddf_dev_get_name(mfun->mdev->ddf_dev));357 usb_device_get_name(mfun->mdev->usb_dev)); 323 358 return EIO; 324 359 } … … 370 405 if (rc != EOK) { 371 406 usb_log_error("Write (10) transport failed, device %s: %s.\n", 372 ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));407 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 373 408 return rc; 374 409 } … … 376 411 if (cmd.status != CMDS_GOOD) { 377 412 usb_log_error("Write (10) command failed, device %s.\n", 378 ddf_dev_get_name(mfun->mdev->ddf_dev));413 usb_device_get_name(mfun->mdev->usb_dev)); 379 414 return EIO; 380 415 } … … 394 429 int usbmast_sync_cache(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks) 395 430 { 396 scsi_cmd_t cmd;397 scsi_cdb_sync_cache_10_t cdb;398 int rc;399 400 431 if (ba > UINT32_MAX) 401 432 return ELIMIT; … … 404 435 return ELIMIT; 405 436 406 memset(&cdb, 0, sizeof(cdb)); 407 cdb.op_code = SCSI_CMD_SYNC_CACHE_10; 408 cdb.lba = host2uint32_t_be(ba); 409 cdb.numlb = host2uint16_t_be(nblocks); 410 411 memset(&cmd, 0, sizeof(cmd)); 412 cmd.cdb = &cdb; 413 cmd.cdb_size = sizeof(cdb); 414 415 rc = usbmast_run_cmd(mfun, &cmd); 437 const scsi_cdb_sync_cache_10_t cdb = { 438 .op_code = SCSI_CMD_SYNC_CACHE_10, 439 .lba = host2uint32_t_be(ba), 440 .numlb = host2uint16_t_be(nblocks), 441 }; 442 443 scsi_cmd_t cmd = { 444 .cdb = &cdb, 445 .cdb_size = sizeof(cdb), 446 }; 447 448 const int rc = usbmast_run_cmd(mfun, &cmd); 416 449 417 450 if (rc != EOK) { 418 451 usb_log_error("Synchronize Cache (10) transport failed, device %s: %s.\n", 419 ddf_dev_get_name(mfun->mdev->ddf_dev), str_error(rc));452 usb_device_get_name(mfun->mdev->usb_dev), str_error(rc)); 420 453 return rc; 421 454 } … … 423 456 if (cmd.status != CMDS_GOOD) { 424 457 usb_log_error("Synchronize Cache (10) command failed, device %s.\n", 425 ddf_dev_get_name(mfun->mdev->ddf_dev));458 usb_device_get_name(mfun->mdev->usb_dev)); 426 459 return EIO; 427 460 } -
uspace/drv/bus/usb/usbmast/usbmast.h
r5b18137 rb4b534ac 43 43 /** Mass storage device. */ 44 44 typedef struct usbmast_dev { 45 /** DDF device */46 ddf_dev_t *ddf_dev;47 45 /** USB device */ 48 46 usb_device_t *usb_dev; … … 51 49 /** LUN functions */ 52 50 ddf_fun_t **luns; 51 /** Data read pipe */ 52 usb_pipe_t *bulk_in_pipe; 53 /** Data write pipe */ 54 usb_pipe_t *bulk_out_pipe; 53 55 } usbmast_dev_t; 54 56 -
uspace/drv/bus/usb/usbmid/explore.c
r5b18137 rb4b534ac 34 34 * Exploration of available interfaces in the USB device. 35 35 */ 36 #include <ddf/driver.h>37 36 #include <errno.h> 38 37 #include <str_error.h> … … 41 40 #include <usb/dev/request.h> 42 41 #include <usb/dev/dp.h> 43 #include <usb/ddfiface.h>44 42 #include "usbmid.h" 45 46 /** Operations of the device itself. */47 static ddf_dev_ops_t mid_device_ops = {48 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl49 };50 43 51 44 /** Tell whether given interface is already in the list. … … 57 50 static bool interface_in_list(const list_t *list, int interface_no) 58 51 { 59 list_foreach(*list, link, usbmid_interface_t, iface) {52 list_foreach(*list, link, const usbmid_interface_t, iface) { 60 53 if (iface->interface_no == interface_no) { 61 54 return true; … … 71 64 * @param config_descriptor_size Size of configuration descriptor in bytes. 72 65 * @param list List where to add the interfaces. 73 * @return EOK on success, ENOMEM if out of memory.74 66 */ 75 static int create_interfaces( usb_mid_t *mid,const uint8_t *config_descriptor,76 size_t config_descriptor_size )67 static int create_interfaces(const uint8_t *config_descriptor, 68 size_t config_descriptor_size, list_t *list, usb_device_t *usb_dev) 77 69 { 70 assert(config_descriptor); 71 assert(usb_dev); 72 78 73 const usb_dp_parser_data_t data = { 79 74 .data = config_descriptor, … … 91 86 /* Walk all descriptors nested in the current configuration decriptor; 92 87 * i.e. all interface descriptors. */ 93 for (; interface_ptr != NULL;88 for (; interface_ptr != NULL; 94 89 interface_ptr = usb_dp_get_sibling_descriptor( 95 90 &parser, &data, config_descriptor, interface_ptr)) … … 103 98 104 99 /* Skip alternate interfaces. */ 105 if (interface_in_list(&mid->interface_list, 106 interface->interface_number)) { 100 if (interface_in_list(list, interface->interface_number)) { 107 101 /* TODO: add the alternatives and create match ids 108 102 * for them. */ … … 110 104 } 111 105 112 /* Create the function */113 ddf_fun_t *fun = ddf_fun_create(mid->dev, fun_inner, NULL);114 if (fun == NULL)115 goto error;116 106 117 usbmid_interface_t *iface = ddf_fun_data_alloc(fun, 118 sizeof(usbmid_interface_t)); 119 if (iface == NULL) 120 goto error; 107 usb_log_info("Creating child for interface %d (%s).\n", 108 interface->interface_number, 109 usb_str_class(interface->interface_class)); 121 110 122 link_initialize(&iface->link); 123 iface->fun = fun; 124 iface->interface_no = interface->interface_number; 125 iface->interface = interface; 126 127 list_append(&iface->link, &mid->interface_list); 111 usbmid_interface_t *iface = NULL; 112 const int rc = usbmid_spawn_interface_child(usb_dev, &iface, 113 &usb_device_descriptors(usb_dev)->device, interface); 114 if (rc != EOK) { 115 //TODO: Do something about that failure. 116 usb_log_error("Failed to create interface child for " 117 "%d (%s): %s.\n", interface->interface_number, 118 usb_str_class(interface->interface_class), 119 str_error(rc)); 120 } else { 121 list_append(&iface->link, list); 122 } 128 123 } 129 130 124 return EOK; 131 error:132 while (!list_empty(&mid->interface_list)) {133 link_t *link = list_first(&mid->interface_list);134 usbmid_interface_t *iface = list_get_instance(link,135 usbmid_interface_t, link);136 137 ddf_fun_destroy(iface->fun);138 }139 140 return ENOMEM;141 125 } 142 126 … … 149 133 * @return Whether to accept this device from devman. 150 134 */ 151 boolusbmid_explore_device(usb_device_t *dev)135 int usbmid_explore_device(usb_device_t *dev) 152 136 { 153 int rc;154 155 unsigned dev_class = dev->descriptors.device.device_class;137 assert(dev); 138 const unsigned dev_class = 139 usb_device_descriptors(dev)->device.device_class; 156 140 if (dev_class != USB_CLASS_USE_INTERFACE) { 157 141 usb_log_warning( … … 159 143 dev_class, usb_str_class(dev_class), 160 144 USB_CLASS_USE_INTERFACE); 161 usb_log_error("Not multiinterface device, refusing.\n");162 return false;145 usb_log_error("Not a multi-interface device, refusing.\n"); 146 return ENOTSUP; 163 147 } 164 148 165 /* Shortcuts to save on typing ;-). */ 166 const void *config_descriptor_raw = dev->descriptors.configuration; 167 size_t config_descriptor_size = dev->descriptors.configuration_size; 149 /* Get coonfiguration descriptor. */ 150 const size_t config_descriptor_size = 151 usb_device_descriptors(dev)->full_config_size; 152 const void *config_descriptor_raw = 153 usb_device_descriptors(dev)->full_config; 168 154 const usb_standard_configuration_descriptor_t *config_descriptor = 169 155 config_descriptor_raw; 170 156 171 157 /* Select the first configuration */ 172 rc = usb_request_set_configuration(&dev->ctrl_pipe,158 int rc = usb_request_set_configuration(usb_device_get_default_pipe(dev), 173 159 config_descriptor->configuration_number); 174 160 if (rc != EOK) { 175 161 usb_log_error("Failed to set device configuration: %s.\n", 176 162 str_error(rc)); 177 return false;163 return rc; 178 164 } 179 165 180 166 /* Create driver soft-state. */ 181 167 usb_mid_t *usb_mid = usb_device_data_alloc(dev, sizeof(usb_mid_t)); 182 168 if (!usb_mid) { 183 169 usb_log_error("Failed to create USB MID structure.\n"); 184 return false;170 return ENOMEM; 185 171 } 186 172 187 usb_mid->dev = dev->ddf_dev;188 189 173 /* Create control function. */ 190 usb_mid->ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");174 usb_mid->ctl_fun = usb_device_ddf_fun_create(dev, fun_exposed, "ctl"); 191 175 if (usb_mid->ctl_fun == NULL) { 192 176 usb_log_error("Failed to create control function.\n"); 193 return false;177 return ENOMEM; 194 178 } 195 ddf_fun_set_ops(usb_mid->ctl_fun, &mid_device_ops);196 179 197 180 /* Bind control function. */ … … 201 184 str_error(rc)); 202 185 ddf_fun_destroy(usb_mid->ctl_fun); 203 return false;186 return rc; 204 187 } 205 188 206 189 /* Create interface children. */ 207 190 list_initialize(&usb_mid->interface_list); 208 create_interfaces(usb_mid, config_descriptor_raw, config_descriptor_size); 191 create_interfaces(config_descriptor_raw, config_descriptor_size, 192 &usb_mid->interface_list, dev); 209 193 210 /* Start child function for every interface. */ 211 list_foreach(usb_mid->interface_list, link, usbmid_interface_t, iface) { 212 usb_log_info("Creating child for interface %d (%s).\n", 213 iface->interface_no, 214 usb_str_class(iface->interface->interface_class)); 215 216 rc = usbmid_spawn_interface_child(dev, iface, 217 &dev->descriptors.device, iface->interface); 218 if (rc != EOK) { 219 usb_log_error("Failed to create interface child: %s.\n", 220 str_error(rc)); 221 } 222 } 223 224 return true; 194 return EOK; 225 195 } 226 196 -
uspace/drv/bus/usb/usbmid/main.c
r5b18137 rb4b534ac 51 51 static int usbmid_device_add(usb_device_t *dev) 52 52 { 53 usb_log_info("Taking care of new MID `%s'.\n", ddf_dev_get_name(dev->ddf_dev));53 usb_log_info("Taking care of new MID `%s'.\n", usb_device_get_name(dev)); 54 54 55 const bool accept = usbmid_explore_device(dev); 56 57 if (!accept) { 58 return ENOTSUP; 59 } 60 61 return EOK; 55 return usbmid_explore_device(dev); 62 56 } 63 57 … … 70 64 { 71 65 assert(dev); 72 usb_mid_t *usb_mid = dev->driver_data;66 usb_mid_t *usb_mid = usb_device_data_get(dev); 73 67 assert(usb_mid); 74 68 … … 89 83 usbmid_interface_t *iface = usbmid_interface_from_link(item); 90 84 91 usb_log_info("Removing child for interface %d (%s).\n", 92 iface->interface_no, 93 usb_str_class(iface->interface->interface_class)); 85 usb_log_info("Removing child `%s'.\n", 86 ddf_fun_get_name(iface->fun)); 94 87 95 88 /* Tell the child to go off-line. */ 96 89 int pret = ddf_fun_offline(iface->fun); 97 90 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)); 91 usb_log_warning("Failed to turn off child `%s': %s\n", 92 ddf_fun_get_name(iface->fun), str_error(pret)); 102 93 ret = pret; 103 94 } … … 106 97 pret = usbmid_interface_destroy(iface); 107 98 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)); 99 usb_log_error("Failed to destroy child `%s': %s\n", 100 ddf_fun_get_name(iface->fun), str_error(pret)); 112 101 ret = pret; 113 102 } … … 124 113 { 125 114 assert(dev); 126 usb_mid_t *usb_mid = dev->driver_data;115 usb_mid_t *usb_mid = usb_device_data_get(dev); 127 116 assert(usb_mid); 128 117 129 usb_log_info("USB MID gone: `%s'.\n", ddf_dev_get_name(dev->ddf_dev));118 usb_log_info("USB MID gone: `%s'.\n", usb_device_get_name(dev)); 130 119 131 120 /* Remove ctl function */ … … 145 134 usbmid_interface_t *iface = usbmid_interface_from_link(item); 146 135 147 usb_log_info("Child for interface %d (%s) gone.\n", 148 iface->interface_no, 149 usb_str_class(iface->interface->interface_class)); 136 usb_log_info("Child `%s' is gone.\n", 137 ddf_fun_get_name(iface->fun)); 150 138 151 139 const int pret = usbmid_interface_destroy(iface); 152 140 if (pret != EOK) { 153 usb_log_error("Failed to remove child for interface " 154 "%d (%s): %s\n", 155 iface->interface_no, 156 usb_str_class(iface->interface->interface_class), 157 str_error(pret)); 141 usb_log_error("Failed to remove child `%s': %s\n", 142 ddf_fun_get_name(iface->fun), str_error(pret)); 158 143 ret = pret; 159 144 } -
uspace/drv/bus/usb/usbmid/usbmid.c
r5b18137 rb4b534ac 39 39 #include <stdlib.h> 40 40 #include <usb_iface.h> 41 #include <usb/ddfiface.h>42 41 #include <usb/dev/pipes.h> 43 42 #include <usb/classes/classes.h> … … 45 44 #include "usbmid.h" 46 45 47 /** Callback for DDF USB interface. */ 48 static int usb_iface_get_interface_impl(ddf_fun_t *fun, int *iface_no) 46 /** Get USB device handle by calling the parent usb_device_t. 47 * 48 * @param[in] fun Device function the operation is running on. 49 * @param[out] handle Device handle. 50 * @return Error code. 51 */ 52 static int usb_iface_device_handle(ddf_fun_t *fun, devman_handle_t *handle) 53 { 54 assert(fun); 55 assert(handle); 56 usb_device_t *usb_dev = usb_device_get(ddf_fun_get_dev(fun)); 57 *handle = usb_device_get_devman_handle(usb_dev); 58 return EOK; 59 } 60 61 /** Callback for DDF USB get interface. */ 62 static int usb_iface_iface_no(ddf_fun_t *fun, int *iface_no) 49 63 { 50 64 usbmid_interface_t *iface = ddf_fun_data_get(fun); 51 65 assert(iface); 52 66 53 if (iface_no != NULL) {67 if (iface_no) 54 68 *iface_no = iface->interface_no; 55 }56 69 57 70 return EOK; 58 71 } 59 72 60 /** DDF interface of the child - interface function. */73 /** DDF interface of the child - USB functions. */ 61 74 static usb_iface_t child_usb_iface = { 62 .get_hc_handle = usb_iface_get_hc_handle_device_impl, 63 .get_my_address = usb_iface_get_my_address_forward_impl, 64 .get_my_interface = usb_iface_get_interface_impl, 75 .get_my_device_handle = usb_iface_device_handle, 76 .get_my_interface = usb_iface_iface_no, 65 77 }; 66 78 … … 78 90 return ret; 79 91 } 80 /* NOTE: usbmid->interface points somewhere, but we did not81 * allocate that space, so don't touch */82 92 ddf_fun_destroy(mid_iface->fun); 83 /* NOTE: mid_iface is invalid at this point, it was assigned to84 * mid_iface->fun->driver_data and freed in ddf_fun_destroy */85 93 return EOK; 86 94 } … … 95 103 */ 96 104 int usbmid_spawn_interface_child(usb_device_t *parent, 97 usbmid_interface_t * iface,105 usbmid_interface_t **iface_ret, 98 106 const usb_standard_device_descriptor_t *device_descriptor, 99 107 const usb_standard_interface_descriptor_t *interface_descriptor) 100 108 { 109 ddf_fun_t *child = NULL; 101 110 char *child_name = NULL; 102 111 int rc; … … 110 119 usb_str_class(interface_descriptor->interface_class), 111 120 interface_descriptor->interface_number); 112 if (rc < 0) 121 if (rc < 0) { 113 122 return ENOMEM; 123 } 114 124 115 rc = ddf_fun_set_name(iface->fun, child_name); 125 /* Create the device. */ 126 child = usb_device_ddf_fun_create(parent, fun_inner, child_name); 116 127 free(child_name); 117 if ( rc != EOK)128 if (child == NULL) { 118 129 return ENOMEM; 130 } 119 131 120 132 match_id_list_t match_ids; … … 123 135 rc = usb_device_create_match_ids_from_interface(device_descriptor, 124 136 interface_descriptor, &match_ids); 125 if (rc != EOK) 137 if (rc != EOK) { 138 ddf_fun_destroy(child); 126 139 return rc; 140 } 127 141 128 142 list_foreach(match_ids.ids, link, match_id_t, match_id) { 129 rc = ddf_fun_add_match_id( iface->fun, match_id->id, match_id->score);143 rc = ddf_fun_add_match_id(child, match_id->id, match_id->score); 130 144 if (rc != EOK) { 131 145 clean_match_ids(&match_ids); 146 ddf_fun_destroy(child); 132 147 return rc; 133 148 } 134 149 } 135 150 clean_match_ids(&match_ids); 151 ddf_fun_set_ops(child, &child_device_ops); 136 152 137 ddf_fun_set_ops(iface->fun, &child_device_ops);153 usbmid_interface_t *iface = ddf_fun_data_alloc(child, sizeof(*iface)); 138 154 139 rc = ddf_fun_bind(iface->fun); 140 if (rc != EOK) 155 iface->fun = child; 156 iface->interface_no = interface_descriptor->interface_number; 157 link_initialize(&iface->link); 158 159 rc = ddf_fun_bind(child); 160 if (rc != EOK) { 161 /* This takes care of match_id deallocation as well. */ 162 ddf_fun_destroy(child); 141 163 return rc; 164 } 165 *iface_ret = iface; 142 166 143 167 return EOK; -
uspace/drv/bus/usb/usbmid/usbmid.h
r5b18137 rb4b534ac 50 50 /** Function container. */ 51 51 ddf_fun_t *fun; 52 /** Interface descriptor. */53 const usb_standard_interface_descriptor_t *interface;54 52 /** Interface number. */ 55 53 int interface_no; … … 60 58 /** Container to hold all the function pointers */ 61 59 typedef struct usb_mid { 62 ddf_dev_t *dev;63 60 ddf_fun_t *ctl_fun; 64 61 list_t interface_list; 65 62 } usb_mid_t; 66 63 67 boolusbmid_explore_device(usb_device_t *);68 int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t * ,64 int usbmid_explore_device(usb_device_t *); 65 int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t **, 69 66 const usb_standard_device_descriptor_t *, 70 67 const usb_standard_interface_descriptor_t *); -
uspace/drv/bus/usb/usbmid/usbmid.ma
r5b18137 rb4b534ac 1 100 usb&class=use-interface 1 2 100 usb&mid -
uspace/drv/bus/usb/vhc/Makefile
r5b18137 rb4b534ac 49 49 hub/virthubops.c \ 50 50 conndev.c \ 51 connhost.c \52 51 devconn.c \ 53 hub.c \54 52 main.c \ 55 53 transfer.c -
uspace/drv/bus/usb/vhc/conndev.c
r5b18137 rb4b534ac 38 38 #include <ddf/driver.h> 39 39 #include <usbvirt/ipc.h> 40 #include <usb/debug.h> 40 41 #include <async.h> 41 #include "conn.h" 42 43 #include "vhcd.h" 42 44 43 45 static fibril_local uintptr_t plugged_device_handle = 0; … … 94 96 ipc_call_t *icall) 95 97 { 96 vhc_data_t *vhc = ddf_ dev_data_get(ddf_fun_get_dev(fun));98 vhc_data_t *vhc = ddf_fun_data_get(fun); 97 99 98 100 async_sess_t *callback = … … 125 127 void on_client_close(ddf_fun_t *fun) 126 128 { 127 vhc_data_t *vhc = ddf_ dev_data_get(ddf_fun_get_dev(fun));129 vhc_data_t *vhc = ddf_fun_data_get(fun); 128 130 129 131 if (plugged_device_handle != 0) { -
uspace/drv/bus/usb/vhc/devconn.c
r5b18137 rb4b534ac 51 51 static int vhc_virtdev_plug_generic(vhc_data_t *vhc, 52 52 async_sess_t *sess, usbvirt_device_t *virtdev, 53 uintptr_t *handle, bool connect )53 uintptr_t *handle, bool connect, usb_address_t address) 54 54 { 55 55 vhc_virtdev_t *dev = vhc_virtdev_create(); … … 60 60 dev->dev_sess = sess; 61 61 dev->dev_local = virtdev; 62 dev->address = address; 62 63 63 64 fibril_mutex_lock(&vhc->guard); … … 78 79 if (connect) { 79 80 // FIXME: check status 80 (void) virthub_connect_device( vhc->hub, dev);81 (void) virthub_connect_device(&vhc->hub, dev); 81 82 } 82 83 … … 86 87 int vhc_virtdev_plug(vhc_data_t *vhc, async_sess_t *sess, uintptr_t *handle) 87 88 { 88 return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true );89 return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true, 0); 89 90 } 90 91 91 92 int vhc_virtdev_plug_local(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle) 92 93 { 93 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true );94 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true, 0); 94 95 } 95 96 96 int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle )97 int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle, usb_address_t address) 97 98 { 98 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false );99 return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false, address); 99 100 } 100 101 … … 104 105 105 106 // FIXME: check status 106 (void) virthub_disconnect_device( vhc->hub, dev);107 (void) virthub_disconnect_device(&vhc->hub, dev); 107 108 108 109 fibril_mutex_lock(&vhc->guard); -
uspace/drv/bus/usb/vhc/hub/virthub.c
r5b18137 rb4b534ac 34 34 */ 35 35 #include <usb/classes/classes.h> 36 #include <usb/classes/hub.h> 36 37 #include <usbvirt/device.h> 37 38 #include <assert.h> 38 39 #include <errno.h> 39 40 #include <str_error.h> 41 #include <stdio.h> 40 42 #include <stdlib.h> 41 43 #include <ddf/driver.h> … … 75 77 .type = USB_DESCTYPE_HUB, 76 78 .port_count = HUB_PORT_COUNT, 77 .characteristics = 0,79 .characteristics = HUB_CHAR_NO_POWER_SWITCH_FLAG | HUB_CHAR_NO_OC_FLAG, 78 80 .power_on_warm_up = 50, /* Huh? */ 79 81 .max_current = 100, /* Huh again. */ … … 96 98 .length = sizeof(usb_standard_configuration_descriptor_t), 97 99 .descriptor_type = USB_DESCTYPE_CONFIGURATION, 98 .total_length = 100 .total_length = 99 101 sizeof(usb_standard_configuration_descriptor_t) 100 102 + sizeof(std_interface_descriptor) … … 144 146 * @return Error code. 145 147 */ 146 int virthub_init(usbvirt_device_t *dev )148 int virthub_init(usbvirt_device_t *dev, const char* name) 147 149 { 148 150 if (dev == NULL) { … … 151 153 dev->ops = &hub_ops; 152 154 dev->descriptors = &descriptors; 155 dev->address = 0; 156 dev->name = str_dup(name); 157 if (!dev->name) 158 return ENOMEM; 153 159 154 160 hub_t *hub = malloc(sizeof(hub_t)); 155 161 if (hub == NULL) { 162 free(dev->name); 156 163 return ENOMEM; 157 164 } -
uspace/drv/bus/usb/vhc/hub/virthub.h
r5b18137 rb4b534ac 79 79 extern hub_descriptor_t hub_descriptor; 80 80 81 int virthub_init(usbvirt_device_t * );81 int virthub_init(usbvirt_device_t *, const char *name); 82 82 int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *); 83 83 int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *); -
uspace/drv/bus/usb/vhc/hub/virthubops.c
r5b18137 rb4b534ac 340 340 341 341 342 /** IN class request. */343 #define CLASS_REQ_IN(recipient) \344 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \345 USBVIRT_REQUEST_TYPE_CLASS, recipient)346 /** OUT class request. */347 #define CLASS_REQ_OUT(recipient) \348 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \349 USBVIRT_REQUEST_TYPE_CLASS, recipient)350 342 351 343 /** Recipient: other. */ … … 353 345 /** Recipient: device. */ 354 346 #define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE 355 /** Direction: in. */ 356 #define DIR_IN USB_DIRECTION_IN 357 /** Direction: out. */ 358 #define DIR_OUT USB_DIRECTION_OUT 359 360 361 /** Create a class request. 362 * 363 * @param direction Request direction. 364 * @param recipient Request recipient. 365 * @param req Request code. 366 */ 367 #define CLASS_REQ(direction, recipient, req) \ 368 .req_direction = direction, \ 369 .req_recipient = recipient, \ 370 .req_type = USB_REQUEST_TYPE_CLASS, \ 371 .request = req 372 373 /** Create a standard request. 374 * 375 * @param direction Request direction. 376 * @param recipient Request recipient. 377 * @param req Request code. 378 */ 379 #define STD_REQ(direction, recipient, req) \ 380 .req_direction = direction, \ 381 .req_recipient = recipient, \ 382 .req_type = USB_REQUEST_TYPE_STANDARD, \ 383 .request = req 347 384 348 385 349 /** Hub operations on control endpoint zero. */ 386 350 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = { 387 351 { 388 STD_REQ (DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),389 .name = "Get Descriptor",352 STD_REQ_IN(USB_REQUEST_RECIPIENT_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), 353 .name = "GetStdDescriptor", 390 354 .callback = req_get_descriptor 391 355 }, 392 356 { 393 CLASS_REQ (DIR_IN,REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),394 .name = "Get Descriptor",357 CLASS_REQ_IN(REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR), 358 .name = "GetClassDescriptor", 395 359 .callback = req_get_descriptor 396 360 }, 397 361 { 398 CLASS_REQ (DIR_IN,REC_OTHER, USB_HUB_REQUEST_GET_STATUS),362 CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATUS), 399 363 .name = "GetPortStatus", 400 364 .callback = req_get_port_status 401 365 }, 402 366 { 403 CLASS_REQ (DIR_OUT,REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),367 CLASS_REQ_OUT(REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE), 404 368 .name = "ClearHubFeature", 405 369 .callback = req_clear_hub_feature 406 370 }, 407 371 { 408 CLASS_REQ (DIR_OUT,REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),372 CLASS_REQ_OUT(REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE), 409 373 .name = "ClearPortFeature", 410 374 .callback = req_clear_port_feature 411 375 }, 412 376 { 413 CLASS_REQ (DIR_IN,REC_OTHER, USB_HUB_REQUEST_GET_STATE),377 CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATE), 414 378 .name = "GetBusState", 415 379 .callback = req_get_bus_state 416 380 }, 417 381 { 418 CLASS_REQ (DIR_IN,REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),382 CLASS_REQ_IN(REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR), 419 383 .name = "GetHubDescriptor", 420 384 .callback = req_get_descriptor 421 385 }, 422 386 { 423 CLASS_REQ (DIR_IN,REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),387 CLASS_REQ_IN(REC_DEVICE, USB_HUB_REQUEST_GET_STATUS), 424 388 .name = "GetHubStatus", 425 389 .callback = req_get_hub_status 426 390 }, 427 391 { 428 CLASS_REQ (DIR_IN,REC_OTHER, USB_HUB_REQUEST_GET_STATUS),392 CLASS_REQ_IN(REC_OTHER, USB_HUB_REQUEST_GET_STATUS), 429 393 .name = "GetPortStatus", 430 394 .callback = req_get_port_status 431 395 }, 432 396 { 433 CLASS_REQ (DIR_OUT,REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),397 CLASS_REQ_OUT(REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE), 434 398 .name = "SetHubFeature", 435 399 .callback = req_set_hub_feature 436 400 }, 437 401 { 438 CLASS_REQ (DIR_OUT,REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),402 CLASS_REQ_OUT(REC_OTHER, USB_HUB_REQUEST_SET_FEATURE), 439 403 .name = "SetPortFeature", 440 404 .callback = req_set_port_feature -
uspace/drv/bus/usb/vhc/main.c
r5b18137 rb4b534ac 34 34 */ 35 35 36 #include <loc.h>37 #include <async.h>38 #include <unistd.h>39 #include <stdlib.h>40 #include <sysinfo.h>41 36 #include <stdio.h> 42 37 #include <errno.h> … … 44 39 #include <ddf/driver.h> 45 40 46 #include <usb/ usb.h>47 #include <usb/ddfiface.h> 48 #include <usb _iface.h>41 #include <usb/host/ddf_helpers.h> 42 43 #include <usb/debug.h> 49 44 #include "vhcd.h" 50 #include "hub.h" 51 #include "conn.h" 45 52 46 53 47 static ddf_dev_ops_t vhc_ops = { 54 .interfaces[USBHC_DEV_IFACE] = &vhc_iface,55 .interfaces[USB_DEV_IFACE] = &vhc_usb_iface,56 48 .close = on_client_close, 57 49 .default_handler = default_connection_handler 58 50 }; 59 51 52 static int vhc_control_node(ddf_dev_t *dev, ddf_fun_t **fun) 53 { 54 assert(dev); 55 assert(fun); 56 57 *fun = ddf_fun_create(dev, fun_exposed, "virtual"); 58 if (!*fun) 59 return ENOMEM; 60 61 vhc_data_t *vhc = ddf_fun_data_alloc(*fun, sizeof(vhc_data_t)); 62 if (!vhc) { 63 ddf_fun_destroy(*fun); 64 } 65 ddf_fun_set_ops(*fun, &vhc_ops); 66 const int ret = ddf_fun_bind(*fun); 67 if (ret != EOK) { 68 ddf_fun_destroy(*fun); 69 *fun = NULL; 70 return ret; 71 } 72 vhc_init(vhc); 73 return EOK; 74 } 75 76 hcd_ops_t vhc_hc_ops = { 77 .schedule = vhc_schedule, 78 }; 79 60 80 static int vhc_dev_add(ddf_dev_t *dev) 61 81 { 62 static int vhc_count = 0; 63 int rc; 82 /* Initialize virtual structure */ 83 ddf_fun_t *ctl_fun = NULL; 84 int ret = vhc_control_node(dev, &ctl_fun); 85 if (ret != EOK) { 86 usb_log_error("Failed to setup control node.\n"); 87 return ret; 88 } 89 vhc_data_t *data = ddf_fun_data_get(ctl_fun); 64 90 65 if (vhc_count > 0) { 66 return ELIMIT; 91 /* Initialize generic structures */ 92 ret = hcd_ddf_setup_hc(dev, USB_SPEED_FULL, 93 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 94 if (ret != EOK) { 95 usb_log_error("Failed to init HCD structures: %s.\n", 96 str_error(ret)); 97 ddf_fun_destroy(ctl_fun); 98 return ret; 67 99 } 68 100 69 vhc_data_t *data = ddf_dev_data_alloc(dev, sizeof(vhc_data_t)); 70 if (data == NULL) { 71 usb_log_fatal("Failed to allocate memory.\n"); 72 return ENOMEM; 73 } 74 data->magic = 0xDEADBEEF; 75 rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1, 76 bandwidth_count_usb11); 77 if (rc != EOK) { 78 usb_log_fatal("Failed to initialize endpoint manager.\n"); 79 free(data); 80 return rc; 81 } 82 usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX); 101 hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops); 83 102 84 ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc"); 85 if (hc == NULL) { 86 usb_log_fatal("Failed to create device function.\n"); 87 free(data); 88 return ENOMEM; 103 /* Add virtual hub device */ 104 ret = vhc_virtdev_plug_hub(data, &data->hub, NULL, 0); 105 if (ret != EOK) { 106 usb_log_error("Failed to plug root hub: %s.\n", str_error(ret)); 107 ddf_fun_destroy(ctl_fun); 108 return ret; 89 109 } 90 110 91 ddf_fun_set_ops(hc, &vhc_ops); 92 list_initialize(&data->devices); 93 fibril_mutex_initialize(&data->guard); 94 data->hub = &virtual_hub_device; 95 data->hc_fun = hc; 96 97 rc = ddf_fun_bind(hc); 98 if (rc != EOK) { 99 usb_log_fatal("Failed to bind HC function: %s.\n", 100 str_error(rc)); 101 free(data); 102 return rc; 111 /* 112 * Creating root hub registers a new USB device so HC 113 * needs to be ready at this time. 114 */ 115 ret = hcd_ddf_setup_root_hub(dev); 116 if (ret != EOK) { 117 usb_log_error("Failed to init VHC root hub: %s\n", 118 str_error(ret)); 119 // TODO do something here... 103 120 } 104 121 105 rc = ddf_fun_add_to_category(hc, USB_HC_CATEGORY); 106 if (rc != EOK) { 107 usb_log_fatal("Failed to add function to HC class: %s.\n", 108 str_error(rc)); 109 free(data); 110 return rc; 111 } 112 113 virtual_hub_device_init(hc); 114 115 usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n", 116 (size_t) ddf_dev_get_handle(dev), (size_t) ddf_fun_get_handle(hc)); 117 118 rc = vhc_virtdev_plug_hub(data, data->hub, NULL); 119 if (rc != EOK) { 120 usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc)); 121 free(data); 122 return rc; 123 } 124 125 return EOK; 122 return ret; 126 123 } 127 124 … … 135 132 }; 136 133 137 138 134 int main(int argc, char * argv[]) 139 { 135 { 140 136 log_init(NAME); 141 142 137 printf(NAME ": virtual USB host controller driver.\n"); 143 138 … … 145 140 } 146 141 147 148 142 /** 149 143 * @} -
uspace/drv/bus/usb/vhc/transfer.c
r5b18137 rb4b534ac 29 29 #include <errno.h> 30 30 #include <str_error.h> 31 #include <usb/debug.h> 31 32 #include <usbvirt/device.h> 32 33 #include <usbvirt/ipc.h> 33 34 #include "vhcd.h" 34 35 vhc_transfer_t *vhc_transfer_create(usb_address_t address, usb_endpoint_t ep, 36 usb_direction_t dir, usb_transfer_type_t tr_type, 37 ddf_fun_t *fun, void *callback_arg) 38 { 39 vhc_transfer_t *result = malloc(sizeof(vhc_transfer_t)); 40 if (result == NULL) { 41 return NULL; 42 } 43 link_initialize(&result->link); 44 result->address = address; 45 result->endpoint = ep; 46 result->direction = dir; 47 result->transfer_type = tr_type; 48 result->setup_buffer = NULL; 49 result->setup_buffer_size = 0; 50 result->data_buffer = NULL; 51 result->data_buffer_size = 0; 52 result->ddf_fun = fun; 53 result->callback_arg = callback_arg; 54 result->callback_in = NULL; 55 result->callback_out = NULL; 56 57 usb_log_debug2("Created transfer %p (%d.%d %s %s)\n", result, 58 address, ep, usb_str_transfer_type_short(tr_type), 59 dir == USB_DIRECTION_IN ? "in" : "out"); 60 61 return result; 62 } 35 #include "hub/virthub.h" 63 36 64 37 static bool is_set_address_transfer(vhc_transfer_t *transfer) 65 38 { 66 if (transfer->endpoint != 0) { 67 return false; 68 } 69 if (transfer->transfer_type != USB_TRANSFER_CONTROL) { 70 return false; 71 } 72 if (transfer->direction != USB_DIRECTION_OUT) { 73 return false; 74 } 75 if (transfer->setup_buffer_size != sizeof(usb_device_request_setup_packet_t)) { 76 return false; 77 } 78 usb_device_request_setup_packet_t *setup = transfer->setup_buffer; 39 if (transfer->batch->ep->endpoint != 0) { 40 return false; 41 } 42 if (transfer->batch->ep->transfer_type != USB_TRANSFER_CONTROL) { 43 return false; 44 } 45 if (usb_transfer_batch_direction(transfer->batch) != USB_DIRECTION_OUT) { 46 return false; 47 } 48 const usb_device_request_setup_packet_t *setup = 49 (void*)transfer->batch->setup_buffer; 79 50 if (setup->request_type != 0) { 80 51 return false; … … 87 58 } 88 59 89 int vhc_virtdev_add_transfer(vhc_data_t *vhc, vhc_transfer_t *transfer) 90 { 91 fibril_mutex_lock(&vhc->guard); 92 93 bool target_found = false; 94 list_foreach(vhc->devices, link, vhc_virtdev_t, dev) { 95 fibril_mutex_lock(&dev->guard); 96 if (dev->address == transfer->address) { 97 if (target_found) { 98 usb_log_warning("Transfer would be accepted by more devices!\n"); 99 goto next; 100 } 101 target_found = true; 102 list_append(&transfer->link, &dev->transfer_queue); 103 } 104 next: 105 fibril_mutex_unlock(&dev->guard); 106 } 107 108 fibril_mutex_unlock(&vhc->guard); 109 110 if (target_found) { 111 return EOK; 60 static int process_transfer_local(usb_transfer_batch_t *batch, 61 usbvirt_device_t *dev, size_t *actual_data_size) 62 { 63 int rc; 64 65 const usb_direction_t dir = usb_transfer_batch_direction(batch); 66 67 if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 68 if (dir == USB_DIRECTION_IN) { 69 rc = usbvirt_control_read(dev, 70 batch->setup_buffer, batch->setup_size, 71 batch->buffer, batch->buffer_size, 72 actual_data_size); 73 } else { 74 assert(dir == USB_DIRECTION_OUT); 75 rc = usbvirt_control_write(dev, 76 batch->setup_buffer, batch->setup_size, 77 batch->buffer, batch->buffer_size); 78 } 112 79 } else { 113 return ENOENT; 114 } 115 } 116 117 static int process_transfer_local(vhc_transfer_t *transfer, 118 usbvirt_device_t *dev, size_t *actual_data_size) 80 if (dir == USB_DIRECTION_IN) { 81 rc = usbvirt_data_in(dev, batch->ep->transfer_type, 82 batch->ep->endpoint, 83 batch->buffer, batch->buffer_size, 84 actual_data_size); 85 } else { 86 assert(dir == USB_DIRECTION_OUT); 87 rc = usbvirt_data_out(dev, batch->ep->transfer_type, 88 batch->ep->endpoint, 89 batch->buffer, batch->buffer_size); 90 } 91 } 92 93 return rc; 94 } 95 96 static int process_transfer_remote(usb_transfer_batch_t *batch, 97 async_sess_t *sess, size_t *actual_data_size) 119 98 { 120 99 int rc; 121 100 122 if (transfer->transfer_type == USB_TRANSFER_CONTROL) { 123 if (transfer->direction == USB_DIRECTION_IN) { 124 rc = usbvirt_control_read(dev, 125 transfer->setup_buffer, transfer->setup_buffer_size, 126 transfer->data_buffer, transfer->data_buffer_size, 127 actual_data_size); 128 } else { 129 assert(transfer->direction == USB_DIRECTION_OUT); 130 rc = usbvirt_control_write(dev, 131 transfer->setup_buffer, transfer->setup_buffer_size, 132 transfer->data_buffer, transfer->data_buffer_size); 101 const usb_direction_t dir = usb_transfer_batch_direction(batch); 102 103 if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 104 if (dir == USB_DIRECTION_IN) { 105 rc = usbvirt_ipc_send_control_read(sess, 106 batch->setup_buffer, batch->setup_size, 107 batch->buffer, batch->buffer_size, 108 actual_data_size); 109 } else { 110 assert(dir == USB_DIRECTION_OUT); 111 rc = usbvirt_ipc_send_control_write(sess, 112 batch->setup_buffer, batch->setup_size, 113 batch->buffer, batch->buffer_size); 133 114 } 134 115 } else { 135 if (transfer->direction == USB_DIRECTION_IN) { 136 rc = usbvirt_data_in(dev, transfer->transfer_type, 137 transfer->endpoint, 138 transfer->data_buffer, transfer->data_buffer_size, 139 actual_data_size); 140 } else { 141 assert(transfer->direction == USB_DIRECTION_OUT); 142 rc = usbvirt_data_out(dev, transfer->transfer_type, 143 transfer->endpoint, 144 transfer->data_buffer, transfer->data_buffer_size); 145 } 146 } 147 148 return rc; 149 } 150 151 static int process_transfer_remote(vhc_transfer_t *transfer, 152 async_sess_t *sess, size_t *actual_data_size) 153 { 154 int rc; 155 156 if (transfer->transfer_type == USB_TRANSFER_CONTROL) { 157 if (transfer->direction == USB_DIRECTION_IN) { 158 rc = usbvirt_ipc_send_control_read(sess, 159 transfer->setup_buffer, transfer->setup_buffer_size, 160 transfer->data_buffer, transfer->data_buffer_size, 161 actual_data_size); 162 } else { 163 assert(transfer->direction == USB_DIRECTION_OUT); 164 rc = usbvirt_ipc_send_control_write(sess, 165 transfer->setup_buffer, transfer->setup_buffer_size, 166 transfer->data_buffer, transfer->data_buffer_size); 167 } 168 } else { 169 if (transfer->direction == USB_DIRECTION_IN) { 170 rc = usbvirt_ipc_send_data_in(sess, transfer->endpoint, 171 transfer->transfer_type, 172 transfer->data_buffer, transfer->data_buffer_size, 173 actual_data_size); 174 } else { 175 assert(transfer->direction == USB_DIRECTION_OUT); 176 rc = usbvirt_ipc_send_data_out(sess, transfer->endpoint, 177 transfer->transfer_type, 178 transfer->data_buffer, transfer->data_buffer_size); 116 if (dir == USB_DIRECTION_IN) { 117 rc = usbvirt_ipc_send_data_in(sess, batch->ep->endpoint, 118 batch->ep->transfer_type, 119 batch->buffer, batch->buffer_size, 120 actual_data_size); 121 } else { 122 assert(dir == USB_DIRECTION_OUT); 123 rc = usbvirt_ipc_send_data_out(sess, batch->ep->endpoint, 124 batch->ep->transfer_type, 125 batch->buffer, batch->buffer_size); 179 126 } 180 127 } … … 195 142 } 196 143 197 198 144 static void execute_transfer_callback_and_free(vhc_transfer_t *transfer, 199 145 size_t data_transfer_size, int outcome) 200 146 { 201 147 assert(outcome != ENAK); 202 203 usb_log_debug2("Transfer %p ended: %s.\n", 204 transfer, str_error(outcome)); 205 206 if (transfer->direction == USB_DIRECTION_IN) { 207 transfer->callback_in(transfer->ddf_fun, outcome, 208 data_transfer_size, transfer->callback_arg); 209 } else { 210 assert(transfer->direction == USB_DIRECTION_OUT); 211 transfer->callback_out(transfer->ddf_fun, outcome, 212 transfer->callback_arg); 213 } 214 148 assert(transfer); 149 assert(transfer->batch); 150 usb_transfer_batch_finish_error(transfer->batch, NULL, 151 data_transfer_size, outcome); 152 usb_transfer_batch_destroy(transfer->batch); 215 153 free(transfer); 154 } 155 156 int vhc_init(vhc_data_t *instance) 157 { 158 assert(instance); 159 list_initialize(&instance->devices); 160 fibril_mutex_initialize(&instance->guard); 161 instance->magic = 0xDEADBEEF; 162 return virthub_init(&instance->hub, "root hub"); 163 } 164 165 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 166 { 167 assert(hcd); 168 assert(batch); 169 vhc_data_t *vhc = hcd_get_driver_data(hcd); 170 assert(vhc); 171 172 vhc_transfer_t *transfer = malloc(sizeof(vhc_transfer_t)); 173 if (!transfer) 174 return ENOMEM; 175 link_initialize(&transfer->link); 176 transfer->batch = batch; 177 178 fibril_mutex_lock(&vhc->guard); 179 180 int targets = 0; 181 182 list_foreach(vhc->devices, link, vhc_virtdev_t, dev) { 183 fibril_mutex_lock(&dev->guard); 184 if (dev->address == transfer->batch->ep->address) { 185 if (!targets) { 186 list_append(&transfer->link, &dev->transfer_queue); 187 } 188 ++targets; 189 } 190 fibril_mutex_unlock(&dev->guard); 191 } 192 193 fibril_mutex_unlock(&vhc->guard); 194 195 if (targets > 1) 196 usb_log_warning("Transfer would be accepted by more devices!\n"); 197 198 return targets ? EOK : ENOENT; 216 199 } 217 200 … … 234 217 size_t data_transfer_size = 0; 235 218 if (dev->dev_sess) { 236 rc = process_transfer_remote(transfer , dev->dev_sess,237 &data_transfer_size);219 rc = process_transfer_remote(transfer->batch, 220 dev->dev_sess, &data_transfer_size); 238 221 } else if (dev->dev_local != NULL) { 239 rc = process_transfer_local(transfer , dev->dev_local,240 &data_transfer_size);222 rc = process_transfer_local(transfer->batch, 223 dev->dev_local, &data_transfer_size); 241 224 } else { 242 225 usb_log_warning("Device has no remote phone nor local node.\n"); … … 251 234 if (is_set_address_transfer(transfer)) { 252 235 usb_device_request_setup_packet_t *setup 253 = transfer->setup_buffer;236 = (void*)transfer->batch->setup_buffer; 254 237 dev->address = setup->value; 255 238 usb_log_debug2("Address changed to %d\n", … … 284 267 return EOK; 285 268 } 286 -
uspace/drv/bus/usb/vhc/vhcd.h
r5b18137 rb4b534ac 36 36 #define VHCD_VHCD_H_ 37 37 38 #include <usb/debug.h>39 38 #include <usbvirt/device.h> 40 #include <usb/host/usb_endpoint_manager.h>41 #include <usb/host/usb_device_manager.h>42 39 #include <usbhc_iface.h> 43 40 #include <async.h> 41 42 #include <usb/host/hcd.h> 43 44 44 45 45 #define NAME "vhc" … … 59 59 list_t devices; 60 60 fibril_mutex_t guard; 61 usb_endpoint_manager_t ep_manager; 62 usb_device_manager_t dev_manager; 63 usbvirt_device_t *hub; 64 ddf_fun_t *hc_fun; 61 usbvirt_device_t hub; 65 62 } vhc_data_t; 66 63 67 64 typedef struct { 68 65 link_t link; 69 usb_address_t address; 70 usb_endpoint_t endpoint; 71 usb_direction_t direction; 72 usb_transfer_type_t transfer_type; 73 void *setup_buffer; 74 size_t setup_buffer_size; 75 void *data_buffer; 76 size_t data_buffer_size; 77 ddf_fun_t *ddf_fun; 78 void *callback_arg; 79 usbhc_iface_transfer_in_callback_t callback_in; 80 usbhc_iface_transfer_out_callback_t callback_out; 66 usb_transfer_batch_t *batch; 81 67 } vhc_transfer_t; 82 68 83 vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t, 84 usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *); 69 70 void on_client_close(ddf_fun_t *fun); 71 void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid, 72 ipc_call_t *icall); 73 85 74 int vhc_virtdev_plug(vhc_data_t *, async_sess_t *, uintptr_t *); 86 75 int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *); 87 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t * );76 int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *, usb_address_t address); 88 77 void vhc_virtdev_unplug(vhc_data_t *, uintptr_t); 89 int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);90 78 79 int vhc_init(vhc_data_t *instance); 80 int vhc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 91 81 int vhc_transfer_queue_processor(void *arg); 92 93 82 94 83 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
