Changeset 361e61b in mainline for uspace/drv
- Timestamp:
- 2011-03-21T14:23:15Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 55e388a1
- Parents:
- c32688d (diff), 48fe0c9 (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
- Files:
-
- 20 added
- 1 deleted
- 43 edited
- 4 moved
-
ehci-hcd/Makefile (modified) (1 diff)
-
ehci-hcd/ehci.h (added)
-
ehci-hcd/hc_iface.c (added)
-
ehci-hcd/main.c (modified) (6 diffs)
-
ehci-hcd/pci.c (modified) (3 diffs)
-
ohci/Makefile (moved) (moved from dist/Makefile ) (2 diffs)
-
ohci/batch.c (added)
-
ohci/batch.h (added)
-
ohci/hc.c (added)
-
ohci/hc.h (added)
-
ohci/iface.c (added)
-
ohci/iface.h (added)
-
ohci/main.c (added)
-
ohci/ohci.ma (added)
-
ohci/ohci_regs.h (added)
-
ohci/pci.c (added)
-
ohci/pci.h (added)
-
ohci/root_hub.c (moved) (moved from uspace/drv/uhci-rhd/port_status.c ) (1 diff)
-
ohci/root_hub.h (moved) (moved from uspace/drv/uhci-hcd/root_hub.h ) (2 diffs)
-
ohci/utils/malloc32.h (added)
-
pciintel/pci.c (modified) (1 diff)
-
uhci-hcd/Makefile (modified) (1 diff)
-
uhci-hcd/batch.c (modified) (22 diffs)
-
uhci-hcd/batch.h (modified) (3 diffs)
-
uhci-hcd/iface.c (modified) (19 diffs)
-
uhci-hcd/iface.h (modified) (2 diffs)
-
uhci-hcd/main.c (modified) (3 diffs)
-
uhci-hcd/pci.c (modified) (3 diffs)
-
uhci-hcd/pci.h (modified) (1 diff)
-
uhci-hcd/root_hub.c (deleted)
-
uhci-hcd/transfer_list.c (modified) (8 diffs)
-
uhci-hcd/transfer_list.h (modified) (3 diffs)
-
uhci-hcd/uhci.c (modified) (4 diffs)
-
uhci-hcd/uhci.h (modified) (2 diffs)
-
uhci-hcd/uhci_hc.c (added)
-
uhci-hcd/uhci_hc.h (added)
-
uhci-hcd/uhci_rh.c (added)
-
uhci-hcd/uhci_rh.h (moved) (moved from uspace/drv/uhci-rhd/port_status.h ) (3 diffs)
-
uhci-hcd/uhci_struct/link_pointer.h (modified) (2 diffs)
-
uhci-hcd/uhci_struct/queue_head.h (modified) (3 diffs)
-
uhci-hcd/uhci_struct/transfer_descriptor.c (modified) (6 diffs)
-
uhci-hcd/uhci_struct/transfer_descriptor.h (modified) (7 diffs)
-
uhci-hcd/utils/malloc32.h (modified) (2 diffs)
-
uhci-rhd/Makefile (modified) (1 diff)
-
uhci-rhd/main.c (modified) (6 diffs)
-
uhci-rhd/port.c (modified) (18 diffs)
-
uhci-rhd/port.h (modified) (3 diffs)
-
uhci-rhd/root_hub.c (modified) (3 diffs)
-
uhci-rhd/root_hub.h (modified) (3 diffs)
-
usbflbk/Makefile (added)
-
usbflbk/main.c (added)
-
usbflbk/usbflbk.ma (added)
-
usbhid/hiddev.c (modified) (2 diffs)
-
usbhid/hiddev.h (modified) (1 diff)
-
usbhid/kbddev.c (modified) (17 diffs)
-
usbhid/kbddev.h (modified) (2 diffs)
-
usbhid/kbdrepeat.c (modified) (1 diff)
-
usbhub/main.c (modified) (1 diff)
-
usbhub/port_status.h (modified) (1 diff)
-
usbhub/usbhub.c (modified) (25 diffs)
-
usbhub/usbhub.h (modified) (3 diffs)
-
usbhub/usbhub_private.h (modified) (4 diffs)
-
usbhub/utils.c (modified) (3 diffs)
-
usbmid/usbmid.c (modified) (1 diff)
-
usbmouse/init.c (modified) (5 diffs)
-
usbmouse/main.c (modified) (4 diffs)
-
usbmouse/mouse.c (modified) (1 diff)
-
usbmouse/mouse.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ehci-hcd/Makefile
rc32688d r361e61b 33 33 34 34 SOURCES = \ 35 hc_iface.c \ 35 36 main.c \ 36 37 pci.c -
uspace/drv/ehci-hcd/main.c
rc32688d r361e61b 27 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 28 */ 29 /** @addtogroup usbdrvehci29 /** @addtogroup drvusbehci 30 30 * @{ 31 31 */ … … 44 44 45 45 #include "pci.h" 46 47 #define NAME "ehci-hcd" 46 #include "ehci.h" 48 47 49 48 static int ehci_add_device(ddf_dev_t *device); … … 57 56 .driver_ops = &ehci_driver_ops 58 57 }; 58 static ddf_dev_ops_t hc_ops = { 59 .interfaces[USBHC_DEV_IFACE] = &ehci_hc_iface, 60 }; 61 59 62 /*----------------------------------------------------------------------------*/ 60 63 /** Initializes a new ddf driver instance of EHCI hcd. … … 71 74 return ret; \ 72 75 } 73 74 usb_log_info("uhci_add_device() called\n");75 76 76 77 uintptr_t mem_reg_base = 0; … … 89 90 "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret)); 90 91 92 ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ehci-hc"); 93 if (hc_fun == NULL) { 94 usb_log_error("Failed to create EHCI function.\n"); 95 return ENOMEM; 96 } 97 hc_fun->ops = &hc_ops; 98 ret = ddf_fun_bind(hc_fun); 99 100 CHECK_RET_RETURN(ret, 101 "Failed to bind EHCI function: %s.\n", 102 str_error(ret)); 103 104 usb_log_info("Controlling new EHCI device `%s' (handle %llu).\n", 105 device->name, device->handle); 106 91 107 return EOK; 92 108 #undef CHECK_RET_RETURN … … 103 119 int main(int argc, char *argv[]) 104 120 { 105 usb_log_enable(USB_LOG_LEVEL_ ERROR, NAME);121 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 106 122 return ddf_driver_main(&ehci_driver); 107 123 } -
uspace/drv/ehci-hcd/pci.c
rc32688d r361e61b 247 247 248 248 249 if ((value & USBLEGSUP_BIOS_CONTROL) != 0) {249 if ((value & USBLEGSUP_BIOS_CONTROL) == 0) { 250 250 usb_log_info("BIOS released control after %d usec.\n", wait); 251 251 } else { 252 252 /* BIOS failed to hand over control, this should not happen. */ 253 usb_log_warning( "BIOS failed to release control after "253 usb_log_warning( "BIOS failed to release control after " 254 254 "%d usecs, force it.\n", wait); 255 255 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), … … 258 258 CHECK_RET_HANGUP_RETURN(ret, 259 259 "Failed(%d) to force OS EHCI control.\n", ret); 260 /* TODO: This does not seem to work on my machine */261 260 } 262 261 … … 280 279 usb_log_debug2("USBLEGSUP: %x.\n", value); 281 280 282 /*283 * TURN OFF EHCI FOR NOW, REMOVE IF THE DRIVER IS IMPLEMENTED 284 */281 /* 282 * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT 283 */ 285 284 286 285 /* Get size of capability registers in memory space. */ -
uspace/drv/ohci/Makefile
rc32688d r361e61b 1 1 # 2 # Copyright (c) 2011 J iri Svoboda2 # Copyright (c) 2011 Jan Vesely 3 3 # All rights reserved. 4 4 # … … 27 27 # 28 28 29 -include ../version 30 -include ../Makefile.config 31 -include ../boot/arch/$(BARCH)/Makefile.inc 32 -include ../boot/Makefile.common 29 USPACE_PREFIX = ../.. 30 LIBS = $(LIBDRV_PREFIX)/libdrv.a $(LIBUSB_PREFIX)/libusb.a 31 EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include -I$(LIBUSB_PREFIX)/include -I. 32 BINARY = ohci 33 33 34 PROFILES = amd64 arm32/GXemul arm32/integratorcp arm32/gta02 ia32 \ 35 ia64/i460GX ia64/ski mips32/GXemul mips32/msim sparc64/niagara \ 36 sparc64/serengeti sparc64/ultra 34 SOURCES = \ 35 iface.c \ 36 batch.c \ 37 main.c \ 38 hc.c \ 39 root_hub.c \ 40 pci.c 37 41 38 ifdef POST_OUTPUT 39 IMGFILE = $(POST_OUTPUT) 40 else 41 IMGFILE = $(BOOT_OUTPUT) 42 endif 43 44 SUFFIX = $(suffix $(IMGFILE)) 45 DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX) 46 47 .PHONY: all clean dist distfile 48 49 all: distfile 50 distfile: $(DISTFILE) 51 52 $(DISTFILE): $(IMGFILE) 53 cp $< $@ 54 55 dist: 56 for profile in $(PROFILES); do \ 57 $(MAKE) -C .. clean ; \ 58 $(MAKE) -C .. PROFILE=$$profile distfile ; \ 59 done 60 61 clean: 62 rm -f $(DISTFILE) 42 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/ohci/root_hub.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbohci 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver32 * @brief OHCI driver 33 33 */ 34 34 #include <assert.h> 35 #include <stdio.h> 35 #include <errno.h> 36 #include <str_error.h> 36 37 37 38 #include <usb/debug.h> 38 39 39 #include " port_status.h"40 #include "root_hub.h" 40 41 41 struct flag_name 42 { 43 uint16_t flag; 44 const char *name; 45 }; 46 47 static const struct flag_name flags[] = 48 { 49 { STATUS_SUSPEND, "suspended" }, 50 { STATUS_IN_RESET, "in reset" }, 51 { STATUS_LOW_SPEED, "low speed device" }, 52 { STATUS_ALWAYS_ONE, "always 1 bit" }, 53 { STATUS_RESUME, "resume" }, 54 { STATUS_LINE_D_MINUS, "line D- value" }, 55 { STATUS_LINE_D_PLUS, "line D+ value" }, 56 { STATUS_ENABLED_CHANGED, "enabled changed" }, 57 { STATUS_ENABLED, "enabled" }, 58 { STATUS_CONNECTED_CHANGED, "connected changed" }, 59 { STATUS_CONNECTED, "connected" } 60 }; 61 62 /** Prints portr status in a human readable way. 63 * 64 * @param[in] value Port value to print. 42 /** Root hub initialization 65 43 * @return Error code. 66 44 */ 67 void print_port_status(port_status_t value)45 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) 68 46 { 69 unsigned i = 0; 70 for (;i < sizeof(flags)/sizeof(struct flag_name); ++i) { 71 usb_log_debug2("\t%s status: %s.\n", flags[i].name, 72 ((value & flags[i].flag) != 0) ? "YES" : "NO"); 47 assert(instance); 48 instance->address = -1; 49 instance->registers = regs; 50 instance->device = dev; 51 52 usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff); 53 54 /* TODO: implement */ 55 return EOK; 56 } 57 /*----------------------------------------------------------------------------*/ 58 int rh_request(rh_t *instance, batch_t *request) 59 { 60 assert(instance); 61 assert(request); 62 /* TODO: implement */ 63 if (request->setup_buffer) { 64 usb_log_info("Root hub got SETUP packet: %s.\n", 65 usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8)); 73 66 } 67 usb_log_error("Root hub request processing not implemented.\n"); 68 batch_finish(request, ENOTSUP); 69 return EOK; 70 } 71 /*----------------------------------------------------------------------------*/ 72 void rh_interrupt(rh_t *instance) 73 { 74 usb_log_error("Root hub interrupt not implemented.\n"); 75 /* TODO: implement */ 74 76 } 75 77 /** -
uspace/drv/ohci/root_hub.h
rc32688d r361e61b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup drvusb uhci29 /** @addtogroup drvusbohci 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief UHCI driver33 * @brief OHCI driver 34 34 */ 35 #ifndef DRV_ UHCI_ROOT_HUB_H36 #define DRV_ UHCI_ROOT_HUB_H35 #ifndef DRV_OHCI_ROOT_HUB_H 36 #define DRV_OHCI_ROOT_HUB_H 37 37 38 #include < ddf/driver.h>38 #include <usb/usb.h> 39 39 40 int setup_root_hub(ddf_fun_t **device, ddf_dev_t *hc); 40 #include "ohci_regs.h" 41 #include "batch.h" 41 42 43 typedef struct rh { 44 ohci_regs_t *registers; 45 usb_address_t address; 46 ddf_dev_t *device; 47 } rh_t; 48 49 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs); 50 51 int rh_request(rh_t *instance, batch_t *request); 52 53 void rh_interrupt(rh_t *instance); 42 54 #endif 43 55 /** -
uspace/drv/pciintel/pci.c
rc32688d r361e61b 92 92 pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data; 93 93 94 sysarg_t apic;95 sysarg_t i8259;94 sysarg_t apic; 95 sysarg_t i8259; 96 96 97 97 int irc_phone = -1; 98 int irc_service = 0;99 100 if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {101 irc_service = SERVICE_APIC;98 int irc_service = -1; 99 100 if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) { 101 irc_service = SERVICE_APIC; 102 102 } else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) { 103 irc_service = SERVICE_I8259;104 } 105 106 if (irc_service == 0) 103 irc_service = SERVICE_I8259; 104 } 105 106 if (irc_service == -1) { 107 107 return false; 108 } 108 109 109 110 irc_phone = service_connect_blocking(irc_service, 0, 0); 110 if (irc_phone < 0) 111 if (irc_phone < 0) { 111 112 return false; 113 } 112 114 113 115 size_t i; 114 for (i = 0; i < dev_data->hw_resources.count; i++) {116 for (i = 0; i < dev_data->hw_resources.count; i++) { 115 117 if (dev_data->hw_resources.resources[i].type == INTERRUPT) { 116 118 int irq = dev_data->hw_resources.resources[i].res.interrupt.irq; -
uspace/drv/uhci-hcd/Makefile
rc32688d r361e61b 35 35 iface.c \ 36 36 main.c \ 37 root_hub.c \38 37 transfer_list.c \ 39 38 uhci.c \ 39 uhci_hc.c \ 40 uhci_rh.c \ 40 41 uhci_struct/transfer_descriptor.c \ 41 utils/device_keeper.c \42 42 pci.c \ 43 43 batch.c -
uspace/drv/uhci-hcd/batch.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver USB transaction structure 33 33 */ 34 34 #include <errno.h> … … 40 40 #include "batch.h" 41 41 #include "transfer_list.h" 42 #include "uhci .h"42 #include "uhci_hc.h" 43 43 #include "utils/malloc32.h" 44 #include "uhci_struct/transfer_descriptor.h" 44 45 45 46 #define DEFAULT_ERROR_COUNT 3 46 47 47 static int batch_schedule(batch_t *instance); 48 typedef struct uhci_batch { 49 qh_t *qh; 50 td_t *tds; 51 size_t packets; 52 device_keeper_t *manager; 53 } uhci_batch_t; 48 54 49 55 static void batch_control(batch_t *instance, 50 56 usb_packet_id data_stage, usb_packet_id status_stage); 51 57 static void batch_data(batch_t *instance, usb_packet_id pid); 52 static void batch_call_in(batch_t *instance);53 static void batch_call_out(batch_t *instance);54 58 static void batch_call_in_and_dispose(batch_t *instance); 55 59 static void batch_call_out_and_dispose(batch_t *instance); 56 static void batch_dispose(batch_t *instance); 57 58 59 /** Allocates memory and initializes internal data structures. 60 61 62 /** Allocate memory and initialize internal data structure. 60 63 * 61 64 * @param[in] fun DDF function to pass to callback. … … 72 75 * @param[in] arg additional parameter to func_in or func_out 73 76 * @param[in] manager Pointer to toggle management structure. 74 * @return False, if there is an active TD, true otherwise. 77 * @return Valid pointer if all substructures were successfully created, 78 * NULL otherwise. 79 * 80 * Determines the number of needed packets (TDs). Prepares a transport buffer 81 * (that is accessible by the hardware). Initializes parameters needed for the 82 * transaction and callback. 75 83 */ 76 84 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 77 85 usb_transfer_type_t transfer_type, size_t max_packet_size, 78 usb_speed_t speed, char *buffer, size_t size,86 usb_speed_t speed, char *buffer, size_t buffer_size, 79 87 char* setup_buffer, size_t setup_size, 80 88 usbhc_iface_transfer_in_callback_t func_in, … … 98 106 CHECK_NULL_DISPOSE_RETURN(instance, 99 107 "Failed to allocate batch instance.\n"); 100 bzero(instance, sizeof(batch_t)); 101 102 instance->qh = malloc32(sizeof(queue_head_t)); 103 CHECK_NULL_DISPOSE_RETURN(instance->qh, 108 batch_init(instance, target, transfer_type, speed, max_packet_size, 109 buffer, NULL, buffer_size, NULL, setup_size, func_in, 110 func_out, arg, fun, NULL); 111 112 113 uhci_batch_t *data = malloc(sizeof(uhci_batch_t)); 114 CHECK_NULL_DISPOSE_RETURN(instance, 115 "Failed to allocate batch instance.\n"); 116 bzero(data, sizeof(uhci_batch_t)); 117 data->manager = manager; 118 instance->private_data = data; 119 120 data->packets = (buffer_size + max_packet_size - 1) / max_packet_size; 121 if (transfer_type == USB_TRANSFER_CONTROL) { 122 data->packets += 2; 123 } 124 125 data->tds = malloc32(sizeof(td_t) * data->packets); 126 CHECK_NULL_DISPOSE_RETURN( 127 data->tds, "Failed to allocate transfer descriptors.\n"); 128 bzero(data->tds, sizeof(td_t) * data->packets); 129 130 data->qh = malloc32(sizeof(qh_t)); 131 CHECK_NULL_DISPOSE_RETURN(data->qh, 104 132 "Failed to allocate batch queue head.\n"); 105 queue_head_init(instance->qh); 106 107 instance->packets = (size + max_packet_size - 1) / max_packet_size; 108 if (transfer_type == USB_TRANSFER_CONTROL) { 109 instance->packets += 2; 110 } 111 112 instance->tds = malloc32(sizeof(td_t) * instance->packets); 113 CHECK_NULL_DISPOSE_RETURN( 114 instance->tds, "Failed to allocate transfer descriptors.\n"); 115 bzero(instance->tds, sizeof(td_t) * instance->packets); 116 117 // const size_t transport_size = max_packet_size * instance->packets; 118 119 if (size > 0) { 120 instance->transport_buffer = malloc32(size); 133 qh_init(data->qh); 134 qh_set_element_td(data->qh, addr_to_phys(data->tds)); 135 136 if (buffer_size > 0) { 137 instance->transport_buffer = malloc32(buffer_size); 121 138 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 122 139 "Failed to allocate device accessible buffer.\n"); … … 130 147 } 131 148 132 133 link_initialize(&instance->link);134 135 instance->max_packet_size = max_packet_size;136 instance->target = target;137 instance->transfer_type = transfer_type;138 instance->buffer = buffer;139 instance->buffer_size = size;140 instance->setup_size = setup_size;141 instance->fun = fun;142 instance->arg = arg;143 instance->speed = speed;144 instance->manager = manager;145 146 if (func_out)147 instance->callback_out = func_out;148 if (func_in)149 instance->callback_in = func_in;150 151 queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds));152 153 149 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 154 150 instance, target.address, target.endpoint); … … 156 152 } 157 153 /*----------------------------------------------------------------------------*/ 158 /** Check sbatch TDs for activity.154 /** Check batch TDs for activity. 159 155 * 160 156 * @param[in] instance Batch structure to use. 161 157 * @return False, if there is an active TD, true otherwise. 158 * 159 * Walk all TDs. Stop with false if there is an active one (it is to be 160 * processed). Stop with true if an error is found. Return true if the last TS 161 * is reached. 162 162 */ 163 163 bool batch_is_complete(batch_t *instance) 164 164 { 165 165 assert(instance); 166 uhci_batch_t *data = instance->private_data; 167 assert(data); 168 166 169 usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n", 167 instance, instance->packets);170 instance, data->packets); 168 171 instance->transfered_size = 0; 169 172 size_t i = 0; 170 for (;i < instance->packets; ++i) {171 if (td_is_active(& instance->tds[i])) {173 for (;i < data->packets; ++i) { 174 if (td_is_active(&data->tds[i])) { 172 175 return false; 173 176 } 174 177 175 instance->error = td_status(& instance->tds[i]);178 instance->error = td_status(&data->tds[i]); 176 179 if (instance->error != EOK) { 177 180 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 178 instance, i, instance->tds[i].status); 179 180 device_keeper_set_toggle(instance->manager, 181 instance->target, td_toggle(&instance->tds[i])); 181 instance, i, data->tds[i].status); 182 td_print_status(&data->tds[i]); 183 184 device_keeper_set_toggle(data->manager, 185 instance->target, instance->direction, 186 td_toggle(&data->tds[i])); 182 187 if (i > 0) 183 188 goto substract_ret; … … 185 190 } 186 191 187 instance->transfered_size += td_act_size(& instance->tds[i]);188 if (td_is_short(& instance->tds[i]))192 instance->transfered_size += td_act_size(&data->tds[i]); 193 if (td_is_short(&data->tds[i])) 189 194 goto substract_ret; 190 195 } … … 197 202 * 198 203 * @param[in] instance Batch structure to use. 204 * 205 * Uses genercir control function with pids OUT and IN. 199 206 */ 200 207 void batch_control_write(batch_t *instance) 201 208 { 202 209 assert(instance); 203 /* we are data out, we are supposed to provide data */210 /* We are data out, we are supposed to provide data */ 204 211 memcpy(instance->transport_buffer, instance->buffer, 205 212 instance->buffer_size); … … 207 214 instance->next_step = batch_call_out_and_dispose; 208 215 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 209 batch_schedule(instance);210 216 } 211 217 /*----------------------------------------------------------------------------*/ … … 213 219 * 214 220 * @param[in] instance Batch structure to use. 221 * 222 * Uses generic control with pids IN and OUT. 215 223 */ 216 224 void batch_control_read(batch_t *instance) … … 220 228 instance->next_step = batch_call_in_and_dispose; 221 229 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 222 batch_schedule(instance); 223 } 224 /*----------------------------------------------------------------------------*/ 225 /** Prepares interrupt in transaction. 226 * 227 * @param[in] instance Batch structure to use. 230 } 231 /*----------------------------------------------------------------------------*/ 232 /** Prepare interrupt in transaction. 233 * 234 * @param[in] instance Batch structure to use. 235 * 236 * Data transaction with PID_IN. 228 237 */ 229 238 void batch_interrupt_in(batch_t *instance) 230 239 { 231 240 assert(instance); 241 instance->direction = USB_DIRECTION_IN; 232 242 batch_data(instance, USB_PID_IN); 233 243 instance->next_step = batch_call_in_and_dispose; 234 244 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 235 batch_schedule(instance); 236 } 237 /*----------------------------------------------------------------------------*/ 238 /** Prepares interrupt out transaction. 239 * 240 * @param[in] instance Batch structure to use. 245 } 246 /*----------------------------------------------------------------------------*/ 247 /** Prepare interrupt out transaction. 248 * 249 * @param[in] instance Batch structure to use. 250 * 251 * Data transaction with PID_OUT. 241 252 */ 242 253 void batch_interrupt_out(batch_t *instance) 243 254 { 244 255 assert(instance); 245 /* we are data out, we are supposed to provide data */ 246 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 256 instance->direction = USB_DIRECTION_OUT; 257 /* We are data out, we are supposed to provide data */ 258 memcpy(instance->transport_buffer, instance->buffer, 259 instance->buffer_size); 247 260 batch_data(instance, USB_PID_OUT); 248 261 instance->next_step = batch_call_out_and_dispose; 249 262 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 250 batch_schedule(instance); 251 } 252 /*----------------------------------------------------------------------------*/ 253 /** Prepares bulk in transaction. 254 * 255 * @param[in] instance Batch structure to use. 263 } 264 /*----------------------------------------------------------------------------*/ 265 /** Prepare bulk in transaction. 266 * 267 * @param[in] instance Batch structure to use. 268 * 269 * Data transaction with PID_IN. 256 270 */ 257 271 void batch_bulk_in(batch_t *instance) … … 259 273 assert(instance); 260 274 batch_data(instance, USB_PID_IN); 275 instance->direction = USB_DIRECTION_IN; 261 276 instance->next_step = batch_call_in_and_dispose; 262 277 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 263 batch_schedule(instance); 264 } 265 /*----------------------------------------------------------------------------*/ 266 /** Prepares bulk out transaction. 267 * 268 * @param[in] instance Batch structure to use. 278 } 279 /*----------------------------------------------------------------------------*/ 280 /** Prepare bulk out transaction. 281 * 282 * @param[in] instance Batch structure to use. 283 * 284 * Data transaction with PID_OUT. 269 285 */ 270 286 void batch_bulk_out(batch_t *instance) 271 287 { 272 288 assert(instance); 273 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 289 instance->direction = USB_DIRECTION_OUT; 290 /* We are data out, we are supposed to provide data */ 291 memcpy(instance->transport_buffer, instance->buffer, 292 instance->buffer_size); 274 293 batch_data(instance, USB_PID_OUT); 275 294 instance->next_step = batch_call_out_and_dispose; 276 295 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 277 batch_schedule(instance); 278 } 279 /*----------------------------------------------------------------------------*/ 280 /** Prepares generic data transaction 296 } 297 /*----------------------------------------------------------------------------*/ 298 /** Prepare generic data transaction 281 299 * 282 300 * @param[in] instance Batch structure to use. 283 301 * @param[in] pid to use for data packets. 302 * 303 * Packets with alternating toggle bit and supplied pid value. 304 * The last packet is marked with IOC flag. 284 305 */ 285 306 void batch_data(batch_t *instance, usb_packet_id pid) 286 307 { 287 308 assert(instance); 309 uhci_batch_t *data = instance->private_data; 310 assert(data); 311 288 312 const bool low_speed = instance->speed == USB_SPEED_LOW; 289 int toggle = 290 d evice_keeper_get_toggle(instance->manager, instance->target);313 int toggle = device_keeper_get_toggle( 314 data->manager, instance->target, instance->direction); 291 315 assert(toggle == 0 || toggle == 1); 292 316 … … 294 318 size_t remain_size = instance->buffer_size; 295 319 while (remain_size > 0) { 296 char * data =320 char *trans_data = 297 321 instance->transport_buffer + instance->buffer_size 298 322 - remain_size; … … 302 326 remain_size : instance->max_packet_size; 303 327 304 td_t *next_packet = (packet + 1 < instance->packets)305 ? & instance->tds[packet + 1] : NULL;306 307 assert(packet < instance->packets);328 td_t *next_packet = (packet + 1 < data->packets) 329 ? &data->tds[packet + 1] : NULL; 330 331 assert(packet < data->packets); 308 332 assert(packet_size <= remain_size); 309 333 310 334 td_init( 311 & instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,312 toggle, false, low_speed, instance->target, pid, data,335 &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 336 toggle, false, low_speed, instance->target, pid, trans_data, 313 337 next_packet); 314 338 … … 318 342 ++packet; 319 343 } 320 device_keeper_set_toggle(instance->manager, instance->target, toggle); 321 } 322 /*----------------------------------------------------------------------------*/ 323 /** Prepares generic control transaction 344 td_set_ioc(&data->tds[packet - 1]); 345 device_keeper_set_toggle(data->manager, instance->target, 346 instance->direction, toggle); 347 } 348 /*----------------------------------------------------------------------------*/ 349 /** Prepare generic control transaction 324 350 * 325 351 * @param[in] instance Batch structure to use. 326 352 * @param[in] data_stage to use for data packets. 327 353 * @param[in] status_stage to use for data packets. 354 * 355 * Setup stage with toggle 0 and USB_PID_SETUP. 356 * Data stage with alternating toggle and pid supplied by parameter. 357 * Status stage with toggle 1 and pid supplied by parameter. 358 * The last packet is marked with IOC. 328 359 */ 329 360 void batch_control(batch_t *instance, … … 331 362 { 332 363 assert(instance); 364 uhci_batch_t *data = instance->private_data; 365 assert(data); 366 assert(data->packets >= 2); 333 367 334 368 const bool low_speed = instance->speed == USB_SPEED_LOW; 335 369 int toggle = 0; 336 370 /* setup stage */ 337 td_init(instance->tds, DEFAULT_ERROR_COUNT, 338 instance->setup_size, toggle, false, low_speed, instance->target, 339 USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]); 371 td_init( 372 data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false, 373 low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer, 374 &data->tds[1]); 340 375 341 376 /* data stage */ … … 343 378 size_t remain_size = instance->buffer_size; 344 379 while (remain_size > 0) { 345 char * data =380 char *control_data = 346 381 instance->transport_buffer + instance->buffer_size 347 382 - remain_size; … … 354 389 355 390 td_init( 356 & instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,391 &data->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 357 392 toggle, false, low_speed, instance->target, data_stage, 358 data, &instance->tds[packet + 1]);393 control_data, &data->tds[packet + 1]); 359 394 360 395 ++packet; 361 assert(packet < instance->packets);396 assert(packet < data->packets); 362 397 assert(packet_size <= remain_size); 363 398 remain_size -= packet_size; … … 365 400 366 401 /* status stage */ 367 assert(packet == instance->packets - 1); 368 td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT, 369 0, 1, false, low_speed, instance->target, status_stage, NULL, NULL); 370 371 372 instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 402 assert(packet == data->packets - 1); 403 404 td_init( 405 &data->tds[packet], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed, 406 instance->target, status_stage, NULL, NULL); 407 td_set_ioc(&data->tds[packet]); 408 373 409 usb_log_debug2("Control last TD status: %x.\n", 374 instance->tds[packet].status); 375 } 376 /*----------------------------------------------------------------------------*/ 377 /** Prepares data, gets error status and calls callback in. 378 * 379 * @param[in] instance Batch structure to use. 380 */ 381 void batch_call_in(batch_t *instance) 382 { 383 assert(instance); 384 assert(instance->callback_in); 385 386 /* we are data in, we need data */ 387 memcpy(instance->buffer, instance->transport_buffer, 388 instance->buffer_size); 389 390 int err = instance->error; 391 usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n", 392 instance, instance->transfer_type, str_error(err), err, 393 instance->transfered_size); 394 395 instance->callback_in( 396 instance->fun, err, instance->transfered_size, instance->arg); 397 } 398 /*----------------------------------------------------------------------------*/ 399 /** Gets error status and calls callback out. 400 * 401 * @param[in] instance Batch structure to use. 402 */ 403 void batch_call_out(batch_t *instance) 404 { 405 assert(instance); 406 assert(instance->callback_out); 407 408 int err = instance->error; 409 usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n", 410 instance, instance->transfer_type, str_error(err), err); 411 instance->callback_out(instance->fun, 412 err, instance->arg); 413 } 414 /*----------------------------------------------------------------------------*/ 415 /** Prepares data, gets error status, calls callback in and dispose. 410 data->tds[packet].status); 411 } 412 /*----------------------------------------------------------------------------*/ 413 qh_t * batch_qh(batch_t *instance) 414 { 415 assert(instance); 416 uhci_batch_t *data = instance->private_data; 417 assert(data); 418 return data->qh; 419 } 420 /*----------------------------------------------------------------------------*/ 421 /** Helper function calls callback and correctly disposes of batch structure. 416 422 * 417 423 * @param[in] instance Batch structure to use. … … 424 430 } 425 431 /*----------------------------------------------------------------------------*/ 426 /** Gets error status, calls callback out and dispose.432 /** Helper function calls callback and correctly disposes of batch structure. 427 433 * 428 434 * @param[in] instance Batch structure to use. … … 435 441 } 436 442 /*----------------------------------------------------------------------------*/ 437 /** Correctly dispose sall used data structures.443 /** Correctly dispose all used data structures. 438 444 * 439 445 * @param[in] instance Batch structure to use. … … 442 448 { 443 449 assert(instance); 450 uhci_batch_t *data = instance->private_data; 451 assert(data); 444 452 usb_log_debug("Batch(%p) disposing.\n", instance); 445 453 /* free32 is NULL safe */ 446 free32( instance->tds);447 free32( instance->qh);454 free32(data->tds); 455 free32(data->qh); 448 456 free32(instance->setup_buffer); 449 457 free32(instance->transport_buffer); 458 free(data); 450 459 free(instance); 451 }452 /*----------------------------------------------------------------------------*/453 int batch_schedule(batch_t *instance)454 {455 assert(instance);456 uhci_t *hc = fun_to_uhci(instance->fun);457 assert(hc);458 return uhci_schedule(hc, instance);459 460 } 460 461 /** -
uspace/drv/uhci-hcd/batch.h
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver USB transaction structure 33 33 */ 34 34 #ifndef DRV_UHCI_BATCH_H … … 39 39 #include <usbhc_iface.h> 40 40 #include <usb/usb.h> 41 #include <usb/host/device_keeper.h> 42 #include <usb/host/batch.h> 41 43 42 #include "uhci_struct/transfer_descriptor.h"43 44 #include "uhci_struct/queue_head.h" 44 #include "utils/device_keeper.h"45 45 46 typedef struct batch 47 { 48 link_t link; 49 usb_speed_t speed; 50 usb_target_t target; 51 usb_transfer_type_t transfer_type; 52 union { 53 usbhc_iface_transfer_in_callback_t callback_in; 54 usbhc_iface_transfer_out_callback_t callback_out; 55 }; 56 void *arg; 57 char *transport_buffer; 58 char *setup_buffer; 59 size_t setup_size; 60 char *buffer; 61 size_t buffer_size; 62 size_t max_packet_size; 63 size_t packets; 64 size_t transfered_size; 65 int error; 66 ddf_fun_t *fun; 67 queue_head_t *qh; 68 td_t *tds; 69 void (*next_step)(struct batch*); 70 device_keeper_t *manager; 71 } batch_t; 72 73 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 74 usb_transfer_type_t transfer_type, size_t max_packet_size, 75 usb_speed_t speed, char *buffer, size_t size, 76 char *setup_buffer, size_t setup_size, 46 batch_t * batch_get( 47 ddf_fun_t *fun, 48 usb_target_t target, 49 usb_transfer_type_t transfer_type, 50 size_t max_packet_size, 51 usb_speed_t speed, 52 char *buffer, 53 size_t size, 54 char *setup_buffer, 55 size_t setup_size, 77 56 usbhc_iface_transfer_in_callback_t func_in, 78 usbhc_iface_transfer_out_callback_t func_out, void *arg, 57 usbhc_iface_transfer_out_callback_t func_out, 58 void *arg, 79 59 device_keeper_t *manager 80 60 ); 61 62 void batch_dispose(batch_t *instance); 81 63 82 64 bool batch_is_complete(batch_t *instance); … … 93 75 94 76 void batch_bulk_out(batch_t *instance); 77 78 qh_t * batch_qh(batch_t *instance); 95 79 #endif 96 80 /** -
uspace/drv/uhci-hcd/iface.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver hc interface implementation 33 33 */ 34 34 #include <ddf/driver.h> … … 40 40 41 41 #include "iface.h" 42 #include "uhci.h" 43 #include "utils/device_keeper.h" 42 #include "uhci_hc.h" 44 43 45 44 /** Reserve default address interface function … … 53 52 { 54 53 assert(fun); 55 uhci_ t *hc = fun_to_uhci(fun);54 uhci_hc_t *hc = fun_to_uhci_hc(fun); 56 55 assert(hc); 57 56 usb_log_debug("Default address request with speed %d.\n", speed); … … 68 67 { 69 68 assert(fun); 70 uhci_ t *hc = fun_to_uhci(fun);69 uhci_hc_t *hc = fun_to_uhci_hc(fun); 71 70 assert(hc); 72 71 usb_log_debug("Default address release.\n"); … … 86 85 { 87 86 assert(fun); 88 uhci_ t *hc = fun_to_uhci(fun);87 uhci_hc_t *hc = fun_to_uhci_hc(fun); 89 88 assert(hc); 90 89 assert(address); … … 109 108 { 110 109 assert(fun); 111 uhci_ t *hc = fun_to_uhci(fun);110 uhci_hc_t *hc = fun_to_uhci_hc(fun); 112 111 assert(hc); 113 112 usb_log_debug("Address bind %d-%d.\n", address, handle); … … 125 124 { 126 125 assert(fun); 127 uhci_ t *hc = fun_to_uhci(fun);126 uhci_hc_t *hc = fun_to_uhci_hc(fun); 128 127 assert(hc); 129 128 usb_log_debug("Address release %d.\n", address); … … 148 147 { 149 148 assert(fun); 150 uhci_ t *hc = fun_to_uhci(fun);149 uhci_hc_t *hc = fun_to_uhci_hc(fun); 151 150 assert(hc); 152 151 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 161 160 return ENOMEM; 162 161 batch_interrupt_out(batch); 162 const int ret = uhci_hc_schedule(hc, batch); 163 if (ret != EOK) { 164 batch_dispose(batch); 165 return ret; 166 } 163 167 return EOK; 164 168 } … … 180 184 { 181 185 assert(fun); 182 uhci_ t *hc = fun_to_uhci(fun);186 uhci_hc_t *hc = fun_to_uhci_hc(fun); 183 187 assert(hc); 184 188 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 192 196 return ENOMEM; 193 197 batch_interrupt_in(batch); 198 const int ret = uhci_hc_schedule(hc, batch); 199 if (ret != EOK) { 200 batch_dispose(batch); 201 return ret; 202 } 194 203 return EOK; 195 204 } … … 211 220 { 212 221 assert(fun); 213 uhci_ t *hc = fun_to_uhci(fun);222 uhci_hc_t *hc = fun_to_uhci_hc(fun); 214 223 assert(hc); 215 224 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 224 233 return ENOMEM; 225 234 batch_bulk_out(batch); 235 const int ret = uhci_hc_schedule(hc, batch); 236 if (ret != EOK) { 237 batch_dispose(batch); 238 return ret; 239 } 226 240 return EOK; 227 241 } … … 243 257 { 244 258 assert(fun); 245 uhci_ t *hc = fun_to_uhci(fun);259 uhci_hc_t *hc = fun_to_uhci_hc(fun); 246 260 assert(hc); 247 261 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 255 269 return ENOMEM; 256 270 batch_bulk_in(batch); 271 const int ret = uhci_hc_schedule(hc, batch); 272 if (ret != EOK) { 273 batch_dispose(batch); 274 return ret; 275 } 257 276 return EOK; 258 277 } … … 277 296 { 278 297 assert(fun); 279 uhci_ t *hc = fun_to_uhci(fun);280 assert(hc); 281 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 282 usb_log_debug("Control WRITE %d:%d %zu(%zu).\n",283 target.address, target.endpoint, size, max_packet_size);298 uhci_hc_t *hc = fun_to_uhci_hc(fun); 299 assert(hc); 300 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 301 usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n", 302 speed, target.address, target.endpoint, size, max_packet_size); 284 303 285 304 if (setup_size != 8) … … 293 312 device_keeper_reset_if_need(&hc->device_manager, target, setup_data); 294 313 batch_control_write(batch); 314 const int ret = uhci_hc_schedule(hc, batch); 315 if (ret != EOK) { 316 batch_dispose(batch); 317 return ret; 318 } 295 319 return EOK; 296 320 } … … 315 339 { 316 340 assert(fun); 317 uhci_ t *hc = fun_to_uhci(fun);318 assert(hc); 319 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 320 321 usb_log_debug("Control READ %d:%d %zu(%zu).\n",322 target.address, target.endpoint, size, max_packet_size);341 uhci_hc_t *hc = fun_to_uhci_hc(fun); 342 assert(hc); 343 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 344 345 usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n", 346 speed, target.address, target.endpoint, size, max_packet_size); 323 347 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, 324 348 max_packet_size, speed, data, size, setup_data, setup_size, callback, … … 327 351 return ENOMEM; 328 352 batch_control_read(batch); 329 return EOK; 330 } 331 /*----------------------------------------------------------------------------*/ 332 usbhc_iface_t uhci_iface = { 353 const int ret = uhci_hc_schedule(hc, batch); 354 if (ret != EOK) { 355 batch_dispose(batch); 356 return ret; 357 } 358 return EOK; 359 } 360 /*----------------------------------------------------------------------------*/ 361 usbhc_iface_t uhci_hc_iface = { 333 362 .reserve_default_address = reserve_default_address, 334 363 .release_default_address = release_default_address, -
uspace/drv/uhci-hcd/iface.h
rc32688d r361e61b 27 27 */ 28 28 29 /** @addtogroup usb29 /** @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief UHCI driver 33 * @brief UHCI driver iface 34 34 */ 35 35 #ifndef DRV_UHCI_IFACE_H … … 38 38 #include <usbhc_iface.h> 39 39 40 extern usbhc_iface_t uhci_ iface;40 extern usbhc_iface_t uhci_hc_iface; 41 41 42 42 #endif -
uspace/drv/uhci-hcd/main.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver initialization 33 33 */ 34 34 #include <ddf/driver.h> 35 #include <ddf/interrupt.h>36 #include <device/hw_res.h>37 35 #include <errno.h> 38 36 #include <str_error.h> 39 37 40 #include <usb_iface.h>41 38 #include <usb/ddfiface.h> 42 39 #include <usb/debug.h> 43 40 44 41 #include "iface.h" 45 #include "pci.h"46 #include "root_hub.h"47 42 #include "uhci.h" 48 43 … … 60 55 }; 61 56 /*----------------------------------------------------------------------------*/ 62 /** IRQ handling callback, identifies devic 63 * 64 * @param[in] dev DDF instance of the device to use. 65 * @param[in] iid (Unused). 66 * @param[in] call Pointer to the call that represents interrupt. 67 */ 68 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 69 { 70 assert(dev); 71 uhci_t *hc = dev_to_uhci(dev); 72 uint16_t status = IPC_GET_ARG1(*call); 73 assert(hc); 74 uhci_interrupt(hc, status); 75 } 76 /*----------------------------------------------------------------------------*/ 77 /** Initializes a new ddf driver instance of UHCI hcd. 57 /** Initialize a new ddf driver instance for uhci hc and hub. 78 58 * 79 59 * @param[in] device DDF instance of the device to initialize. 80 60 * @return Error code. 81 *82 * Gets and initialies hardware resources, disables any legacy support,83 * and reports root hub device.84 61 */ 85 62 int uhci_add_device(ddf_dev_t *device) 86 63 { 64 usb_log_info("uhci_add_device() called\n"); 87 65 assert(device); 88 uhci_t *hcd = NULL; 89 #define CHECK_RET_FREE_HC_RETURN(ret, message...) \ 90 if (ret != EOK) { \ 91 usb_log_error(message); \ 92 if (hcd != NULL) \ 93 free(hcd); \ 94 return ret; \ 95 } 66 uhci_t *uhci = malloc(sizeof(uhci_t)); 67 if (uhci == NULL) { 68 usb_log_error("Failed to allocate UHCI driver.\n"); 69 return ENOMEM; 70 } 96 71 97 usb_log_info("uhci_add_device() called\n"); 98 99 uintptr_t io_reg_base = 0; 100 size_t io_reg_size = 0; 101 int irq = 0; 102 103 int ret = 104 pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq); 105 CHECK_RET_FREE_HC_RETURN(ret, 106 "Failed(%d) to get I/O addresses:.\n", ret, device->handle); 107 usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n", 108 io_reg_base, io_reg_size, irq); 109 110 ret = pci_disable_legacy(device); 111 CHECK_RET_FREE_HC_RETURN(ret, 112 "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret)); 113 114 #if 0 115 ret = pci_enable_interrupts(device); 72 int ret = uhci_init(uhci, device); 116 73 if (ret != EOK) { 117 usb_log_warning( 118 "Failed(%d) to enable interrupts, fall back to polling.\n", 119 ret); 74 usb_log_error("Failed to initialzie UHCI driver.\n"); 75 return ret; 120 76 } 121 #endif 122 123 hcd = malloc(sizeof(uhci_t)); 124 ret = (hcd != NULL) ? EOK : ENOMEM; 125 CHECK_RET_FREE_HC_RETURN(ret, 126 "Failed(%d) to allocate memory for uhci hcd.\n", ret); 127 128 ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size); 129 CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 130 #undef CHECK_RET_FREE_HC_RETURN 131 132 /* 133 * We might free hcd, but that does not matter since no one 134 * else would access driver_data anyway. 135 */ 136 device->driver_data = hcd; 137 138 ddf_fun_t *rh = NULL; 139 #define CHECK_RET_FINI_FREE_RETURN(ret, message...) \ 140 if (ret != EOK) { \ 141 usb_log_error(message); \ 142 if (hcd != NULL) {\ 143 uhci_fini(hcd); \ 144 free(hcd); \ 145 } \ 146 if (rh != NULL) \ 147 free(rh); \ 148 return ret; \ 149 } 150 151 /* It does no harm if we register this on polling */ 152 ret = register_interrupt_handler(device, irq, irq_handler, 153 &hcd->interrupt_code); 154 CHECK_RET_FINI_FREE_RETURN(ret, 155 "Failed(%d) to register interrupt handler.\n", ret); 156 157 ret = setup_root_hub(&rh, device); 158 CHECK_RET_FINI_FREE_RETURN(ret, 159 "Failed(%d) to setup UHCI root hub.\n", ret); 160 rh->driver_data = hcd->ddf_instance; 161 162 ret = ddf_fun_bind(rh); 163 CHECK_RET_FINI_FREE_RETURN(ret, 164 "Failed(%d) to register UHCI root hub.\n", ret); 165 77 device->driver_data = uhci; 166 78 return EOK; 167 #undef CHECK_RET_FINI_FREE_RETURN168 79 } 169 80 /*----------------------------------------------------------------------------*/ 170 /** Initialize sglobal driver structures (NONE).81 /** Initialize global driver structures (NONE). 171 82 * 172 83 * @param[in] argc Nmber of arguments in argv vector (ignored). … … 178 89 int main(int argc, char *argv[]) 179 90 { 180 sleep(3); 91 sleep(3); /* TODO: remove in final version */ 181 92 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 182 93 -
uspace/drv/uhci-hcd/pci.c
rc32688d r361e61b 27 27 */ 28 28 /** 29 * @addtogroup drvusbuhci 29 * @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ … … 117 117 } 118 118 /*----------------------------------------------------------------------------*/ 119 /** Call sthe PCI driver with a request to enable interrupts119 /** Call the PCI driver with a request to enable interrupts 120 120 * 121 121 * @param[in] device Device asking for interrupts … … 131 131 } 132 132 /*----------------------------------------------------------------------------*/ 133 /** Call sthe PCI driver with a request to clear legacy support register133 /** Call the PCI driver with a request to clear legacy support register 134 134 * 135 135 * @param[in] device Device asking to disable interrupts -
uspace/drv/uhci-hcd/pci.h
rc32688d r361e61b 27 27 */ 28 28 29 /** @addtogroup drvusbuhci 29 /** @addtogroup drvusbuhcihc 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief UHCI driver 33 * @brief UHCI driver PCI helper functions 34 34 */ 35 35 #ifndef DRV_UHCI_PCI_H -
uspace/drv/uhci-hcd/transfer_list.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver transfer list implementation 33 33 */ 34 34 #include <errno.h> 35 36 35 #include <usb/debug.h> 37 36 … … 41 40 transfer_list_t *instance, batch_t *batch); 42 41 /*----------------------------------------------------------------------------*/ 43 /** Initialize stransfer list structures.42 /** Initialize transfer list structures. 44 43 * 45 44 * @param[in] instance Memory place to use. 46 * @param[in] name Name of t e new list.47 * @return Error code 48 * 49 * Allocates memory for interna t queue_head_t structure.45 * @param[in] name Name of the new list. 46 * @return Error code 47 * 48 * Allocates memory for internal qh_t structure. 50 49 */ 51 50 int transfer_list_init(transfer_list_t *instance, const char *name) 52 51 { 53 52 assert(instance); 54 instance->next = NULL;55 53 instance->name = name; 56 instance->queue_head = malloc32(sizeof(q ueue_head_t));54 instance->queue_head = malloc32(sizeof(qh_t)); 57 55 if (!instance->queue_head) { 58 56 usb_log_error("Failed to allocate queue head.\n"); … … 61 59 instance->queue_head_pa = addr_to_phys(instance->queue_head); 62 60 63 q ueue_head_init(instance->queue_head);61 qh_init(instance->queue_head); 64 62 list_initialize(&instance->batch_list); 65 63 fibril_mutex_initialize(&instance->guard); … … 67 65 } 68 66 /*----------------------------------------------------------------------------*/ 69 /** Set the next list in chain.67 /** Set the next list in transfer list chain. 70 68 * 71 69 * @param[in] instance List to lead. 72 70 * @param[in] next List to append. 73 71 * @return Error code 72 * 73 * Does not check whether this replaces an existing list . 74 74 */ 75 75 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next) … … 79 79 if (!instance->queue_head) 80 80 return; 81 queue_head_append_qh(instance->queue_head, next->queue_head_pa); 82 instance->queue_head->element = instance->queue_head->next_queue; 83 } 84 /*----------------------------------------------------------------------------*/ 85 /** Submits a new transfer batch to list and queue. 81 /* Set both next and element to point to the same QH */ 82 qh_set_next_qh(instance->queue_head, next->queue_head_pa); 83 qh_set_element_qh(instance->queue_head, next->queue_head_pa); 84 } 85 /*----------------------------------------------------------------------------*/ 86 /** Submit transfer batch to the list and queue. 86 87 * 87 88 * @param[in] instance List to use. 88 89 * @param[in] batch Transfer batch to submit. 89 90 * @return Error code 91 * 92 * The batch is added to the end of the list and queue. 90 93 */ 91 94 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch) … … 93 96 assert(instance); 94 97 assert(batch); 95 usb_log_debug2( 96 "Adding batch(%p) to queue %s.\n", batch, instance->name); 97 98 uint32_t pa = (uintptr_t)addr_to_phys(batch->qh); 98 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch); 99 100 const uint32_t pa = addr_to_phys(batch_qh(batch)); 99 101 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa); 100 pa |= LINK_POINTER_QUEUE_HEAD_FLAG; 101 102 batch->qh->next_queue = instance->queue_head->next_queue; 102 103 /* New batch will be added to the end of the current list 104 * so set the link accordingly */ 105 qh_set_next_qh(batch_qh(batch), instance->queue_head->next); 103 106 104 107 fibril_mutex_lock(&instance->guard); 105 108 106 if (instance->queue_head->element == instance->queue_head->next_queue) { 107 /* there is nothing scheduled */ 108 list_append(&batch->link, &instance->batch_list); 109 instance->queue_head->element = pa; 110 usb_log_debug("Batch(%p) added to queue %s first.\n", 111 batch, instance->name); 112 fibril_mutex_unlock(&instance->guard); 113 return; 114 } 115 /* now we can be sure that there is someting scheduled */ 116 assert(!list_empty(&instance->batch_list)); 109 /* Add to the hardware queue. */ 110 if (list_empty(&instance->batch_list)) { 111 /* There is nothing scheduled */ 112 qh_t *qh = instance->queue_head; 113 assert(qh->element == qh->next); 114 qh_set_element_qh(qh, pa); 115 } else { 116 /* There is something scheduled */ 117 batch_t *last = list_get_instance( 118 instance->batch_list.prev, batch_t, link); 119 qh_set_next_qh(batch_qh(last), pa); 120 } 121 /* Add to the driver list */ 122 list_append(&batch->link, &instance->batch_list); 123 117 124 batch_t *first = list_get_instance( 118 instance->batch_list.next, batch_t, link); 119 batch_t *last = list_get_instance( 120 instance->batch_list.prev, batch_t, link); 121 queue_head_append_qh(last->qh, pa); 122 list_append(&batch->link, &instance->batch_list); 123 124 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 125 instance->batch_list.next, batch_t, link); 126 usb_log_debug("Batch(%p) added to queue %s, first is %p.\n", 125 127 batch, instance->name, first); 126 128 fibril_mutex_unlock(&instance->guard); 127 129 } 128 130 /*----------------------------------------------------------------------------*/ 129 /** Removes a transfer batch from list and queue. 130 * 131 * @param[in] instance List to use. 132 * @param[in] batch Transfer batch to remove. 133 * @return Error code 134 */ 135 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) 136 { 137 assert(instance); 138 assert(batch); 139 assert(instance->queue_head); 140 assert(batch->qh); 141 usb_log_debug2( 142 "Removing batch(%p) from queue %s.\n", batch, instance->name); 143 144 if (batch->link.prev == &instance->batch_list) { 145 /* I'm the first one here */ 146 usb_log_debug( 147 "Batch(%p) removed (FIRST) from %s, next element %x.\n", 148 batch, instance->name, batch->qh->next_queue); 149 instance->queue_head->element = batch->qh->next_queue; 150 } else { 151 usb_log_debug( 152 "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n", 153 batch, instance->name, batch->qh->next_queue); 154 batch_t *prev = 155 list_get_instance(batch->link.prev, batch_t, link); 156 prev->qh->next_queue = batch->qh->next_queue; 157 } 158 list_remove(&batch->link); 159 } 160 /*----------------------------------------------------------------------------*/ 161 /** Checks list for finished transfers. 162 * 163 * @param[in] instance List to use. 164 * @return Error code 131 /** Check list for finished batches. 132 * 133 * @param[in] instance List to use. 134 * @return Error code 135 * 136 * Creates a local list of finished batches and calls next_step on each and 137 * every one. This is safer because next_step may theoretically access 138 * this transfer list leading to the deadlock if its done inline. 165 139 */ 166 140 void transfer_list_remove_finished(transfer_list_t *instance) … … 177 151 178 152 if (batch_is_complete(batch)) { 153 /* Save for post-processing */ 179 154 transfer_list_remove_batch(instance, batch); 180 155 list_append(current, &done); … … 191 166 } 192 167 } 168 /*----------------------------------------------------------------------------*/ 169 /** Walk the list and abort all batches. 170 * 171 * @param[in] instance List to use. 172 */ 173 void transfer_list_abort_all(transfer_list_t *instance) 174 { 175 fibril_mutex_lock(&instance->guard); 176 while (list_empty(&instance->batch_list)) { 177 link_t *current = instance->batch_list.next; 178 batch_t *batch = list_get_instance(current, batch_t, link); 179 transfer_list_remove_batch(instance, batch); 180 batch_finish(batch, EIO); 181 } 182 fibril_mutex_unlock(&instance->guard); 183 } 184 /*----------------------------------------------------------------------------*/ 185 /** Remove a transfer batch from the list and queue. 186 * 187 * @param[in] instance List to use. 188 * @param[in] batch Transfer batch to remove. 189 * @return Error code 190 * 191 * Does not lock the transfer list, caller is responsible for that. 192 */ 193 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) 194 { 195 assert(instance); 196 assert(instance->queue_head); 197 assert(batch); 198 assert(batch_qh(batch)); 199 usb_log_debug2( 200 "Queue %s: removing batch(%p).\n", instance->name, batch); 201 202 const char * pos = NULL; 203 /* Remove from the hardware queue */ 204 if (batch->link.prev == &instance->batch_list) { 205 /* I'm the first one here */ 206 qh_set_element_qh(instance->queue_head, batch_qh(batch)->next); 207 pos = "FIRST"; 208 } else { 209 batch_t *prev = 210 list_get_instance(batch->link.prev, batch_t, link); 211 qh_set_next_qh(batch_qh(prev), batch_qh(batch)->next); 212 pos = "NOT FIRST"; 213 } 214 /* Remove from the driver list */ 215 list_remove(&batch->link); 216 usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n", 217 batch, pos, instance->name, batch_qh(batch)->next); 218 } 193 219 /** 194 220 * @} -
uspace/drv/uhci-hcd/transfer_list.h
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 32 * @brief UHCI driver transfer list structure 33 33 */ 34 34 #ifndef DRV_UHCI_TRANSFER_LIST_H … … 44 44 { 45 45 fibril_mutex_t guard; 46 q ueue_head_t *queue_head;46 qh_t *queue_head; 47 47 uint32_t queue_head_pa; 48 struct transfer_list *next;49 48 const char *name; 50 49 link_t batch_list; 51 50 } transfer_list_t; 51 52 /** Dispose transfer list structures. 53 * 54 * @param[in] instance Memory place to use. 55 * 56 * Frees memory for internal qh_t structure. 57 */ 58 static inline void transfer_list_fini(transfer_list_t *instance) 59 { 60 assert(instance); 61 free32(instance->queue_head); 62 } 52 63 53 64 int transfer_list_init(transfer_list_t *instance, const char *name); … … 55 66 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next); 56 67 57 static inline void transfer_list_fini(transfer_list_t *instance) 58 { 59 assert(instance); 60 free32(instance->queue_head); 61 } 68 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch); 69 62 70 void transfer_list_remove_finished(transfer_list_t *instance); 63 71 64 void transfer_list_a dd_batch(transfer_list_t *instance, batch_t *batch);72 void transfer_list_abort_all(transfer_list_t *instance); 65 73 #endif 66 74 /** -
uspace/drv/uhci-hcd/uhci.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb 28 29 /** @addtogroup drvusbuhci 29 30 * @{ 30 31 */ … … 34 35 #include <errno.h> 35 36 #include <str_error.h> 36 #include < adt/list.h>37 #include < libarch/ddi.h>38 37 #include <ddf/interrupt.h> 38 #include <usb_iface.h> 39 #include <usb/ddfiface.h> 39 40 #include <usb/debug.h> 40 #include <usb/usb.h>41 #include <usb/ddfiface.h>42 #include <usb_iface.h>43 41 44 42 #include "uhci.h" 45 43 #include "iface.h" 46 47 static irq_cmd_t uhci_cmds[] = { 48 { 49 .cmd = CMD_PIO_READ_16, 50 .addr = NULL, /* patched for every instance */ 51 .dstarg = 1 52 }, 53 { 54 .cmd = CMD_PIO_WRITE_16, 55 .addr = NULL, /* pathed for every instance */ 56 .value = 0x1f 57 },58 {59 .cmd = CMD_ACCEPT60 }61 };62 63 /* * Gets USB address of the calling device.64 * 65 * @param[in] fun UHCI hc function.66 * @param[in] handle Handle of the device seeking address.67 * @param[ out] address Place to store found address.68 * @ return Error code.44 #include "pci.h" 45 46 47 /** IRQ handling callback, identifies device 48 * 49 * @param[in] dev DDF instance of the device to use. 50 * @param[in] iid (Unused). 51 * @param[in] call Pointer to the call that represents interrupt. 52 */ 53 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 54 { 55 assert(dev); 56 uhci_hc_t *hc = &((uhci_t*)dev->driver_data)->hc; 57 uint16_t status = IPC_GET_ARG1(*call); 58 assert(hc); 59 uhci_hc_interrupt(hc, status); 60 } 61 /*----------------------------------------------------------------------------*/ 62 /** Get address of the device identified by handle. 63 * 64 * @param[in] dev DDF instance of the device to use. 65 * @param[in] iid (Unused). 66 * @param[in] call Pointer to the call that represents interrupt. 69 67 */ 70 68 static int usb_iface_get_address( … … 72 70 { 73 71 assert(fun); 74 uhci_t *hc = fun_to_uhci(fun); 75 assert(hc); 76 77 usb_address_t addr = device_keeper_find(&hc->device_manager, 78 handle); 72 device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.device_manager; 73 74 usb_address_t addr = device_keeper_find(manager, handle); 79 75 if (addr < 0) { 80 76 return addr; … … 88 84 } 89 85 /*----------------------------------------------------------------------------*/ 90 static usb_iface_t hc_usb_iface = { 91 .get_hc_handle = usb_iface_get_hc_handle_hc_impl, 86 /** Gets handle of the respective hc (this or parent device). 87 * 88 * @param[in] root_hub_fun Root hub function seeking hc handle. 89 * @param[out] handle Place to write the handle. 90 * @return Error code. 91 */ 92 static int usb_iface_get_hc_handle( 93 ddf_fun_t *fun, devman_handle_t *handle) 94 { 95 assert(handle); 96 ddf_fun_t *hc_fun = ((uhci_t*)fun->dev->driver_data)->hc_fun; 97 assert(hc_fun != NULL); 98 99 *handle = hc_fun->handle; 100 return EOK; 101 } 102 /*----------------------------------------------------------------------------*/ 103 /** This iface is generic for both RH and HC. */ 104 static usb_iface_t usb_iface = { 105 .get_hc_handle = usb_iface_get_hc_handle, 92 106 .get_address = usb_iface_get_address 93 107 }; 94 108 /*----------------------------------------------------------------------------*/ 95 static ddf_dev_ops_t uhci_ops = { 96 .interfaces[USB_DEV_IFACE] = &hc_usb_iface, 97 .interfaces[USBHC_DEV_IFACE] = &uhci_iface, 98 }; 99 /*----------------------------------------------------------------------------*/ 100 static int uhci_init_transfer_lists(uhci_t *instance); 101 static int uhci_init_mem_structures(uhci_t *instance); 102 static void uhci_init_hw(uhci_t *instance); 103 104 static int uhci_interrupt_emulator(void *arg); 105 static int uhci_debug_checker(void *arg); 106 107 static bool allowed_usb_packet( 108 bool low_speed, usb_transfer_type_t transfer, size_t size); 109 /*----------------------------------------------------------------------------*/ 110 /** Initializes UHCI hcd driver structure 111 * 112 * @param[in] instance Memory place to initialize. 113 * @param[in] dev DDF device. 114 * @param[in] regs Address of I/O control registers. 115 * @param[in] size Size of I/O control registers. 116 * @return Error code. 117 * @note Should be called only once on any structure. 118 */ 119 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 120 { 121 assert(reg_size >= sizeof(regs_t)); 122 int ret; 123 109 static ddf_dev_ops_t uhci_hc_ops = { 110 .interfaces[USB_DEV_IFACE] = &usb_iface, 111 .interfaces[USBHC_DEV_IFACE] = &uhci_hc_iface, /* see iface.h/c */ 112 }; 113 /*----------------------------------------------------------------------------*/ 114 /** Get root hub hw resources (I/O registers). 115 * 116 * @param[in] fun Root hub function. 117 * @return Pointer to the resource list used by the root hub. 118 */ 119 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun) 120 { 121 assert(fun); 122 return &((uhci_rh_t*)fun->driver_data)->resource_list; 123 } 124 /*----------------------------------------------------------------------------*/ 125 static hw_res_ops_t hw_res_iface = { 126 .get_resource_list = get_resource_list, 127 .enable_interrupt = NULL 128 }; 129 /*----------------------------------------------------------------------------*/ 130 static ddf_dev_ops_t uhci_rh_ops = { 131 .interfaces[USB_DEV_IFACE] = &usb_iface, 132 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 133 }; 134 /*----------------------------------------------------------------------------*/ 135 /** Initialize hc and rh ddf structures and their respective drivers. 136 * 137 * @param[in] instance UHCI structure to use. 138 * @param[in] device DDF instance of the device to use. 139 * 140 * This function does all the preparatory work for hc and rh drivers: 141 * - gets device hw resources 142 * - disables UHCI legacy support 143 * - asks for interrupt 144 * - registers interrupt handler 145 */ 146 int uhci_init(uhci_t *instance, ddf_dev_t *device) 147 { 148 assert(instance); 149 instance->hc_fun = NULL; 150 instance->rh_fun = NULL; 124 151 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \ 125 if (ret != EOK) { \ 126 usb_log_error(message); \ 127 if (instance->ddf_instance) \ 128 ddf_fun_destroy(instance->ddf_instance); \ 129 return ret; \ 130 } else (void) 0 131 132 /* Create UHCI function. */ 133 instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci"); 134 ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK; 135 CHECK_RET_DEST_FUN_RETURN(ret, 136 "Failed to create UHCI device function.\n"); 137 138 instance->ddf_instance->ops = &uhci_ops; 139 instance->ddf_instance->driver_data = instance; 140 141 ret = ddf_fun_bind(instance->ddf_instance); 152 if (ret != EOK) { \ 153 usb_log_error(message); \ 154 if (instance->hc_fun) \ 155 ddf_fun_destroy(instance->hc_fun); \ 156 if (instance->rh_fun) \ 157 ddf_fun_destroy(instance->rh_fun); \ 158 return ret; \ 159 } 160 161 uintptr_t io_reg_base = 0; 162 size_t io_reg_size = 0; 163 int irq = 0; 164 165 int ret = 166 pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq); 167 CHECK_RET_DEST_FUN_RETURN(ret, 168 "Failed(%d) to get I/O addresses:.\n", ret, device->handle); 169 usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n", 170 io_reg_base, io_reg_size, irq); 171 172 ret = pci_disable_legacy(device); 173 CHECK_RET_DEST_FUN_RETURN(ret, 174 "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret)); 175 176 bool interrupts = false; 177 ret = pci_enable_interrupts(device); 178 if (ret != EOK) { 179 usb_log_warning( 180 "Failed(%d) to enable interrupts, fall back to polling.\n", 181 ret); 182 } else { 183 usb_log_debug("Hw interrupts enabled.\n"); 184 interrupts = true; 185 } 186 187 instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci-hc"); 188 ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 189 CHECK_RET_DEST_FUN_RETURN(ret, 190 "Failed(%d) to create HC function.\n", ret); 191 192 ret = uhci_hc_init(&instance->hc, instance->hc_fun, 193 (void*)io_reg_base, io_reg_size, interrupts); 194 CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 195 instance->hc_fun->ops = &uhci_hc_ops; 196 instance->hc_fun->driver_data = &instance->hc; 197 ret = ddf_fun_bind(instance->hc_fun); 142 198 CHECK_RET_DEST_FUN_RETURN(ret, 143 199 "Failed(%d) to bind UHCI device function: %s.\n", 144 200 ret, str_error(ret)); 145 146 /* allow access to hc control registers */ 147 regs_t *io; 148 ret = pio_enable(regs, reg_size, (void**)&io); 149 CHECK_RET_DEST_FUN_RETURN(ret, 150 "Failed(%d) to gain access to registers at %p: %s.\n", 151 ret, str_error(ret), io); 152 instance->registers = io; 153 usb_log_debug("Device registers at %p(%u) accessible.\n", 154 io, reg_size); 155 156 ret = uhci_init_mem_structures(instance); 157 CHECK_RET_DEST_FUN_RETURN(ret, 158 "Failed to initialize UHCI memory structures.\n"); 159 160 uhci_init_hw(instance); 161 instance->cleaner = 162 fibril_create(uhci_interrupt_emulator, instance); 163 fibril_add_ready(instance->cleaner); 164 165 instance->debug_checker = fibril_create(uhci_debug_checker, instance); 166 fibril_add_ready(instance->debug_checker); 167 168 usb_log_info("Started UHCI driver.\n"); 201 #undef CHECK_RET_HC_RETURN 202 203 #define CHECK_RET_FINI_RETURN(ret, message...) \ 204 if (ret != EOK) { \ 205 usb_log_error(message); \ 206 if (instance->hc_fun) \ 207 ddf_fun_destroy(instance->hc_fun); \ 208 if (instance->rh_fun) \ 209 ddf_fun_destroy(instance->rh_fun); \ 210 uhci_hc_fini(&instance->hc); \ 211 return ret; \ 212 } 213 214 /* It does no harm if we register this on polling */ 215 ret = register_interrupt_handler(device, irq, irq_handler, 216 &instance->hc.interrupt_code); 217 CHECK_RET_FINI_RETURN(ret, 218 "Failed(%d) to register interrupt handler.\n", ret); 219 220 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh"); 221 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 222 CHECK_RET_FINI_RETURN(ret, 223 "Failed(%d) to create root hub function.\n", ret); 224 225 ret = uhci_rh_init(&instance->rh, instance->rh_fun, 226 (uintptr_t)instance->hc.registers + 0x10, 4); 227 CHECK_RET_FINI_RETURN(ret, 228 "Failed(%d) to setup UHCI root hub.\n", ret); 229 230 instance->rh_fun->ops = &uhci_rh_ops; 231 instance->rh_fun->driver_data = &instance->rh; 232 ret = ddf_fun_bind(instance->rh_fun); 233 CHECK_RET_FINI_RETURN(ret, 234 "Failed(%d) to register UHCI root hub.\n", ret); 235 169 236 return EOK; 170 #undef CHECK_RET_DEST_FUN_RETURN 171 } 172 /*----------------------------------------------------------------------------*/ 173 /** Initializes UHCI hcd hw resources. 174 * 175 * @param[in] instance UHCI structure to use. 176 */ 177 void uhci_init_hw(uhci_t *instance) 178 { 179 assert(instance); 180 regs_t *registers = instance->registers; 181 182 /* Reset everything, who knows what touched it before us */ 183 pio_write_16(®isters->usbcmd, UHCI_CMD_GLOBAL_RESET); 184 async_usleep(10000); /* 10ms according to USB spec */ 185 pio_write_16(®isters->usbcmd, 0); 186 187 /* Reset hc, all states and counters */ 188 pio_write_16(®isters->usbcmd, UHCI_CMD_HCRESET); 189 do { async_usleep(10); } 190 while ((pio_read_16(®isters->usbcmd) & UHCI_CMD_HCRESET) != 0); 191 192 /* Set framelist pointer */ 193 const uint32_t pa = addr_to_phys(instance->frame_list); 194 pio_write_32(®isters->flbaseadd, pa); 195 196 /* Enable all interrupts, but resume interrupt */ 197 // pio_write_16(&instance->registers->usbintr, 198 // UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET); 199 200 uint16_t status = pio_read_16(®isters->usbcmd); 201 if (status != 0) 202 usb_log_warning("Previous command value: %x.\n", status); 203 204 /* Start the hc with large(64B) packet FSBR */ 205 pio_write_16(®isters->usbcmd, 206 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); 207 } 208 /*----------------------------------------------------------------------------*/ 209 /** Initializes UHCI hcd memory structures. 210 * 211 * @param[in] instance UHCI structure to use. 212 * @return Error code 213 * @note Should be called only once on any structure. 214 */ 215 int uhci_init_mem_structures(uhci_t *instance) 216 { 217 assert(instance); 218 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \ 219 if (ret != EOK) { \ 220 usb_log_error(message); \ 221 if (instance->interrupt_code.cmds != NULL) \ 222 free(instance->interrupt_code.cmds); \ 223 return ret; \ 224 } else (void) 0 225 226 /* Init interrupt code */ 227 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 228 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 229 CHECK_RET_DEST_CMDS_RETURN(ret, 230 "Failed to allocate interrupt cmds space.\n"); 231 232 { 233 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 234 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 235 interrupt_commands[0].addr = 236 (void*)&instance->registers->usbsts; 237 interrupt_commands[1].addr = 238 (void*)&instance->registers->usbsts; 239 instance->interrupt_code.cmdcount = 240 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 241 } 242 243 /* Init transfer lists */ 244 ret = uhci_init_transfer_lists(instance); 245 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n"); 246 usb_log_debug("Initialized transfer lists.\n"); 247 248 /* Init USB frame list page*/ 249 instance->frame_list = get_page(); 250 ret = instance ? EOK : ENOMEM; 251 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n"); 252 usb_log_debug("Initialized frame list.\n"); 253 254 /* Set all frames to point to the first queue head */ 255 const uint32_t queue = 256 instance->transfers_interrupt.queue_head_pa 257 | LINK_POINTER_QUEUE_HEAD_FLAG; 258 259 unsigned i = 0; 260 for(; i < UHCI_FRAME_LIST_COUNT; ++i) { 261 instance->frame_list[i] = queue; 262 } 263 264 /* Init device keeper*/ 265 device_keeper_init(&instance->device_manager); 266 usb_log_debug("Initialized device manager.\n"); 267 268 return EOK; 269 #undef CHECK_RET_DEST_CMDS_RETURN 270 } 271 /*----------------------------------------------------------------------------*/ 272 /** Initializes UHCI hcd transfer lists. 273 * 274 * @param[in] instance UHCI structure to use. 275 * @return Error code 276 * @note Should be called only once on any structure. 277 */ 278 int uhci_init_transfer_lists(uhci_t *instance) 279 { 280 assert(instance); 281 #define CHECK_RET_CLEAR_RETURN(ret, message...) \ 282 if (ret != EOK) { \ 283 usb_log_error(message); \ 284 transfer_list_fini(&instance->transfers_bulk_full); \ 285 transfer_list_fini(&instance->transfers_control_full); \ 286 transfer_list_fini(&instance->transfers_control_slow); \ 287 transfer_list_fini(&instance->transfers_interrupt); \ 288 return ret; \ 289 } else (void) 0 290 291 /* initialize TODO: check errors */ 292 int ret; 293 ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL"); 294 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 295 296 ret = transfer_list_init( 297 &instance->transfers_control_full, "CONTROL_FULL"); 298 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 299 300 ret = transfer_list_init( 301 &instance->transfers_control_slow, "CONTROL_SLOW"); 302 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 303 304 ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT"); 305 CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list."); 306 307 transfer_list_set_next(&instance->transfers_control_full, 308 &instance->transfers_bulk_full); 309 transfer_list_set_next(&instance->transfers_control_slow, 310 &instance->transfers_control_full); 311 transfer_list_set_next(&instance->transfers_interrupt, 312 &instance->transfers_control_slow); 313 314 /*FSBR*/ 315 #ifdef FSBR 316 transfer_list_set_next(&instance->transfers_bulk_full, 317 &instance->transfers_control_full); 318 #endif 319 320 /* Assign pointers to be used during scheduling */ 321 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] = 322 &instance->transfers_interrupt; 323 instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] = 324 &instance->transfers_interrupt; 325 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] = 326 &instance->transfers_control_full; 327 instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] = 328 &instance->transfers_control_slow; 329 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] = 330 &instance->transfers_bulk_full; 331 332 return EOK; 333 #undef CHECK_RET_CLEAR_RETURN 334 } 335 /*----------------------------------------------------------------------------*/ 336 /** Schedules batch for execution. 337 * 338 * @param[in] instance UHCI structure to use. 339 * @param[in] batch Transfer batch to schedule. 340 * @return Error code 341 */ 342 int uhci_schedule(uhci_t *instance, batch_t *batch) 343 { 344 assert(instance); 345 assert(batch); 346 const int low_speed = (batch->speed == USB_SPEED_LOW); 347 if (!allowed_usb_packet( 348 low_speed, batch->transfer_type, batch->max_packet_size)) { 349 usb_log_warning( 350 "Invalid USB packet specified %s SPEED %d %zu.\n", 351 low_speed ? "LOW" : "FULL" , batch->transfer_type, 352 batch->max_packet_size); 353 return ENOTSUP; 354 } 355 /* TODO: check available bandwith here */ 356 357 transfer_list_t *list = 358 instance->transfers[low_speed][batch->transfer_type]; 359 assert(list); 360 transfer_list_add_batch(list, batch); 361 362 return EOK; 363 } 364 /*----------------------------------------------------------------------------*/ 365 /** Takes action based on the interrupt cause. 366 * 367 * @param[in] instance UHCI structure to use. 368 * @param[in] status Value of the stsatus regiser at the time of interrupt. 369 */ 370 void uhci_interrupt(uhci_t *instance, uint16_t status) 371 { 372 assert(instance); 373 /* TODO: Check interrupt cause here */ 374 transfer_list_remove_finished(&instance->transfers_interrupt); 375 transfer_list_remove_finished(&instance->transfers_control_slow); 376 transfer_list_remove_finished(&instance->transfers_control_full); 377 transfer_list_remove_finished(&instance->transfers_bulk_full); 378 } 379 /*----------------------------------------------------------------------------*/ 380 /** Polling function, emulates interrupts. 381 * 382 * @param[in] arg UHCI structure to use. 383 * @return EOK 384 */ 385 int uhci_interrupt_emulator(void* arg) 386 { 387 usb_log_debug("Started interrupt emulator.\n"); 388 uhci_t *instance = (uhci_t*)arg; 389 assert(instance); 390 391 while (1) { 392 uint16_t status = pio_read_16(&instance->registers->usbsts); 393 if (status != 0) 394 usb_log_debug2("UHCI status: %x.\n", status); 395 status |= 1; 396 uhci_interrupt(instance, status); 397 pio_write_16(&instance->registers->usbsts, 0x1f); 398 async_usleep(UHCI_CLEANER_TIMEOUT); 399 } 400 return EOK; 401 } 402 /*---------------------------------------------------------------------------*/ 403 /** Debug function, checks consistency of memory structures. 404 * 405 * @param[in] arg UHCI structure to use. 406 * @return EOK 407 */ 408 int uhci_debug_checker(void *arg) 409 { 410 uhci_t *instance = (uhci_t*)arg; 411 assert(instance); 412 413 #define QH(queue) \ 414 instance->transfers_##queue.queue_head 415 416 while (1) { 417 const uint16_t cmd = pio_read_16(&instance->registers->usbcmd); 418 const uint16_t sts = pio_read_16(&instance->registers->usbsts); 419 const uint16_t intr = 420 pio_read_16(&instance->registers->usbintr); 421 422 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) { 423 usb_log_debug2("Command: %X Status: %X Intr: %x\n", 424 cmd, sts, intr); 425 } 426 427 uintptr_t frame_list = 428 pio_read_32(&instance->registers->flbaseadd) & ~0xfff; 429 if (frame_list != addr_to_phys(instance->frame_list)) { 430 usb_log_debug("Framelist address: %p vs. %p.\n", 431 frame_list, addr_to_phys(instance->frame_list)); 432 } 433 434 int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff; 435 usb_log_debug2("Framelist item: %d \n", frnum ); 436 437 uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf); 438 uintptr_t real_pa = addr_to_phys(QH(interrupt)); 439 if (expected_pa != real_pa) { 440 usb_log_debug("Interrupt QH: %p vs. %p.\n", 441 expected_pa, real_pa); 442 } 443 444 expected_pa = QH(interrupt)->next_queue & (~0xf); 445 real_pa = addr_to_phys(QH(control_slow)); 446 if (expected_pa != real_pa) { 447 usb_log_debug("Control Slow QH: %p vs. %p.\n", 448 expected_pa, real_pa); 449 } 450 451 expected_pa = QH(control_slow)->next_queue & (~0xf); 452 real_pa = addr_to_phys(QH(control_full)); 453 if (expected_pa != real_pa) { 454 usb_log_debug("Control Full QH: %p vs. %p.\n", 455 expected_pa, real_pa); 456 } 457 458 expected_pa = QH(control_full)->next_queue & (~0xf); 459 real_pa = addr_to_phys(QH(bulk_full)); 460 if (expected_pa != real_pa ) { 461 usb_log_debug("Bulk QH: %p vs. %p.\n", 462 expected_pa, real_pa); 463 } 464 async_usleep(UHCI_DEBUGER_TIMEOUT); 465 } 466 return EOK; 467 #undef QH 468 } 469 /*----------------------------------------------------------------------------*/ 470 /** Checks transfer packets, for USB validity 471 * 472 * @param[in] low_speed Transfer speed. 473 * @param[in] transfer Transer type 474 * @param[in] size Maximum size of used packets 475 * @return EOK 476 */ 477 bool allowed_usb_packet( 478 bool low_speed, usb_transfer_type_t transfer, size_t size) 479 { 480 /* see USB specification chapter 5.5-5.8 for magic numbers used here */ 481 switch(transfer) 482 { 483 case USB_TRANSFER_ISOCHRONOUS: 484 return (!low_speed && size < 1024); 485 case USB_TRANSFER_INTERRUPT: 486 return size <= (low_speed ? 8 : 64); 487 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 488 return (size <= (low_speed ? 8 : 64)); 489 case USB_TRANSFER_BULK: /* device specifies its own max size */ 490 return (!low_speed && size <= 64); 491 } 492 return false; 237 #undef CHECK_RET_FINI_RETURN 493 238 } 494 239 /** -
uspace/drv/uhci-hcd/uhci.h
rc32688d r361e61b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief UHCI driver 33 * @brief UHCI driver main structure for both host controller and root-hub. 34 34 */ 35 35 #ifndef DRV_UHCI_UHCI_H 36 36 #define DRV_UHCI_UHCI_H 37 #include <ddi.h> 38 #include <ddf/driver.h> 37 39 38 #include <fibril.h> 39 #include <fibril_synch.h> 40 #include <adt/list.h> 41 #include <ddi.h> 42 43 #include <usbhc_iface.h> 44 45 #include "batch.h" 46 #include "transfer_list.h" 47 #include "utils/device_keeper.h" 48 49 typedef struct uhci_regs { 50 uint16_t usbcmd; 51 #define UHCI_CMD_MAX_PACKET (1 << 7) 52 #define UHCI_CMD_CONFIGURE (1 << 6) 53 #define UHCI_CMD_DEBUG (1 << 5) 54 #define UHCI_CMD_FORCE_GLOBAL_RESUME (1 << 4) 55 #define UHCI_CMD_FORCE_GLOBAL_SUSPEND (1 << 3) 56 #define UHCI_CMD_GLOBAL_RESET (1 << 2) 57 #define UHCI_CMD_HCRESET (1 << 1) 58 #define UHCI_CMD_RUN_STOP (1 << 0) 59 60 uint16_t usbsts; 61 #define UHCI_STATUS_HALTED (1 << 5) 62 #define UHCI_STATUS_PROCESS_ERROR (1 << 4) 63 #define UHCI_STATUS_SYSTEM_ERROR (1 << 3) 64 #define UHCI_STATUS_RESUME (1 << 2) 65 #define UHCI_STATUS_ERROR_INTERRUPT (1 << 1) 66 #define UHCI_STATUS_INTERRUPT (1 << 0) 67 68 uint16_t usbintr; 69 #define UHCI_INTR_SHORT_PACKET (1 << 3) 70 #define UHCI_INTR_COMPLETE (1 << 2) 71 #define UHCI_INTR_RESUME (1 << 1) 72 #define UHCI_INTR_CRC (1 << 0) 73 74 uint16_t frnum; 75 uint32_t flbaseadd; 76 uint8_t sofmod; 77 } regs_t; 78 79 #define UHCI_FRAME_LIST_COUNT 1024 80 #define UHCI_CLEANER_TIMEOUT 10000 81 #define UHCI_DEBUGER_TIMEOUT 5000000 40 #include "uhci_hc.h" 41 #include "uhci_rh.h" 82 42 83 43 typedef struct uhci { 84 device_keeper_t device_manager; 44 ddf_fun_t *hc_fun; 45 ddf_fun_t *rh_fun; 85 46 86 regs_t *registers; 87 88 link_pointer_t *frame_list; 89 90 transfer_list_t transfers_bulk_full; 91 transfer_list_t transfers_control_full; 92 transfer_list_t transfers_control_slow; 93 transfer_list_t transfers_interrupt; 94 95 transfer_list_t *transfers[2][4]; 96 97 irq_code_t interrupt_code; 98 99 fid_t cleaner; 100 fid_t debug_checker; 101 102 ddf_fun_t *ddf_instance; 47 uhci_hc_t hc; 48 uhci_rh_t rh; 103 49 } uhci_t; 104 50 105 /* init uhci specifics in device.driver_data */ 106 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size); 107 108 static inline void uhci_fini(uhci_t *instance) {}; 109 110 int uhci_schedule(uhci_t *instance, batch_t *batch); 111 112 void uhci_interrupt(uhci_t *instance, uint16_t status); 113 114 static inline uhci_t * dev_to_uhci(ddf_dev_t *dev) 115 { return (uhci_t*)dev->driver_data; } 116 117 static inline uhci_t * fun_to_uhci(ddf_fun_t *fun) 118 { return (uhci_t*)fun->driver_data; } 119 51 int uhci_init(uhci_t *instance, ddf_dev_t *device); 120 52 121 53 #endif -
uspace/drv/uhci-hcd/uhci_rh.h
rc32688d r361e61b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 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 usb 28 29 /** @addtogroup drvusbuhci 29 30 * @{ 30 31 */ … … 32 33 * @brief UHCI driver 33 34 */ 34 #ifndef DRV_UHCI_ TD_PORT_STATUS_H35 #define DRV_UHCI_ TD_PORT_STATUS_H35 #ifndef DRV_UHCI_UHCI_RH_H 36 #define DRV_UHCI_UHCI_RH_H 36 37 37 #include <libarch/ddi.h> /* pio_read and pio_write */ 38 #include <ddf/driver.h> 39 #include <ops/hw_res.h> 38 40 39 #include <stdint.h> 41 typedef struct uhci_rh { 42 hw_resource_list_t resource_list; 43 hw_resource_t io_regs; 44 } uhci_rh_t; 40 45 41 typedef uint16_t port_status_t; 46 int uhci_rh_init( 47 uhci_rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size); 42 48 43 #define STATUS_CONNECTED (1 << 0)44 #define STATUS_CONNECTED_CHANGED (1 << 1)45 #define STATUS_ENABLED (1 << 2)46 #define STATUS_ENABLED_CHANGED (1 << 3)47 #define STATUS_LINE_D_PLUS (1 << 4)48 #define STATUS_LINE_D_MINUS (1 << 5)49 #define STATUS_RESUME (1 << 6)50 #define STATUS_ALWAYS_ONE (1 << 7)51 52 #define STATUS_LOW_SPEED (1 << 8)53 #define STATUS_IN_RESET (1 << 9)54 #define STATUS_SUSPEND (1 << 12)55 56 static inline port_status_t port_status_read(port_status_t * address)57 { return pio_read_16(address); }58 59 static inline void port_status_write(60 port_status_t *address, port_status_t value)61 { pio_write_16(address, value); }62 63 void print_port_status(const port_status_t status);64 49 #endif 65 50 /** -
uspace/drv/uhci-hcd/uhci_struct/link_pointer.h
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ … … 46 46 #define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */ 47 47 48 #define LINK_POINTER_QH(address) \ 49 ((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG) 50 48 51 #endif 49 52 /** -
uspace/drv/uhci-hcd/uhci_struct/queue_head.h
rc32688d r361e61b 1 2 1 /* 3 2 * Copyright (c) 2010 Jan Vesely … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 29 /** @addtogroup usb28 /** @addtogroup drv usbuhcihc 30 29 * @{ 31 30 */ … … 43 42 44 43 typedef struct queue_head { 45 volatile link_pointer_t next _queue;44 volatile link_pointer_t next; 46 45 volatile link_pointer_t element; 47 } __attribute__((packed)) queue_head_t; 48 49 static inline void queue_head_init(queue_head_t *instance) 46 } __attribute__((packed)) qh_t; 47 /*----------------------------------------------------------------------------*/ 48 /** Initialize queue head structure 49 * 50 * @param[in] instance qh_t structure to initialize. 51 * 52 * Sets both pointer to terminal NULL. 53 */ 54 static inline void qh_init(qh_t *instance) 50 55 { 51 56 assert(instance); 52 57 53 58 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG; 54 instance->next _queue= 0 | LINK_POINTER_TERMINATE_FLAG;59 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG; 55 60 } 56 57 static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa) 61 /*----------------------------------------------------------------------------*/ 62 /** Set queue head next pointer 63 * 64 * @param[in] instance qh_t structure to use. 65 * @param[in] pa Physical address of the next queue head. 66 * 67 * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal 68 * NULL. 69 */ 70 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa) 58 71 { 59 if (pa) { 60 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK) 72 /* Address is valid and not terminal */ 73 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 74 instance->next = (pa & LINK_POINTER_ADDRESS_MASK) 61 75 | LINK_POINTER_QUEUE_HEAD_FLAG; 76 } else { 77 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG; 62 78 } 63 79 } 64 65 static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa) 80 /*----------------------------------------------------------------------------*/ 81 /** Set queue head element pointer 82 * 83 * @param[in] instance qh_t structure to initialize. 84 * @param[in] pa Physical address of the next queue head. 85 * 86 * Adds proper flag. If the pointer is NULL or terminal, sets element 87 * to terminal NULL. 88 */ 89 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa) 66 90 { 67 if (pa) { 68 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK) 91 /* Address is valid and not terminal */ 92 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 93 instance->element = (pa & LINK_POINTER_ADDRESS_MASK) 69 94 | LINK_POINTER_QUEUE_HEAD_FLAG; 95 } else { 96 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG; 70 97 } 71 98 } 72 73 static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa) 99 /*----------------------------------------------------------------------------*/ 100 /** Set queue head element pointer 101 * 102 * @param[in] instance qh_t structure to initialize. 103 * @param[in] pa Physical address of the TD structure. 104 * 105 * Adds proper flag. If the pointer is NULL or terminal, sets element 106 * to terminal NULL. 107 */ 108 static inline void qh_set_element_td(qh_t *instance, uint32_t pa) 74 109 { 75 if (pa ) {110 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 76 111 instance->element = (pa & LINK_POINTER_ADDRESS_MASK); 112 } else { 113 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG; 77 114 } 78 115 } -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ … … 38 38 #include "utils/malloc32.h" 39 39 40 /** Initialize sTransfer Descriptor40 /** Initialize Transfer Descriptor 41 41 * 42 42 * @param[in] instance Memory place to initialize. … … 44 44 * @param[in] size Size of data source. 45 45 * @param[in] toggle Value of toggle bit. 46 * @param[in] iso True if TD is forIsochronous transfer.46 * @param[in] iso True if TD represents Isochronous transfer. 47 47 * @param[in] low_speed Target device's speed. 48 48 * @param[in] target Address and endpoint receiving the transfer. … … 51 51 * @param[in] next Net TD in transaction. 52 52 * @return Error code. 53 * 54 * Uses a mix of supplied and default values. 55 * Implicit values: 56 * - all TDs have vertical flag set (makes transfers to endpoints atomic) 57 * - in the error field only active it is set 58 * - if the packet uses PID_IN and is not isochronous SPD is set 59 * 60 * Dumps 8 bytes of buffer if PID_SETUP is used. 53 61 */ 54 62 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso, … … 88 96 } 89 97 90 usb_log_debug2("Created TD : %X:%X:%X:%X(%p).\n",91 instance ->next, instance->status, instance->device,98 usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n", 99 instance, instance->next, instance->status, instance->device, 92 100 instance->buffer_ptr, buffer); 101 td_print_status(instance); 93 102 if (pid == USB_PID_SETUP) { 94 103 usb_log_debug("SETUP BUFFER: %s\n", 95 usb_debug_str_buffer(buffer, 8, 8));104 usb_debug_str_buffer(buffer, 8, 8)); 96 105 } 97 106 } 98 107 /*----------------------------------------------------------------------------*/ 99 /** Convert sTD status into standard error code108 /** Convert TD status into standard error code 100 109 * 101 110 * @param[in] instance TD structure to use. … … 126 135 return EOK; 127 136 } 137 /*----------------------------------------------------------------------------*/ 138 /** Print values in status field (dw1) in a human readable way. 139 * 140 * @param[in] instance TD structure to use. 141 */ 142 void td_print_status(td_t *instance) 143 { 144 assert(instance); 145 const uint32_t s = instance->status; 146 usb_log_debug2("TD(%p) status(%#x):%s %d,%s%s%s%s%s%s%s%s%s%s%s %d.\n", 147 instance, instance->status, 148 (s & TD_STATUS_SPD_FLAG) ? " SPD," : "", 149 (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK, 150 (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "", 151 (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "", 152 (s & TD_STATUS_IOC_FLAG) ? " IOC," : "", 153 (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "", 154 (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "", 155 (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "", 156 (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "", 157 (s & TD_STATUS_ERROR_NAK) ? " NAK," : "", 158 (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "", 159 (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "", 160 (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "", 161 td_act_size(instance) 162 ); 163 } 128 164 /** 129 165 * @} -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
rc32688d r361e61b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 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 usb28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ … … 45 45 46 46 volatile uint32_t status; 47 48 47 #define TD_STATUS_RESERVED_MASK 0xc000f800 49 48 #define TD_STATUS_SPD_FLAG ( 1 << 29 ) 50 49 #define TD_STATUS_ERROR_COUNT_POS ( 27 ) 51 50 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 ) 52 #define TD_STATUS_ERROR_COUNT_DEFAULT 353 51 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 ) 54 52 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 ) 55 #define TD_STATUS_ COMPLETE_INTERRUPT_FLAG ( 1 << 24 )53 #define TD_STATUS_IOC_FLAG ( 1 << 24 ) 56 54 57 55 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23 ) … … 70 68 71 69 volatile uint32_t device; 72 73 70 #define TD_DEVICE_MAXLEN_POS 21 74 71 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff ) … … 85 82 86 83 /* there is 16 bytes of data available here, according to UHCI 87 * Design guide, according to linux kernel the hardware does not care 88 * we don't use it anyway84 * Design guide, according to linux kernel the hardware does not care, 85 * it just needs to be aligned, we don't use it anyway 89 86 */ 90 87 } __attribute__((packed)) td_t; 91 88 92 89 93 void td_init(td_t *instance, int error_count, size_t size, bool toggle, bool iso,94 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,95 td_t *next);90 void td_init(td_t *instance, int error_count, size_t size, bool toggle, 91 bool iso, bool low_speed, usb_target_t target, usb_packet_id pid, 92 void *buffer, td_t *next); 96 93 97 94 int td_status(td_t *instance); 98 95 96 void td_print_status(td_t *instance); 97 /*----------------------------------------------------------------------------*/ 98 /** Helper function for parsing actual size out of TD. 99 * 100 * @param[in] instance TD structure to use. 101 * @return Parsed actual size. 102 */ 99 103 static inline size_t td_act_size(td_t *instance) 100 104 { 101 105 assert(instance); 102 return 103 ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) 104 & TD_STATUS_ACTLEN_MASK; 106 const uint32_t s = instance->status; 107 return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK; 105 108 } 106 109 /*----------------------------------------------------------------------------*/ 110 /** Check whether less than max data were recieved and packet is marked as SPD. 111 * 112 * @param[in] instance TD structure to use. 113 * @return True if packet is short (less than max bytes and SPD set), false 114 * otherwise. 115 */ 107 116 static inline bool td_is_short(td_t *instance) 108 117 { … … 114 123 (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size; 115 124 } 116 125 /*----------------------------------------------------------------------------*/ 126 /** Helper function for parsing value of toggle bit. 127 * 128 * @param[in] instance TD structure to use. 129 * @return Toggle bit value. 130 */ 117 131 static inline int td_toggle(td_t *instance) 118 132 { 119 133 assert(instance); 120 return ((instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) != 0) 121 ? 1 : 0; 134 return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0; 122 135 } 123 136 /*----------------------------------------------------------------------------*/ 137 /** Helper function for parsing value of active bit 138 * 139 * @param[in] instance TD structure to use. 140 * @return Active bit value. 141 */ 124 142 static inline bool td_is_active(td_t *instance) 125 143 { … … 127 145 return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0; 128 146 } 147 /*----------------------------------------------------------------------------*/ 148 /** Helper function for setting IOC bit. 149 * 150 * @param[in] instance TD structure to use. 151 */ 152 static inline void td_set_ioc(td_t *instance) 153 { 154 assert(instance); 155 instance->status |= TD_STATUS_IOC_FLAG; 156 } 157 /*----------------------------------------------------------------------------*/ 129 158 #endif 130 159 /** -
uspace/drv/uhci-hcd/utils/malloc32.h
rc32688d r361e61b 43 43 #define UHCI_REQUIRED_PAGE_SIZE 4096 44 44 45 /** Get physical address translation 46 * 47 * @param[in] addr Virtual address to translate 48 * @return Physical address if exists, NULL otherwise. 49 */ 45 50 static inline uintptr_t addr_to_phys(void *addr) 46 51 { … … 48 53 int ret = as_get_physical_mapping(addr, &result); 49 54 50 assert(ret == 0); 55 if (ret != EOK) 56 return 0; 51 57 return (result | ((uintptr_t)addr & 0xfff)); 52 58 } 53 59 /*----------------------------------------------------------------------------*/ 60 /** Physical mallocator simulator 61 * 62 * @param[in] size Size of the required memory space 63 * @return Address of the alligned and big enough memory place, NULL on failure. 64 */ 54 65 static inline void * malloc32(size_t size) 55 66 { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); } 56 57 static inline void * get_page() 67 /*----------------------------------------------------------------------------*/ 68 /** Physical mallocator simulator 69 * 70 * @param[in] addr Address of the place allocated by malloc32 71 */ 72 static inline void free32(void *addr) 73 { if (addr) free(addr); } 74 /*----------------------------------------------------------------------------*/ 75 /** Create 4KB page mapping 76 * 77 * @return Address of the mapped page, NULL on failure. 78 */ 79 static inline void * get_page(void) 58 80 { 59 81 void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE); 60 82 assert(free_address); 61 83 if (free_address == 0) 62 return 0;84 return NULL; 63 85 void* ret = 64 86 as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE, 65 87 AS_AREA_READ | AS_AREA_WRITE); 66 88 if (ret != free_address) 67 return 0;89 return NULL; 68 90 return ret; 69 91 } 70 71 static inline void free32(void *addr)72 { if (addr) free(addr); }73 92 74 93 #endif -
uspace/drv/uhci-rhd/Makefile
rc32688d r361e61b 35 35 main.c \ 36 36 port.c \ 37 port_status.c \38 37 root_hub.c 39 38 -
uspace/drv/uhci-rhd/main.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver32 * @brief UHCI root hub initialization routines 33 33 */ 34 34 #include <ddf/driver.h> … … 40 40 #include <usb/debug.h> 41 41 42 43 44 42 #include "root_hub.h" 45 43 … … 47 45 static int hc_get_my_registers(ddf_dev_t *dev, 48 46 uintptr_t *io_reg_address, size_t *io_reg_size); 47 #if 0 49 48 /*----------------------------------------------------------------------------*/ 50 49 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) … … 67 66 .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface, 68 67 }; 68 #endif 69 69 /*----------------------------------------------------------------------------*/ 70 /** Initialize sa new ddf driver instance of UHCI root hub.70 /** Initialize a new ddf driver instance of UHCI root hub. 71 71 * 72 72 * @param[in] device DDF instance of the device to initialize. … … 81 81 82 82 //device->ops = &uhci_rh_ops; 83 (void) uhci_rh_ops;84 85 uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t));86 if (!rh) {87 usb_log_error("Failed to allocate memory for driver instance.\n");88 return ENOMEM;89 }90 91 83 uintptr_t io_regs = 0; 92 84 size_t io_size = 0; 93 85 94 86 int ret = hc_get_my_registers(device, &io_regs, &io_size); 95 assert(ret == EOK); 87 if (ret != EOK) { 88 usb_log_error("Failed(%d) to get registers from parent hc.", 89 ret); 90 } 91 usb_log_info("I/O regs at %#X (size %zu).\n", io_regs, io_size); 96 92 97 /* TODO: verify values from hc */ 98 usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size); 93 uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t)); 94 if (!rh) { 95 usb_log_error("Failed to allocate driver instance.\n"); 96 return ENOMEM; 97 } 98 99 99 ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device); 100 100 if (ret != EOK) { … … 119 119 }; 120 120 /*----------------------------------------------------------------------------*/ 121 /** Initialize sglobal driver structures (NONE).121 /** Initialize global driver structures (NONE). 122 122 * 123 123 * @param[in] argc Nmber of arguments in argv vector (ignored). -
uspace/drv/uhci-rhd/port.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver 33 */ 32 * @brief UHCI root hub port routines 33 */ 34 #include <libarch/ddi.h> /* pio_read and pio_write */ 34 35 #include <errno.h> 35 36 #include <str_error.h> … … 37 38 38 39 #include <usb/usb.h> /* usb_address_t */ 39 #include <usb/usbdevice.h>40 40 #include <usb/hub.h> 41 #include <usb/request.h>42 41 #include <usb/debug.h> 43 #include <usb/recognise.h>44 42 45 43 #include "port.h" 46 #include "port_status.h"47 44 48 45 static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed); … … 51 48 static int uhci_port_check(void *port); 52 49 static int uhci_port_reset_enable(int portno, void *arg); 53 /*----------------------------------------------------------------------------*/ 54 /** Initializes UHCI root hub port instance. 50 static void uhci_port_print_status( 51 uhci_port_t *port, const port_status_t value); 52 53 /** Register reading helper function. 54 * 55 * @param[in] port Structure to use. 56 * @return Error code. (Always EOK) 57 */ 58 static inline port_status_t uhci_port_read_status(uhci_port_t *port) 59 { 60 assert(port); 61 return pio_read_16(port->address); 62 } 63 /*----------------------------------------------------------------------------*/ 64 /** Register writing helper function. 65 * 66 * @param[in] port Structure to use. 67 * @param[in] value New register value. 68 * @return Error code. (Always EOK) 69 */ 70 static inline void uhci_port_write_status( 71 uhci_port_t *port, port_status_t value) 72 { 73 assert(port); 74 pio_write_16(port->address, value); 75 } 76 77 /*----------------------------------------------------------------------------*/ 78 /** Initialize UHCI root hub port instance. 55 79 * 56 80 * @param[in] port Memory structure to use. … … 61 85 * @return Error code. 62 86 * 63 * Starts the polling fibril.87 * Creates and starts the polling fibril. 64 88 */ 65 89 int uhci_port_init(uhci_port_t *port, … … 67 91 { 68 92 assert(port); 93 asprintf(&port->id_string, "Port (%p - %d)", port, number); 94 if (port->id_string == NULL) { 95 return ENOMEM; 96 } 69 97 70 98 port->address = address; … … 83 111 port->checker = fibril_create(uhci_port_check, port); 84 112 if (port->checker == 0) { 85 usb_log_error(" Port(%p - %d): failed to launch root hubfibril.",86 port-> address, port->number);113 usb_log_error("%s: failed to create polling fibril.", 114 port->id_string); 87 115 return ENOMEM; 88 116 } 89 117 90 118 fibril_add_ready(port->checker); 91 usb_log_debug(" Port(%p - %d): Added fibril. %x\n",92 port-> address, port->number, port->checker);93 return EOK; 94 } 95 /*----------------------------------------------------------------------------*/ 96 /** FinishesUHCI root hub port instance.119 usb_log_debug("%s: Started polling fibril(%x).\n", 120 port->id_string, port->checker); 121 return EOK; 122 } 123 /*----------------------------------------------------------------------------*/ 124 /** Cleanup UHCI root hub port instance. 97 125 * 98 126 * @param[in] port Memory structure to use. … … 102 130 void uhci_port_fini(uhci_port_t *port) 103 131 { 132 assert(port); 133 free(port->id_string); 104 134 /* TODO: Kill fibril here */ 105 135 return; … … 108 138 /** Periodically checks port status and reports new devices. 109 139 * 110 * @param[in] port Memorystructure to use.140 * @param[in] port Port structure to use. 111 141 * @return Error code. 112 142 */ … … 116 146 assert(instance); 117 147 118 /* Iteration count, for debug purposes only */119 unsigned count = 0;120 121 148 while (1) { 122 149 async_usleep(instance->wait_period_usec); 123 150 124 /* read register value */ 125 port_status_t port_status = port_status_read(instance->address); 126 127 /* debug print mutex */ 128 static fibril_mutex_t dbg_mtx = 129 FIBRIL_MUTEX_INITIALIZER(dbg_mtx); 130 fibril_mutex_lock(&dbg_mtx); 131 usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n", 132 instance->address, instance->number, port_status, count++); 133 // print_port_status(port_status); 134 fibril_mutex_unlock(&dbg_mtx); 151 /* Read register value */ 152 port_status_t port_status = uhci_port_read_status(instance); 153 154 /* Print the value if it's interesting */ 155 if (port_status & ~STATUS_ALWAYS_ONE) 156 uhci_port_print_status(instance, port_status); 135 157 136 158 if ((port_status & STATUS_CONNECTED_CHANGED) == 0) 137 159 continue; 138 160 139 usb_log_debug(" Port(%p - %d): Connected change detected: %x.\n",140 instance-> address, instance->number, port_status);161 usb_log_debug("%s: Connected change detected: %x.\n", 162 instance->id_string, port_status); 141 163 142 164 int rc = 143 165 usb_hc_connection_open(&instance->hc_connection); 144 166 if (rc != EOK) { 145 usb_log_error(" Port(%p - %d): Failed to connect to HC.",146 instance-> address, instance->number);167 usb_log_error("%s: Failed to connect to HC.", 168 instance->id_string); 147 169 continue; 148 170 } … … 150 172 /* Remove any old device */ 151 173 if (instance->attached_device) { 152 usb_log_debug2(" Port(%p - %d): Removing device.\n",153 instance-> address, instance->number);174 usb_log_debug2("%s: Removing device.\n", 175 instance->id_string); 154 176 uhci_port_remove_device(instance); 155 177 } … … 163 185 } else { 164 186 /* Write one to WC bits, to ack changes */ 165 port_status_write(instance->address, port_status);166 usb_log_debug(" Port(%p - %d): Change statusACK.\n",167 instance-> address, instance->number);187 uhci_port_write_status(instance, port_status); 188 usb_log_debug("%s: status change ACK.\n", 189 instance->id_string); 168 190 } 169 191 170 192 rc = usb_hc_connection_close(&instance->hc_connection); 171 193 if (rc != EOK) { 172 usb_log_error(" Port(%p - %d): Failed to disconnect.",173 instance-> address, instance->number);194 usb_log_error("%s: Failed to disconnect.", 195 instance->id_string); 174 196 } 175 197 } … … 182 204 * @param arg Pointer to uhci_port_t of port with the new device. 183 205 * @return Error code. 206 * 207 * Resets and enables the ub port. 184 208 */ 185 209 int uhci_port_reset_enable(int portno, void *arg) … … 187 211 uhci_port_t *port = (uhci_port_t *) arg; 188 212 189 usb_log_debug2("Port(%p - %d): new_device_enable_port.\n", 190 port->address, port->number); 213 usb_log_debug2("%s: new_device_enable_port.\n", port->id_string); 191 214 192 215 /* … … 196 219 async_usleep(100000); 197 220 198 199 /* The hub maintains the reset signal to that port for 10 ms 200 * (See Section 11.5.1.5) 221 /* 222 * Resets from root ports should be nominally 50ms 201 223 */ 202 224 { 203 usb_log_debug("Port(%p - %d): Reset Signal start.\n", 204 port->address, port->number); 205 port_status_t port_status = 206 port_status_read(port->address); 225 usb_log_debug("%s: Reset Signal start.\n", port->id_string); 226 port_status_t port_status = uhci_port_read_status(port); 207 227 port_status |= STATUS_IN_RESET; 208 port_status_write(port->address, port_status);209 async_usleep( 10000);210 port_status = port_status_read(port->address);228 uhci_port_write_status(port, port_status); 229 async_usleep(50000); 230 port_status = uhci_port_read_status(port); 211 231 port_status &= ~STATUS_IN_RESET; 212 port_status_write(port->address, port_status); 213 usb_log_debug("Port(%p - %d): Reset Signal stop.\n", 214 port->address, port->number); 215 } 232 uhci_port_write_status(port, port_status); 233 usb_log_debug("%s: Reset Signal stop.\n", port->id_string); 234 } 235 236 /* the reset recovery time 10ms */ 237 async_usleep(10000); 216 238 217 239 /* Enable the port. */ 218 240 uhci_port_set_enabled(port, true); 219 return EOK; 220 } 221 /*----------------------------------------------------------------------------*/ 222 /** Initializes and reports connected device. 223 * 224 * @param[in] port Memory structure to use. 241 242 return EOK; 243 } 244 /*----------------------------------------------------------------------------*/ 245 /** Initialize and report connected device. 246 * 247 * @param[in] port Port structure to use. 225 248 * @param[in] speed Detected speed. 226 249 * @return Error code. … … 233 256 assert(usb_hc_connection_is_opened(&port->hc_connection)); 234 257 235 usb_log_info("Port(%p-%d): Detected new device.\n", 236 port->address, port->number); 258 usb_log_info("%s: Detected new device.\n", port->id_string); 237 259 238 260 usb_address_t dev_addr; … … 242 264 243 265 if (rc != EOK) { 244 usb_log_error(" Port(%p-%d): Failed(%d) to add device: %s.\n",245 port-> address, port->number, rc, str_error(rc));266 usb_log_error("%s: Failed(%d) to add device: %s.\n", 267 port->id_string, rc, str_error(rc)); 246 268 uhci_port_set_enabled(port, false); 247 269 return rc; 248 270 } 249 271 250 usb_log_info(" Port(%p-%d): New device has address %d (handle %zu).\n",251 port-> address, port->number, dev_addr, port->attached_device);252 253 return EOK; 254 } 255 /*----------------------------------------------------------------------------*/ 256 /** Remove sdevice.272 usb_log_info("%s: New device has address %d (handle %zu).\n", 273 port->id_string, dev_addr, port->attached_device); 274 275 return EOK; 276 } 277 /*----------------------------------------------------------------------------*/ 278 /** Remove device. 257 279 * 258 280 * @param[in] port Memory structure to use. 259 281 * @return Error code. 260 282 * 261 * Does not work DDF does not support device removal. 283 * Does not work, DDF does not support device removal. 284 * Does not even free used USB address (it would be dangerous if tis driver 285 * is still running). 262 286 */ 263 287 int uhci_port_remove_device(uhci_port_t *port) 264 288 { 265 usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n", 266 port->address, port->number, (unsigned int)port->attached_device); 267 return EOK; 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** Enables and disables port. 271 * 272 * @param[in] port Memory structure to use. 289 usb_log_error("%s: Don't know how to remove device %d.\n", 290 port->id_string, (unsigned int)port->attached_device); 291 return EOK; 292 } 293 /*----------------------------------------------------------------------------*/ 294 /** Enable or disable root hub port. 295 * 296 * @param[in] port Port structure to use. 297 * @param[in] enabled Port status to set. 273 298 * @return Error code. (Always EOK) 274 299 */ … … 278 303 279 304 /* Read register value */ 280 port_status_t port_status = port_status_read(port->address);305 port_status_t port_status = uhci_port_read_status(port); 281 306 282 307 /* Set enabled bit */ … … 288 313 289 314 /* Write new value. */ 290 port_status_write(port->address, port_status); 291 292 usb_log_info("Port(%p-%d): %sabled port.\n", 293 port->address, port->number, enabled ? "En" : "Dis"); 294 return EOK; 295 } 296 /*----------------------------------------------------------------------------*/ 315 uhci_port_write_status(port, port_status); 316 317 usb_log_info("%s: %sabled port.\n", 318 port->id_string, enabled ? "En" : "Dis"); 319 return EOK; 320 } 321 /*----------------------------------------------------------------------------*/ 322 /** Print the port status value in a human friendly way 323 * 324 * @param[in] port Port structure to use. 325 * @param[in] value Port register value to print. 326 * @return Error code. (Always EOK) 327 */ 328 void uhci_port_print_status(uhci_port_t *port, const port_status_t value) 329 { 330 assert(port); 331 usb_log_debug2("%s Port status(%#x):%s%s%s%s%s%s%s%s%s%s%s.\n", 332 port->id_string, value, 333 (value & STATUS_SUSPEND) ? " SUSPENDED," : "", 334 (value & STATUS_RESUME) ? " IN RESUME," : "", 335 (value & STATUS_IN_RESET) ? " IN RESET," : "", 336 (value & STATUS_LINE_D_MINUS) ? " VD-," : "", 337 (value & STATUS_LINE_D_PLUS) ? " VD+," : "", 338 (value & STATUS_LOW_SPEED) ? " LOWSPEED," : "", 339 (value & STATUS_ENABLED_CHANGED) ? " ENABLED-CHANGE," : "", 340 (value & STATUS_ENABLED) ? " ENABLED," : "", 341 (value & STATUS_CONNECTED_CHANGED) ? " CONNECTED-CHANGE," : "", 342 (value & STATUS_CONNECTED) ? " CONNECTED," : "", 343 (value & STATUS_ALWAYS_ONE) ? " ALWAYS ONE" : " ERROR: NO ALWAYS ONE" 344 ); 345 } 297 346 /** 298 347 * @} -
uspace/drv/uhci-rhd/port.h
rc32688d r361e61b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 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 usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI port driver32 * @brief UHCI root hub port routines 33 33 */ 34 34 #ifndef DRV_UHCI_PORT_H 35 35 #define DRV_UHCI_PORT_H 36 36 37 #include <assert.h> 37 #include <stdint.h> 38 #include <fibril.h> 38 39 #include <ddf/driver.h> 39 #include <stdint.h> 40 #include <usb/usbdevice.h> 40 #include <usb/usbdevice.h> /* usb_hc_connection_t */ 41 41 42 #include "port_status.h" 42 typedef uint16_t port_status_t; 43 #define STATUS_CONNECTED (1 << 0) 44 #define STATUS_CONNECTED_CHANGED (1 << 1) 45 #define STATUS_ENABLED (1 << 2) 46 #define STATUS_ENABLED_CHANGED (1 << 3) 47 #define STATUS_LINE_D_PLUS (1 << 4) 48 #define STATUS_LINE_D_MINUS (1 << 5) 49 #define STATUS_RESUME (1 << 6) 50 #define STATUS_ALWAYS_ONE (1 << 7) 51 52 #define STATUS_LOW_SPEED (1 << 8) 53 #define STATUS_IN_RESET (1 << 9) 54 #define STATUS_SUSPEND (1 << 12) 43 55 44 56 typedef struct uhci_port 45 57 { 58 char *id_string; 46 59 port_status_t *address; 47 60 unsigned number; … … 58 71 59 72 void uhci_port_fini(uhci_port_t *port); 73 60 74 #endif 61 75 /** -
uspace/drv/uhci-rhd/root_hub.c
rc32688d r361e61b 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver32 * @brief UHCI root hub driver 33 33 */ 34 34 #include <errno.h> 35 #include <stdint.h>36 35 #include <ddi.h> 37 #include <devman.h>38 36 #include <usb/debug.h> 39 37 40 38 #include "root_hub.h" 41 39 42 /** Initialize sUHCI root hub instance.40 /** Initialize UHCI root hub instance. 43 41 * 44 42 * @param[in] instance Driver memory structure to use. 45 43 * @param[in] addr Address of I/O registers. 46 44 * @param[in] size Size of available I/O space. 47 * @param[in] rh Pointer to ddf instance fothe root hub driver.45 * @param[in] rh Pointer to ddf instance of the root hub driver. 48 46 * @return Error code. 49 47 */ … … 61 59 if (ret < 0) { 62 60 usb_log_error( 63 "Failed to gain access to port registers at %p\n", regs); 61 "Failed(%d) to gain access to port registers at %p\n", 62 ret, regs); 64 63 return ret; 65 64 } 66 65 67 /* add fibrils for periodic port checks */66 /* Initialize root hub ports */ 68 67 unsigned i = 0; 69 68 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { … … 82 81 } 83 82 /*----------------------------------------------------------------------------*/ 84 /** FinishesUHCI root hub instance.83 /** Cleanup UHCI root hub instance. 85 84 * 86 * @param[in] instance Driver memorystructure to use.85 * @param[in] instance Root hub structure to use. 87 86 * @return Error code. 88 87 */ -
uspace/drv/uhci-rhd/root_hub.h
rc32688d r361e61b 1 1 /* 2 * Copyright (c) 201 0Jan Vesely2 * Copyright (c) 2011 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 usb28 /** @addtogroup drvusbuhcirh 29 29 * @{ 30 30 */ … … 35 35 #define DRV_UHCI_ROOT_HUB_H 36 36 37 #include <fibril.h>38 37 #include <ddf/driver.h> 39 38 -
uspace/drv/usbhid/hiddev.c
rc32688d r361e61b 411 411 return rc; 412 412 } 413 413 rc = usb_endpoint_pipe_probe_default_control(&hid_dev->ctrl_pipe); 414 if (rc != EOK) { 415 usb_log_error("Probing default control pipe failed: %s.\n", 416 str_error(rc)); 417 return rc; 418 } 419 414 420 /* 415 421 * Initialize the report parser. … … 434 440 if (rc != EOK) { 435 441 /* TODO: end session?? */ 442 usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 436 443 usb_log_error("Failed to process descriptors: %s.\n", 437 444 str_error(rc)); -
uspace/drv/usbhid/hiddev.h
rc32688d r361e61b 32 32 /** @file 33 33 * Generic USB HID device structure and API. 34 * 35 * @todo Add function for parsing report - this is generic HID function, not 36 * keyboard-specific, as the report parser is also generic. 37 * @todo Add function for polling as that is also a generic HID process. 38 * @todo Add interrupt in pipe to the structure. 34 39 */ 35 40 -
uspace/drv/usbhid/kbddev.c
rc32688d r361e61b 51 51 #include <usb/classes/hidparser.h> 52 52 #include <usb/classes/classes.h> 53 #include <usb/classes/hidut.h> 53 54 54 55 #include "kbddev.h" … … 93 94 .flags = 0 94 95 }; 96 97 typedef enum usbhid_kbd_flags { 98 USBHID_KBD_STATUS_UNINITIALIZED = 0, 99 USBHID_KBD_STATUS_INITIALIZED = 1, 100 USBHID_KBD_STATUS_TO_DESTROY = -1 101 } usbhid_kbd_flags; 95 102 96 103 /*----------------------------------------------------------------------------*/ … … 124 131 }; 125 132 133 typedef enum usbhid_lock_code { 134 USBHID_LOCK_NUM = 0x53, 135 USBHID_LOCK_CAPS = 0x39, 136 USBHID_LOCK_SCROLL = 0x47, 137 USBHID_LOCK_COUNT = 3 138 } usbhid_lock_code; 139 140 static const usbhid_lock_code usbhid_lock_codes[USBHID_LOCK_COUNT] = { 141 USBHID_LOCK_NUM, 142 USBHID_LOCK_CAPS, 143 USBHID_LOCK_SCROLL 144 }; 145 126 146 /*----------------------------------------------------------------------------*/ 127 147 /* IPC method handler */ … … 218 238 219 239 assert(kbd_dev->hid_dev != NULL); 220 assert(kbd_dev->hid_dev->initialized );240 assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 221 241 usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 222 242 buffer, BOOTP_BUFFER_OUT_SIZE); … … 346 366 * @sa usbhid_kbd_push_ev() 347 367 */ 348 static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 349 uint8_t modifiers) 350 { 351 /* 352 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 353 * both as modifiers and as keys with their own scancodes??? 354 * 355 * modifiers should be sent as normal keys to usbhid_parse_scancode()!! 356 * so maybe it would be better if I received it from report parser in 357 * that way 358 */ 359 360 int i; 361 for (i = 0; i < USB_HID_MOD_COUNT; ++i) { 362 if ((modifiers & usb_hid_modifiers_consts[i]) && 363 !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 364 // modifier pressed 365 if (usbhid_modifiers_keycodes[i] != 0) { 366 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 367 usbhid_modifiers_keycodes[i]); 368 } 369 } else if (!(modifiers & usb_hid_modifiers_consts[i]) && 370 (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 371 // modifier released 372 if (usbhid_modifiers_keycodes[i] != 0) { 373 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 374 usbhid_modifiers_keycodes[i]); 375 } 376 } // no change 377 } 378 379 kbd_dev->modifiers = modifiers; 368 //static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 369 // const uint8_t *key_codes, size_t count) 370 //{ 371 // /* 372 // * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK 373 // * both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes??? 374 // * 375 // * modifiers should be sent as normal keys to usbhid_parse_scancode()!! 376 // * so maybe it would be better if I received it from report parser in 377 // * that way 378 // */ 379 380 // int i; 381 // for (i = 0; i < count; ++i) { 382 // if ((modifiers & usb_hid_modifiers_consts[i]) && 383 // !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 384 // // modifier pressed 385 // if (usbhid_modifiers_keycodes[i] != 0) { 386 // usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, 387 // usbhid_modifiers_keycodes[i]); 388 // } 389 // } else if (!(modifiers & usb_hid_modifiers_consts[i]) && 390 // (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) { 391 // // modifier released 392 // if (usbhid_modifiers_keycodes[i] != 0) { 393 // usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, 394 // usbhid_modifiers_keycodes[i]); 395 // } 396 // } // no change 397 // } 398 399 // kbd_dev->modifiers = modifiers; 400 //} 401 402 /*----------------------------------------------------------------------------*/ 403 404 static inline int usbhid_kbd_is_lock(unsigned int key_code) 405 { 406 return (key_code == KC_NUM_LOCK 407 || key_code == KC_SCROLL_LOCK 408 || key_code == KC_CAPS_LOCK); 380 409 } 381 410 … … 404 433 /* 405 434 * First of all, check if the kbd have reported phantom state. 435 * 436 * TODO: this must be changed as we don't know which keys are modifiers 437 * and which are regular keys. 406 438 */ 407 439 i = 0; … … 434 466 // not found, i.e. the key was released 435 467 key = usbhid_parse_scancode(kbd_dev->keys[j]); 436 usbhid_kbd_repeat_stop(kbd_dev, key); 468 if (!usbhid_kbd_is_lock(key)) { 469 usbhid_kbd_repeat_stop(kbd_dev, key); 470 } 437 471 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 438 472 usb_log_debug2("Key released: %d\n", key); … … 458 492 key_codes[i]); 459 493 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 460 usbhid_kbd_repeat_start(kbd_dev, key); 494 if (!usbhid_kbd_is_lock(key)) { 495 usbhid_kbd_repeat_start(kbd_dev, key); 496 } 461 497 } else { 462 498 // found, nothing happens … … 510 546 } 511 547 512 usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);548 ///usbhid_kbd_check_modifier_changes(kbd_dev, key_codes, count); 513 549 usbhid_kbd_check_key_changes(kbd_dev, key_codes, count); 514 550 } … … 535 571 uint8_t *buffer, size_t actual_size) 536 572 { 537 assert(kbd_dev->initialized );573 assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 538 574 assert(kbd_dev->hid_dev->parser != NULL); 539 575 … … 589 625 590 626 kbd_dev->console_phone = -1; 591 kbd_dev->initialized = 0;627 kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED; 592 628 593 629 return kbd_dev; … … 595 631 596 632 /*----------------------------------------------------------------------------*/ 597 /** 598 * Properly destroys the USB/HID keyboard structure. 599 * 600 * @param kbd_dev Pointer to the structure to be destroyed. 601 */ 602 static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev) 603 { 604 if (kbd_dev == NULL || *kbd_dev == NULL) { 605 return; 606 } 607 608 // hangup phone to the console 609 async_hangup((*kbd_dev)->console_phone); 610 611 if ((*kbd_dev)->hid_dev != NULL) { 612 usbhid_dev_free(&(*kbd_dev)->hid_dev); 613 assert((*kbd_dev)->hid_dev == NULL); 614 } 615 616 if ((*kbd_dev)->repeat_mtx != NULL) { 617 /* TODO: replace by some check and wait */ 618 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)); 619 free((*kbd_dev)->repeat_mtx); 620 } 621 622 free(*kbd_dev); 623 *kbd_dev = NULL; 633 634 static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev) 635 { 636 kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY; 624 637 } 625 638 … … 663 676 } 664 677 665 if (kbd_dev->initialized ) {678 if (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED) { 666 679 usb_log_warning("Keyboard structure already initialized.\n"); 667 680 return EINVAL; … … 676 689 } 677 690 678 assert(kbd_dev->hid_dev->initialized );691 assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 679 692 680 693 // save the size of the report (boot protocol report by default) 681 kbd_dev->key_count = BOOTP_REPORT_SIZE; 694 // kbd_dev->key_count = BOOTP_REPORT_SIZE; 695 696 usb_hid_report_path_t path; 697 path.usage_page = USB_HIDUT_PAGE_KEYBOARD; 698 kbd_dev->key_count = usb_hid_report_input_length( 699 kbd_dev->hid_dev->parser, &path); 700 701 usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count); 702 682 703 kbd_dev->keys = (uint8_t *)calloc( 683 704 kbd_dev->key_count, sizeof(uint8_t)); … … 720 741 usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE); 721 742 722 kbd_dev->initialized = 1;743 kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED; 723 744 usb_log_info("HID/KBD device structure initialized.\n"); 724 745 … … 834 855 usbhid_kbd_poll(kbd_dev); 835 856 857 // as there is another fibril using this device, so we must leave the 858 // structure to it, but mark it for destroying. 859 usbhid_kbd_mark_unusable(kbd_dev); 836 860 // at the end, properly destroy the KBD structure 837 usbhid_kbd_free(&kbd_dev);838 assert(kbd_dev == NULL);861 // usbhid_kbd_free(&kbd_dev); 862 // assert(kbd_dev == NULL); 839 863 840 864 return EOK; … … 958 982 } 959 983 984 /*----------------------------------------------------------------------------*/ 985 986 int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev) 987 { 988 return (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED); 989 } 990 991 /*----------------------------------------------------------------------------*/ 992 /** 993 * Properly destroys the USB/HID keyboard structure. 994 * 995 * @param kbd_dev Pointer to the structure to be destroyed. 996 */ 997 void usbhid_kbd_free(usbhid_kbd_t **kbd_dev) 998 { 999 if (kbd_dev == NULL || *kbd_dev == NULL) { 1000 return; 1001 } 1002 1003 // hangup phone to the console 1004 async_hangup((*kbd_dev)->console_phone); 1005 1006 if ((*kbd_dev)->hid_dev != NULL) { 1007 usbhid_dev_free(&(*kbd_dev)->hid_dev); 1008 assert((*kbd_dev)->hid_dev == NULL); 1009 } 1010 1011 if ((*kbd_dev)->repeat_mtx != NULL) { 1012 /* TODO: replace by some check and wait */ 1013 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)); 1014 free((*kbd_dev)->repeat_mtx); 1015 } 1016 1017 free(*kbd_dev); 1018 *kbd_dev = NULL; 1019 } 1020 960 1021 /** 961 1022 * @} -
uspace/drv/usbhid/kbddev.h
rc32688d r361e61b 101 101 fibril_mutex_t *repeat_mtx; 102 102 103 /** State of the structure (for checking before use). */ 103 /** State of the structure (for checking before use). 104 * 105 * 0 - not initialized 106 * 1 - initialized 107 * -1 - ready for destroying 108 */ 104 109 int initialized; 105 110 } usbhid_kbd_t; … … 108 113 109 114 int usbhid_kbd_try_add_device(ddf_dev_t *dev); 115 116 int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev); 117 118 void usbhid_kbd_free(usbhid_kbd_t **kbd_dev); 110 119 111 120 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key); -
uspace/drv/usbhid/kbdrepeat.c
rc32688d r361e61b 77 77 78 78 while (true) { 79 // check if the kbd structure is usable 80 if (!usbhid_kbd_is_usable(kbd)) { 81 usbhid_kbd_free(&kbd); 82 assert(kbd == NULL); 83 return; 84 } 85 79 86 fibril_mutex_lock(kbd->repeat_mtx); 80 87 -
uspace/drv/usbhub/main.c
rc32688d r361e61b 36 36 #include <stdio.h> 37 37 38 #include <usb/devdrv.h> 39 #include <usb/classes/classes.h> 40 38 41 #include "usbhub.h" 39 42 #include "usbhub_private.h" 40 43 41 44 42 usb_general_list_t usb_hub_list; 43 fibril_mutex_t usb_hub_list_lock; 44 45 static driver_ops_t hub_driver_ops = { 46 .add_device = usb_add_hub_device, 45 usb_endpoint_description_t hub_status_change_endpoint_description = { 46 .transfer_type = USB_TRANSFER_INTERRUPT, 47 .direction = USB_DIRECTION_IN, 48 .interface_class = USB_CLASS_HUB, 49 .interface_subclass = 0, 50 .interface_protocol = 0, 51 .flags = 0 47 52 }; 48 53 49 static driver_t hub_driver = { 54 55 static usb_driver_ops_t usb_hub_driver_ops = { 56 .add_device = usb_hub_add_device 57 }; 58 59 static usb_driver_t usb_hub_driver = { 50 60 .name = "usbhub", 51 . driver_ops = &hub_driver_ops61 .ops = &usb_hub_driver_ops 52 62 }; 63 53 64 54 65 int main(int argc, char *argv[]) 55 66 { 56 67 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 57 dprintf(USB_LOG_LEVEL_INFO, "starting hub driver");68 usb_log_info("starting hub driver\n"); 58 69 59 //this is probably not needed anymore60 fibril_mutex_initialize(&usb_hub_list_lock);61 fibril_mutex_lock(&usb_hub_list_lock);62 usb_lst_init(&usb_hub_list);63 fibril_mutex_unlock(&usb_hub_list_lock);64 70 65 return ddf_driver_main(&hub_driver); 71 usb_hub_driver.endpoints = (usb_endpoint_description_t**) 72 malloc(2 * sizeof(usb_endpoint_description_t*)); 73 usb_hub_driver.endpoints[0] = &hub_status_change_endpoint_description; 74 usb_hub_driver.endpoints[1] = NULL; 75 76 return usb_driver_main(&usb_hub_driver); 66 77 } 67 78 -
uspace/drv/usbhub/port_status.h
rc32688d r361e61b 270 270 } 271 271 272 //low speed device attached 273 static inline bool usb_port_high_speed(usb_port_status_t * status){ 274 return usb_port_get_bit(status,10); 275 } 276 277 static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){ 278 usb_port_set_bit(status,10,high_speed); 279 } 280 281 static inline usb_speed_t usb_port_speed(usb_port_status_t * status){ 282 if(usb_port_low_speed(status)) 283 return USB_SPEED_LOW; 284 if(usb_port_high_speed(status)) 285 return USB_SPEED_HIGH; 286 return USB_SPEED_FULL; 287 } 288 272 289 273 290 //connect change -
uspace/drv/usbhub/usbhub.c
rc32688d r361e61b 53 53 #include "usb/classes/classes.h" 54 54 55 static ddf_dev_ops_t hub_device_ops = {56 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl57 };58 59 /** Hub status-change endpoint description60 *61 * For more see usb hub specification in 11.15.1 of62 */63 static usb_endpoint_description_t status_change_endpoint_description = {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 = 070 };71 72 55 int usb_hub_control_loop(void * hub_info_param){ 73 56 usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param; 74 while(true){ 75 usb_hub_check_hub_changes(hub_info); 57 int errorCode = EOK; 58 59 while(errorCode == EOK){ 60 errorCode = usb_hub_check_hub_changes(hub_info); 76 61 async_usleep(1000 * 1000 );/// \TODO proper number once 77 62 } 63 usb_log_error("something in ctrl loop went wrong, errno %d\n",errorCode); 64 78 65 return 0; 79 66 } … … 87 74 88 75 /** 89 * Initialize connnections to host controller, device, and device 90 * control endpoint 91 * @param hub 92 * @param device 76 * create usb_hub_info_t structure 77 * 78 * Does only basic copying of known information into new structure. 79 * @param usb_dev usb device structure 80 * @return basic usb_hub_info_t structure 81 */ 82 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) { 83 usb_hub_info_t * result = usb_new(usb_hub_info_t); 84 if(!result) return NULL; 85 result->usb_device = usb_dev; 86 result->status_change_pipe = usb_dev->pipes[0].pipe; 87 result->control_pipe = &usb_dev->ctrl_pipe; 88 result->is_default_address_used = false; 89 return result; 90 } 91 92 /** 93 * Load hub-specific information into hub_info structure. 94 * 95 * Particularly read port count and initialize structure holding port 96 * information. 97 * This function is hub-specific and should be run only after the hub is 98 * configured using usb_hub_set_configuration function. 99 * @param hub_info pointer to structure with usb hub data 100 * @return error code 101 */ 102 static int usb_hub_get_hub_specific_info(usb_hub_info_t * hub_info){ 103 // get hub descriptor 104 usb_log_debug("creating serialized descriptor\n"); 105 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE); 106 usb_hub_descriptor_t * descriptor; 107 108 /* this was one fix of some bug, should not be needed anymore 109 int opResult = usb_request_set_configuration(&result->endpoints.control, 1); 110 if(opResult!=EOK){ 111 usb_log_error("could not set default configuration, errno %d",opResult); 112 return opResult; 113 } 114 */ 115 size_t received_size; 116 int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe, 117 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 118 USB_DESCTYPE_HUB, 119 0, 0, serialized_descriptor, 120 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 121 122 if (opResult != EOK) { 123 usb_log_error("failed when receiving hub descriptor, badcode = %d\n", 124 opResult); 125 free(serialized_descriptor); 126 return opResult; 127 } 128 usb_log_debug2("deserializing descriptor\n"); 129 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor); 130 if(descriptor==NULL){ 131 usb_log_warning("could not deserialize descriptor \n"); 132 return opResult; 133 } 134 usb_log_info("setting port count to %d\n",descriptor->ports_count); 135 hub_info->port_count = descriptor->ports_count; 136 hub_info->attached_devs = (usb_hc_attached_device_t*) 137 malloc((hub_info->port_count+1) * sizeof(usb_hc_attached_device_t)); 138 int i; 139 for(i=0;i<hub_info->port_count+1;++i){ 140 hub_info->attached_devs[i].handle=0; 141 hub_info->attached_devs[i].address=0; 142 } 143 usb_log_debug2("freeing data\n"); 144 free(serialized_descriptor); 145 free(descriptor->devices_removable); 146 free(descriptor); 147 return EOK; 148 } 149 /** 150 * Set configuration of hub 151 * 152 * Check whether there is at least one configuration and sets the first one. 153 * This function should be run prior to running any hub-specific action. 154 * @param hub_info 93 155 * @return 94 156 */ 95 static int usb_hub_init_communication(usb_hub_info_t * hub){ 96 usb_log_debug("Initializing hub USB communication (hub->device->handle=%zu).\n", hub->device->handle); 97 int opResult; 98 opResult = usb_device_connection_initialize_from_device( 99 &hub->device_connection, 100 hub->device); 101 if(opResult != EOK){ 102 dprintf(USB_LOG_LEVEL_ERROR, 103 "could not initialize connection to hc, errno %d",opResult); 104 return opResult; 105 } 106 usb_log_debug("Initializing USB wire abstraction.\n"); 107 opResult = usb_hc_connection_initialize_from_device(&hub->connection, 108 hub->device); 109 if(opResult != EOK){ 110 dprintf(USB_LOG_LEVEL_ERROR, 111 "could not initialize connection to device, errno %d",opResult); 112 return opResult; 113 } 114 usb_log_debug("Initializing default control pipe.\n"); 115 opResult = usb_endpoint_pipe_initialize_default_control(&hub->endpoints.control, 116 &hub->device_connection); 117 if(opResult != EOK){ 118 dprintf(USB_LOG_LEVEL_ERROR, 119 "could not initialize connection to device endpoint, errno %d",opResult); 120 } 121 return opResult; 122 } 123 124 /** 125 * When entering this function, hub->endpoints.control should be active. 126 * @param hub 127 * @return 128 */ 129 static int usb_hub_process_configuration_descriptors( 130 usb_hub_info_t * hub){ 131 if(hub==NULL) { 132 return EINVAL; 133 } 134 int opResult; 135 157 static int usb_hub_set_configuration(usb_hub_info_t * hub_info){ 136 158 //device descriptor 137 159 usb_standard_device_descriptor_t std_descriptor; 138 opResult = usb_request_get_device_descriptor(&hub->endpoints.control, 160 int opResult = usb_request_get_device_descriptor( 161 &hub_info->usb_device->ctrl_pipe, 139 162 &std_descriptor); 140 163 if(opResult!=EOK){ 141 dprintf(USB_LOG_LEVEL_ERROR, "could not get device descriptor, %d",opResult);142 return opResult; 143 } 144 dprintf(USB_LOG_LEVEL_INFO, "hub has %d configurations",164 usb_log_error("could not get device descriptor, %d\n",opResult); 165 return opResult; 166 } 167 usb_log_info("hub has %d configurations\n", 145 168 std_descriptor.configuration_count); 146 169 if(std_descriptor.configuration_count<1){ 147 dprintf(USB_LOG_LEVEL_ERROR, "THERE ARE NO CONFIGURATIONS AVAILABLE");170 usb_log_error("THERE ARE NO CONFIGURATIONS AVAILABLE\n"); 148 171 //shouldn`t I return? 149 172 } … … 153 176 size_t descriptors_size = 0; 154 177 opResult = usb_request_get_full_configuration_descriptor_alloc( 155 &hub ->endpoints.control, 0,178 &hub_info->usb_device->ctrl_pipe, 0, 156 179 (void **) &descriptors, &descriptors_size); 157 180 if (opResult != EOK) { … … 164 187 165 188 /* Set configuration. */ 166 opResult = usb_request_set_configuration(&hub ->endpoints.control,189 opResult = usb_request_set_configuration(&hub_info->usb_device->ctrl_pipe, 167 190 config_descriptor->configuration_number); 168 191 … … 172 195 return opResult; 173 196 } 174 dprintf(USB_LOG_LEVEL_DEBUG, "\tused configuration %d",197 usb_log_debug("\tused configuration %d\n", 175 198 config_descriptor->configuration_number); 176 177 usb_endpoint_mapping_t endpoint_mapping[1] = {178 {179 .pipe = &hub->endpoints.status_change,180 .description = &status_change_endpoint_description,181 .interface_no =182 usb_device_get_assigned_interface(hub->device)183 }184 };185 opResult = usb_endpoint_pipe_initialize_from_configuration(186 endpoint_mapping, 1,187 descriptors, descriptors_size,188 &hub->device_connection);189 if (opResult != EOK) {190 dprintf(USB_LOG_LEVEL_ERROR,191 "Failed to initialize status change pipe: %s",192 str_error(opResult));193 return opResult;194 }195 if (!endpoint_mapping[0].present) {196 dprintf(USB_LOG_LEVEL_ERROR,"Not accepting device, " \197 "cannot understand what is happenning");198 return EREFUSED;199 }200 201 199 free(descriptors); 202 200 return EOK; 201 } 202 203 /** 204 * Initialize hub device driver fibril 205 * 206 * Creates hub representation and fibril that periodically checks hub`s status. 207 * Hub representation is passed to the fibril. 208 * @param usb_dev generic usb device information 209 * @return error code 210 */ 211 int usb_hub_add_device(usb_device_t * usb_dev){ 212 if(!usb_dev) return EINVAL; 213 usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev); 214 //create hc connection 215 usb_log_debug("Initializing USB wire abstraction.\n"); 216 int opResult = usb_hc_connection_initialize_from_device( 217 &hub_info->connection, 218 hub_info->usb_device->ddf_dev); 219 if(opResult != EOK){ 220 usb_log_error("could not initialize connection to device, errno %d\n", 221 opResult); 222 free(hub_info); 223 return opResult; 224 } 203 225 204 } 205 206 207 /** 208 * Create hub representation from device information. 209 * @param device 210 * @return pointer to created structure or NULL in case of error 211 */ 212 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device) { 213 usb_hub_info_t* result = usb_new(usb_hub_info_t); 214 result->device = device; 215 int opResult; 216 opResult = usb_hub_init_communication(result); 217 if(opResult != EOK){ 218 free(result); 219 return NULL; 220 } 221 222 //result->device = device; 223 result->port_count = -1; 224 result->device = device; 225 226 //result->usb_device = usb_new(usb_hcd_attached_device_info_t); 227 size_t received_size; 228 229 // get hub descriptor 230 dprintf(USB_LOG_LEVEL_DEBUG, "creating serialized descripton"); 231 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE); 232 usb_hub_descriptor_t * descriptor; 233 dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction"); 234 usb_endpoint_pipe_start_session(&result->endpoints.control); 235 opResult = usb_request_set_configuration(&result->endpoints.control, 1); 236 assert(opResult == EOK); 237 238 opResult = usb_request_get_descriptor(&result->endpoints.control, 239 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 240 USB_DESCTYPE_HUB, 241 0, 0, serialized_descriptor, 242 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 243 usb_endpoint_pipe_end_session(&result->endpoints.control); 244 245 if (opResult != EOK) { 246 dprintf(USB_LOG_LEVEL_ERROR, "failed when receiving hub descriptor, badcode = %d",opResult); 247 free(serialized_descriptor); 248 free(result); 249 return NULL; 250 } 251 dprintf(USB_LOG_LEVEL_DEBUG2, "deserializing descriptor"); 252 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor); 253 if(descriptor==NULL){ 254 dprintf(USB_LOG_LEVEL_WARNING, "could not deserialize descriptor "); 255 free(result); 256 return NULL; 257 } 258 259 dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count); 260 result->port_count = descriptor->ports_count; 261 result->attached_devs = (usb_hc_attached_device_t*) 262 malloc((result->port_count+1) * sizeof(usb_hc_attached_device_t)); 263 int i; 264 for(i=0;i<result->port_count+1;++i){ 265 result->attached_devs[i].handle=0; 266 result->attached_devs[i].address=0; 267 } 268 dprintf(USB_LOG_LEVEL_DEBUG2, "freeing data"); 269 free(serialized_descriptor); 270 free(descriptor->devices_removable); 271 free(descriptor); 272 273 //finish 274 275 dprintf(USB_LOG_LEVEL_INFO, "hub info created"); 276 277 return result; 278 } 279 280 /** 281 * Create hub representation and add it into hub list 282 * @param dev 283 * @return 284 */ 285 int usb_add_hub_device(ddf_dev_t *dev) { 286 dprintf(USB_LOG_LEVEL_INFO, "add_hub_device(handle=%d)", (int) dev->handle); 287 288 //dev->ops = &hub_device_ops; 289 (void) hub_device_ops; 290 291 usb_hub_info_t * hub_info = usb_create_hub_info(dev); 292 if(!hub_info){ 293 return EINTR; 294 } 295 296 int opResult; 297 298 //perform final configurations 299 usb_endpoint_pipe_start_session(&hub_info->endpoints.control); 300 // process descriptors 301 opResult = usb_hub_process_configuration_descriptors(hub_info); 302 if(opResult != EOK){ 303 dprintf(USB_LOG_LEVEL_ERROR,"could not get configuration descriptors, %d", 304 opResult); 305 return opResult; 306 } 307 //power ports 308 usb_device_request_setup_packet_t request; 309 int port; 310 for (port = 1; port < hub_info->port_count+1; ++port) { 311 usb_hub_set_power_port_request(&request, port); 312 opResult = usb_endpoint_pipe_control_write(&hub_info->endpoints.control, 313 &request,sizeof(usb_device_request_setup_packet_t), NULL, 0); 314 dprintf(USB_LOG_LEVEL_INFO, "powering port %d",port); 315 if (opResult != EOK) { 316 dprintf(USB_LOG_LEVEL_WARNING, "something went wrong when setting hub`s %dth port", port); 317 } 318 } 319 //ports powered, hub seems to be enabled 320 usb_endpoint_pipe_end_session(&hub_info->endpoints.control); 321 322 //add the hub to list 323 //is this needed now? 324 fibril_mutex_lock(&usb_hub_list_lock); 325 usb_lst_append(&usb_hub_list, hub_info); 326 fibril_mutex_unlock(&usb_hub_list_lock); 327 dprintf(USB_LOG_LEVEL_DEBUG, "hub info added to list"); 328 329 dprintf(USB_LOG_LEVEL_DEBUG, "adding to ddf"); 330 ddf_fun_t *hub_fun = ddf_fun_create(dev, fun_exposed, "hub"); 226 usb_endpoint_pipe_start_session(hub_info->control_pipe); 227 //set hub configuration 228 opResult = usb_hub_set_configuration(hub_info); 229 if(opResult!=EOK){ 230 usb_log_error("could not set hub configuration, errno %d\n",opResult); 231 free(hub_info); 232 return opResult; 233 } 234 //get port count and create attached_devs 235 opResult = usb_hub_get_hub_specific_info(hub_info); 236 if(opResult!=EOK){ 237 usb_log_error("could not set hub configuration, errno %d\n",opResult); 238 free(hub_info); 239 return opResult; 240 } 241 usb_endpoint_pipe_end_session(hub_info->control_pipe); 242 243 244 /// \TODO what is this? 245 usb_log_debug("adding to ddf"); 246 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev, 247 fun_exposed, "hub"); 331 248 assert(hub_fun != NULL); 332 249 hub_fun->ops = NULL; … … 337 254 assert(rc == EOK); 338 255 256 //create fibril for the hub control loop 339 257 fid_t fid = fibril_create(usb_hub_control_loop, hub_info); 340 258 if (fid == 0) { 341 dprintf(USB_LOG_LEVEL_ERROR, 342 ": failed to start monitoring fibril for new hub"); 259 usb_log_error("failed to start monitoring fibril for new hub"); 343 260 return ENOMEM; 344 261 } 345 262 fibril_add_ready(fid); 346 347 dprintf(USB_LOG_LEVEL_DEBUG, "hub fibril created"); 348 //(void)hub_info; 349 //usb_hub_check_hub_changes(); 350 351 dprintf(USB_LOG_LEVEL_INFO, "hub dev added"); 352 //address is lost... 353 dprintf(USB_LOG_LEVEL_DEBUG, "\taddress %d, has %d ports ", 354 //hub_info->endpoints.control., 355 hub_info->port_count); 356 263 usb_log_debug("hub fibril created"); 264 usb_log_debug("has %d ports ",hub_info->port_count); 357 265 return EOK; 358 //return ENOTSUP;359 266 } 360 267 … … 367 274 368 275 /** 276 * release default address used by given hub 277 * 278 * Also unsets hub->is_default_address_used. Convenience wrapper function. 279 * @note hub->connection MUST be open for communication 280 * @param hub hub representation 281 * @return error code 282 */ 283 static int usb_hub_release_default_address(usb_hub_info_t * hub){ 284 int opResult = usb_hc_release_default_address(&hub->connection); 285 if(opResult!=EOK){ 286 usb_log_error("could not release default address, errno %d\n",opResult); 287 return opResult; 288 } 289 hub->is_default_address_used = false; 290 return EOK; 291 } 292 293 /** 369 294 * Reset the port with new device and reserve the default address. 370 295 * @param hc … … 372 297 * @param target 373 298 */ 374 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port) { 299 static void usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port, 300 usb_speed_t speed) { 301 //if this hub already uses default address, it cannot request it once more 302 if(hub->is_default_address_used) return; 303 usb_log_info("some connection changed\n"); 304 assert(hub->control_pipe->hc_phone); 305 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 306 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 307 if(opResult != EOK){ 308 usb_log_warning("could not clear port-change-connection flag\n"); 309 } 375 310 usb_device_request_setup_packet_t request; 376 int opResult; 377 dprintf(USB_LOG_LEVEL_INFO, "some connection changed"); 378 assert(hub->endpoints.control.hc_phone); 311 379 312 //get default address 380 //opResult = usb_drv_reserve_default_address(hc); 381 opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW); 313 opResult = usb_hc_reserve_default_address(&hub->connection, speed); 382 314 383 315 if (opResult != EOK) { 384 dprintf(USB_LOG_LEVEL_WARNING, 385 "cannot assign default address, it is probably used %d",opResult); 386 return; 387 } 316 usb_log_warning("cannot assign default address, it is probably used %d\n", 317 opResult); 318 return; 319 } 320 hub->is_default_address_used = true; 388 321 //reset port 389 322 usb_hub_set_reset_port_request(&request, port); 390 323 opResult = usb_endpoint_pipe_control_write( 391 &hub->endpoints.control,324 hub->control_pipe, 392 325 &request,sizeof(usb_device_request_setup_packet_t), 393 326 NULL, 0 394 327 ); 395 328 if (opResult != EOK) { 396 dprintf(USB_LOG_LEVEL_ERROR, 397 "something went wrong when reseting a port %d",opResult); 329 usb_log_error("something went wrong when reseting a port %d\n",opResult); 398 330 //usb_hub_release_default_address(hc); 399 usb_hc_release_default_address(&hub->connection); 400 } 331 usb_hub_release_default_address(hub); 332 } 333 return; 401 334 } 402 335 … … 408 341 */ 409 342 static void usb_hub_finalize_add_device( usb_hub_info_t * hub, 410 uint16_t port, bool isLowSpeed) {343 uint16_t port, usb_speed_t speed) { 411 344 412 345 int opResult; 413 dprintf(USB_LOG_LEVEL_INFO, "finalizing add device");414 opResult = usb_hub_clear_port_feature( &hub->endpoints.control,346 usb_log_info("finalizing add device\n"); 347 opResult = usb_hub_clear_port_feature(hub->control_pipe, 415 348 port, USB_HUB_FEATURE_C_PORT_RESET); 416 349 417 350 if (opResult != EOK) { 418 dprintf(USB_LOG_LEVEL_ERROR, "failed to clear port reset feature");419 usb_h c_release_default_address(&hub->connection);351 usb_log_error("failed to clear port reset feature\n"); 352 usb_hub_release_default_address(hub); 420 353 return; 421 354 } … … 430 363 &new_device_pipe, 431 364 &new_device_connection); 432 /// \TODO get highspeed info 433 usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL; 434 365 usb_endpoint_pipe_probe_default_control(&new_device_pipe); 435 366 436 367 /* Request address from host controller. */ 437 368 usb_address_t new_device_address = usb_hc_request_address( 438 369 &hub->connection, 439 speed /// \TODO fullspeed??370 speed 440 371 ); 441 372 if (new_device_address < 0) { 442 dprintf(USB_LOG_LEVEL_ERROR, "failed to get free USB address");373 usb_log_error("failed to get free USB address\n"); 443 374 opResult = new_device_address; 444 usb_h c_release_default_address(&hub->connection);445 return; 446 } 447 dprintf(USB_LOG_LEVEL_INFO, "setting new address %d",new_device_address);375 usb_hub_release_default_address(hub); 376 return; 377 } 378 usb_log_info("setting new address %d\n",new_device_address); 448 379 //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT, 449 380 // new_device_address); … … 452 383 usb_endpoint_pipe_end_session(&new_device_pipe); 453 384 if (opResult != EOK) { 454 dprintf(USB_LOG_LEVEL_ERROR, 455 "could not set address for new device %d",opResult); 456 usb_hc_release_default_address(&hub->connection); 385 usb_log_error("could not set address for new device %d\n",opResult); 386 usb_hub_release_default_address(hub); 457 387 return; 458 388 } … … 460 390 461 391 //opResult = usb_hub_release_default_address(hc); 462 opResult = usb_h c_release_default_address(&hub->connection);392 opResult = usb_hub_release_default_address(hub); 463 393 if(opResult!=EOK){ 464 394 return; … … 468 398 //?? 469 399 opResult = usb_device_register_child_in_devman(new_device_address, 470 hub->connection.hc_handle, hub-> device, &child_handle,400 hub->connection.hc_handle, hub->usb_device->ddf_dev, &child_handle, 471 401 NULL, NULL, NULL); 472 402 473 403 if (opResult != EOK) { 474 dprintf(USB_LOG_LEVEL_ERROR, 475 "could not start driver for new device %d",opResult); 404 usb_log_error("could not start driver for new device %d\n",opResult); 476 405 return; 477 406 } … … 484 413 &hub->attached_devs[port]); 485 414 if (opResult != EOK) { 486 dprintf(USB_LOG_LEVEL_ERROR, 487 "could not assign address of device in hcd %d",opResult); 488 return; 489 } 490 dprintf(USB_LOG_LEVEL_INFO, "new device address %d, handle %zu", 415 usb_log_error("could not assign address of device in hcd %d\n",opResult); 416 return; 417 } 418 usb_log_info("new device address %d, handle %zu\n", 491 419 new_device_address, child_handle); 492 420 … … 501 429 static void usb_hub_removed_device( 502 430 usb_hub_info_t * hub,uint16_t port) { 503 //usb_device_request_setup_packet_t request; 504 int opResult; 505 431 432 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 433 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 434 if(opResult != EOK){ 435 usb_log_warning("could not clear port-change-connection flag\n"); 436 } 506 437 /** \TODO remove device from device manager - not yet implemented in 507 438 * devide manager … … 510 441 //close address 511 442 if(hub->attached_devs[port].address!=0){ 512 / /opResult = usb_drv_release_address(hc,hub->attached_devs[port].address);443 /*uncomment this code to use it when DDF allows device removal 513 444 opResult = usb_hc_unregister_device( 514 445 &hub->connection, hub->attached_devs[port].address); … … 519 450 hub->attached_devs[port].address = 0; 520 451 hub->attached_devs[port].handle = 0; 452 */ 521 453 }else{ 522 dprintf(USB_LOG_LEVEL_WARNING, "this is strange, disconnected device had no address");454 usb_log_warning("this is strange, disconnected device had no address\n"); 523 455 //device was disconnected before it`s port was reset - return default address 524 //usb_drv_release_default_address(hc); 525 usb_hc_release_default_address(&hub->connection); 526 } 527 } 528 529 530 /** 531 *Process over current condition on port. 456 usb_hub_release_default_address(hub); 457 } 458 } 459 460 461 /** 462 * Process over current condition on port. 532 463 * 533 464 * Turn off the power on the port. … … 539 470 uint16_t port){ 540 471 int opResult; 541 opResult = usb_hub_clear_port_feature( &hub->endpoints.control,472 opResult = usb_hub_clear_port_feature(hub->control_pipe, 542 473 port, USB_HUB_FEATURE_PORT_POWER); 543 474 if(opResult!=EOK){ 544 dprintf(USB_LOG_LEVEL_ERROR, "cannot power off port %d; %d",475 usb_log_error("cannot power off port %d; %d\n", 545 476 port, opResult); 546 477 } … … 555 486 static void usb_hub_process_interrupt(usb_hub_info_t * hub, 556 487 uint16_t port) { 557 dprintf(USB_LOG_LEVEL_DEBUG, "interrupt at port %d", port);488 usb_log_debug("interrupt at port %d\n", port); 558 489 //determine type of change 559 usb_endpoint_pipe_t *pipe = &hub->endpoints.control;490 usb_endpoint_pipe_t *pipe = hub->control_pipe; 560 491 561 492 int opResult; … … 574 505 ); 575 506 if (opResult != EOK) { 576 dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");507 usb_log_error("could not get port status\n"); 577 508 return; 578 509 } 579 510 if (rcvd_size != sizeof (usb_port_status_t)) { 580 dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");511 usb_log_error("received status has incorrect size\n"); 581 512 return; 582 513 } 583 514 //something connected/disconnected 584 515 if (usb_port_connect_change(&status)) { 585 opResult = usb_hub_clear_port_feature(pipe,586 port, USB_HUB_FEATURE_C_PORT_CONNECTION);587 // TODO: check opResult588 516 if (usb_port_dev_connected(&status)) { 589 dprintf(USB_LOG_LEVEL_INFO, "some connection changed");590 usb_hub_init_add_device(hub, port );517 usb_log_info("some connection changed\n"); 518 usb_hub_init_add_device(hub, port, usb_port_speed(&status)); 591 519 } else { 592 520 usb_hub_removed_device(hub, port); … … 599 527 usb_hub_over_current(hub,port); 600 528 }else{ 601 dprintf(USB_LOG_LEVEL_INFO,602 "over current condition was auto-resolved on port %d",port);529 usb_log_info("over current condition was auto-resolved on port %d\n", 530 port); 603 531 } 604 532 } 605 533 //port reset 606 534 if (usb_port_reset_completed(&status)) { 607 dprintf(USB_LOG_LEVEL_INFO,"port reset complete");535 usb_log_info("port reset complete"); 608 536 if (usb_port_enabled(&status)) { 609 usb_hub_finalize_add_device(hub, port, usb_port_ low_speed(&status));537 usb_hub_finalize_add_device(hub, port, usb_port_speed(&status)); 610 538 } else { 611 dprintf(USB_LOG_LEVEL_WARNING, "port reset, but port still not enabled");539 usb_log_warning("port reset, but port still not enabled\n"); 612 540 } 613 541 } … … 618 546 usb_port_set_dev_connected(&status, false); 619 547 if (status>>16) { 620 dprintf(USB_LOG_LEVEL_INFO, "there was some unsupported change on port %d: %X",port,status);621 622 } 623 /// \TODO handle other changes548 usb_log_info("there was some unsupported change on port %d: %X\n", 549 port,status); 550 551 } 624 552 } 625 553 626 554 /** 627 555 * Check changes on particular hub 628 * @param hub_info_param 629 */ 630 void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){ 556 * @param hub_info_param pointer to usb_hub_info_t structure 557 * @return error code if there is problem when initializing communication with 558 * hub, EOK otherwise 559 */ 560 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info){ 631 561 int opResult; 632 opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change); 562 opResult = usb_endpoint_pipe_start_session( 563 hub_info->status_change_pipe); 633 564 if(opResult != EOK){ 634 dprintf(USB_LOG_LEVEL_ERROR,635 "could not initialize communication for hub; %d",opResult);636 return ;565 usb_log_error("could not initialize communication for hub; %d\n", 566 opResult); 567 return opResult; 637 568 } 638 569 … … 648 579 */ 649 580 opResult = usb_endpoint_pipe_read( 650 &hub_info->endpoints.status_change,581 hub_info->status_change_pipe, 651 582 change_bitmap, byte_length, &actual_size 652 583 ); … … 654 585 if (opResult != EOK) { 655 586 free(change_bitmap); 656 dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");657 usb_endpoint_pipe_end_session( &hub_info->endpoints.status_change);658 return ;587 usb_log_warning("something went wrong while getting status of hub\n"); 588 usb_endpoint_pipe_end_session(hub_info->status_change_pipe); 589 return opResult; 659 590 } 660 591 unsigned int port; 661 opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.control); 662 if(opResult!=EOK){ 663 dprintf(USB_LOG_LEVEL_ERROR, "could not start control pipe session %d", 592 opResult = usb_endpoint_pipe_start_session(hub_info->control_pipe); 593 if(opResult!=EOK){ 594 usb_log_error("could not start control pipe session %d\n", opResult); 595 usb_endpoint_pipe_end_session(hub_info->status_change_pipe); 596 return opResult; 597 } 598 opResult = usb_hc_connection_open(&hub_info->connection); 599 if(opResult!=EOK){ 600 usb_log_error("could not start host controller session %d\n", 664 601 opResult); 665 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change); 666 return; 667 } 668 opResult = usb_hc_connection_open(&hub_info->connection); 669 if(opResult!=EOK){ 670 dprintf(USB_LOG_LEVEL_ERROR, "could not start host controller session %d", 671 opResult); 672 usb_endpoint_pipe_end_session(&hub_info->endpoints.control); 673 usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change); 674 return; 602 usb_endpoint_pipe_end_session(hub_info->control_pipe); 603 usb_endpoint_pipe_end_session(hub_info->status_change_pipe); 604 return opResult; 675 605 } 676 606 … … 685 615 } 686 616 usb_hc_connection_close(&hub_info->connection); 687 usb_endpoint_pipe_end_session( &hub_info->endpoints.control);688 usb_endpoint_pipe_end_session( &hub_info->endpoints.status_change);617 usb_endpoint_pipe_end_session(hub_info->control_pipe); 618 usb_endpoint_pipe_end_session(hub_info->status_change_pipe); 689 619 free(change_bitmap); 620 return EOK; 690 621 } 691 622 -
uspace/drv/usbhub/usbhub.h
rc32688d r361e61b 45 45 46 46 #include <usb/pipes.h> 47 #include <usb/devdrv.h> 48 49 50 /** Hub status-change endpoint description 51 * 52 * For more see usb hub specification in 11.15.1 of 53 */ 54 extern usb_endpoint_description_t hub_status_change_endpoint_description; 55 56 47 57 48 58 /* Hub endpoints. */ 49 typedef struct {59 /*typedef struct { 50 60 usb_endpoint_pipe_t control; 51 61 usb_endpoint_pipe_t status_change; 52 62 } usb_hub_endpoints_t; 53 63 */ 54 64 55 65 … … 58 68 /** Number of ports. */ 59 69 int port_count; 70 60 71 /** attached device handles, for each port one */ 61 72 usb_hc_attached_device_t * attached_devs; 62 /** General usb device info. */ 63 //usb_hcd_attached_device_info_t * usb_device; 64 /** General device info*/ 65 ddf_dev_t * device; 73 66 74 /** connection to hcd */ 67 //usb_device_connection_t connection;68 75 usb_hc_connection_t connection; 69 /** */ 70 usb_device_connection_t device_connection; 71 /** hub endpoints */ 72 usb_hub_endpoints_t endpoints; 76 77 /** default address is used indicator 78 * 79 * If default address is requested by this device, it cannot 80 * be requested by the same hub again, otherwise a deadlock will occur. 81 */ 82 bool is_default_address_used; 83 84 /** convenience pointer to status change pipe 85 * 86 * Status change pipe is initialized in usb_device structure. This is 87 * pointer into this structure, so that it does not have to be 88 * searched again and again for the 'right pipe'. 89 */ 90 usb_endpoint_pipe_t * status_change_pipe; 91 92 /** convenience pointer to control pipe 93 * 94 * Control pipe is initialized in usb_device structure. This is 95 * pointer into this structure, so that it does not have to be 96 * searched again and again for the 'right pipe'. 97 */ 98 usb_endpoint_pipe_t * control_pipe; 99 100 /** generic usb device data*/ 101 usb_device_t * usb_device; 73 102 } usb_hub_info_t; 74 103 … … 79 108 int usb_hub_control_loop(void * hub_info_param); 80 109 81 /** Callback when new hub device is detected. 82 * 83 * @param dev New device. 84 * @return Error code. 110 /** 111 * Check changes on specified hub 112 * @param hub_info_param pointer to usb_hub_info_t structure 113 * @return error code if there is problem when initializing communication with 114 * hub, EOK otherwise 85 115 */ 86 int usb_add_hub_device(ddf_dev_t *dev); 87 88 /** 89 * check changes on specified hub 90 * @param hub_info_param pointer to usb_hub_info_t structure 91 */ 92 void usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param); 116 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param); 93 117 94 118 95 96 119 int usb_hub_add_device(usb_device_t * usb_dev); 97 120 98 121 #endif -
uspace/drv/usbhub/usbhub_private.h
rc32688d r361e61b 58 58 59 59 60 //************61 //62 // convenience debug printf for usb hub63 //64 //************65 #define dprintf(level, format, ...) \66 usb_log_printf((level), format "\n", ##__VA_ARGS__)67 68 69 60 /** 70 61 * Create hub structure instance … … 77 68 */ 78 69 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device); 79 80 /** List of hubs maanged by this driver */81 extern usb_general_list_t usb_hub_list;82 83 /** Lock for hub list*/84 extern fibril_mutex_t usb_hub_list_lock;85 86 87 /**88 * Perform complete control read transaction89 *90 * Manages all three steps of transaction: setup, read and finalize91 * @param phone92 * @param target93 * @param request Request packet94 * @param rcvd_buffer Received data95 * @param rcvd_size96 * @param actual_size Actual size of received data97 * @return error code98 */99 /*100 int usb_drv_sync_control_read(101 usb_endpoint_pipe_t *pipe,102 usb_device_request_setup_packet_t * request,103 void * rcvd_buffer, size_t rcvd_size, size_t * actual_size104 );*/105 106 /**107 * Perform complete control write transaction108 *109 * Manages all three steps of transaction: setup, write and finalize110 * @param phone111 * @param target112 * @param request Request packet to send data113 * @param sent_buffer114 * @param sent_size115 * @return error code116 */117 /*int usb_drv_sync_control_write(118 usb_endpoint_pipe_t *pipe,119 usb_device_request_setup_packet_t * request,120 void * sent_buffer, size_t sent_size121 );*/122 70 123 71 /** … … 163 111 164 112 /** 165 * @briefcreate uint8_t array with serialized descriptor113 * create uint8_t array with serialized descriptor 166 114 * 167 115 * @param descriptor … … 171 119 172 120 /** 173 * @briefcreate deserialized desriptor structure out of serialized descriptor121 * create deserialized desriptor structure out of serialized descriptor 174 122 * 175 123 * The serialized descriptor must be proper usb hub descriptor, -
uspace/drv/usbhub/utils.c
rc32688d r361e61b 88 88 89 89 if (sdescriptor[1] != USB_DESCTYPE_HUB) { 90 dprintf(1,"[usb_hub]wrong descriptor %x\n",sdescriptor[1]);90 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]); 91 91 return NULL; 92 92 } … … 103 103 ? 1 : 0); 104 104 result->devices_removable = (uint8_t*) malloc(var_size); 105 //printf("[usb_hub] getting removable devices data \n"); 105 106 106 size_t i; 107 107 for (i = 0; i < var_size; ++i) { … … 111 111 } 112 112 113 //control transactions114 /*115 int usb_drv_sync_control_read(116 int phone, usb_target_t target,117 usb_device_request_setup_packet_t * request,118 void * rcvd_buffer, size_t rcvd_size, size_t * actual_size119 ) {120 usb_handle_t handle;121 int opResult;122 //setup123 opResult = usb_drv_async_control_read_setup(phone, target,124 request, sizeof (usb_device_request_setup_packet_t),125 &handle);126 if (opResult != EOK) {127 return opResult;128 }129 opResult = usb_drv_async_wait_for(handle);130 if (opResult != EOK) {131 return opResult;132 }133 //read134 opResult = usb_drv_async_control_read_data(phone, target,135 rcvd_buffer, rcvd_size, actual_size,136 &handle);137 if (opResult != EOK) {138 return opResult;139 }140 opResult = usb_drv_async_wait_for(handle);141 if (opResult != EOK) {142 return opResult;143 }144 //finalize145 opResult = usb_drv_async_control_read_status(phone, target,146 &handle);147 if (opResult != EOK) {148 return opResult;149 }150 opResult = usb_drv_async_wait_for(handle);151 if (opResult != EOK) {152 return opResult;153 }154 return EOK;155 }156 157 int usb_drv_sync_control_write(158 int phone, usb_target_t target,159 usb_device_request_setup_packet_t * request,160 void * sent_buffer, size_t sent_size161 ) {162 usb_handle_t handle;163 int opResult;164 //setup165 opResult = usb_drv_async_control_write_setup(phone, target,166 request, sizeof (usb_device_request_setup_packet_t),167 &handle);168 if (opResult != EOK) {169 return opResult;170 }171 opResult = usb_drv_async_wait_for(handle);172 if (opResult != EOK) {173 return opResult;174 }175 //write176 opResult = usb_drv_async_control_write_data(phone, target,177 sent_buffer, sent_size,178 &handle);179 if (opResult != EOK) {180 return opResult;181 }182 opResult = usb_drv_async_wait_for(handle);183 if (opResult != EOK) {184 return opResult;185 }186 //finalize187 opResult = usb_drv_async_control_write_status(phone, target,188 &handle);189 if (opResult != EOK) {190 return opResult;191 }192 opResult = usb_drv_async_wait_for(handle);193 if (opResult != EOK) {194 return opResult;195 }196 return EOK;197 }198 199 */200 201 113 202 114 -
uspace/drv/usbmid/usbmid.c
rc32688d r361e61b 116 116 return NULL; 117 117 } 118 rc = usb_endpoint_pipe_probe_default_control(&mid->ctrl_pipe); 119 if (rc != EOK) { 120 usb_log_error("Probing default control pipe failed: %s.\n", 121 str_error(rc)); 122 free(mid); 123 return NULL; 124 } 118 125 119 126 mid->dev = dev; -
uspace/drv/usbmouse/init.c
rc32688d r361e61b 42 42 43 43 /** Mouse polling endpoint description for boot protocol subclass. */ 44 staticusb_endpoint_description_t poll_endpoint_description = {44 usb_endpoint_description_t poll_endpoint_description = { 45 45 .transfer_type = USB_TRANSFER_INTERRUPT, 46 46 .direction = USB_DIRECTION_IN, … … 50 50 .flags = 0 51 51 }; 52 53 /** Initialize poll pipe.54 *55 * Expects that session is already started on control pipe zero.56 *57 * @param mouse Mouse device.58 * @param my_interface Interface number.59 * @return Error code.60 */61 static int intialize_poll_pipe(usb_mouse_t *mouse, int my_interface)62 {63 assert(usb_endpoint_pipe_is_session_started(&mouse->ctrl_pipe));64 65 int rc;66 67 void *config_descriptor;68 size_t config_descriptor_size;69 70 rc = usb_request_get_full_configuration_descriptor_alloc(71 &mouse->ctrl_pipe, 0, &config_descriptor, &config_descriptor_size);72 if (rc != EOK) {73 return rc;74 }75 76 usb_endpoint_mapping_t endpoint_mapping[1] = {77 {78 .pipe = &mouse->poll_pipe,79 .description = &poll_endpoint_description,80 .interface_no = my_interface81 }82 };83 84 rc = usb_endpoint_pipe_initialize_from_configuration(endpoint_mapping,85 1, config_descriptor, config_descriptor_size, &mouse->wire);86 if (rc != EOK) {87 return rc;88 }89 90 if (!endpoint_mapping[0].present) {91 return ENOENT;92 }93 94 mouse->poll_interval_us = 1000 * endpoint_mapping[0].descriptor->poll_interval;95 96 usb_log_debug("prepared polling endpoint %d (interval %zu).\n",97 mouse->poll_pipe.endpoint_no, mouse->poll_interval_us);98 99 return EOK;100 }101 52 102 53 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); … … 143 94 * @return Error code. 144 95 */ 145 int usb_mouse_create( ddf_dev_t *dev)96 int usb_mouse_create(usb_device_t *dev) 146 97 { 147 98 usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t)); … … 149 100 return ENOMEM; 150 101 } 151 mouse->dev ice= dev;102 mouse->dev = dev; 152 103 mouse->console_phone = -1; 153 104 154 105 int rc; 155 106 156 /* Initialize the backing connection. */157 rc = usb_device_connection_initialize_from_device(&mouse->wire, dev);158 if (rc != EOK) {159 goto leave;160 }161 162 /* Initialize the default control pipe. */163 rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe,164 &mouse->wire);165 if (rc != EOK) {166 goto leave;167 }168 169 rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe);170 if (rc != EOK) {171 goto leave;172 }173 174 rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev));175 176 /* We can ignore error here. */177 usb_endpoint_pipe_end_session(&mouse->ctrl_pipe);178 179 if (rc != EOK) {180 goto leave;181 }182 183 107 /* Create DDF function. */ 184 mouse->mouse_fun = ddf_fun_create(dev , fun_exposed, "mouse");108 mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse"); 185 109 if (mouse->mouse_fun == NULL) { 186 110 rc = ENOMEM; … … 200 124 goto leave; 201 125 } 126 127 /* Open the control pipe. */ 128 rc = usb_endpoint_pipe_start_session(&dev->ctrl_pipe); 129 if (rc != EOK) { 130 goto leave; 131 } 132 133 /* Set the boot protocol. */ 134 rc = usb_control_request_set(&dev->ctrl_pipe, 135 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 136 USB_HIDREQ_SET_PROTOCOL, USB_HID_PROTOCOL_BOOT, dev->interface_no, 137 NULL, 0); 138 if (rc != EOK) { 139 goto leave; 140 } 141 142 /* Close the control pipe (ignore errors). */ 143 usb_endpoint_pipe_end_session(&dev->ctrl_pipe); 144 202 145 203 146 /* Everything allright. */ -
uspace/drv/usbmouse/main.c
rc32688d r361e61b 44 44 * @return Error code. 45 45 */ 46 static int usbmouse_add_device( ddf_dev_t *dev)46 static int usbmouse_add_device(usb_device_t *dev) 47 47 { 48 48 int rc = usb_mouse_create(dev); … … 53 53 } 54 54 55 fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev); 56 if (poll_fibril == 0) { 57 usb_log_error("Failed to initialize polling fibril.\n"); 58 /* FIXME: free allocated resources. */ 59 return ENOMEM; 55 usb_log_debug("Polling pipe at endpoint %d.\n", dev->pipes[0].pipe->endpoint_no); 56 57 rc = usb_device_auto_poll(dev, 0, 58 usb_mouse_polling_callback, dev->pipes[0].pipe->max_packet_size, 59 usb_mouse_polling_ended_callback, dev->driver_data); 60 61 if (rc != EOK) { 62 usb_log_error("Failed to start polling fibril: %s.\n", 63 str_error(rc)); 64 return rc; 60 65 } 61 66 62 fibril_add_ready(poll_fibril);63 64 67 usb_log_info("controlling new mouse (handle %llu).\n", 65 dev-> handle);68 dev->ddf_dev->handle); 66 69 67 70 return EOK; … … 69 72 70 73 /** USB mouse driver ops. */ 71 static driver_ops_t mouse_driver_ops = {74 static usb_driver_ops_t mouse_driver_ops = { 72 75 .add_device = usbmouse_add_device, 73 76 }; 74 77 78 static usb_endpoint_description_t *endpoints[] = { 79 &poll_endpoint_description, 80 NULL 81 }; 82 75 83 /** USB mouse driver. */ 76 static driver_t mouse_driver = {84 static usb_driver_t mouse_driver = { 77 85 .name = NAME, 78 .driver_ops = &mouse_driver_ops 86 .ops = &mouse_driver_ops, 87 .endpoints = endpoints 79 88 }; 80 89 … … 83 92 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 84 93 85 return ddf_driver_main(&mouse_driver);94 return usb_driver_main(&mouse_driver); 86 95 } 87 96 -
uspace/drv/usbmouse/mouse.c
rc32688d r361e61b 40 40 #include <ipc/mouse.h> 41 41 42 /** Fibril function for polling the mouse device.42 /** Mouse polling callback. 43 43 * 44 * This function shall not terminate unless the device breaks and fails45 * to send data (e.g. stalls on data request).46 * 47 * @param arg ddf_dev_t type representing the mouse device.48 * @return EOK Always.44 * @param dev Device that is being polled. 45 * @param buffer Data buffer. 46 * @param buffer_size Buffer size in bytes. 47 * @param arg Custom argument - points to usb_mouse_t. 48 * @return Always true. 49 49 */ 50 int usb_mouse_polling_fibril(void *arg) 50 bool usb_mouse_polling_callback(usb_device_t *dev, 51 uint8_t *buffer, size_t buffer_size, void *arg) 51 52 { 52 assert(arg != NULL); 53 ddf_dev_t *dev = (ddf_dev_t *) arg; 54 usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data; 53 usb_mouse_t *mouse = (usb_mouse_t *) arg; 55 54 56 assert(mouse); 55 usb_log_debug2("got buffer: %s.\n", 56 usb_debug_str_buffer(buffer, buffer_size, 0)); 57 57 58 size_t buffer_size = mouse->poll_pipe.max_packet_size; 58 uint8_t butt = buffer[0]; 59 char str_buttons[4] = { 60 butt & 1 ? '#' : '.', 61 butt & 2 ? '#' : '.', 62 butt & 4 ? '#' : '.', 63 0 64 }; 59 65 60 if (buffer_size < 4) { 61 usb_log_error("Weird mouse, results will be skewed.\n"); 62 buffer_size = 4; 66 int shift_x = ((int) buffer[1]) - 127; 67 int shift_y = ((int) buffer[2]) - 127; 68 int wheel = ((int) buffer[3]) - 127; 69 70 if (buffer[1] == 0) { 71 shift_x = 0; 72 } 73 if (buffer[2] == 0) { 74 shift_y = 0; 75 } 76 if (buffer[3] == 0) { 77 wheel = 0; 63 78 } 64 79 65 uint8_t *buffer = malloc(buffer_size); 66 if (buffer == NULL) { 67 usb_log_error("Out of memory, poll fibril aborted.\n"); 68 return ENOMEM; 80 if (mouse->console_phone >= 0) { 81 if ((shift_x != 0) || (shift_y != 0)) { 82 /* FIXME: guessed for QEMU */ 83 async_req_2_0(mouse->console_phone, 84 MEVENT_MOVE, 85 - shift_x / 10, - shift_y / 10); 86 } 87 if (butt) { 88 /* FIXME: proper button clicking. */ 89 async_req_2_0(mouse->console_phone, 90 MEVENT_BUTTON, 1, 1); 91 async_req_2_0(mouse->console_phone, 92 MEVENT_BUTTON, 1, 0); 93 } 69 94 } 70 95 71 while (true) {72 async_usleep(mouse->poll_interval_us);96 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n", 97 str_buttons, shift_x, shift_y, wheel); 73 98 74 size_t actual_size;75 int rc;99 /* Guess. */ 100 async_usleep(1000); 76 101 77 /* 78 * Error checking note: 79 * - failure when starting a session is considered 80 * temporary (e.g. out of phones, next try might succeed) 81 * - failure of transfer considered fatal (probably the 82 * device was unplugged) 83 * - session closing not checked (shall not fail anyway) 84 */ 102 return true; 103 } 85 104 86 rc = usb_endpoint_pipe_start_session(&mouse->poll_pipe); 87 if (rc != EOK) { 88 usb_log_warning("Failed to start session, will try again: %s.\n", 89 str_error(rc)); 90 continue; 91 } 105 /** Callback when polling is terminated. 106 * 107 * @param dev Device where the polling terminated. 108 * @param recurring_errors Whether the polling was terminated due to 109 * recurring errors. 110 * @param arg Custom argument - points to usb_mouse_t. 111 */ 112 void usb_mouse_polling_ended_callback(usb_device_t *dev, 113 bool recurring_errors, void *arg) 114 { 115 usb_mouse_t *mouse = (usb_mouse_t *) arg; 92 116 93 rc = usb_endpoint_pipe_read(&mouse->poll_pipe,94 buffer, buffer_size, &actual_size);95 96 usb_endpoint_pipe_end_session(&mouse->poll_pipe);97 98 if (rc != EOK) {99 usb_log_error("Failed reading mouse input: %s.\n",100 str_error(rc));101 break;102 }103 104 usb_log_debug2("got buffer: %s.\n",105 usb_debug_str_buffer(buffer, buffer_size, 0));106 107 uint8_t butt = buffer[0];108 char str_buttons[4] = {109 butt & 1 ? '#' : '.',110 butt & 2 ? '#' : '.',111 butt & 4 ? '#' : '.',112 0113 };114 115 int shift_x = ((int) buffer[1]) - 127;116 int shift_y = ((int) buffer[2]) - 127;117 int wheel = ((int) buffer[3]) - 127;118 119 if (buffer[1] == 0) {120 shift_x = 0;121 }122 if (buffer[2] == 0) {123 shift_y = 0;124 }125 if (buffer[3] == 0) {126 wheel = 0;127 }128 129 if (mouse->console_phone >= 0) {130 if ((shift_x != 0) || (shift_y != 0)) {131 /* FIXME: guessed for QEMU */132 async_req_2_0(mouse->console_phone,133 MEVENT_MOVE,134 - shift_x / 10, - shift_y / 10);135 }136 if (butt) {137 /* FIXME: proper button clicking. */138 async_req_2_0(mouse->console_phone,139 MEVENT_BUTTON, 1, 1);140 async_req_2_0(mouse->console_phone,141 MEVENT_BUTTON, 1, 0);142 }143 }144 145 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n",146 str_buttons, shift_x, shift_y, wheel);147 }148 149 /*150 * Device was probably unplugged.151 * Hang-up the phone to the console.152 * FIXME: release allocated memory.153 */154 117 async_hangup(mouse->console_phone); 155 118 mouse->console_phone = -1; 156 157 usb_log_error("Mouse polling fibril terminated.\n");158 159 return EOK;160 119 } 161 162 120 163 121 /** -
uspace/drv/usbmouse/mouse.h
rc32688d r361e61b 37 37 #define USBMOUSE_MOUSE_H_ 38 38 39 #include < ddf/driver.h>39 #include <usb/devdrv.h> 40 40 #include <usb/pipes.h> 41 41 #include <time.h> … … 46 46 typedef struct { 47 47 /** Generic device container. */ 48 ddf_dev_t *device;48 usb_device_t *dev; 49 49 /** Function representing the device. */ 50 50 ddf_fun_t *mouse_fun; 51 /** Representation of connection to the device. */52 usb_device_connection_t wire;53 /** Default (zero) control pipe. */54 usb_endpoint_pipe_t ctrl_pipe;55 /** Polling (in) pipe. */56 usb_endpoint_pipe_t poll_pipe;57 51 /** Polling interval in microseconds. */ 58 52 suseconds_t poll_interval_us; … … 61 55 } usb_mouse_t; 62 56 63 int usb_mouse_create(ddf_dev_t *); 57 #define POLL_PIPE(dev) ((dev)->pipes[0].pipe) 64 58 65 int usb_mouse_polling_fibril(void *); 59 extern usb_endpoint_description_t poll_endpoint_description; 60 61 int usb_mouse_create(usb_device_t *); 62 63 bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t, void *); 64 void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *); 66 65 67 66 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
