Changes in / [72af8da:3e7b7cd] in mainline
- Files:
-
- 7 added
- 14 deleted
- 78 edited
-
.bzrignore (modified) (1 diff)
-
boot/arch/amd64/Makefile.inc (modified) (1 diff)
-
boot/arch/mips32/src/asm.S (modified) (3 diffs)
-
dist/Makefile (modified) (2 diffs)
-
uspace/Makefile (modified) (2 diffs)
-
uspace/app/bdsh/cmds/modules/mkfile/mkfile.c (modified) (1 diff)
-
uspace/app/usbinfo/info.c (modified) (1 diff)
-
uspace/app/usbinfo/main.c (modified) (1 diff)
-
uspace/doc/doxygroups.h (modified) (1 diff)
-
uspace/drv/ehci-hcd/Makefile (deleted)
-
uspace/drv/ehci-hcd/ehci-hcd.ma (deleted)
-
uspace/drv/ehci-hcd/main.c (deleted)
-
uspace/drv/ehci-hcd/pci.c (deleted)
-
uspace/drv/ehci-hcd/pci.h (deleted)
-
uspace/drv/pciintel/pci.c (modified) (4 diffs)
-
uspace/drv/uhci-hcd/Makefile (modified) (1 diff)
-
uspace/drv/uhci-hcd/batch.c (modified) (16 diffs)
-
uspace/drv/uhci-hcd/batch.h (modified) (6 diffs)
-
uspace/drv/uhci-hcd/iface.c (modified) (14 diffs)
-
uspace/drv/uhci-hcd/iface.h (modified) (2 diffs)
-
uspace/drv/uhci-hcd/main.c (modified) (2 diffs)
-
uspace/drv/uhci-hcd/pci.c (modified) (6 diffs)
-
uspace/drv/uhci-hcd/pci.h (modified) (1 diff)
-
uspace/drv/uhci-hcd/root_hub.c (added)
-
uspace/drv/uhci-hcd/root_hub.h (added)
-
uspace/drv/uhci-hcd/transfer_list.c (modified) (5 diffs)
-
uspace/drv/uhci-hcd/transfer_list.h (modified) (3 diffs)
-
uspace/drv/uhci-hcd/uhci.c (modified) (3 diffs)
-
uspace/drv/uhci-hcd/uhci.h (modified) (2 diffs)
-
uspace/drv/uhci-hcd/uhci_hc.c (deleted)
-
uspace/drv/uhci-hcd/uhci_hc.h (deleted)
-
uspace/drv/uhci-hcd/uhci_rh.c (deleted)
-
uspace/drv/uhci-hcd/uhci_rh.h (deleted)
-
uspace/drv/uhci-hcd/uhci_struct/link_pointer.h (modified) (2 diffs)
-
uspace/drv/uhci-hcd/uhci_struct/queue_head.h (modified) (3 diffs)
-
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c (modified) (5 diffs)
-
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h (modified) (5 diffs)
-
uspace/drv/uhci-hcd/utils/device_keeper.c (modified) (10 diffs)
-
uspace/drv/uhci-hcd/utils/device_keeper.h (modified) (3 diffs)
-
uspace/drv/uhci-hcd/utils/malloc32.h (modified) (3 diffs)
-
uspace/drv/uhci-rhd/Makefile (modified) (1 diff)
-
uspace/drv/uhci-rhd/main.c (modified) (9 diffs)
-
uspace/drv/uhci-rhd/port.c (modified) (8 diffs)
-
uspace/drv/uhci-rhd/port.h (modified) (3 diffs)
-
uspace/drv/uhci-rhd/port_status.c (added)
-
uspace/drv/uhci-rhd/port_status.h (added)
-
uspace/drv/uhci-rhd/root_hub.c (modified) (3 diffs)
-
uspace/drv/uhci-rhd/root_hub.h (modified) (3 diffs)
-
uspace/drv/usbhid/Makefile (modified) (1 diff)
-
uspace/drv/usbhid/conv.c (modified) (2 diffs)
-
uspace/drv/usbhid/descdump.c (modified) (7 diffs)
-
uspace/drv/usbhid/hiddev.c (modified) (6 diffs)
-
uspace/drv/usbhid/hiddev.h (modified) (1 diff)
-
uspace/drv/usbhid/hidreq.c (modified) (5 diffs)
-
uspace/drv/usbhid/hidreq.h (modified) (1 diff)
-
uspace/drv/usbhid/kbddev.c (modified) (34 diffs)
-
uspace/drv/usbhid/kbddev.h (modified) (3 diffs)
-
uspace/drv/usbhid/kbdrepeat.c (deleted)
-
uspace/drv/usbhid/kbdrepeat.h (deleted)
-
uspace/drv/usbhid/main.c (modified) (2 diffs)
-
uspace/drv/usbhub/usbhub.c (modified) (3 diffs)
-
uspace/drv/usbmid/main.c (modified) (2 diffs)
-
uspace/drv/usbmid/usbmid.c (modified) (4 diffs)
-
uspace/drv/usbmid/usbmid.h (modified) (2 diffs)
-
uspace/drv/usbmouse/init.c (modified) (5 diffs)
-
uspace/drv/usbmouse/main.c (modified) (3 diffs)
-
uspace/drv/usbmouse/mouse.c (modified) (1 diff)
-
uspace/drv/usbmouse/mouse.h (modified) (2 diffs)
-
uspace/drv/vhc/conndev.c (modified) (1 diff)
-
uspace/lib/block/libblock.c (modified) (2 diffs)
-
uspace/lib/drv/generic/remote_usbhc.c (modified) (3 diffs)
-
uspace/lib/drv/include/usbhc_iface.h (modified) (2 diffs)
-
uspace/lib/usb/Makefile (modified) (2 diffs)
-
uspace/lib/usb/include/usb/classes/classes.h (modified) (1 diff)
-
uspace/lib/usb/include/usb/debug.h (modified) (4 diffs)
-
uspace/lib/usb/include/usb/descriptor.h (modified) (3 diffs)
-
uspace/lib/usb/include/usb/devdrv.h (deleted)
-
uspace/lib/usb/include/usb/dp.h (modified) (3 diffs)
-
uspace/lib/usb/include/usb/hub.h (modified) (1 diff)
-
uspace/lib/usb/include/usb/pipes.h (modified) (4 diffs)
-
uspace/lib/usb/include/usb/request.h (modified) (1 diff)
-
uspace/lib/usb/include/usb/usb.h (modified) (2 diffs)
-
uspace/lib/usb/include/usb/usbmem.h (added)
-
uspace/lib/usb/src/ddfiface.c (modified) (6 diffs)
-
uspace/lib/usb/src/debug.c (modified) (4 diffs)
-
uspace/lib/usb/src/devdrv.c (deleted)
-
uspace/lib/usb/src/devpoll.c (deleted)
-
uspace/lib/usb/src/dp.c (modified) (1 diff)
-
uspace/lib/usb/src/dump.c (modified) (5 diffs)
-
uspace/lib/usb/src/hcdhubd_private.h (added)
-
uspace/lib/usb/src/hub.c (modified) (6 diffs)
-
uspace/lib/usb/src/pipes.c (modified) (1 diff)
-
uspace/lib/usb/src/pipesinit.c (modified) (2 diffs)
-
uspace/lib/usb/src/pipesio.c (modified) (2 diffs)
-
uspace/lib/usb/src/recognise.c (modified) (7 diffs)
-
uspace/lib/usb/src/request.c (modified) (8 diffs)
-
uspace/lib/usb/src/usb.c (modified) (2 diffs)
-
uspace/lib/usb/src/usbmem.c (added)
-
uspace/srv/hw/irc/apic/apic.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
r72af8da r3e7b7cd 84 84 ./uspace/drv/test1/test1 85 85 ./uspace/drv/test2/test2 86 ./uspace/drv/ehci-hcd/ehci-hcd87 86 ./uspace/drv/uhci-hcd/uhci-hcd 88 87 ./uspace/drv/uhci-rhd/uhci-rhd -
boot/arch/amd64/Makefile.inc
r72af8da r3e7b7cd 43 43 isa \ 44 44 ns8250 \ 45 ehci-hcd \46 45 uhci-hcd \ 47 46 uhci-rhd \ -
boot/arch/mips32/src/asm.S
r72af8da r3e7b7cd 41 41 42 42 start: 43 /* 44 * Setup the CP0 configuration 45 * - Disable 64-bit kernel addressing mode 46 * - DIsable 64-bit supervisor adressing mode 47 * - Disable 64-bit user addressing mode 48 */ 49 mfc0 $a0, $status 50 la $a1, 0xffffff1f 51 and $a0, $a1, $a0 52 mtc0 $a0, $status 53 54 /* 55 * Setup CPU map (on msim this code 56 * is executed in parallel on all CPUs, 57 * but it not an issue). 58 */ 43 /* Setup CPU map (on msim this code 44 is executed in parallel on all CPUs, 45 but it not an issue) */ 59 46 la $a0, PA2KA(CPUMAP_OFFSET) 60 47 … … 107 94 lw $k1, ($k0) 108 95 109 /* 110 * If we are not running on BSP 111 * then end in an infinite loop. 112 */ 96 /* If we are not running on BSP 97 then end in an infinite loop */ 113 98 beq $k1, $zero, bsp 114 99 nop … … 142 127 143 128 jump_to_kernel: 144 /* 145 * TODO: 146 * 147 * Make sure that the I-cache, D-cache and memory are mutually 148 * coherent before passing control to the copied code. 149 */ 129 # 130 # TODO: 131 # Make sure that the I-cache, D-cache and memory are mutually coherent 132 # before passing control to the copied code. 133 # 150 134 j $a0 151 135 nop -
dist/Makefile
r72af8da r3e7b7cd 43 43 44 44 SUFFIX = $(suffix $(IMGFILE)) 45 46 ifdef PROFILE 47 DISTFILE = Helenos-$(shell echo $(PROFILE) | tr '/' '-')$(SUFFIX) 48 else 49 DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX) 50 endif 45 DISTFILE = HelenOS-$(RELEASE)-$(PLATFORM)-$(MACHINE)-$(PROCESSOR)$(SUFFIX) 51 46 52 47 .PHONY: all clean dist distfile … … 58 53 cp $< $@ 59 54 60 $(IMGFILE):61 $(MAKE) -C ..62 63 55 dist: 64 56 for profile in $(PROFILES); do \ -
uspace/Makefile
r72af8da r3e7b7cd 117 117 srv/hw/irc/apic \ 118 118 srv/hw/irc/i8259 \ 119 drv/ehci-hcd \120 119 drv/uhci-hcd \ 121 120 drv/uhci-rhd \ … … 135 134 srv/hw/irc/apic \ 136 135 srv/hw/irc/i8259 \ 137 drv/ehci-hcd \138 136 drv/uhci-hcd \ 139 137 drv/uhci-rhd \ -
uspace/app/bdsh/cmds/modules/mkfile/mkfile.c
r72af8da r3e7b7cd 125 125 126 126 for (c = 0, optind = 0, opt_ind = 0; c != -1;) { 127 c = getopt_long(argc, argv, " s:h", long_options, &opt_ind);127 c = getopt_long(argc, argv, "pvhVfm:", long_options, &opt_ind); 128 128 switch (c) { 129 129 case 'h': -
uspace/app/usbinfo/info.c
r72af8da r3e7b7cd 65 65 goto leave; 66 66 } 67 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);68 if (rc != EOK) {69 fprintf(stderr,70 NAME ": probing default control pipe failed: %s.\n",71 str_error(rc));72 goto leave;73 }74 67 rc = usb_endpoint_pipe_start_session(&ctrl_pipe); 75 68 if (rc != EOK) { -
uspace/app/usbinfo/main.c
r72af8da r3e7b7cd 82 82 83 83 if (str_cmp(path, "uhci") == 0) { 84 path = "/hw/pci0/00:01.2/uhci -hc";84 path = "/hw/pci0/00:01.2/uhci"; 85 85 } 86 86 -
uspace/doc/doxygroups.h
r72af8da r3e7b7cd 253 253 * @defgroup drvusbuhci UHCI driver 254 254 * @ingroup usb 255 * @brief Drivers for USB UHCI host controller and root hub. 256 */ 257 258 /** 259 * @defgroup drvusbuhcirh UHCI root hub driver 260 * @ingroup drvusbuhci 261 * @brief Driver for UHCI complaint root hub. 262 */ 263 264 /** 265 * @defgroup drvusbuhcihc UHCI host controller driver 266 * @ingroup drvusbuhci 267 * @brief Driver for UHCI complaint USB host controller. 268 */ 269 270 /** 271 * @defgroup drvusbehci EHCI driver 272 * @ingroup usb 273 * @brief Driver for EHCI host controller. 274 */ 275 276 255 * @brief Driver for USB host controller UHCI. 256 */ 257 -
uspace/drv/pciintel/pci.c
r72af8da r3e7b7cd 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 = -1;99 100 if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {101 irc_service = SERVICE_APIC;98 int irc_service = 0; 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 == -1) { 103 irc_service = SERVICE_I8259; 104 } 105 106 if (irc_service == 0) 107 107 return false; 108 }109 108 110 109 irc_phone = service_connect_blocking(irc_service, 0, 0); 111 if (irc_phone < 0) {110 if (irc_phone < 0) 112 111 return false; 113 }114 112 115 113 size_t i; 116 for (i = 0; i < dev_data->hw_resources.count; i++) {114 for (i = 0; i < dev_data->hw_resources.count; i++) { 117 115 if (dev_data->hw_resources.resources[i].type == INTERRUPT) { 118 116 int irq = dev_data->hw_resources.resources[i].res.interrupt.irq; … … 129 127 } 130 128 131 static int pci_config_space_write_32( 132 ddf_fun_t *fun, uint32_t address, uint32_t data) 133 { 134 if (address > 252) 135 return EINVAL; 136 pci_conf_write_32(PCI_FUN(fun), address, data); 137 return EOK; 138 } 139 140 static int pci_config_space_write_16( 141 ddf_fun_t *fun, uint32_t address, uint16_t data) 129 static int pci_config_space_write_16(ddf_fun_t *fun, uint32_t address, uint16_t data) 142 130 { 143 131 if (address > 254) … … 147 135 } 148 136 149 static int pci_config_space_write_8(150 ddf_fun_t *fun, uint32_t address, uint8_t data)151 {152 if (address > 255)153 return EINVAL;154 pci_conf_write_8(PCI_FUN(fun), address, data);155 return EOK;156 }157 158 static int pci_config_space_read_32(159 ddf_fun_t *fun, uint32_t address, uint32_t *data)160 {161 if (address > 252)162 return EINVAL;163 *data = pci_conf_read_32(PCI_FUN(fun), address);164 return EOK;165 }166 167 static int pci_config_space_read_16(168 ddf_fun_t *fun, uint32_t address, uint16_t *data)169 {170 if (address > 254)171 return EINVAL;172 *data = pci_conf_read_16(PCI_FUN(fun), address);173 return EOK;174 }175 176 static int pci_config_space_read_8(177 ddf_fun_t *fun, uint32_t address, uint8_t *data)178 {179 if (address > 255)180 return EINVAL;181 *data = pci_conf_read_8(PCI_FUN(fun), address);182 return EOK;183 }184 137 185 138 static hw_res_ops_t pciintel_hw_res_ops = { … … 189 142 190 143 static pci_dev_iface_t pci_dev_ops = { 191 .config_space_read_8 = &pci_config_space_read_8,192 .config_space_read_16 = &pci_config_space_read_16,193 .config_space_read_32 = &pci_config_space_read_32,194 .config_space_write_8 = &pci_config_space_write_8,144 .config_space_read_8 = NULL, 145 .config_space_read_16 = NULL, 146 .config_space_read_32 = NULL, 147 .config_space_write_8 = NULL, 195 148 .config_space_write_16 = &pci_config_space_write_16, 196 .config_space_write_32 = &pci_config_space_write_32149 .config_space_write_32 = NULL 197 150 }; 198 151 -
uspace/drv/uhci-hcd/Makefile
r72af8da r3e7b7cd 35 35 iface.c \ 36 36 main.c \ 37 root_hub.c \ 37 38 transfer_list.c \ 38 39 uhci.c \ 39 uhci_hc.c \40 uhci_rh.c \41 40 uhci_struct/transfer_descriptor.c \ 42 41 utils/device_keeper.c \ -
uspace/drv/uhci-hcd/batch.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver USB transaction structure32 * @brief UHCI driver 33 33 */ 34 34 #include <errno.h> … … 40 40 #include "batch.h" 41 41 #include "transfer_list.h" 42 #include "uhci _hc.h"42 #include "uhci.h" 43 43 #include "utils/malloc32.h" 44 44 45 45 #define DEFAULT_ERROR_COUNT 3 46 46 47 static void batch_control(batch_t *instance, 48 usb_packet_id data_stage, usb_packet_id status_stage); 49 static void batch_data(batch_t *instance, usb_packet_id pid); 47 static int batch_schedule(batch_t *instance); 48 49 static void batch_control( 50 batch_t *instance, int data_stage, int status_stage); 50 51 static void batch_call_in(batch_t *instance); 51 52 static void batch_call_out(batch_t *instance); … … 54 55 55 56 56 /** Allocate memory and initialize internal data structure.57 *58 * @param[in] fun DDF function to pass to callback.59 * @param[in] target Device and endpoint target of the transaction.60 * @param[in] transfer_type Interrupt, Control or Bulk.61 * @param[in] max_packet_size maximum allowed size of data packets.62 * @param[in] speed Speed of the transaction.63 * @param[in] buffer Data source/destination.64 * @param[in] size Size of the buffer.65 * @param[in] setup_buffer Setup data source (if not NULL)66 * @param[in] setup_size Size of setup_buffer (should be always 8)67 * @param[in] func_in function to call on inbound transaction completion68 * @param[in] func_out function to call on outbound transaction completion69 * @param[in] arg additional parameter to func_in or func_out70 * @param[in] manager Pointer to toggle management structure.71 * @return Valid pointer if all substructures were successfully created,72 * NULL otherwise.73 *74 * Determines the number of needed packets (TDs). Prepares a transport buffer75 * (that is accessible by the hardware). Initializes parameters needed for the76 * transaction and callback.77 */78 57 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 79 58 usb_transfer_type_t transfer_type, size_t max_packet_size, … … 81 60 char* setup_buffer, size_t setup_size, 82 61 usbhc_iface_transfer_in_callback_t func_in, 83 usbhc_iface_transfer_out_callback_t func_out, void *arg, 84 device_keeper_t *manager 85 ) 62 usbhc_iface_transfer_out_callback_t func_out, void *arg) 86 63 { 87 64 assert(func_in == NULL || func_out == NULL); 88 65 assert(func_in != NULL || func_out != NULL); 89 66 90 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \91 if (ptr == NULL) { \92 usb_log_error(message); \93 if (instance) { \94 batch_dispose(instance); \95 } \96 return NULL; \97 } else (void)098 99 67 batch_t *instance = malloc(sizeof(batch_t)); 100 CHECK_NULL_DISPOSE_RETURN(instance, 101 "Failed to allocate batch instance.\n"); 102 bzero(instance, sizeof(batch_t)); 103 104 instance->qh = malloc32(sizeof(qh_t)); 105 CHECK_NULL_DISPOSE_RETURN(instance->qh, 106 "Failed to allocate batch queue head.\n"); 107 qh_init(instance->qh); 68 if (instance == NULL) { 69 usb_log_error("Failed to allocate batch instance.\n"); 70 return NULL; 71 } 72 73 instance->qh = queue_head_get(); 74 if (instance->qh == NULL) { 75 usb_log_error("Failed to allocate queue head.\n"); 76 free(instance); 77 return NULL; 78 } 108 79 109 80 instance->packets = (size + max_packet_size - 1) / max_packet_size; … … 112 83 } 113 84 114 instance->tds = malloc32(sizeof(td_t) * instance->packets); 115 CHECK_NULL_DISPOSE_RETURN( 116 instance->tds, "Failed to allocate transfer descriptors.\n"); 117 bzero(instance->tds, sizeof(td_t) * instance->packets); 118 119 if (size > 0) { 120 instance->transport_buffer = malloc32(size); 121 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 122 "Failed to allocate device accessible buffer.\n"); 123 } 124 125 if (setup_size > 0) { 126 instance->setup_buffer = malloc32(setup_size); 127 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 128 "Failed to allocate device accessible setup buffer.\n"); 85 instance->tds = malloc32(sizeof(transfer_descriptor_t) * instance->packets); 86 if (instance->tds == NULL) { 87 usb_log_error("Failed to allocate transfer descriptors.\n"); 88 queue_head_dispose(instance->qh); 89 free(instance); 90 return NULL; 91 } 92 bzero(instance->tds, sizeof(transfer_descriptor_t) * instance->packets); 93 94 const size_t transport_size = max_packet_size * instance->packets; 95 96 instance->transport_buffer = 97 (size > 0) ? malloc32(transport_size) : NULL; 98 99 if ((size > 0) && (instance->transport_buffer == NULL)) { 100 usb_log_error("Failed to allocate device accessible buffer.\n"); 101 queue_head_dispose(instance->qh); 102 free32(instance->tds); 103 free(instance); 104 return NULL; 105 } 106 107 instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL; 108 if ((setup_size > 0) && (instance->setup_buffer == NULL)) { 109 usb_log_error("Failed to allocate device accessible setup buffer.\n"); 110 queue_head_dispose(instance->qh); 111 free32(instance->tds); 112 free32(instance->transport_buffer); 113 free(instance); 114 return NULL; 115 } 116 if (instance->setup_buffer) { 129 117 memcpy(instance->setup_buffer, setup_buffer, setup_size); 130 118 } 131 119 120 instance->max_packet_size = max_packet_size; 132 121 133 122 link_initialize(&instance->link); 134 123 135 instance->max_packet_size = max_packet_size;136 124 instance->target = target; 137 125 instance->transfer_type = transfer_type; 126 127 if (func_out) 128 instance->callback_out = func_out; 129 if (func_in) 130 instance->callback_in = func_in; 131 138 132 instance->buffer = buffer; 139 133 instance->buffer_size = size; … … 142 136 instance->arg = arg; 143 137 instance->speed = speed; 144 instance->manager = manager; 145 instance->callback_out = func_out; 146 instance->callback_in = func_in; 147 148 qh_set_element_td(instance->qh, addr_to_phys(instance->tds)); 149 138 139 queue_head_element_td(instance->qh, addr_to_phys(instance->tds)); 150 140 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 151 141 instance, target.address, target.endpoint); … … 153 143 } 154 144 /*----------------------------------------------------------------------------*/ 155 /** Check batch TDs for activity.156 *157 * @param[in] instance Batch structure to use.158 * @return False, if there is an active TD, true otherwise.159 *160 * Walk all TDs. Stop with false if there is an active one (it is to be161 * processed). Stop with true if an error is found. Return true if the last TS162 * is reached.163 */164 145 bool batch_is_complete(batch_t *instance) 165 146 { … … 170 151 size_t i = 0; 171 152 for (;i < instance->packets; ++i) { 172 if (t d_is_active(&instance->tds[i])) {153 if (transfer_descriptor_is_active(&instance->tds[i])) { 173 154 return false; 174 155 } 175 176 instance->error = td_status(&instance->tds[i]); 156 instance->error = transfer_descriptor_status(&instance->tds[i]); 177 157 if (instance->error != EOK) { 158 if (i > 0) 159 instance->transfered_size -= instance->setup_size; 178 160 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 179 instance, i, instance->tds[i].status); 180 td_print_status(&instance->tds[i]); 181 182 device_keeper_set_toggle(instance->manager, 183 instance->target, td_toggle(&instance->tds[i])); 184 if (i > 0) 185 goto substract_ret; 161 instance, i, instance->tds[i].status); 186 162 return true; 187 163 } 188 189 instance->transfered_size += td_act_size(&instance->tds[i]); 190 if (td_is_short(&instance->tds[i])) 191 goto substract_ret; 192 } 193 substract_ret: 164 instance->transfered_size += 165 transfer_descriptor_actual_size(&instance->tds[i]); 166 } 194 167 instance->transfered_size -= instance->setup_size; 195 168 return true; 196 169 } 197 170 /*----------------------------------------------------------------------------*/ 198 /** Prepares control write transaction.199 *200 * @param[in] instance Batch structure to use.201 *202 * Uses genercir control function with pids OUT and IN.203 */204 171 void batch_control_write(batch_t *instance) 205 172 { 206 173 assert(instance); 207 /* We are data out, we are supposed to provide data */ 208 memcpy(instance->transport_buffer, instance->buffer, 209 instance->buffer_size); 174 /* we are data out, we are supposed to provide data */ 175 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 210 176 batch_control(instance, USB_PID_OUT, USB_PID_IN); 211 177 instance->next_step = batch_call_out_and_dispose; 212 178 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 213 } 214 /*----------------------------------------------------------------------------*/ 215 /** Prepares control read transaction. 216 * 217 * @param[in] instance Batch structure to use. 218 * 219 * Uses generic control with pids IN and OUT. 220 */ 179 batch_schedule(instance); 180 } 181 /*----------------------------------------------------------------------------*/ 221 182 void batch_control_read(batch_t *instance) 222 183 { … … 225 186 instance->next_step = batch_call_in_and_dispose; 226 187 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 227 } 228 /*----------------------------------------------------------------------------*/ 229 /** Prepare interrupt in transaction. 230 * 231 * @param[in] instance Batch structure to use. 232 * 233 * Data transaction with PID_IN. 234 */ 188 batch_schedule(instance); 189 } 190 /*----------------------------------------------------------------------------*/ 235 191 void batch_interrupt_in(batch_t *instance) 236 192 { 237 193 assert(instance); 238 batch_data(instance, USB_PID_IN); 194 195 const bool low_speed = instance->speed == USB_SPEED_LOW; 196 int toggle = 1; 197 size_t i = 0; 198 for (;i < instance->packets; ++i) { 199 char *data = 200 instance->transport_buffer + (i * instance->max_packet_size); 201 transfer_descriptor_t *next = (i + 1) < instance->packets ? 202 &instance->tds[i + 1] : NULL; 203 toggle = 1 - toggle; 204 205 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 206 instance->max_packet_size, toggle, false, low_speed, 207 instance->target, USB_PID_IN, data, next); 208 } 209 210 instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 211 239 212 instance->next_step = batch_call_in_and_dispose; 240 213 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 241 } 242 /*----------------------------------------------------------------------------*/ 243 /** Prepare interrupt out transaction. 244 * 245 * @param[in] instance Batch structure to use. 246 * 247 * Data transaction with PID_OUT. 248 */ 214 batch_schedule(instance); 215 } 216 /*----------------------------------------------------------------------------*/ 249 217 void batch_interrupt_out(batch_t *instance) 250 218 { 251 219 assert(instance); 252 /* We are data out, we are supposed to provide data */253 220 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 254 batch_data(instance, USB_PID_OUT); 221 222 const bool low_speed = instance->speed == USB_SPEED_LOW; 223 int toggle = 1; 224 size_t i = 0; 225 for (;i < instance->packets; ++i) { 226 char *data = 227 instance->transport_buffer + (i * instance->max_packet_size); 228 transfer_descriptor_t *next = (i + 1) < instance->packets ? 229 &instance->tds[i + 1] : NULL; 230 toggle = 1 - toggle; 231 232 transfer_descriptor_init(&instance->tds[i], DEFAULT_ERROR_COUNT, 233 instance->max_packet_size, toggle++, false, low_speed, 234 instance->target, USB_PID_OUT, data, next); 235 } 236 237 instance->tds[i - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 238 255 239 instance->next_step = batch_call_out_and_dispose; 256 240 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 257 } 258 /*----------------------------------------------------------------------------*/ 259 /** Prepare bulk in transaction. 260 * 261 * @param[in] instance Batch structure to use. 262 * 263 * Data transaction with PID_IN. 264 */ 265 void batch_bulk_in(batch_t *instance) 266 { 267 assert(instance); 268 batch_data(instance, USB_PID_IN); 269 instance->next_step = batch_call_in_and_dispose; 270 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 271 } 272 /*----------------------------------------------------------------------------*/ 273 /** Prepare bulk out transaction. 274 * 275 * @param[in] instance Batch structure to use. 276 * 277 * Data transaction with PID_OUT. 278 */ 279 void batch_bulk_out(batch_t *instance) 280 { 281 assert(instance); 282 /* We are data out, we are supposed to provide data */ 283 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 284 batch_data(instance, USB_PID_OUT); 285 instance->next_step = batch_call_out_and_dispose; 286 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 287 } 288 /*----------------------------------------------------------------------------*/ 289 /** Prepare generic data transaction 290 * 291 * @param[in] instance Batch structure to use. 292 * @param[in] pid to use for data packets. 293 * 294 * Packets with alternating toggle bit and supplied pid value. 295 * The last packet is marked with IOC flag. 296 */ 297 void batch_data(batch_t *instance, usb_packet_id pid) 298 { 299 assert(instance); 300 const bool low_speed = instance->speed == USB_SPEED_LOW; 301 int toggle = 302 device_keeper_get_toggle(instance->manager, instance->target); 303 assert(toggle == 0 || toggle == 1); 304 305 size_t packet = 0; 306 size_t remain_size = instance->buffer_size; 307 while (remain_size > 0) { 308 char *data = 309 instance->transport_buffer + instance->buffer_size 310 - remain_size; 311 312 const size_t packet_size = 313 (instance->max_packet_size > remain_size) ? 314 remain_size : instance->max_packet_size; 315 316 td_t *next_packet = (packet + 1 < instance->packets) 317 ? &instance->tds[packet + 1] : NULL; 318 319 assert(packet < instance->packets); 320 assert(packet_size <= remain_size); 321 322 td_init( 323 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 324 toggle, false, low_speed, instance->target, pid, data, 325 next_packet); 326 327 328 toggle = 1 - toggle; 329 remain_size -= packet_size; 330 ++packet; 331 } 332 td_set_ioc(&instance->tds[packet - 1]); 333 device_keeper_set_toggle(instance->manager, instance->target, toggle); 334 } 335 /*----------------------------------------------------------------------------*/ 336 /** Prepare generic control transaction 337 * 338 * @param[in] instance Batch structure to use. 339 * @param[in] data_stage to use for data packets. 340 * @param[in] status_stage to use for data packets. 341 * 342 * Setup stage with toggle 0 and USB_PID_SETUP. 343 * Data stage with alternating toggle and pid supplied by parameter. 344 * Status stage with toggle 1 and pid supplied by parameter. 345 * The last packet is marked with IOC. 346 */ 347 void batch_control(batch_t *instance, 348 usb_packet_id data_stage, usb_packet_id status_stage) 241 batch_schedule(instance); 242 } 243 /*----------------------------------------------------------------------------*/ 244 static void batch_control( 245 batch_t *instance, int data_stage, int status_stage) 349 246 { 350 247 assert(instance); … … 353 250 int toggle = 0; 354 251 /* setup stage */ 355 t d_init(instance->tds, DEFAULT_ERROR_COUNT,252 transfer_descriptor_init(instance->tds, DEFAULT_ERROR_COUNT, 356 253 instance->setup_size, toggle, false, low_speed, instance->target, 357 254 USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]); … … 371 268 remain_size : instance->max_packet_size; 372 269 373 t d_init(374 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,375 toggle, false, low_speed, instance->target, data_stage,376 data,&instance->tds[packet + 1]);270 transfer_descriptor_init(&instance->tds[packet], 271 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed, 272 instance->target, data_stage, data, 273 &instance->tds[packet + 1]); 377 274 378 275 ++packet; … … 384 281 /* status stage */ 385 282 assert(packet == instance->packets - 1); 386 t d_init(&instance->tds[packet], DEFAULT_ERROR_COUNT,283 transfer_descriptor_init(&instance->tds[packet], DEFAULT_ERROR_COUNT, 387 284 0, 1, false, low_speed, instance->target, status_stage, NULL, NULL); 388 285 389 td_set_ioc(&instance->tds[packet]); 286 287 instance->tds[packet].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 390 288 usb_log_debug2("Control last TD status: %x.\n", 391 289 instance->tds[packet].status); 392 290 } 393 291 /*----------------------------------------------------------------------------*/ 394 /** Prepare data, get error status and call callback in.395 *396 * @param[in] instance Batch structure to use.397 * Copies data from transport buffer, and calls callback with appropriate398 * parameters.399 */400 292 void batch_call_in(batch_t *instance) 401 293 { … … 403 295 assert(instance->callback_in); 404 296 405 /* We are data in, we need data */ 406 memcpy(instance->buffer, instance->transport_buffer, 407 instance->buffer_size); 297 memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size); 408 298 409 299 int err = instance->error; … … 412 302 instance->transfered_size); 413 303 414 instance->callback_in( 415 instance->fun, err, instance->transfered_size, instance->arg); 416 } 417 /*----------------------------------------------------------------------------*/ 418 /** Get error status and call callback out. 419 * 420 * @param[in] instance Batch structure to use. 421 */ 304 instance->callback_in(instance->fun, 305 err, instance->transfered_size, 306 instance->arg); 307 } 308 /*----------------------------------------------------------------------------*/ 422 309 void batch_call_out(batch_t *instance) 423 310 { … … 432 319 } 433 320 /*----------------------------------------------------------------------------*/ 434 /** Helper function calls callback and correctly disposes of batch structure.435 *436 * @param[in] instance Batch structure to use.437 */438 321 void batch_call_in_and_dispose(batch_t *instance) 439 322 { 440 323 assert(instance); 441 324 batch_call_in(instance); 442 batch_dispose(instance);443 }444 /*----------------------------------------------------------------------------*/445 /** Helper function calls callback and correctly disposes of batch structure.446 *447 * @param[in] instance Batch structure to use.448 */449 void batch_call_out_and_dispose(batch_t *instance)450 {451 assert(instance);452 batch_call_out(instance);453 batch_dispose(instance);454 }455 /*----------------------------------------------------------------------------*/456 /** Correctly dispose all used data structures.457 *458 * @param[in] instance Batch structure to use.459 */460 void batch_dispose(batch_t *instance)461 {462 assert(instance);463 325 usb_log_debug("Batch(%p) disposing.\n", instance); 464 /* free32 is NULL safe */465 326 free32(instance->tds); 466 327 free32(instance->qh); … … 469 330 free(instance); 470 331 } 332 /*----------------------------------------------------------------------------*/ 333 void batch_call_out_and_dispose(batch_t *instance) 334 { 335 assert(instance); 336 batch_call_out(instance); 337 usb_log_debug("Batch(%p) disposing.\n", instance); 338 free32(instance->tds); 339 free32(instance->qh); 340 free32(instance->setup_buffer); 341 free32(instance->transport_buffer); 342 free(instance); 343 } 344 /*----------------------------------------------------------------------------*/ 345 int batch_schedule(batch_t *instance) 346 { 347 assert(instance); 348 uhci_t *hc = fun_to_uhci(instance->fun); 349 assert(hc); 350 return uhci_schedule(hc, instance); 351 } 471 352 /** 472 353 * @} -
uspace/drv/uhci-hcd/batch.h
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver USB transaction structure32 * @brief UHCI driver 33 33 */ 34 34 #ifndef DRV_UHCI_BATCH_H … … 42 42 #include "uhci_struct/transfer_descriptor.h" 43 43 #include "uhci_struct/queue_head.h" 44 #include "utils/device_keeper.h"45 44 46 45 typedef struct batch … … 50 49 usb_target_t target; 51 50 usb_transfer_type_t transfer_type; 52 usbhc_iface_transfer_in_callback_t callback_in; 53 usbhc_iface_transfer_out_callback_t callback_out; 51 union { 52 usbhc_iface_transfer_in_callback_t callback_in; 53 usbhc_iface_transfer_out_callback_t callback_out; 54 }; 54 55 void *arg; 55 56 char *transport_buffer; … … 63 64 int error; 64 65 ddf_fun_t *fun; 65 q h_t *qh;66 t d_t *tds;66 queue_head_t *qh; 67 transfer_descriptor_t *tds; 67 68 void (*next_step)(struct batch*); 68 device_keeper_t *manager;69 69 } batch_t; 70 70 … … 74 74 char *setup_buffer, size_t setup_size, 75 75 usbhc_iface_transfer_in_callback_t func_in, 76 usbhc_iface_transfer_out_callback_t func_out, void *arg, 77 device_keeper_t *manager 78 ); 79 80 void batch_dispose(batch_t *instance); 76 usbhc_iface_transfer_out_callback_t func_out, void *arg); 81 77 82 78 bool batch_is_complete(batch_t *instance); … … 90 86 void batch_interrupt_out(batch_t *instance); 91 87 92 void batch_bulk_in(batch_t *instance); 88 /* DEPRECATED FUNCTIONS NEEDED BY THE OLD API */ 89 void batch_control_setup_old(batch_t *instance); 93 90 94 void batch_bulk_out(batch_t *instance); 91 void batch_control_write_data_old(batch_t *instance); 92 93 void batch_control_read_data_old(batch_t *instance); 94 95 void batch_control_write_status_old(batch_t *instance); 96 97 void batch_control_read_status_old(batch_t *instance); 95 98 #endif 96 99 /** -
uspace/drv/uhci-hcd/iface.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver hc interface implementation32 * @brief UHCI driver 33 33 */ 34 34 #include <ddf/driver.h> … … 40 40 41 41 #include "iface.h" 42 #include "uhci _hc.h"42 #include "uhci.h" 43 43 #include "utils/device_keeper.h" 44 44 45 /** Reserve default address interface function46 *47 * @param[in] fun DDF function that was called.48 * @param[in] speed Speed to associate with the new default address.49 * @return Error code.50 */51 45 /*----------------------------------------------------------------------------*/ 52 46 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) 53 47 { 54 48 assert(fun); 55 uhci_ hc_t *hc = fun_to_uhci_hc(fun);49 uhci_t *hc = fun_to_uhci(fun); 56 50 assert(hc); 57 51 usb_log_debug("Default address request with speed %d.\n", speed); … … 60 54 } 61 55 /*----------------------------------------------------------------------------*/ 62 /** Release default address interface function63 *64 * @param[in] fun DDF function that was called.65 * @return Error code.66 */67 56 static int release_default_address(ddf_fun_t *fun) 68 57 { 69 58 assert(fun); 70 uhci_ hc_t *hc = fun_to_uhci_hc(fun);59 uhci_t *hc = fun_to_uhci(fun); 71 60 assert(hc); 72 61 usb_log_debug("Default address release.\n"); … … 75 64 } 76 65 /*----------------------------------------------------------------------------*/ 77 /** Request address interface function78 *79 * @param[in] fun DDF function that was called.80 * @param[in] speed Speed to associate with the new default address.81 * @param[out] address Place to write a new address.82 * @return Error code.83 */84 66 static int request_address(ddf_fun_t *fun, usb_speed_t speed, 85 67 usb_address_t *address) 86 68 { 87 69 assert(fun); 88 uhci_ hc_t *hc = fun_to_uhci_hc(fun);70 uhci_t *hc = fun_to_uhci(fun); 89 71 assert(hc); 90 72 assert(address); … … 98 80 } 99 81 /*----------------------------------------------------------------------------*/ 100 /** Bind address interface function101 *102 * @param[in] fun DDF function that was called.103 * @param[in] address Address of the device104 * @param[in] handle Devman handle of the device driver.105 * @return Error code.106 */107 82 static int bind_address( 108 83 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle) 109 84 { 110 85 assert(fun); 111 uhci_ hc_t *hc = fun_to_uhci_hc(fun);86 uhci_t *hc = fun_to_uhci(fun); 112 87 assert(hc); 113 88 usb_log_debug("Address bind %d-%d.\n", address, handle); … … 116 91 } 117 92 /*----------------------------------------------------------------------------*/ 118 /** Release address interface function119 *120 * @param[in] fun DDF function that was called.121 * @param[in] address USB address to be released.122 * @return Error code.123 */124 93 static int release_address(ddf_fun_t *fun, usb_address_t address) 125 94 { 126 95 assert(fun); 127 uhci_ hc_t *hc = fun_to_uhci_hc(fun);96 uhci_t *hc = fun_to_uhci(fun); 128 97 assert(hc); 129 98 usb_log_debug("Address release %d.\n", address); … … 132 101 } 133 102 /*----------------------------------------------------------------------------*/ 134 /** Interrupt out transaction interface function135 *136 * @param[in] fun DDF function that was called.137 * @param[in] target USB device to write to.138 * @param[in] max_packet_size maximum size of data packet the device accepts139 * @param[in] data Source of data.140 * @param[in] size Size of data source.141 * @param[in] callback Function to call on transaction completion142 * @param[in] arg Additional for callback function.143 * @return Error code.144 */145 103 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 146 104 size_t max_packet_size, void *data, size_t size, … … 148 106 { 149 107 assert(fun); 150 uhci_ hc_t *hc = fun_to_uhci_hc(fun);108 uhci_t *hc = fun_to_uhci(fun); 151 109 assert(hc); 152 110 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 156 114 157 115 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT, 158 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg, 159 &hc->device_manager); 116 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg); 160 117 if (!batch) 161 118 return ENOMEM; 162 119 batch_interrupt_out(batch); 163 const int ret = uhci_hc_schedule(hc, batch); 164 if (ret != EOK) { 165 batch_dispose(batch); 166 return ret; 167 } 168 return EOK; 169 } 170 /*----------------------------------------------------------------------------*/ 171 /** Interrupt in transaction interface function 172 * 173 * @param[in] fun DDF function that was called. 174 * @param[in] target USB device to write to. 175 * @param[in] max_packet_size maximum size of data packet the device accepts 176 * @param[out] data Data destination. 177 * @param[in] size Size of data source. 178 * @param[in] callback Function to call on transaction completion 179 * @param[in] arg Additional for callback function. 180 * @return Error code. 181 */ 120 return EOK; 121 } 122 /*----------------------------------------------------------------------------*/ 182 123 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 183 124 size_t max_packet_size, void *data, size_t size, … … 185 126 { 186 127 assert(fun); 187 uhci_ hc_t *hc = fun_to_uhci_hc(fun);128 uhci_t *hc = fun_to_uhci(fun); 188 129 assert(hc); 189 130 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); … … 192 133 193 134 batch_t *batch = batch_get(fun, target, USB_TRANSFER_INTERRUPT, 194 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg, 195 &hc->device_manager); 135 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg); 196 136 if (!batch) 197 137 return ENOMEM; 198 138 batch_interrupt_in(batch); 199 const int ret = uhci_hc_schedule(hc, batch); 200 if (ret != EOK) { 201 batch_dispose(batch); 202 return ret; 203 } 204 return EOK; 205 } 206 /*----------------------------------------------------------------------------*/ 207 /** Bulk out transaction interface function 208 * 209 * @param[in] fun DDF function that was called. 210 * @param[in] target USB device to write to. 211 * @param[in] max_packet_size maximum size of data packet the device accepts 212 * @param[in] data Source of data. 213 * @param[in] size Size of data source. 214 * @param[in] callback Function to call on transaction completion 215 * @param[in] arg Additional for callback function. 216 * @return Error code. 217 */ 218 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 219 size_t max_packet_size, void *data, size_t size, 220 usbhc_iface_transfer_out_callback_t callback, void *arg) 221 { 222 assert(fun); 223 uhci_hc_t *hc = fun_to_uhci_hc(fun); 224 assert(hc); 225 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 226 227 usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n", 228 target.address, target.endpoint, size, max_packet_size); 229 230 batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK, 231 max_packet_size, speed, data, size, NULL, 0, NULL, callback, arg, 232 &hc->device_manager); 233 if (!batch) 234 return ENOMEM; 235 batch_bulk_out(batch); 236 const int ret = uhci_hc_schedule(hc, batch); 237 if (ret != EOK) { 238 batch_dispose(batch); 239 return ret; 240 } 241 return EOK; 242 } 243 /*----------------------------------------------------------------------------*/ 244 /** Bulk in transaction interface function 245 * 246 * @param[in] fun DDF function that was called. 247 * @param[in] target USB device to write to. 248 * @param[in] max_packet_size maximum size of data packet the device accepts 249 * @param[out] data Data destination. 250 * @param[in] size Size of data source. 251 * @param[in] callback Function to call on transaction completion 252 * @param[in] arg Additional for callback function. 253 * @return Error code. 254 */ 255 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 256 size_t max_packet_size, void *data, size_t size, 257 usbhc_iface_transfer_in_callback_t callback, void *arg) 258 { 259 assert(fun); 260 uhci_hc_t *hc = fun_to_uhci_hc(fun); 261 assert(hc); 262 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 263 usb_log_debug("Bulk IN %d:%d %zu(%zu).\n", 264 target.address, target.endpoint, size, max_packet_size); 265 266 batch_t *batch = batch_get(fun, target, USB_TRANSFER_BULK, 267 max_packet_size, speed, data, size, NULL, 0, callback, NULL, arg, 268 &hc->device_manager); 269 if (!batch) 270 return ENOMEM; 271 batch_bulk_in(batch); 272 const int ret = uhci_hc_schedule(hc, batch); 273 if (ret != EOK) { 274 batch_dispose(batch); 275 return ret; 276 } 277 return EOK; 278 } 279 /*----------------------------------------------------------------------------*/ 280 /** Control write transaction interface function 281 * 282 * @param[in] fun DDF function that was called. 283 * @param[in] target USB device to write to. 284 * @param[in] max_packet_size maximum size of data packet the device accepts. 285 * @param[in] setup_data Data to send with SETUP packet. 286 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). 287 * @param[in] data Source of data. 288 * @param[in] size Size of data source. 289 * @param[in] callback Function to call on transaction completion. 290 * @param[in] arg Additional for callback function. 291 * @return Error code. 292 */ 139 return EOK; 140 } 141 /*----------------------------------------------------------------------------*/ 293 142 static int control_write(ddf_fun_t *fun, usb_target_t target, 294 143 size_t max_packet_size, … … 297 146 { 298 147 assert(fun); 299 uhci_hc_t *hc = fun_to_uhci_hc(fun); 300 assert(hc); 301 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 302 usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n", 303 speed, target.address, target.endpoint, size, max_packet_size); 304 305 if (setup_size != 8) 306 return EINVAL; 148 uhci_t *hc = fun_to_uhci(fun); 149 assert(hc); 150 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 151 usb_log_debug("Control WRITE %d:%d %zu(%zu).\n", 152 target.address, target.endpoint, size, max_packet_size); 307 153 308 154 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, 309 155 max_packet_size, speed, data, size, setup_data, setup_size, 310 NULL, callback, arg, &hc->device_manager); 311 if (!batch) 312 return ENOMEM; 313 device_keeper_reset_if_need(&hc->device_manager, target, setup_data); 156 NULL, callback, arg); 157 if (!batch) 158 return ENOMEM; 314 159 batch_control_write(batch); 315 const int ret = uhci_hc_schedule(hc, batch); 316 if (ret != EOK) { 317 batch_dispose(batch); 318 return ret; 319 } 320 return EOK; 321 } 322 /*----------------------------------------------------------------------------*/ 323 /** Control read transaction interface function 324 * 325 * @param[in] fun DDF function that was called. 326 * @param[in] target USB device to write to. 327 * @param[in] max_packet_size maximum size of data packet the device accepts. 328 * @param[in] setup_data Data to send with SETUP packet. 329 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). 330 * @param[out] data Source of data. 331 * @param[in] size Size of data source. 332 * @param[in] callback Function to call on transaction completion. 333 * @param[in] arg Additional for callback function. 334 * @return Error code. 335 */ 160 return EOK; 161 } 162 /*----------------------------------------------------------------------------*/ 336 163 static int control_read(ddf_fun_t *fun, usb_target_t target, 337 164 size_t max_packet_size, … … 340 167 { 341 168 assert(fun); 342 uhci_ hc_t *hc = fun_to_uhci_hc(fun);343 assert(hc); 344 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 345 346 usb_log_debug("Control READ (%d)%d:%d %zu(%zu).\n",347 speed,target.address, target.endpoint, size, max_packet_size);169 uhci_t *hc = fun_to_uhci(fun); 170 assert(hc); 171 usb_speed_t speed = device_keeper_speed(&hc->device_manager, target.address); 172 173 usb_log_debug("Control READ %d:%d %zu(%zu).\n", 174 target.address, target.endpoint, size, max_packet_size); 348 175 batch_t *batch = batch_get(fun, target, USB_TRANSFER_CONTROL, 349 176 max_packet_size, speed, data, size, setup_data, setup_size, callback, 350 NULL, arg , &hc->device_manager);177 NULL, arg); 351 178 if (!batch) 352 179 return ENOMEM; 353 180 batch_control_read(batch); 354 const int ret = uhci_hc_schedule(hc, batch); 355 if (ret != EOK) { 356 batch_dispose(batch); 357 return ret; 358 } 359 return EOK; 360 } 361 /*----------------------------------------------------------------------------*/ 362 usbhc_iface_t uhci_hc_iface = { 181 return EOK; 182 } 183 184 185 /*----------------------------------------------------------------------------*/ 186 usbhc_iface_t uhci_iface = { 363 187 .reserve_default_address = reserve_default_address, 364 188 .release_default_address = release_default_address, … … 370 194 .interrupt_in = interrupt_in, 371 195 372 .bulk_in = bulk_in,373 .bulk_out = bulk_out,374 375 196 .control_read = control_read, 376 197 .control_write = control_write, -
uspace/drv/uhci-hcd/iface.h
r72af8da r3e7b7cd 27 27 */ 28 28 29 /** @addtogroup drvusbuhcihc29 /** @addtogroup usb 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief UHCI driver iface33 * @brief UHCI driver 34 34 */ 35 35 #ifndef DRV_UHCI_IFACE_H … … 38 38 #include <usbhc_iface.h> 39 39 40 extern usbhc_iface_t uhci_ hc_iface;40 extern usbhc_iface_t uhci_iface; 41 41 42 42 #endif -
uspace/drv/uhci-hcd/main.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver initialization32 * @brief UHCI driver 33 33 */ 34 34 #include <ddf/driver.h> 35 #include <ddf/interrupt.h> 36 #include <device/hw_res.h> 35 37 #include <errno.h> 36 38 #include <str_error.h> 37 39 40 #include <usb_iface.h> 38 41 #include <usb/ddfiface.h> 39 42 #include <usb/debug.h> 40 43 41 44 #include "iface.h" 45 #include "pci.h" 46 #include "root_hub.h" 42 47 #include "uhci.h" 43 48 … … 55 60 }; 56 61 /*----------------------------------------------------------------------------*/ 57 /** Initialize a new ddf driver instance for uhci hc and hub. 58 * 59 * @param[in] device DDF instance of the device to initialize. 60 * @return Error code. 61 */ 62 int uhci_add_device(ddf_dev_t *device) 62 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 63 63 { 64 usb_log_info("uhci_add_device() called\n"); 65 assert(device); 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 } 71 72 int ret = uhci_init(uhci, device); 73 if (ret != EOK) { 74 usb_log_error("Failed to initialzie UHCI driver.\n"); 75 return ret; 76 } 77 device->driver_data = uhci; 78 return EOK; 64 assert(dev); 65 uhci_t *hc = dev_to_uhci(dev); 66 uint16_t status = IPC_GET_ARG1(*call); 67 assert(hc); 68 uhci_interrupt(hc, status); 79 69 } 80 70 /*----------------------------------------------------------------------------*/ 81 /** Initialize global driver structures (NONE). 82 * 83 * @param[in] argc Nmber of arguments in argv vector (ignored). 84 * @param[in] argv Cmdline argument vector (ignored). 85 * @return Error code. 86 * 87 * Driver debug level is set here. 88 */ 71 static int uhci_add_device(ddf_dev_t *device) 72 { 73 assert(device); 74 uhci_t *hcd = NULL; 75 #define CHECK_RET_FREE_HC_RETURN(ret, message...) \ 76 if (ret != EOK) { \ 77 usb_log_error(message); \ 78 if (hcd != NULL) \ 79 free(hcd); \ 80 return ret; \ 81 } 82 83 usb_log_info("uhci_add_device() called\n"); 84 85 uintptr_t io_reg_base = 0; 86 size_t io_reg_size = 0; 87 int irq = 0; 88 89 int ret = 90 pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq); 91 CHECK_RET_FREE_HC_RETURN(ret, 92 "Failed(%d) to get I/O addresses:.\n", ret, device->handle); 93 usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n", 94 io_reg_base, io_reg_size, irq); 95 96 ret = pci_disable_legacy(device); 97 CHECK_RET_FREE_HC_RETURN(ret, 98 "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret)); 99 100 #if 0 101 ret = pci_enable_interrupts(device); 102 if (ret != EOK) { 103 usb_log_warning( 104 "Failed(%d) to enable interrupts, fall back to polling.\n", 105 ret); 106 } 107 #endif 108 109 hcd = malloc(sizeof(uhci_t)); 110 ret = (hcd != NULL) ? EOK : ENOMEM; 111 CHECK_RET_FREE_HC_RETURN(ret, 112 "Failed(%d) to allocate memory for uhci hcd.\n", ret); 113 114 ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size); 115 CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", 116 ret); 117 #undef CHECK_RET_FREE_HC_RETURN 118 119 /* 120 * We might free hcd, but that does not matter since no one 121 * else would access driver_data anyway. 122 */ 123 device->driver_data = hcd; 124 125 ddf_fun_t *rh = NULL; 126 #define CHECK_RET_FINI_FREE_RETURN(ret, message...) \ 127 if (ret != EOK) { \ 128 usb_log_error(message); \ 129 if (hcd != NULL) {\ 130 uhci_fini(hcd); \ 131 free(hcd); \ 132 } \ 133 if (rh != NULL) \ 134 free(rh); \ 135 return ret; \ 136 } 137 138 /* It does no harm if we register this on polling */ 139 ret = register_interrupt_handler(device, irq, irq_handler, 140 &hcd->interrupt_code); 141 CHECK_RET_FINI_FREE_RETURN(ret, 142 "Failed(%d) to register interrupt handler.\n", ret); 143 144 ret = setup_root_hub(&rh, device); 145 CHECK_RET_FINI_FREE_RETURN(ret, 146 "Failed(%d) to setup UHCI root hub.\n", ret); 147 rh->driver_data = hcd->ddf_instance; 148 149 ret = ddf_fun_bind(rh); 150 CHECK_RET_FINI_FREE_RETURN(ret, 151 "Failed(%d) to register UHCI root hub.\n", ret); 152 153 return EOK; 154 #undef CHECK_RET_FINI_FREE_RETURN 155 } 156 /*----------------------------------------------------------------------------*/ 89 157 int main(int argc, char *argv[]) 90 158 { 91 sleep(3); /* TODO: remove in final version */159 sleep(3); 92 160 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 93 161 -
uspace/drv/uhci-hcd/pci.c
r72af8da r3e7b7cd 27 27 */ 28 28 /** 29 * @addtogroup drvusbuhci hc29 * @addtogroup drvusbuhci 30 30 * @{ 31 31 */ … … 65 65 66 66 int rc; 67 67 68 hw_resource_list_t hw_resources; 68 69 rc = hw_res_get_resource_list(parent_phone, &hw_resources); … … 81 82 for (i = 0; i < hw_resources.count; i++) { 82 83 hw_resource_t *res = &hw_resources.resources[i]; 83 switch (res->type) 84 { 85 case INTERRUPT: 86 irq = res->res.interrupt.irq; 87 irq_found = true; 88 usb_log_debug2("Found interrupt: %d.\n", irq); 89 break; 90 91 case IO_RANGE: 92 io_address = res->res.io_range.address; 93 io_size = res->res.io_range.size; 94 usb_log_debug2("Found io: %llx %zu.\n", 95 res->res.io_range.address, res->res.io_range.size); 96 io_found = true; 97 98 default: 99 break; 84 switch (res->type) { 85 case INTERRUPT: 86 irq = res->res.interrupt.irq; 87 irq_found = true; 88 usb_log_debug2("Found interrupt: %d.\n", irq); 89 break; 90 case IO_RANGE: 91 io_address = res->res.io_range.address; 92 io_size = res->res.io_range.size; 93 usb_log_debug2("Found io: %llx %zu.\n", 94 res->res.io_range.address, res->res.io_range.size); 95 io_found = true; 96 break; 97 default: 98 break; 100 99 } 101 100 } 102 101 103 if (!io_found || !irq_found) { 102 if (!io_found) { 103 rc = ENOENT; 104 goto leave; 105 } 106 107 if (!irq_found) { 104 108 rc = ENOENT; 105 109 goto leave; … … 117 121 } 118 122 /*----------------------------------------------------------------------------*/ 119 /** Call the PCI driver with a request to enable interrupts120 *121 * @param[in] device Device asking for interrupts122 * @return Error code.123 */124 123 int pci_enable_interrupts(ddf_dev_t *device) 125 124 { … … 131 130 } 132 131 /*----------------------------------------------------------------------------*/ 133 /** Call the PCI driver with a request to clear legacy support register134 *135 * @param[in] device Device asking to disable interrupts136 * @return Error code.137 */138 132 int pci_disable_legacy(ddf_dev_t *device) 139 133 { 140 134 assert(device); 141 int parent_phone = 142 devman_parent_device_connect(device->handle,IPC_FLAG_BLOCKING);135 int parent_phone = devman_parent_device_connect(device->handle, 136 IPC_FLAG_BLOCKING); 143 137 if (parent_phone < 0) { 144 138 return parent_phone; … … 150 144 sysarg_t value = 0x8f00; 151 145 152 int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),146 int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 153 147 IPC_M_CONFIG_SPACE_WRITE_16, address, value); 154 148 async_hangup(parent_phone); 155 149 156 return rc;150 return rc; 157 151 } 158 152 /*----------------------------------------------------------------------------*/ -
uspace/drv/uhci-hcd/pci.h
r72af8da r3e7b7cd 27 27 */ 28 28 29 /** @addtogroup drvusbuhci hc29 /** @addtogroup drvusbuhci 30 30 * @{ 31 31 */ 32 32 /** @file 33 * @brief UHCI driver PCI helper functions33 * @brief UHCI driver 34 34 */ 35 35 #ifndef DRV_UHCI_PCI_H -
uspace/drv/uhci-hcd/transfer_list.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver transfer list implementation32 * @brief UHCI driver 33 33 */ 34 34 #include <errno.h> 35 35 36 #include <usb/debug.h> 36 37 37 38 #include "transfer_list.h" 38 39 39 static void transfer_list_remove_batch(40 transfer_list_t *instance, batch_t *batch);41 /*----------------------------------------------------------------------------*/42 /** Initialize transfer list structures.43 *44 * @param[in] instance Memory place to use.45 * @param[in] name Name of the new list.46 * @return Error code47 *48 * Allocates memory for internal qh_t structure.49 */50 40 int transfer_list_init(transfer_list_t *instance, const char *name) 51 41 { 52 42 assert(instance); 43 instance->next = NULL; 53 44 instance->name = name; 54 instance->queue_head = malloc32(sizeof(qh_t));45 instance->queue_head = queue_head_get(); 55 46 if (!instance->queue_head) { 56 47 usb_log_error("Failed to allocate queue head.\n"); 57 48 return ENOMEM; 58 49 } 59 instance->queue_head_pa = addr_to_phys(instance->queue_head);50 instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head); 60 51 61 q h_init(instance->queue_head);52 queue_head_init(instance->queue_head); 62 53 list_initialize(&instance->batch_list); 63 54 fibril_mutex_initialize(&instance->guard); … … 65 56 } 66 57 /*----------------------------------------------------------------------------*/ 67 /** Set the next list in transfer list chain.68 *69 * @param[in] instance List to lead.70 * @param[in] next List to append.71 * @return Error code72 *73 * Does not check whether this replaces an existing list .74 */75 58 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next) 76 59 { … … 79 62 if (!instance->queue_head) 80 63 return; 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); 64 queue_head_append_qh(instance->queue_head, next->queue_head_pa); 65 instance->queue_head->element = instance->queue_head->next_queue; 84 66 } 85 67 /*----------------------------------------------------------------------------*/ 86 /** Submit transfer batch to the list and queue.87 *88 * @param[in] instance List to use.89 * @param[in] batch Transfer batch to submit.90 * @return Error code91 *92 * The batch is added to the end of the list and queue.93 */94 68 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch) 95 69 { 96 70 assert(instance); 97 71 assert(batch); 98 usb_log_debug2(" Queue %s: Adding batch(%p).\n", instance->name, batch);72 usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name); 99 73 100 const uint32_t pa =addr_to_phys(batch->qh);74 uint32_t pa = (uintptr_t)addr_to_phys(batch->qh); 101 75 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa); 76 pa |= LINK_POINTER_QUEUE_HEAD_FLAG; 102 77 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, instance->queue_head->next); 78 batch->qh->next_queue = instance->queue_head->next_queue; 106 79 107 80 fibril_mutex_lock(&instance->guard); 108 81 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(last->qh, pa); 82 if (instance->queue_head->element == instance->queue_head->next_queue) { 83 /* there is nothing scheduled */ 84 list_append(&batch->link, &instance->batch_list); 85 instance->queue_head->element = pa; 86 usb_log_debug("Batch(%p) added to queue %s first.\n", 87 batch, instance->name); 88 fibril_mutex_unlock(&instance->guard); 89 return; 120 90 } 121 /* Add to the driver list */ 91 /* now we can be sure that there is someting scheduled */ 92 assert(!list_empty(&instance->batch_list)); 93 batch_t *first = list_get_instance( 94 instance->batch_list.next, batch_t, link); 95 batch_t *last = list_get_instance( 96 instance->batch_list.prev, batch_t, link); 97 queue_head_append_qh(last->qh, pa); 122 98 list_append(&batch->link, &instance->batch_list); 123 124 batch_t *first = list_get_instance( 125 instance->batch_list.next, batch_t, link); 126 usb_log_debug("Batch(%p) added to queue %s, first is %p.\n", 127 batch, instance->name, first); 99 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 100 batch, instance->name, first ); 128 101 fibril_mutex_unlock(&instance->guard); 129 102 } 130 103 /*----------------------------------------------------------------------------*/ 131 /** Remove a transfer batch from the list and queue. 132 * 133 * @param[in] instance List to use. 134 * @param[in] batch Transfer batch to remove. 135 * @return Error code 136 * 137 * Does not lock the transfer list, caller is responsible for that. 138 */ 139 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) 104 static void transfer_list_remove_batch( 105 transfer_list_t *instance, batch_t *batch) 140 106 { 141 107 assert(instance); … … 143 109 assert(instance->queue_head); 144 110 assert(batch->qh); 145 usb_log_debug2( 146 "Queue %s: removing batch(%p).\n", instance->name, batch); 111 usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name); 147 112 148 const char * pos = NULL; 149 /* Remove from the hardware queue */ 113 /* I'm the first one here */ 150 114 if (batch->link.prev == &instance->batch_list) { 151 /* I'm the first one here */152 qh_set_element_qh(instance->queue_head, batch->qh->next);153 pos = "FIRST";115 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n", 116 batch, instance->name, batch->qh->next_queue); 117 instance->queue_head->element = batch->qh->next_queue; 154 118 } else { 155 batch_t *prev =156 list_get_instance(batch->link.prev, batch_t, link);157 qh_set_next_qh(prev->qh, batch->qh->next);158 p os = "NOT FIRST";119 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n", 120 batch, instance->name, batch->qh->next_queue); 121 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link); 122 prev->qh->next_queue = batch->qh->next_queue; 159 123 } 160 /* Remove from the driver list */161 124 list_remove(&batch->link); 162 usb_log_debug("Batch(%p) removed (%s) from %s, next element %x.\n",163 batch, pos, instance->name, batch->qh->next);164 125 } 165 126 /*----------------------------------------------------------------------------*/ 166 /** Check list for finished batches.167 *168 * @param[in] instance List to use.169 * @return Error code170 *171 * Creates a local list of finished batches and calls next_step on each and172 * every one. This is safer because next_step may theoretically access173 * this transfer list leading to the deadlock if its done inline.174 */175 127 void transfer_list_remove_finished(transfer_list_t *instance) 176 128 { … … 186 138 187 139 if (batch_is_complete(batch)) { 188 /* Save for post-processing */189 140 transfer_list_remove_batch(instance, batch); 190 141 list_append(current, &done); -
uspace/drv/uhci-hcd/transfer_list.h
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver transfer list structure32 * @brief UHCI driver 33 33 */ 34 34 #ifndef DRV_UHCI_TRANSFER_LIST_H … … 44 44 { 45 45 fibril_mutex_t guard; 46 q h_t *queue_head;46 queue_head_t *queue_head; 47 47 uint32_t queue_head_pa; 48 struct transfer_list *next; 48 49 const char *name; 49 50 link_t batch_list; 50 51 } 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 }63 52 64 53 int transfer_list_init(transfer_list_t *instance, const char *name); … … 66 55 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next); 67 56 57 static inline void transfer_list_fini(transfer_list_t *instance) 58 { 59 assert(instance); 60 queue_head_dispose(instance->queue_head); 61 } 68 62 void transfer_list_remove_finished(transfer_list_t *instance); 69 63 -
uspace/drv/uhci-hcd/uhci.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 /** @addtogroup drvusbuhci 28 /** @addtogroup usb 30 29 * @{ 31 30 */ … … 35 34 #include <errno.h> 36 35 #include <str_error.h> 37 #include <ddf/interrupt.h> 36 #include <adt/list.h> 37 #include <libarch/ddi.h> 38 39 #include <usb/debug.h> 40 #include <usb/usb.h> 41 #include <usb/ddfiface.h> 38 42 #include <usb_iface.h> 39 #include <usb/ddfiface.h>40 #include <usb/debug.h>41 43 42 44 #include "uhci.h" 43 45 #include "iface.h" 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); 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_ACCEPT 60 } 61 }; 62 63 static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle, 64 usb_address_t *address) 65 { 66 assert(fun); 67 uhci_t *hc = fun_to_uhci(fun); 58 68 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. 67 */ 68 static int usb_iface_get_address( 69 ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address) 70 { 71 assert(fun); 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); 69 70 usb_address_t addr = device_keeper_find(&hc->device_manager, 71 handle); 75 72 if (addr < 0) { 76 73 return addr; … … 84 81 } 85 82 /*----------------------------------------------------------------------------*/ 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, 83 static usb_iface_t hc_usb_iface = { 84 .get_hc_handle = usb_iface_get_hc_handle_hc_impl, 106 85 .get_address = usb_iface_get_address 107 86 }; 108 87 /*----------------------------------------------------------------------------*/ 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 */88 static ddf_dev_ops_t uhci_ops = { 89 .interfaces[USB_DEV_IFACE] = &hc_usb_iface, 90 .interfaces[USBHC_DEV_IFACE] = &uhci_iface, 112 91 }; 113 92 /*----------------------------------------------------------------------------*/ 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; 93 static int uhci_init_transfer_lists(uhci_t *instance); 94 static int uhci_init_mem_structures(uhci_t *instance); 95 static void uhci_init_hw(uhci_t *instance); 96 97 static int uhci_interrupt_emulator(void *arg); 98 static int uhci_debug_checker(void *arg); 99 100 static bool allowed_usb_packet( 101 bool low_speed, usb_transfer_type_t, size_t size); 102 103 104 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 105 { 106 assert(reg_size >= sizeof(regs_t)); 107 int ret; 108 151 109 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \ 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); 110 if (ret != EOK) { \ 111 usb_log_error(message); \ 112 if (instance->ddf_instance) \ 113 ddf_fun_destroy(instance->ddf_instance); \ 114 return ret; \ 115 } else (void) 0 116 117 /* Create UHCI function. */ 118 instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci"); 119 ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK; 167 120 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); 121 "Failed to create UHCI device function.\n"); 122 123 instance->ddf_instance->ops = &uhci_ops; 124 instance->ddf_instance->driver_data = instance; 125 126 ret = ddf_fun_bind(instance->ddf_instance); 198 127 CHECK_RET_DEST_FUN_RETURN(ret, 199 128 "Failed(%d) to bind UHCI device function: %s.\n", 200 129 ret, str_error(ret)); 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 236 return EOK; 237 #undef CHECK_RET_FINI_RETURN 130 131 /* allow access to hc control registers */ 132 regs_t *io; 133 ret = pio_enable(regs, reg_size, (void**)&io); 134 CHECK_RET_DEST_FUN_RETURN(ret, 135 "Failed(%d) to gain access to registers at %p: %s.\n", 136 ret, str_error(ret), io); 137 instance->registers = io; 138 usb_log_debug("Device registers at %p(%u) accessible.\n", 139 io, reg_size); 140 141 ret = uhci_init_mem_structures(instance); 142 CHECK_RET_DEST_FUN_RETURN(ret, 143 "Failed to initialize UHCI memory structures.\n"); 144 145 uhci_init_hw(instance); 146 instance->cleaner = 147 fibril_create(uhci_interrupt_emulator, instance); 148 fibril_add_ready(instance->cleaner); 149 150 instance->debug_checker = fibril_create(uhci_debug_checker, instance); 151 fibril_add_ready(instance->debug_checker); 152 153 usb_log_info("Started UHCI driver.\n"); 154 return EOK; 155 #undef CHECK_RET_DEST_FUN_RETURN 156 } 157 /*----------------------------------------------------------------------------*/ 158 void uhci_init_hw(uhci_t *instance) 159 { 160 assert(instance); 161 162 /* reset everything, who knows what touched it before us */ 163 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET); 164 async_usleep(10000); /* 10ms according to USB spec */ 165 pio_write_16(&instance->registers->usbcmd, 0); 166 167 /* reset hc, all states and counters */ 168 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET); 169 while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0) 170 { async_usleep(10); } 171 172 /* set framelist pointer */ 173 const uint32_t pa = addr_to_phys(instance->frame_list); 174 pio_write_32(&instance->registers->flbaseadd, pa); 175 176 /* enable all interrupts, but resume interrupt */ 177 pio_write_16(&instance->registers->usbintr, 178 UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET); 179 180 /* Start the hc with large(64B) packet FSBR */ 181 pio_write_16(&instance->registers->usbcmd, 182 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); 183 } 184 /*----------------------------------------------------------------------------*/ 185 int uhci_init_mem_structures(uhci_t *instance) 186 { 187 assert(instance); 188 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \ 189 if (ret != EOK) { \ 190 usb_log_error(message); \ 191 if (instance->interrupt_code.cmds != NULL) \ 192 free(instance->interrupt_code.cmds); \ 193 return ret; \ 194 } else (void) 0 195 196 /* init interrupt code */ 197 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 198 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 199 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n"); 200 201 { 202 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 203 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 204 interrupt_commands[0].addr = (void*)&instance->registers->usbsts; 205 interrupt_commands[1].addr = (void*)&instance->registers->usbsts; 206 instance->interrupt_code.cmdcount = 207 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 208 } 209 210 /* init transfer lists */ 211 ret = uhci_init_transfer_lists(instance); 212 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n"); 213 usb_log_debug("Initialized transfer lists.\n"); 214 215 /* frame list initialization */ 216 instance->frame_list = get_page(); 217 ret = instance ? EOK : ENOMEM; 218 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n"); 219 usb_log_debug("Initialized frame list.\n"); 220 221 /* initialize all frames to point to the first queue head */ 222 const uint32_t queue = 223 instance->transfers_interrupt.queue_head_pa 224 | LINK_POINTER_QUEUE_HEAD_FLAG; 225 226 unsigned i = 0; 227 for(; i < UHCI_FRAME_LIST_COUNT; ++i) { 228 instance->frame_list[i] = queue; 229 } 230 231 /* init address keeper(libusb) */ 232 device_keeper_init(&instance->device_manager); 233 usb_log_debug("Initialized device manager.\n"); 234 235 return EOK; 236 #undef CHECK_RET_DEST_CMDS_RETURN 237 } 238 /*----------------------------------------------------------------------------*/ 239 int uhci_init_transfer_lists(uhci_t *instance) 240 { 241 assert(instance); 242 #define CHECK_RET_CLEAR_RETURN(ret, message...) \ 243 if (ret != EOK) { \ 244 usb_log_error(message); \ 245 transfer_list_fini(&instance->transfers_bulk_full); \ 246 transfer_list_fini(&instance->transfers_control_full); \ 247 transfer_list_fini(&instance->transfers_control_slow); \ 248 transfer_list_fini(&instance->transfers_interrupt); \ 249 return ret; \ 250 } else (void) 0 251 252 /* initialize TODO: check errors */ 253 int ret; 254 ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL"); 255 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 256 257 ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL"); 258 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 259 260 ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW"); 261 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 262 263 ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT"); 264 CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list."); 265 266 transfer_list_set_next(&instance->transfers_control_full, 267 &instance->transfers_bulk_full); 268 transfer_list_set_next(&instance->transfers_control_slow, 269 &instance->transfers_control_full); 270 transfer_list_set_next(&instance->transfers_interrupt, 271 &instance->transfers_control_slow); 272 273 /*FSBR*/ 274 #ifdef FSBR 275 transfer_list_set_next(&instance->transfers_bulk_full, 276 &instance->transfers_control_full); 277 #endif 278 279 instance->transfers[0][USB_TRANSFER_INTERRUPT] = 280 &instance->transfers_interrupt; 281 instance->transfers[1][USB_TRANSFER_INTERRUPT] = 282 &instance->transfers_interrupt; 283 instance->transfers[0][USB_TRANSFER_CONTROL] = 284 &instance->transfers_control_full; 285 instance->transfers[1][USB_TRANSFER_CONTROL] = 286 &instance->transfers_control_slow; 287 instance->transfers[0][USB_TRANSFER_BULK] = 288 &instance->transfers_bulk_full; 289 290 return EOK; 291 #undef CHECK_RET_CLEAR_RETURN 292 } 293 /*----------------------------------------------------------------------------*/ 294 int uhci_schedule(uhci_t *instance, batch_t *batch) 295 { 296 assert(instance); 297 assert(batch); 298 const int low_speed = (batch->speed == USB_SPEED_LOW); 299 if (!allowed_usb_packet( 300 low_speed, batch->transfer_type, batch->max_packet_size)) { 301 usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n", 302 low_speed ? "LOW" : "FULL" , batch->transfer_type, 303 batch->max_packet_size); 304 return ENOTSUP; 305 } 306 /* TODO: check available bandwith here */ 307 308 transfer_list_t *list = 309 instance->transfers[low_speed][batch->transfer_type]; 310 assert(list); 311 transfer_list_add_batch(list, batch); 312 313 return EOK; 314 } 315 /*----------------------------------------------------------------------------*/ 316 void uhci_interrupt(uhci_t *instance, uint16_t status) 317 { 318 assert(instance); 319 transfer_list_remove_finished(&instance->transfers_interrupt); 320 transfer_list_remove_finished(&instance->transfers_control_slow); 321 transfer_list_remove_finished(&instance->transfers_control_full); 322 transfer_list_remove_finished(&instance->transfers_bulk_full); 323 } 324 /*----------------------------------------------------------------------------*/ 325 int uhci_interrupt_emulator(void* arg) 326 { 327 usb_log_debug("Started interrupt emulator.\n"); 328 uhci_t *instance = (uhci_t*)arg; 329 assert(instance); 330 331 while (1) { 332 uint16_t status = pio_read_16(&instance->registers->usbsts); 333 if (status != 0) 334 usb_log_debug2("UHCI status: %x.\n", status); 335 status |= 1; 336 uhci_interrupt(instance, status); 337 pio_write_16(&instance->registers->usbsts, 0x1f); 338 async_usleep(UHCI_CLEANER_TIMEOUT * 5); 339 } 340 return EOK; 341 } 342 /*---------------------------------------------------------------------------*/ 343 int uhci_debug_checker(void *arg) 344 { 345 uhci_t *instance = (uhci_t*)arg; 346 assert(instance); 347 348 #define QH(queue) \ 349 instance->transfers_##queue.queue_head 350 351 while (1) { 352 const uint16_t cmd = pio_read_16(&instance->registers->usbcmd); 353 const uint16_t sts = pio_read_16(&instance->registers->usbsts); 354 const uint16_t intr = 355 pio_read_16(&instance->registers->usbintr); 356 357 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) { 358 usb_log_debug2("Command: %X Status: %X Intr: %x\n", 359 cmd, sts, intr); 360 } 361 362 uintptr_t frame_list = 363 pio_read_32(&instance->registers->flbaseadd) & ~0xfff; 364 if (frame_list != addr_to_phys(instance->frame_list)) { 365 usb_log_debug("Framelist address: %p vs. %p.\n", 366 frame_list, addr_to_phys(instance->frame_list)); 367 } 368 369 int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff; 370 usb_log_debug2("Framelist item: %d \n", frnum ); 371 372 uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf); 373 uintptr_t real_pa = addr_to_phys(QH(interrupt)); 374 if (expected_pa != real_pa) { 375 usb_log_debug("Interrupt QH: %p vs. %p.\n", 376 expected_pa, real_pa); 377 } 378 379 expected_pa = QH(interrupt)->next_queue & (~0xf); 380 real_pa = addr_to_phys(QH(control_slow)); 381 if (expected_pa != real_pa) { 382 usb_log_debug("Control Slow QH: %p vs. %p.\n", 383 expected_pa, real_pa); 384 } 385 386 expected_pa = QH(control_slow)->next_queue & (~0xf); 387 real_pa = addr_to_phys(QH(control_full)); 388 if (expected_pa != real_pa) { 389 usb_log_debug("Control Full QH: %p vs. %p.\n", 390 expected_pa, real_pa); 391 } 392 393 expected_pa = QH(control_full)->next_queue & (~0xf); 394 real_pa = addr_to_phys(QH(bulk_full)); 395 if (expected_pa != real_pa ) { 396 usb_log_debug("Bulk QH: %p vs. %p.\n", 397 expected_pa, real_pa); 398 } 399 async_usleep(UHCI_DEBUGER_TIMEOUT); 400 } 401 return 0; 402 #undef QH 403 } 404 /*----------------------------------------------------------------------------*/ 405 bool allowed_usb_packet( 406 bool low_speed, usb_transfer_type_t transfer, size_t size) 407 { 408 /* see USB specification chapter 5.5-5.8 for magic numbers used here */ 409 switch(transfer) 410 { 411 case USB_TRANSFER_ISOCHRONOUS: 412 return (!low_speed && size < 1024); 413 case USB_TRANSFER_INTERRUPT: 414 return size <= (low_speed ? 8 : 64); 415 case USB_TRANSFER_CONTROL: /* device specifies its own max size */ 416 return (size <= (low_speed ? 8 : 64)); 417 case USB_TRANSFER_BULK: /* device specifies its own max size */ 418 return (!low_speed && size <= 64); 419 } 420 return false; 238 421 } 239 422 /** -
uspace/drv/uhci-hcd/uhci.h
r72af8da r3e7b7cd 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2010 Jan Vesely 3 3 * All rights reserved. 4 4 * … … 31 31 */ 32 32 /** @file 33 * @brief UHCI driver main structure for both host controller and root-hub.33 * @brief UHCI driver 34 34 */ 35 35 #ifndef DRV_UHCI_UHCI_H 36 36 #define DRV_UHCI_UHCI_H 37 38 #include <fibril.h> 39 #include <fibril_synch.h> 40 #include <adt/list.h> 37 41 #include <ddi.h> 38 #include <ddf/driver.h>39 42 40 #include "uhci_hc.h" 41 #include "uhci_rh.h" 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 42 82 43 83 typedef struct uhci { 44 ddf_fun_t *hc_fun; 45 ddf_fun_t *rh_fun; 84 device_keeper_t device_manager; 46 85 47 uhci_hc_t hc; 48 uhci_rh_t rh; 86 volatile 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; 49 103 } uhci_t; 50 104 51 int uhci_init(uhci_t *instance, ddf_dev_t *device); 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 52 120 53 121 #endif -
uspace/drv/uhci-hcd/uhci_struct/link_pointer.h
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 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 51 48 #endif 52 49 /** -
uspace/drv/uhci-hcd/uhci_struct/queue_head.h
r72af8da r3e7b7cd 1 1 2 /* 2 3 * Copyright (c) 2010 Jan Vesely … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 /** @addtogroup drv usbuhcihc29 /** @addtogroup usb 29 30 * @{ 30 31 */ … … 42 43 43 44 typedef struct queue_head { 44 volatile link_pointer_t next ;45 volatile link_pointer_t next_queue; 45 46 volatile link_pointer_t element; 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) 47 } __attribute__((packed)) queue_head_t; 48 49 static inline void queue_head_init(queue_head_t *instance) 55 50 { 56 51 assert(instance); 57 52 58 53 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG; 59 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;54 instance->next_queue = 0 | LINK_POINTER_TERMINATE_FLAG; 60 55 } 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) 56 57 static inline void queue_head_append_qh(queue_head_t *instance, uint32_t pa) 71 58 { 72 /* Address is valid and not terminal */ 73 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 74 instance->next = (pa & LINK_POINTER_ADDRESS_MASK) 59 if (pa) { 60 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK) 75 61 | LINK_POINTER_QUEUE_HEAD_FLAG; 76 } else {77 instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;78 62 } 79 63 } 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) 64 65 static inline void queue_head_element_qh(queue_head_t *instance, uint32_t pa) 90 66 { 91 /* Address is valid and not terminal */ 92 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) { 93 instance->element = (pa & LINK_POINTER_ADDRESS_MASK) 67 if (pa) { 68 instance->next_queue = (pa & LINK_POINTER_ADDRESS_MASK) 94 69 | LINK_POINTER_QUEUE_HEAD_FLAG; 95 } else {96 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;97 70 } 98 71 } 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) 72 73 static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa) 109 74 { 110 if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {75 if (pa) { 111 76 instance->element = (pa & LINK_POINTER_ADDRESS_MASK); 112 } else {113 instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;114 77 } 115 78 } 79 80 static inline queue_head_t * queue_head_get() { 81 queue_head_t *ret = malloc32(sizeof(queue_head_t)); 82 if (ret) 83 queue_head_init(ret); 84 return ret; 85 } 86 87 static inline void queue_head_dispose(queue_head_t *head) 88 { free32(head); } 89 116 90 117 91 #endif -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ … … 38 38 #include "utils/malloc32.h" 39 39 40 /** Initialize Transfer Descriptor 41 * 42 * @param[in] instance Memory place to initialize. 43 * @param[in] err_count Number of retries hc should attempt. 44 * @param[in] size Size of data source. 45 * @param[in] toggle Value of toggle bit. 46 * @param[in] iso True if TD represents Isochronous transfer. 47 * @param[in] low_speed Target device's speed. 48 * @param[in] target Address and endpoint receiving the transfer. 49 * @param[in] pid Packet identification (SETUP, IN or OUT). 50 * @param[in] buffer Source of data. 51 * @param[in] next Net TD in transaction. 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. 61 */ 62 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso, 63 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer, 64 td_t *next) 40 void transfer_descriptor_init(transfer_descriptor_t *instance, 41 int error_count, size_t size, bool toggle, bool isochronous, bool low_speed, 42 usb_target_t target, int pid, void *buffer, transfer_descriptor_t *next) 65 43 { 66 44 assert(instance); 67 assert(size < 1024);68 assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)69 || (pid == USB_PID_OUT));70 45 71 46 instance->next = 0 … … 74 49 75 50 instance->status = 0 76 | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS) 77 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0) 78 | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0) 79 | TD_STATUS_ERROR_ACTIVE; 51 | ((error_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS) 52 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0) 53 | TD_STATUS_ERROR_ACTIVE; 80 54 81 if (pid == USB_PID_IN && !iso) { 82 instance->status |= TD_STATUS_SPD_FLAG; 83 } 84 55 assert(size < 1024); 85 56 instance->device = 0 86 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)87 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)88 | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)89 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)90 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);57 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS) 58 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0) 59 | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS) 60 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS) 61 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS); 91 62 92 63 instance->buffer_ptr = 0; … … 96 67 } 97 68 98 usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n", 99 instance, instance->next, instance->status, instance->device, 100 instance->buffer_ptr, buffer); 101 td_print_status(instance); 102 if (pid == USB_PID_SETUP) { 103 usb_log_debug("SETUP BUFFER: %s\n", 104 usb_debug_str_buffer(buffer, 8, 8)); 105 } 69 usb_log_debug2("Created TD: %X:%X:%X:%X(%p).\n", 70 instance->next, instance->status, instance->device, 71 instance->buffer_ptr, buffer); 106 72 } 107 73 /*----------------------------------------------------------------------------*/ 108 /** Convert TD status into standard error code 109 * 110 * @param[in] instance TD structure to use. 111 * @return Error code. 112 */ 113 int td_status(td_t *instance) 74 int transfer_descriptor_status(transfer_descriptor_t *instance) 114 75 { 115 76 assert(instance); … … 135 96 return EOK; 136 97 } 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 (s >> TD_STATUS_ACTLEN_POS) & TD_STATUS_ACTLEN_MASK162 );163 }164 98 /** 165 99 * @} -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.h
r72af8da r3e7b7cd 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2010 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 drvusbuhcihc28 /** @addtogroup usb 29 29 * @{ 30 30 */ … … 45 45 46 46 volatile uint32_t status; 47 47 48 #define TD_STATUS_RESERVED_MASK 0xc000f800 48 49 #define TD_STATUS_SPD_FLAG ( 1 << 29 ) 49 50 #define TD_STATUS_ERROR_COUNT_POS ( 27 ) 50 51 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 ) 52 #define TD_STATUS_ERROR_COUNT_DEFAULT 3 51 53 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 ) 52 54 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 ) 53 #define TD_STATUS_ IOC_FLAG ( 1 << 24 )55 #define TD_STATUS_COMPLETE_INTERRUPT_FLAG ( 1 << 24 ) 54 56 55 57 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23 ) … … 68 70 69 71 volatile uint32_t device; 72 70 73 #define TD_DEVICE_MAXLEN_POS 21 71 74 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff ) … … 82 85 83 86 /* there is 16 bytes of data available here, according to UHCI 84 * Design guide, according to linux kernel the hardware does not care ,85 * it just needs to be aligned,we don't use it anyway87 * Design guide, according to linux kernel the hardware does not care 88 * we don't use it anyway 86 89 */ 87 } __attribute__((packed)) t d_t;90 } __attribute__((packed)) transfer_descriptor_t; 88 91 89 92 90 void t d_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);93 void transfer_descriptor_init(transfer_descriptor_t *instance, 94 int error_count, size_t size, bool toggle, bool isochronous, bool low_speed, 95 usb_target_t target, int pid, void *buffer, transfer_descriptor_t * next); 93 96 94 int t d_status(td_t *instance);97 int transfer_descriptor_status(transfer_descriptor_t *instance); 95 98 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 */ 103 static inline size_t td_act_size(td_t *instance) 99 static inline size_t transfer_descriptor_actual_size( 100 transfer_descriptor_t *instance) 104 101 { 105 102 assert(instance); 106 const uint32_t s = instance->status;107 return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;103 return 104 ((instance->status >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK; 108 105 } 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 */ 116 static inline bool td_is_short(td_t *instance) 117 { 118 const size_t act_size = td_act_size(instance); 119 const size_t max_size = 120 ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1) 121 & TD_DEVICE_MAXLEN_MASK; 122 return 123 (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size; 124 } 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 */ 131 static inline int td_toggle(td_t *instance) 132 { 133 assert(instance); 134 return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0; 135 } 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 */ 142 static inline bool td_is_active(td_t *instance) 106 107 static inline bool transfer_descriptor_is_active( 108 transfer_descriptor_t *instance) 143 109 { 144 110 assert(instance); 145 111 return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0; 146 112 } 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 /*----------------------------------------------------------------------------*/158 113 #endif 159 114 /** -
uspace/drv/uhci-hcd/utils/device_keeper.c
r72af8da r3e7b7cd 27 27 */ 28 28 29 /** @addtogroup drvusbuhci hc29 /** @addtogroup drvusbuhci 30 30 * @{ 31 31 */ … … 35 35 #include <assert.h> 36 36 #include <errno.h> 37 #include <usb/debug.h>38 37 39 38 #include "device_keeper.h" 40 39 41 40 /*----------------------------------------------------------------------------*/ 42 /** Initialize device keeper structure.43 *44 * @param[in] instance Memory place to initialize.45 *46 * Set all values to false/0.47 */48 41 void device_keeper_init(device_keeper_t *instance) 49 42 { … … 56 49 instance->devices[i].occupied = false; 57 50 instance->devices[i].handle = 0; 58 instance->devices[i].toggle_status = 0;59 51 } 60 52 } 61 53 /*----------------------------------------------------------------------------*/ 62 /** Attempt to obtain address 0, blocks. 63 * 64 * @param[in] instance Device keeper structure to use. 65 * @param[in] speed Speed of the device requesting default address. 66 */ 67 void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed) 54 void device_keeper_reserve_default( 55 device_keeper_t *instance, usb_speed_t speed) 68 56 { 69 57 assert(instance); … … 78 66 } 79 67 /*----------------------------------------------------------------------------*/ 80 /** Attempt to obtain address 0, blocks.81 *82 * @param[in] instance Device keeper structure to use.83 * @param[in] speed Speed of the device requesting default address.84 */85 68 void device_keeper_release_default(device_keeper_t *instance) 86 69 { … … 92 75 } 93 76 /*----------------------------------------------------------------------------*/ 94 /** Check setup packet data for signs of toggle reset.95 *96 * @param[in] instance Device keeper structure to use.97 * @param[in] target Device to receive setup packet.98 * @param[in] data Setup packet data.99 *100 * Really ugly one.101 */102 void device_keeper_reset_if_need(103 device_keeper_t *instance, usb_target_t target, const unsigned char *data)104 {105 assert(instance);106 fibril_mutex_lock(&instance->guard);107 if (target.endpoint > 15 || target.endpoint < 0108 || target.address >= USB_ADDRESS_COUNT || target.address < 0109 || !instance->devices[target.address].occupied) {110 fibril_mutex_unlock(&instance->guard);111 usb_log_error("Invalid data when checking for toggle reset.\n");112 return;113 }114 115 switch (data[1])116 {117 case 0x01: /*clear feature*/118 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */119 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {120 /* endpoint number is < 16, thus first byte is enough */121 instance->devices[target.address].toggle_status &=122 ~(1 << data[4]);123 }124 break;125 126 case 0x9: /* set configuration */127 case 0x11: /* set interface */128 /* target must be device */129 if ((data[0] & 0xf) == 0) {130 instance->devices[target.address].toggle_status = 0;131 }132 break;133 }134 fibril_mutex_unlock(&instance->guard);135 }136 /*----------------------------------------------------------------------------*/137 /** Get current value of endpoint toggle.138 *139 * @param[in] instance Device keeper structure to use.140 * @param[in] target Device and endpoint used.141 * @return Error code142 */143 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)144 {145 assert(instance);146 int ret;147 fibril_mutex_lock(&instance->guard);148 if (target.endpoint > 15 || target.endpoint < 0149 || target.address >= USB_ADDRESS_COUNT || target.address < 0150 || !instance->devices[target.address].occupied) {151 usb_log_error("Invalid data when asking for toggle value.\n");152 ret = EINVAL;153 } else {154 ret = (instance->devices[target.address].toggle_status155 >> target.endpoint) & 1;156 }157 fibril_mutex_unlock(&instance->guard);158 return ret;159 }160 /*----------------------------------------------------------------------------*/161 /** Set current value of endpoint toggle.162 *163 * @param[in] instance Device keeper structure to use.164 * @param[in] target Device and endpoint used.165 * @param[in] toggle Toggle value.166 * @return Error code.167 */168 int device_keeper_set_toggle(169 device_keeper_t *instance, usb_target_t target, bool toggle)170 {171 assert(instance);172 int ret;173 fibril_mutex_lock(&instance->guard);174 if (target.endpoint > 15 || target.endpoint < 0175 || target.address >= USB_ADDRESS_COUNT || target.address < 0176 || !instance->devices[target.address].occupied) {177 usb_log_error("Invalid data when setting toggle value.\n");178 ret = EINVAL;179 } else {180 if (toggle) {181 instance->devices[target.address].toggle_status |= (1 << target.endpoint);182 } else {183 instance->devices[target.address].toggle_status &= ~(1 << target.endpoint);184 }185 ret = EOK;186 }187 fibril_mutex_unlock(&instance->guard);188 return ret;189 }190 /*----------------------------------------------------------------------------*/191 /** Get a free USB address192 *193 * @param[in] instance Device keeper structure to use.194 * @param[in] speed Speed of the device requiring address.195 * @return Free address, or error code.196 */197 77 usb_address_t device_keeper_request( 198 78 device_keeper_t *instance, usb_speed_t speed) … … 216 96 instance->devices[new_address].occupied = true; 217 97 instance->devices[new_address].speed = speed; 218 instance->devices[new_address].toggle_status = 0;219 98 instance->last_address = new_address; 220 99 fibril_mutex_unlock(&instance->guard); … … 222 101 } 223 102 /*----------------------------------------------------------------------------*/ 224 /** Bind USB address to devman handle.225 *226 * @param[in] instance Device keeper structure to use.227 * @param[in] address Device address228 * @param[in] handle Devman handle of the device.229 */230 103 void device_keeper_bind( 231 104 device_keeper_t *instance, usb_address_t address, devman_handle_t handle) … … 240 113 } 241 114 /*----------------------------------------------------------------------------*/ 242 /** Release used USB address.243 *244 * @param[in] instance Device keeper structure to use.245 * @param[in] address Device address246 */247 115 void device_keeper_release(device_keeper_t *instance, usb_address_t address) 248 116 { … … 257 125 } 258 126 /*----------------------------------------------------------------------------*/ 259 /** Find USB address associated with the device260 *261 * @param[in] instance Device keeper structure to use.262 * @param[in] handle Devman handle of the device seeking its address.263 * @return USB Address, or error code.264 */265 127 usb_address_t device_keeper_find( 266 128 device_keeper_t *instance, devman_handle_t handle) … … 280 142 } 281 143 /*----------------------------------------------------------------------------*/ 282 /** Get speed associated with the address283 *284 * @param[in] instance Device keeper structure to use.285 * @param[in] address Address of the device.286 * @return USB speed.287 */288 144 usb_speed_t device_keeper_speed( 289 145 device_keeper_t *instance, usb_address_t address) -
uspace/drv/uhci-hcd/utils/device_keeper.h
r72af8da r3e7b7cd 27 27 */ 28 28 29 /** @addtogroup drvusbuhci hc29 /** @addtogroup drvusbuhci 30 30 * @{ 31 31 */ … … 44 44 usb_speed_t speed; 45 45 bool occupied; 46 uint16_t toggle_status;47 46 devman_handle_t handle; 48 47 }; … … 56 55 57 56 void device_keeper_init(device_keeper_t *instance); 58 59 57 void device_keeper_reserve_default( 60 58 device_keeper_t *instance, usb_speed_t speed); 61 62 59 void device_keeper_release_default(device_keeper_t *instance); 63 64 void device_keeper_reset_if_need(65 device_keeper_t *instance, usb_target_t target, const unsigned char *setup_data);66 67 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target);68 69 int device_keeper_set_toggle(70 device_keeper_t *instance, usb_target_t target, bool toggle);71 60 72 61 usb_address_t device_keeper_request( 73 62 device_keeper_t *instance, usb_speed_t speed); 74 75 63 void device_keeper_bind( 76 64 device_keeper_t *instance, usb_address_t address, devman_handle_t handle); 77 78 65 void device_keeper_release(device_keeper_t *instance, usb_address_t address); 79 80 66 usb_address_t device_keeper_find( 81 67 device_keeper_t *instance, devman_handle_t handle); -
uspace/drv/uhci-hcd/utils/malloc32.h
r72af8da r3e7b7cd 35 35 #define DRV_UHCI_TRANSLATOR_H 36 36 37 #include <usb/usbmem.h> 38 37 39 #include <assert.h> 38 40 #include <malloc.h> … … 43 45 #define UHCI_REQUIRED_PAGE_SIZE 4096 44 46 45 /** Get physical address translation46 *47 * @param[in] addr Virtual address to translate48 * @return Physical address if exists, NULL otherwise.49 */50 47 static inline uintptr_t addr_to_phys(void *addr) 51 48 { … … 53 50 int ret = as_get_physical_mapping(addr, &result); 54 51 55 if (ret != EOK) 56 return 0; 52 assert(ret == 0); 57 53 return (result | ((uintptr_t)addr & 0xfff)); 58 54 } 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 */ 55 65 56 static inline void * malloc32(size_t size) 66 57 { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); } 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 59 static inline void * get_page() 80 60 { 81 61 void * free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE); 82 62 assert(free_address); 83 63 if (free_address == 0) 84 return NULL;64 return 0; 85 65 void* ret = 86 66 as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE, 87 67 AS_AREA_READ | AS_AREA_WRITE); 88 68 if (ret != free_address) 89 return NULL;69 return 0; 90 70 return ret; 91 71 } 72 73 static inline void free32(void *addr) 74 { if (addr) free(addr); } 92 75 93 76 #endif -
uspace/drv/uhci-rhd/Makefile
r72af8da r3e7b7cd 35 35 main.c \ 36 36 port.c \ 37 port_status.c \ 37 38 root_hub.c 38 39 -
uspace/drv/uhci-rhd/main.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcirh28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI root hub initialization routines32 * @brief UHCI driver 33 33 */ 34 34 #include <ddf/driver.h> 35 35 #include <devman.h> 36 36 #include <device/hw_res.h> 37 #include <errno.h>38 37 #include <usb_iface.h> 39 38 #include <usb/ddfiface.h> 39 40 #include <errno.h> 41 40 42 #include <usb/debug.h> 41 43 … … 45 47 static int hc_get_my_registers(ddf_dev_t *dev, 46 48 uintptr_t *io_reg_address, size_t *io_reg_size); 47 #if 0 48 /*----------------------------------------------------------------------------*/ 49 49 50 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 50 51 { … … 57 58 return EOK; 58 59 } 59 /*----------------------------------------------------------------------------*/ 60 60 61 static usb_iface_t uhci_rh_usb_iface = { 61 62 .get_hc_handle = usb_iface_get_hc_handle, 62 63 .get_address = usb_iface_get_address_hub_impl 63 64 }; 64 /*----------------------------------------------------------------------------*/ 65 65 66 static ddf_dev_ops_t uhci_rh_ops = { 66 67 .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface, 67 68 }; 68 #endif 69 /*----------------------------------------------------------------------------*/ 70 /** Initialize a new ddf driver instance of UHCI root hub. 71 * 72 * @param[in] device DDF instance of the device to initialize. 73 * @return Error code. 74 */ 69 75 70 static int uhci_rh_add_device(ddf_dev_t *device) 76 71 { … … 81 76 82 77 //device->ops = &uhci_rh_ops; 78 (void) uhci_rh_ops; 79 80 uhci_root_hub_t *rh = malloc(sizeof(uhci_root_hub_t)); 81 if (!rh) { 82 usb_log_error("Failed to allocate memory for driver instance.\n"); 83 return ENOMEM; 84 } 85 83 86 uintptr_t io_regs = 0; 84 87 size_t io_size = 0; 85 88 86 89 int ret = hc_get_my_registers(device, &io_regs, &io_size); 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); 90 assert(ret == EOK); 92 91 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 92 /* TODO: verify values from hc */ 93 usb_log_info("I/O regs at 0x%X (size %zu).\n", io_regs, io_size); 99 94 ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device); 100 95 if (ret != EOK) { … … 109 104 return EOK; 110 105 } 111 /*----------------------------------------------------------------------------*/ 106 112 107 static driver_ops_t uhci_rh_driver_ops = { 113 108 .add_device = uhci_rh_add_device, 114 109 }; 115 /*----------------------------------------------------------------------------*/ 110 116 111 static driver_t uhci_rh_driver = { 117 112 .name = NAME, … … 119 114 }; 120 115 /*----------------------------------------------------------------------------*/ 121 /** Initialize global driver structures (NONE).122 *123 * @param[in] argc Nmber of arguments in argv vector (ignored).124 * @param[in] argv Cmdline argument vector (ignored).125 * @return Error code.126 *127 * Driver debug level is set here.128 */129 116 int main(int argc, char *argv[]) 130 117 { … … 133 120 } 134 121 /*----------------------------------------------------------------------------*/ 135 /** Get address of I/O registers. 136 * 137 * @param[in] dev Device asking for the addresses. 138 * @param[out] io_reg_address Base address of the memory range. 139 * @param[out] io_reg_size Size of the memory range. 140 * @return Error code. 141 */ 142 int hc_get_my_registers( 143 ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size) 122 int hc_get_my_registers(ddf_dev_t *dev, 123 uintptr_t *io_reg_address, size_t *io_reg_size) 144 124 { 145 125 assert(dev != NULL); … … 166 146 for (i = 0; i < hw_resources.count; i++) { 167 147 hw_resource_t *res = &hw_resources.resources[i]; 168 switch (res->type) 169 {170 case IO_RANGE:171 io_address = (uintptr_t)res->res.io_range.address;172 io_size = res->res.io_range.size;173 io_found = true;174 175 default:176 break;148 switch (res->type) { 149 case IO_RANGE: 150 io_address = (uintptr_t) 151 res->res.io_range.address; 152 io_size = res->res.io_range.size; 153 io_found = true; 154 break; 155 default: 156 break; 177 157 } 178 158 } … … 190 170 } 191 171 rc = EOK; 192 193 172 leave: 194 173 async_hangup(parent_phone); 174 195 175 return rc; 196 176 } -
uspace/drv/uhci-rhd/port.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcirh28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI root hub port routines 33 */ 34 #include <libarch/ddi.h> /* pio_read and pio_write */ 32 * @brief UHCI driver 33 */ 35 34 #include <errno.h> 36 35 #include <str_error.h> … … 38 37 39 38 #include <usb/usb.h> /* usb_address_t */ 39 #include <usb/usbdevice.h> 40 40 #include <usb/hub.h> 41 #include <usb/request.h> 41 42 #include <usb/debug.h> 43 #include <usb/recognise.h> 42 44 43 45 #include "port.h" 44 45 static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed); 46 #include "port_status.h" 47 48 static int uhci_port_new_device(uhci_port_t *port, uint16_t status); 46 49 static int uhci_port_remove_device(uhci_port_t *port); 47 50 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled); 48 51 static int uhci_port_check(void *port); 49 static int uhci_port_reset_enable(int portno, void *arg); 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) 52 static int new_device_enable_port(int portno, void *arg); 53 54 int uhci_port_init( 55 uhci_port_t *port, port_status_t *address, unsigned number, 56 unsigned usec, ddf_dev_t *rh) 59 57 { 60 58 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.79 *80 * @param[in] port Memory structure to use.81 * @param[in] addr Address of I/O register.82 * @param[in] number Port number.83 * @param[in] usec Polling interval.84 * @param[in] rh Pointer to ddf instance fo the root hub driver.85 * @return Error code.86 *87 * Creates and starts the polling fibril.88 */89 int uhci_port_init(uhci_port_t *port,90 port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)91 {92 assert(port);93 asprintf(&port->id_string, "Port (%p - %d)", port, number);94 if (port->id_string == NULL) {95 return ENOMEM;96 }97 98 59 port->address = address; 99 60 port->number = number; … … 101 62 port->attached_device = 0; 102 63 port->rh = rh; 103 104 64 int rc = usb_hc_connection_initialize_from_device( 105 65 &port->hc_connection, rh); … … 111 71 port->checker = fibril_create(uhci_port_check, port); 112 72 if (port->checker == 0) { 113 usb_log_error(" %s: failed to create pollingfibril.",114 port-> id_string);73 usb_log_error("Port(%p - %d): failed to launch root hub fibril.", 74 port->address, port->number); 115 75 return ENOMEM; 116 76 } 117 118 77 fibril_add_ready(port->checker); 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. 125 * 126 * @param[in] port Memory structure to use. 127 * 128 * Stops the polling fibril. 129 */ 78 usb_log_debug("Port(%p - %d): Added fibril. %x\n", 79 port->address, port->number, port->checker); 80 return EOK; 81 } 82 /*----------------------------------------------------------------------------*/ 130 83 void uhci_port_fini(uhci_port_t *port) 131 84 { 132 assert(port); 133 free(port->id_string); 134 /* TODO: Kill fibril here */ 85 // TODO: destroy fibril 86 // TODO: hangup phone 87 // fibril_teardown(port->checker); 135 88 return; 136 89 } 137 90 /*----------------------------------------------------------------------------*/ 138 /** Periodically checks port status and reports new devices.139 *140 * @param[in] port Port structure to use.141 * @return Error code.142 */143 91 int uhci_port_check(void *port) 144 92 { 145 uhci_port_t *instance = port; 146 assert(instance); 93 uhci_port_t *port_instance = port; 94 assert(port_instance); 95 // port_status_write(port_instance->address, 0); 96 97 unsigned count = 0; 147 98 148 99 while (1) { 149 async_usleep(instance->wait_period_usec); 150 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); 157 158 if ((port_status & STATUS_CONNECTED_CHANGED) == 0) 159 continue; 160 161 usb_log_debug("%s: Connected change detected: %x.\n", 162 instance->id_string, port_status); 163 164 int rc = 165 usb_hc_connection_open(&instance->hc_connection); 166 if (rc != EOK) { 167 usb_log_error("%s: Failed to connect to HC.", 168 instance->id_string); 169 continue; 100 async_usleep(port_instance->wait_period_usec); 101 102 /* read register value */ 103 port_status_t port_status = 104 port_status_read(port_instance->address); 105 106 /* debug print */ 107 static fibril_mutex_t dbg_mtx = FIBRIL_MUTEX_INITIALIZER(dbg_mtx); 108 fibril_mutex_lock(&dbg_mtx); 109 usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n", 110 port_instance->address, port_instance->number, port_status, count++); 111 // print_port_status(port_status); 112 fibril_mutex_unlock(&dbg_mtx); 113 114 if ((port_status & STATUS_CONNECTED_CHANGED) != 0) { 115 usb_log_debug("Port(%p - %d): Connected change detected: %x.\n", 116 port_instance->address, port_instance->number, port_status); 117 118 119 int rc = usb_hc_connection_open( 120 &port_instance->hc_connection); 121 if (rc != EOK) { 122 usb_log_error("Port(%p - %d): Failed to connect to HC.", 123 port_instance->address, port_instance->number); 124 continue; 125 } 126 127 /* remove any old device */ 128 if (port_instance->attached_device) { 129 usb_log_debug("Port(%p - %d): Removing device.\n", 130 port_instance->address, port_instance->number); 131 uhci_port_remove_device(port_instance); 132 } 133 134 if ((port_status & STATUS_CONNECTED) != 0) { 135 /* new device */ 136 uhci_port_new_device(port_instance, port_status); 137 } else { 138 /* ack changes by writing one to WC bits */ 139 port_status_write(port_instance->address, port_status); 140 usb_log_debug("Port(%p - %d): Change status ACK.\n", 141 port_instance->address, port_instance->number); 142 } 143 144 rc = usb_hc_connection_close( 145 &port_instance->hc_connection); 146 if (rc != EOK) { 147 usb_log_error("Port(%p - %d): Failed to disconnect from HC.", 148 port_instance->address, port_instance->number); 149 } 170 150 } 171 172 /* Remove any old device */ 173 if (instance->attached_device) { 174 usb_log_debug2("%s: Removing device.\n", 175 instance->id_string); 176 uhci_port_remove_device(instance); 177 } 178 179 if ((port_status & STATUS_CONNECTED) != 0) { 180 /* New device */ 181 const usb_speed_t speed = 182 ((port_status & STATUS_LOW_SPEED) != 0) ? 183 USB_SPEED_LOW : USB_SPEED_FULL; 184 uhci_port_new_device(instance, speed); 185 } else { 186 /* Write one to WC bits, to ack changes */ 187 uhci_port_write_status(instance, port_status); 188 usb_log_debug("%s: status change ACK.\n", 189 instance->id_string); 190 } 191 192 rc = usb_hc_connection_close(&instance->hc_connection); 193 if (rc != EOK) { 194 usb_log_error("%s: Failed to disconnect.", 195 instance->id_string); 196 } 197 } 198 return EOK; 199 } 200 /*----------------------------------------------------------------------------*/ 151 } 152 return EOK; 153 } 154 201 155 /** Callback for enabling port during adding a new device. 202 156 * … … 204 158 * @param arg Pointer to uhci_port_t of port with the new device. 205 159 * @return Error code. 206 * 207 * Resets and enables the ub port. 208 */ 209 int uhci_port_reset_enable(int portno, void *arg) 160 */ 161 static int new_device_enable_port(int portno, void *arg) 210 162 { 211 163 uhci_port_t *port = (uhci_port_t *) arg; 212 164 213 usb_log_debug2("%s: new_device_enable_port.\n", port->id_string); 165 usb_log_debug2("Port(%p - %d): new_device_enable_port.\n", 166 port->address, port->number); 214 167 215 168 /* … … 219 172 async_usleep(100000); 220 173 221 /* 222 * Resets from root ports should be nominally 50ms 174 175 /* The hub maintains the reset signal to that port for 10 ms 176 * (See Section 11.5.1.5) 223 177 */ 224 178 { 225 usb_log_debug("%s: Reset Signal start.\n", port->id_string); 226 port_status_t port_status = uhci_port_read_status(port); 179 usb_log_debug("Port(%p - %d): Reset Signal start.\n", 180 port->address, port->number); 181 port_status_t port_status = 182 port_status_read(port->address); 227 183 port_status |= STATUS_IN_RESET; 228 uhci_port_write_status(port, port_status); 229 async_usleep(50000); 230 port_status = uhci_port_read_status(port); 184 port_status_write(port->address, port_status); 185 async_usleep(10000); 186 port_status = 187 port_status_read(port->address); 231 188 port_status &= ~STATUS_IN_RESET; 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); 189 port_status_write(port->address, port_status); 190 usb_log_debug("Port(%p - %d): Reset Signal stop.\n", 191 port->address, port->number); 192 } 238 193 239 194 /* Enable the port. */ … … 242 197 return EOK; 243 198 } 244 /*----------------------------------------------------------------------------*/ 245 /** Initialize and report connected device. 246 * 247 * @param[in] port Port structure to use. 248 * @param[in] speed Detected speed. 249 * @return Error code. 250 * 251 * Uses libUSB function to do the actual work. 252 */ 253 int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed) 199 200 /*----------------------------------------------------------------------------*/ 201 static int uhci_port_new_device(uhci_port_t *port, uint16_t status) 254 202 { 255 203 assert(port); 256 204 assert(usb_hc_connection_is_opened(&port->hc_connection)); 257 205 258 usb_log_info("%s: Detected new device.\n", port->id_string); 206 usb_log_info("Port(%p-%d): Detected new device.\n", 207 port->address, port->number); 259 208 260 209 usb_address_t dev_addr; 261 210 int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection, 262 speed, uhci_port_reset_enable, port->number, port, 211 ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL, 212 new_device_enable_port, port->number, port, 263 213 &dev_addr, &port->attached_device, NULL, NULL, NULL); 264 214 265 215 if (rc != EOK) { 266 usb_log_error(" %s: Failed(%d) to adddevice: %s.\n",267 port-> id_string, rc, str_error(rc));216 usb_log_error("Port(%p-%d): Failed(%d) adding new device: %s.\n", 217 port->address, port->number, rc, str_error(rc)); 268 218 uhci_port_set_enabled(port, false); 269 219 return rc; 270 220 } 271 221 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. 279 * 280 * @param[in] port Memory structure to use. 281 * @return Error code. 282 * 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). 286 */ 287 int uhci_port_remove_device(uhci_port_t *port) 288 { 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. 298 * @return Error code. (Always EOK) 299 */ 300 int uhci_port_set_enabled(uhci_port_t *port, bool enabled) 222 usb_log_info("Port(%p-%d): New device has address %d (handle %zu).\n", 223 port->address, port->number, dev_addr, port->attached_device); 224 225 return EOK; 226 } 227 228 /*----------------------------------------------------------------------------*/ 229 static int uhci_port_remove_device(uhci_port_t *port) 230 { 231 usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n", 232 port->address, port->number, (unsigned int)port->attached_device); 233 // uhci_port_set_enabled(port, false); 234 return EOK; 235 } 236 /*----------------------------------------------------------------------------*/ 237 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled) 301 238 { 302 239 assert(port); 303 240 304 /* Read register value */ 305 port_status_t port_status = uhci_port_read_status(port); 306 307 /* Set enabled bit */ 241 /* read register value */ 242 port_status_t port_status 243 = port_status_read(port->address); 244 245 /* enable port: register write */ 308 246 if (enabled) { 309 247 port_status |= STATUS_ENABLED; … … 311 249 port_status &= ~STATUS_ENABLED; 312 250 } 313 314 /* Write new value. */ 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 } 251 port_status_write(port->address, port_status); 252 253 usb_log_info("Port(%p-%d): %sabled port.\n", 254 port->address, port->number, enabled ? "En" : "Dis"); 255 return EOK; 256 } 257 /*----------------------------------------------------------------------------*/ 346 258 /** 347 259 * @} -
uspace/drv/uhci-rhd/port.h
r72af8da r3e7b7cd 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2010 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 drvusbuhcirh28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI root hub port routines32 * @brief UHCI port driver 33 33 */ 34 34 #ifndef DRV_UHCI_PORT_H 35 35 #define DRV_UHCI_PORT_H 36 36 37 #include <assert.h> 38 #include <ddf/driver.h> 37 39 #include <stdint.h> 38 #include <fibril.h> 39 #include <ddf/driver.h> 40 #include <usb/usbdevice.h> /* usb_hc_connection_t */ 40 #include <usb/usbdevice.h> 41 41 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) 42 #include "port_status.h" 55 43 56 44 typedef struct uhci_port 57 45 { 58 char *id_string;59 46 port_status_t *address; 60 47 unsigned number; … … 71 58 72 59 void uhci_port_fini(uhci_port_t *port); 73 74 60 #endif 75 61 /** -
uspace/drv/uhci-rhd/root_hub.c
r72af8da r3e7b7cd 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusbuhcirh28 /** @addtogroup usb 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI root hubdriver32 * @brief UHCI driver 33 33 */ 34 34 #include <errno.h> 35 #include <stdint.h> 35 36 #include <ddi.h> 37 #include <devman.h> 36 38 #include <usb/debug.h> 37 39 38 40 #include "root_hub.h" 39 41 40 /** Initialize UHCI root hub instance.41 *42 * @param[in] instance Driver memory structure to use.43 * @param[in] addr Address of I/O registers.44 * @param[in] size Size of available I/O space.45 * @param[in] rh Pointer to ddf instance of the root hub driver.46 * @return Error code.47 */48 42 int uhci_root_hub_init( 49 43 uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh) … … 53 47 int ret; 54 48 55 /* Allow access to root hub portregisters */56 assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);49 /* allow access to root hub registers */ 50 assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size); 57 51 port_status_t *regs; 58 52 ret = pio_enable(addr, size, (void**)®s); 53 59 54 if (ret < 0) { 60 usb_log_error( 61 "Failed(%d) to gain access to port registers at %p\n", 62 ret, regs); 55 usb_log_error("Failed to gain access to port registers at %p\n", regs); 63 56 return ret; 64 57 } 65 58 66 /* Initialize root hub ports */59 /* add fibrils for periodic port checks */ 67 60 unsigned i = 0; 68 61 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { 69 /* NOTE: mind pointer arithmetics here*/62 /* mind pointer arithmetics */ 70 63 ret = uhci_port_init( 71 &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);64 &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh); 72 65 if (ret != EOK) { 73 66 unsigned j = 0; … … 81 74 } 82 75 /*----------------------------------------------------------------------------*/ 83 /** Cleanup UHCI root hub instance. 84 * 85 * @param[in] instance Root hub structure to use. 86 * @return Error code. 87 */ 88 int uhci_root_hub_fini(uhci_root_hub_t* instance) 76 int uhci_root_hub_fini( uhci_root_hub_t* instance ) 89 77 { 90 assert(instance); 91 unsigned i = 0; 92 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { 93 uhci_port_fini(&instance->ports[i]); 94 } 78 assert( instance ); 79 // TODO: 80 //destroy fibril here 81 //disable access to registers 95 82 return EOK; 96 83 } -
uspace/drv/uhci-rhd/root_hub.h
r72af8da r3e7b7cd 1 1 /* 2 * Copyright (c) 201 1Jan Vesely2 * Copyright (c) 2010 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 drvusbuhcirh28 /** @addtogroup usb 29 29 * @{ 30 30 */ … … 35 35 #define DRV_UHCI_ROOT_HUB_H 36 36 37 #include <fibril.h> 37 38 #include <ddf/driver.h> 38 39 -
uspace/drv/usbhid/Makefile
r72af8da r3e7b7cd 42 42 hidreq.c \ 43 43 kbddev.c \ 44 kbdrepeat.c \45 44 hiddev.c \ 46 45 $(STOLEN_LAYOUT_SOURCES) -
uspace/drv/usbhid/conv.c
r72af8da r3e7b7cd 40 40 #include "conv.h" 41 41 42 /**43 * Mapping between USB HID key codes (from HID Usage Tables) and corresponding44 * HelenOS key codes.45 */46 42 static int scanmap_simple[255] = { 47 43 … … 167 163 }; 168 164 169 /**170 * Translate USB HID key codes (from HID Usage Tables) to generic key codes171 * recognized by HelenOS.172 *173 * @param scancode USB HID key code (from HID Usage Tables).174 *175 * @retval HelenOS key code corresponding to the given USB HID key code.176 */177 165 unsigned int usbhid_parse_scancode(int scancode) 178 166 { -
uspace/drv/usbhid/descdump.c
r72af8da r3e7b7cd 44 44 #define BYTES_PER_LINE 12 45 45 46 /**47 * Dumps the given buffer in hexadecimal format to standard output.48 *49 * @param msg Message to print before the buffer.50 * @param buffer Buffer to print.51 * @param length Size of the buffer in bytes.52 */53 46 static void dump_buffer(const char *msg, const uint8_t *buffer, size_t length) 54 47 { … … 69 62 #define INDENT " " 70 63 71 /**72 * Print standard configuration descriptor to standard output.73 *74 * @param index Index of the descriptor.75 * @param d Standard configuration descriptor to print.76 */77 64 void dump_standard_configuration_descriptor( 78 65 int index, const usb_standard_configuration_descriptor_t *d) … … 97 84 } 98 85 99 /**100 * Print standard interface descriptor to standard output.101 *102 * @param d Standard interface descriptor to print.103 */104 86 void dump_standard_interface_descriptor( 105 87 const usb_standard_interface_descriptor_t *d) … … 117 99 } 118 100 119 /**120 * Print standard endpoint descriptor to standard output.121 *122 * @param d Standard endpoint descriptor to print.123 */124 101 void dump_standard_endpoint_descriptor( 125 102 const usb_standard_endpoint_descriptor_t *d) … … 149 126 } 150 127 151 /**152 * Print standard HID descriptor to standard output.153 *154 * @param d Standard HID descriptor to print.155 */156 128 void dump_standard_hid_descriptor_header( 157 129 const usb_standard_hid_descriptor_t *d) … … 167 139 } 168 140 169 /**170 * Print HID class-specific descriptor header (type and length) to standard171 * output.172 *173 * @param d HID class-specific descriptor header to print.174 */175 141 void dump_standard_hid_class_descriptor_info( 176 142 const usb_standard_hid_class_descriptor_info_t *d) … … 180 146 } 181 147 182 /**183 * Print HID class-specific descriptor (without the header) to standard output.184 *185 * @param index Index of the descriptor.186 * @param type Type of the HID class-specific descriptor (Report or Physical).187 * @param d HID class descriptor to print.188 * @param size Size of the descriptor in bytes.189 */190 148 void dump_hid_class_descriptor(int index, uint8_t type, 191 149 const uint8_t *d, size_t size ) -
uspace/drv/usbhid/hiddev.c
r72af8da r3e7b7cd 53 53 /* Non-API functions */ 54 54 /*----------------------------------------------------------------------------*/ 55 /** 56 * Retreives HID Report descriptor from the device. 57 * 58 * This function first parses the HID descriptor from the Interface descriptor 59 * to get the size of the Report descriptor and then requests the Report 60 * descriptor from the device. 61 * 62 * @param hid_dev HID device structure. 63 * @param config_desc Full configuration descriptor (including all nested 64 * descriptors). 65 * @param config_desc_size Size of the full configuration descriptor (in bytes). 66 * @param iface_desc Pointer to the interface descriptor inside the full 67 * configuration descriptor (@a config_desc) for the interface 68 * assigned with this device (@a hid_dev). 69 * 70 * @retval EOK if successful. 71 * @retval ENOENT if no HID descriptor could be found. 72 * @retval EINVAL if the HID descriptor or HID report descriptor have different 73 * size than expected. 74 * @retval ENOMEM if some allocation failed. 75 * @return Other value inherited from function usb_request_get_descriptor(). 76 * 77 * @sa usb_request_get_descriptor() 78 */ 55 79 56 static int usbhid_dev_get_report_descriptor(usbhid_dev_t *hid_dev, 80 57 uint8_t *config_desc, size_t config_desc_size, uint8_t *iface_desc) … … 164 141 165 142 /*----------------------------------------------------------------------------*/ 166 /** 167 * Retreives descriptors from the device, initializes pipes and stores 168 * important information from descriptors. 169 * 170 * Initializes the polling pipe described by the given endpoint description 171 * (@a poll_ep_desc). 172 * 173 * Information retreived from descriptors and stored in the HID device structure: 174 * - Assigned interface number (the interface controlled by this instance of 175 * the driver) 176 * - Polling interval (from the interface descriptor) 177 * - Report descriptor 178 * 179 * @param hid_dev HID device structure to be initialized. 180 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint 181 * that has to be present in the device in order to 182 * successfuly initialize the structure. 183 * 184 * @sa usb_endpoint_pipe_initialize_from_configuration(), 185 * usbhid_dev_get_report_descriptor() 186 */ 143 187 144 static int usbhid_dev_process_descriptors(usbhid_dev_t *hid_dev, 188 145 usb_endpoint_description_t *poll_ep_desc) … … 273 230 /* API functions */ 274 231 /*----------------------------------------------------------------------------*/ 275 /** 276 * Creates new uninitialized HID device structure. 277 * 278 * @return Pointer to the new HID device structure, or NULL if an error occured. 279 */ 232 280 233 usbhid_dev_t *usbhid_dev_new(void) 281 234 { … … 296 249 297 250 /*----------------------------------------------------------------------------*/ 298 /** 299 * Properly destroys the HID device structure. 300 * 301 * @note Currently does not clean-up the used pipes, as there are no functions 302 * offering such functionality. 303 * 304 * @param hid_dev Pointer to the structure to be destroyed. 305 */ 251 306 252 void usbhid_dev_free(usbhid_dev_t **hid_dev) 307 253 { … … 326 272 327 273 /*----------------------------------------------------------------------------*/ 328 /** 329 * Initializes HID device structure. 330 * 331 * @param hid_dev HID device structure to be initialized. 332 * @param dev DDF device representing the HID device. 333 * @param poll_ep_desc Description of the polling (Interrupt In) endpoint 334 * that has to be present in the device in order to 335 * successfuly initialize the structure. 336 * 337 * @retval EOK if successful. 338 * @retval EINVAL if some argument is missing. 339 * @return Other value inherited from one of functions 340 * usb_device_connection_initialize_from_device(), 341 * usb_endpoint_pipe_initialize_default_control(), 342 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 343 * usbhid_dev_process_descriptors(). 344 * 345 * @sa usbhid_dev_process_descriptors() 346 */ 274 347 275 int usbhid_dev_init(usbhid_dev_t *hid_dev, ddf_dev_t *dev, 348 276 usb_endpoint_description_t *poll_ep_desc) … … 391 319 return rc; 392 320 } 393 rc = usb_endpoint_pipe_probe_default_control(&hid_dev->ctrl_pipe);394 if (rc != EOK) {395 usb_log_error("Probing default control pipe failed: %s.\n",396 str_error(rc));397 return rc;398 }399 321 400 322 /* 401 323 * Get descriptors, parse descriptors and save endpoints. 402 324 */ 403 rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 404 if (rc != EOK) { 405 usb_log_error("Failed to start session on the control pipe: %s" 406 ".\n", str_error(rc)); 407 return rc; 408 } 325 usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe); 409 326 410 327 rc = usbhid_dev_process_descriptors(hid_dev, poll_ep_desc); 411 if (rc != EOK) { 412 /* TODO: end session?? */ 328 329 usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); 330 if (rc != EOK) { 413 331 usb_log_error("Failed to process descriptors: %s.\n", 414 332 str_error(rc)); 415 return rc;416 }417 418 rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);419 if (rc != EOK) {420 usb_log_warning("Failed to start session on the control pipe: "421 "%s.\n", str_error(rc));422 333 return rc; 423 334 } -
uspace/drv/usbhid/hiddev.h
r72af8da r3e7b7cd 48 48 49 49 /** 50 * USB/HID device type. 51 * 52 * Holds a reference to DDF device structure, and HID-specific data, such 53 * as information about used pipes (one Control pipe and one Interrupt In pipe), 54 * polling interval, assigned interface number, Report descriptor and a 55 * reference to the Report parser used to parse incoming reports and composing 56 * outgoing reports. 50 * @brief USB/HID device type. 57 51 */ 58 52 typedef struct { 59 /** DDF device representing the controlled HID device. */60 53 ddf_dev_t *device; 61 54 62 /** Physical connection to the device. */63 55 usb_device_connection_t wire; 64 /** USB pipe corresponding to the default Control endpoint. */65 56 usb_endpoint_pipe_t ctrl_pipe; 66 /** USB pipe corresponding to the Interrupt In (polling) pipe. */67 57 usb_endpoint_pipe_t poll_pipe; 68 58 69 /** Polling interval retreived from the Interface descriptor. */70 59 short poll_interval; 71 60 72 /** Interface number assigned to this device. */73 61 uint16_t iface; 74 62 75 /** Report descriptor. */76 63 uint8_t *report_desc; 77 /** HID Report parser. */78 64 usb_hid_report_parser_t *parser; 79 65 80 /** State of the structure (for checking before use). */81 66 int initialized; 82 67 } usbhid_dev_t; -
uspace/drv/usbhid/hidreq.c
r72af8da r3e7b7cd 46 46 47 47 /*----------------------------------------------------------------------------*/ 48 /** 49 * Send Set Report request to the HID device. 50 * 51 * @param hid_dev HID device to send the request to. 52 * @param type Type of the report. 53 * @param buffer Report data. 54 * @param buf_size Report data size (in bytes). 55 * 56 * @retval EOK if successful. 57 * @retval EINVAL if no HID device is given. 58 * @return Other value inherited from one of functions 59 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 60 * usb_control_request_set(). 61 */ 48 62 49 int usbhid_req_set_report(usbhid_dev_t *hid_dev, 63 50 usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size) … … 82 69 return sess_rc; 83 70 } 84 85 uint16_t value = 0;86 value |= (type << 8);87 71 88 72 usb_log_debug("Sending Set_Report request to the device.\n"); … … 90 74 rc = usb_control_request_set(&hid_dev->ctrl_pipe, 91 75 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 92 USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size);76 USB_HIDREQ_SET_REPORT, type, hid_dev->iface, buffer, buf_size); 93 77 94 78 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe); … … 110 94 111 95 /*----------------------------------------------------------------------------*/ 112 /** 113 * Send Set Protocol request to the HID device. 114 * 115 * @param hid_dev HID device to send the request to. 116 * @param protocol Protocol to set. 117 * 118 * @retval EOK if successful. 119 * @retval EINVAL if no HID device is given. 120 * @return Other value inherited from one of functions 121 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(), 122 * usb_control_request_set(). 123 */ 96 124 97 int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol) 125 98 { … … 169 142 170 143 /*----------------------------------------------------------------------------*/ 171 /**172 * Send Set Idle request to the HID device.173 *174 * @param hid_dev HID device to send the request to.175 * @param duration Duration value (is multiplicated by 4 by the device to176 * get real duration in miliseconds).177 *178 * @retval EOK if successful.179 * @retval EINVAL if no HID device is given.180 * @return Other value inherited from one of functions181 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),182 * usb_control_request_set().183 */184 int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration)185 {186 if (hid_dev == NULL) {187 usb_log_error("usbhid_req_set_idle(): no HID device "188 "structure given.\n");189 return EINVAL;190 }191 192 /*193 * No need for checking other parameters, as they are checked in194 * the called function (usb_control_request_set()).195 */196 197 int rc, sess_rc;198 199 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);200 if (sess_rc != EOK) {201 usb_log_warning("Failed to start a session: %s.\n",202 str_error(sess_rc));203 return sess_rc;204 }205 206 usb_log_debug("Sending Set_Idle request to the device ("207 "duration: %u, iface: %d).\n", duration, hid_dev->iface);208 209 uint16_t value = duration << 8;210 211 rc = usb_control_request_set(&hid_dev->ctrl_pipe,212 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,213 USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0);214 215 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);216 217 if (rc != EOK) {218 usb_log_warning("Error sending output report to the keyboard: "219 "%s.\n", str_error(rc));220 return rc;221 }222 223 if (sess_rc != EOK) {224 usb_log_warning("Error closing session: %s.\n",225 str_error(sess_rc));226 return sess_rc;227 }228 229 return EOK;230 }231 232 /*----------------------------------------------------------------------------*/233 /**234 * Send Get Report request to the HID device.235 *236 * @param[in] hid_dev HID device to send the request to.237 * @param[in] type Type of the report.238 * @param[in][out] buffer Buffer for the report data.239 * @param[in] buf_size Size of the buffer (in bytes).240 * @param[out] actual_size Actual size of report received from the device241 * (in bytes).242 *243 * @retval EOK if successful.244 * @retval EINVAL if no HID device is given.245 * @return Other value inherited from one of functions246 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),247 * usb_control_request_set().248 */249 int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,250 uint8_t *buffer, size_t buf_size, size_t *actual_size)251 {252 if (hid_dev == NULL) {253 usb_log_error("usbhid_req_set_report(): no HID device structure"254 " given.\n");255 return EINVAL;256 }257 258 /*259 * No need for checking other parameters, as they are checked in260 * the called function (usb_control_request_set()).261 */262 263 int rc, sess_rc;264 265 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);266 if (sess_rc != EOK) {267 usb_log_warning("Failed to start a session: %s.\n",268 str_error(sess_rc));269 return sess_rc;270 }271 272 uint16_t value = 0;273 value |= (type << 8);274 275 usb_log_debug("Sending Get_Report request to the device.\n");276 277 rc = usb_control_request_get(&hid_dev->ctrl_pipe,278 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,279 USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size,280 actual_size);281 282 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);283 284 if (rc != EOK) {285 usb_log_warning("Error sending output report to the keyboard: "286 "%s.\n", str_error(rc));287 return rc;288 }289 290 if (sess_rc != EOK) {291 usb_log_warning("Error closing session: %s.\n",292 str_error(sess_rc));293 return sess_rc;294 }295 296 return EOK;297 }298 299 /*----------------------------------------------------------------------------*/300 /**301 * Send Get Protocol request to the HID device.302 *303 * @param[in] hid_dev HID device to send the request to.304 * @param[out] protocol Current protocol of the device.305 *306 * @retval EOK if successful.307 * @retval EINVAL if no HID device is given.308 * @return Other value inherited from one of functions309 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),310 * usb_control_request_set().311 */312 int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol)313 {314 if (hid_dev == NULL) {315 usb_log_error("usbhid_req_set_protocol(): no HID device "316 "structure given.\n");317 return EINVAL;318 }319 320 /*321 * No need for checking other parameters, as they are checked in322 * the called function (usb_control_request_set()).323 */324 325 int rc, sess_rc;326 327 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);328 if (sess_rc != EOK) {329 usb_log_warning("Failed to start a session: %s.\n",330 str_error(sess_rc));331 return sess_rc;332 }333 334 usb_log_debug("Sending Get_Protocol request to the device ("335 "iface: %d).\n", hid_dev->iface);336 337 uint8_t buffer[1];338 size_t actual_size = 0;339 340 rc = usb_control_request_get(&hid_dev->ctrl_pipe,341 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,342 USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size);343 344 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);345 346 if (rc != EOK) {347 usb_log_warning("Error sending output report to the keyboard: "348 "%s.\n", str_error(rc));349 return rc;350 }351 352 if (sess_rc != EOK) {353 usb_log_warning("Error closing session: %s.\n",354 str_error(sess_rc));355 return sess_rc;356 }357 358 if (actual_size != 1) {359 usb_log_warning("Wrong data size: %zu, expected: 1.\n",360 actual_size);361 return ELIMIT;362 }363 364 *protocol = buffer[0];365 366 return EOK;367 }368 369 /*----------------------------------------------------------------------------*/370 /**371 * Send Get Idle request to the HID device.372 *373 * @param[in] hid_dev HID device to send the request to.374 * @param[out] duration Duration value (multiplicate by 4 to get real duration375 * in miliseconds).376 *377 * @retval EOK if successful.378 * @retval EINVAL if no HID device is given.379 * @return Other value inherited from one of functions380 * usb_endpoint_pipe_start_session(), usb_endpoint_pipe_end_session(),381 * usb_control_request_set().382 */383 int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration)384 {385 if (hid_dev == NULL) {386 usb_log_error("usbhid_req_set_idle(): no HID device "387 "structure given.\n");388 return EINVAL;389 }390 391 /*392 * No need for checking other parameters, as they are checked in393 * the called function (usb_control_request_set()).394 */395 396 int rc, sess_rc;397 398 sess_rc = usb_endpoint_pipe_start_session(&hid_dev->ctrl_pipe);399 if (sess_rc != EOK) {400 usb_log_warning("Failed to start a session: %s.\n",401 str_error(sess_rc));402 return sess_rc;403 }404 405 usb_log_debug("Sending Get_Idle request to the device ("406 "iface: %d).\n", hid_dev->iface);407 408 uint16_t value = 0;409 uint8_t buffer[1];410 size_t actual_size = 0;411 412 rc = usb_control_request_get(&hid_dev->ctrl_pipe,413 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,414 USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1,415 &actual_size);416 417 sess_rc = usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);418 419 if (rc != EOK) {420 usb_log_warning("Error sending output report to the keyboard: "421 "%s.\n", str_error(rc));422 return rc;423 }424 425 if (sess_rc != EOK) {426 usb_log_warning("Error closing session: %s.\n",427 str_error(sess_rc));428 return sess_rc;429 }430 431 if (actual_size != 1) {432 usb_log_warning("Wrong data size: %zu, expected: 1.\n",433 actual_size);434 return ELIMIT;435 }436 437 *duration = buffer[0];438 439 return EOK;440 }441 442 /*----------------------------------------------------------------------------*/443 144 444 145 /** -
uspace/drv/usbhid/hidreq.h
r72af8da r3e7b7cd 50 50 int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol); 51 51 52 int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration);53 54 int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type,55 uint8_t *buffer, size_t buf_size, size_t *actual_size);56 57 int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol);58 59 int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration);60 61 52 /*----------------------------------------------------------------------------*/ 62 53 -
uspace/drv/usbhid/kbddev.c
r72af8da r3e7b7cd 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include < stdio.h>39 #include <fibril.h> 40 40 41 41 #include <io/keycode.h> 42 42 #include <ipc/kbd.h> 43 43 #include <async.h> 44 #include <fibril.h>45 #include <fibril_synch.h>46 44 47 45 #include <usb/usb.h> … … 57 55 #include "layout.h" 58 56 #include "conv.h" 59 #include "kbdrepeat.h" 60 61 /*----------------------------------------------------------------------------*/ 62 /** Default modifiers when the keyboard is initialized. */ 57 58 /*----------------------------------------------------------------------------*/ 59 63 60 static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK; 64 65 /** Boot protocol report size (key part). */66 61 static const size_t BOOTP_REPORT_SIZE = 6; 67 68 /** Boot protocol total report size. */69 62 static const size_t BOOTP_BUFFER_SIZE = 8; 70 71 /** Boot protocol output report size. */72 63 static const size_t BOOTP_BUFFER_OUT_SIZE = 1; 73 74 /** Boot protocol error key code. */75 static const uint8_t BOOTP_ERROR_ROLLOVER = 1;76 77 /** Default idle rate for keyboards. */78 static const uint8_t IDLE_RATE = 0;79 80 /** Delay before a pressed key starts auto-repeating. */81 static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;82 83 /** Delay between two repeats of a pressed key when auto-repeating. */84 static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;85 64 86 65 /** Keyboard polling endpoint description for boot protocol class. */ … … 100 79 #define NUM_LAYOUTS 3 101 80 102 /** Keyboard layout map. */103 81 static layout_op_t *layout[NUM_LAYOUTS] = { 104 82 &us_qwerty_op, … … 112 90 /* Modifier constants */ 113 91 /*----------------------------------------------------------------------------*/ 114 /** Mapping of USB modifier key codes to generic modifier key codes. */ 92 115 93 static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = { 116 94 KC_LCTRL, /* USB_HID_MOD_LCTRL */ … … 133 111 }; 134 112 135 /** 136 * Default handler for IPC methods not handled by DDF. 113 /** Default handler for IPC methods not handled by DDF. 137 114 * 138 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it 139 * assumes the caller is the console and thus it stores IPC phone to it for 140 * later use by the driver to notify about key events. 141 * 142 * @param fun Device function handling the call. 115 * @param dev Device handling the call. 143 116 * @param icallid Call id. 144 117 * @param icall Call data. … … 171 144 /* Key processing functions */ 172 145 /*----------------------------------------------------------------------------*/ 173 /** 174 * Handles turning of LED lights on and off. 175 * 176 * In case of USB keyboards, the LEDs are handled in the driver, not in the 177 * device. When there should be a change (lock key was pressed), the driver 178 * uses a Set_Report request sent to the device to set the state of the LEDs. 179 * 180 * This functions sets the LED lights according to current settings of modifiers 181 * kept in the keyboard device structure. 182 * 183 * @param kbd_dev Keyboard device structure. 184 */ 146 185 147 static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev) 186 148 { 187 149 uint8_t buffer[BOOTP_BUFFER_OUT_SIZE]; 188 150 int rc= 0; 151 unsigned i; 189 152 190 153 memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE); … … 214 177 } 215 178 216 usb_log_debug("Output report buffer: %s\n", 217 usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0)); 218 179 // TODO: REFACTOR!!! 180 181 usb_log_debug("Output report buffer: "); 182 for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) { 183 usb_log_debug("0x%x ", buffer[i]); 184 } 185 usb_log_debug("\n"); 186 187 uint16_t value = 0; 188 value |= (USB_HID_REPORT_TYPE_OUTPUT << 8); 189 219 190 assert(kbd_dev->hid_dev != NULL); 220 191 assert(kbd_dev->hid_dev->initialized); 221 usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 222 buffer, BOOTP_BUFFER_OUT_SIZE); 223 } 224 225 /*----------------------------------------------------------------------------*/ 226 /** 227 * Processes key events. 228 * 229 * @note This function was copied from AT keyboard driver and modified to suit 230 * USB keyboard. 231 * 232 * @note Lock keys are not sent to the console, as they are completely handled 233 * in the driver. It may, however, be required later that the driver 234 * sends also these keys to application (otherwise it cannot use those 235 * keys at all). 236 * 237 * @param kbd_dev Keyboard device structure. 238 * @param type Type of the event (press / release). Recognized values: 239 * KEY_PRESS, KEY_RELEASE 240 * @param key Key code of the key according to HID Usage Tables. 241 */ 242 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key) 192 usbhid_req_set_report(kbd_dev->hid_dev, value, buffer, 193 BOOTP_BUFFER_OUT_SIZE); 194 } 195 196 /*----------------------------------------------------------------------------*/ 197 198 static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, 199 unsigned int key) 243 200 { 244 201 console_event_t ev; 245 202 unsigned mod_mask; 246 203 247 /* 248 * These parts are copy-pasted from the AT keyboard driver. 249 * 250 * They definitely require some refactoring, but will keep it for later 251 * when the console and keyboard system is changed in HelenOS. 252 */ 204 // TODO: replace by our own parsing?? or are the key codes identical?? 253 205 switch (key) { 254 206 case KC_LCTRL: mod_mask = KM_LCTRL; break; … … 276 228 277 229 if (mod_mask != 0) { 230 usb_log_debug2("\n\nChanging mods and lock keys\n"); 231 usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods); 232 usb_log_debug2("\nLock keys before:0x%x\n\n", 233 kbd_dev->lock_keys); 234 278 235 if (type == KEY_PRESS) { 236 usb_log_debug2("\nKey pressed.\n"); 279 237 /* 280 238 * Only change lock state on transition from released … … 282 240 * up the lock state. 283 241 */ 284 unsigned int locks_old = kbd_dev->lock_keys;285 286 242 kbd_dev->mods = 287 243 kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys); … … 289 245 290 246 /* Update keyboard lock indicator lights. */ 291 if (kbd_dev->lock_keys != locks_old) { 292 usbhid_kbd_set_led(kbd_dev); 293 } 247 usbhid_kbd_set_led(kbd_dev); 294 248 } else { 249 usb_log_debug2("\nKey released.\n"); 295 250 kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask; 296 251 } 297 252 } 298 253 254 usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods); 255 usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys); 256 299 257 if (key == KC_CAPS_LOCK || key == KC_NUM_LOCK || key == KC_SCROLL_LOCK) { 300 258 // do not send anything to the console, this is our business … … 323 281 ev.key = key; 324 282 ev.mods = kbd_dev->mods; 283 284 if (ev.mods & KM_NUM_LOCK) { 285 usb_log_debug("\n\nNum Lock turned on.\n\n"); 286 } 325 287 326 288 ev.c = layout[active_layout]->parse_ev(&ev); … … 338 300 339 301 /*----------------------------------------------------------------------------*/ 340 /** 341 * Checks if modifiers were pressed or released and generates key events. 342 * 343 * @param kbd_dev Keyboard device structure. 344 * @param modifiers Bitmap of modifiers. 345 * 346 * @sa usbhid_kbd_push_ev() 347 */ 302 348 303 static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev, 349 304 uint8_t modifiers) … … 381 336 382 337 /*----------------------------------------------------------------------------*/ 383 /** 384 * Checks if some keys were pressed or released and generates key events. 385 * 386 * An event is created only when key is pressed or released. Besides handling 387 * the events (usbhid_kbd_push_ev()), the auto-repeat fibril is notified about 388 * key presses and releases (see usbhid_kbd_repeat_start() and 389 * usbhid_kbd_repeat_stop()). 390 * 391 * @param kbd_dev Keyboard device structure. 392 * @param key_codes Parsed keyboard report - codes of currently pressed keys 393 * according to HID Usage Tables. 394 * @param count Number of key codes in report (size of the report). 395 * 396 * @sa usbhid_kbd_push_ev(), usbhid_kbd_repeat_start(), usbhid_kbd_repeat_stop() 397 */ 338 398 339 static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev, 399 const uint8_t *key_codes, size_t count) 400 { 340 const uint8_t *key_codes) 341 { 342 // TODO: phantom state!! 343 401 344 unsigned int key; 402 345 unsigned int i, j; 403 346 404 /* 405 * First of all, check if the kbd have reported phantom state. 406 */ 407 i = 0; 408 // all fields should report Error Rollover 409 while (i < count && 410 key_codes[i] == BOOTP_ERROR_ROLLOVER) { 411 ++i; 412 } 413 if (i == count) { 414 usb_log_debug("Phantom state occured.\n"); 415 // phantom state, do nothing 416 return; 417 } 418 419 /* TODO: quite dummy right now, think of better implementation */ 420 assert(count == kbd_dev->key_count); 347 // TODO: quite dummy right now, think of better implementation 421 348 422 349 /* 423 350 * 1) Key releases 424 351 */ 425 for (j = 0; j < count; ++j) {352 for (j = 0; j < kbd_dev->keycode_count; ++j) { 426 353 // try to find the old key in the new key list 427 354 i = 0; 428 while (i < kbd_dev->key _count429 && key_codes[i] != kbd_dev->key s[j]) {355 while (i < kbd_dev->keycode_count 356 && key_codes[i] != kbd_dev->keycodes[j]) { 430 357 ++i; 431 358 } 432 359 433 if (i == count) {360 if (i == kbd_dev->keycode_count) { 434 361 // not found, i.e. the key was released 435 key = usbhid_parse_scancode(kbd_dev->keys[j]); 436 usbhid_kbd_repeat_stop(kbd_dev, key); 362 key = usbhid_parse_scancode(kbd_dev->keycodes[j]); 437 363 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key); 438 usb_log_debug2(" Key released: %d\n", key);364 usb_log_debug2("\nKey released: %d\n", key); 439 365 } else { 440 366 // found, nothing happens … … 445 371 * 1) Key presses 446 372 */ 447 for (i = 0; i < kbd_dev->key _count; ++i) {373 for (i = 0; i < kbd_dev->keycode_count; ++i) { 448 374 // try to find the new key in the old key list 449 375 j = 0; 450 while (j < count && kbd_dev->keys[j] != key_codes[i]) { 376 while (j < kbd_dev->keycode_count 377 && kbd_dev->keycodes[j] != key_codes[i]) { 451 378 ++j; 452 379 } 453 380 454 if (j == count) {381 if (j == kbd_dev->keycode_count) { 455 382 // not found, i.e. new key pressed 456 383 key = usbhid_parse_scancode(key_codes[i]); 457 usb_log_debug2(" Key pressed: %d (keycode: %d)\n", key,384 usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key, 458 385 key_codes[i]); 459 386 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key); 460 usbhid_kbd_repeat_start(kbd_dev, key);461 387 } else { 462 388 // found, nothing happens … … 464 390 } 465 391 466 memcpy(kbd_dev->keys, key_codes, count); 467 468 usb_log_debug("New stored keycodes: %s\n", 469 usb_debug_str_buffer(kbd_dev->keys, kbd_dev->key_count, 0)); 392 memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count); 393 394 usb_log_debug2("\nNew stored keycodes: "); 395 for (i = 0; i < kbd_dev->keycode_count; ++i) { 396 usb_log_debug2("%d ", kbd_dev->keycodes[i]); 397 } 470 398 } 471 399 … … 473 401 /* Callbacks for parser */ 474 402 /*----------------------------------------------------------------------------*/ 475 /** 476 * Callback function for the HID report parser. 477 * 478 * This function is called by the HID report parser with the parsed report. 479 * The parsed report is used to check if any events occured (key was pressed or 480 * released, modifier was pressed or released). 481 * 482 * @param key_codes Parsed keyboard report - codes of currently pressed keys 483 * according to HID Usage Tables. 484 * @param count Number of key codes in report (size of the report). 485 * @param modifiers Bitmap of modifiers (Ctrl, Alt, Shift, GUI). 486 * @param arg User-specified argument. Expects pointer to the keyboard device 487 * structure representing the keyboard. 488 * 489 * @sa usbhid_kbd_check_key_changes(), usbhid_kbd_check_modifier_changes() 490 */ 403 491 404 static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count, 492 405 uint8_t modifiers, void *arg) … … 497 410 return; 498 411 } 412 413 usb_log_debug2("Got keys from parser: "); 414 unsigned i; 415 for (i = 0; i < count; ++i) { 416 usb_log_debug2("%d ", key_codes[i]); 417 } 418 usb_log_debug2("\n"); 499 419 500 420 usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg; 501 421 assert(kbd_dev != NULL); 502 503 usb_log_debug("Got keys from parser: %s\n", 504 usb_debug_str_buffer(key_codes, kbd_dev->key_count, 0)); 505 506 if (count != kbd_dev->key_count) { 422 423 if (count != kbd_dev->keycode_count) { 507 424 usb_log_warning("Number of received keycodes (%d) differs from" 508 " expected number (%d).\n", count, kbd_dev->key _count);425 " expected number (%d).\n", count, kbd_dev->keycode_count); 509 426 return; 510 427 } 511 428 512 429 usbhid_kbd_check_modifier_changes(kbd_dev, modifiers); 513 usbhid_kbd_check_key_changes(kbd_dev, key_codes , count);430 usbhid_kbd_check_key_changes(kbd_dev, key_codes); 514 431 } 515 432 … … 517 434 /* General kbd functions */ 518 435 /*----------------------------------------------------------------------------*/ 519 /** 520 * Processes data received from the device in form of report. 521 * 522 * This function uses the HID report parser to translate the data received from 523 * the device into generic USB HID key codes and into generic modifiers bitmap. 524 * The parser then calls the given callback (usbhid_kbd_process_keycodes()). 525 * 526 * @note Currently, only the boot protocol is supported. 527 * 528 * @param kbd_dev Keyboard device structure (must be initialized). 529 * @param buffer Data from the keyboard (i.e. the report). 530 * @param actual_size Size of the data from keyboard (report size) in bytes. 531 * 532 * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(). 533 */ 436 534 437 static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev, 535 438 uint8_t *buffer, size_t actual_size) … … 541 444 callbacks->keyboard = usbhid_kbd_process_keycodes; 542 445 543 usb_log_debug("Calling usb_hid_boot_keyboard_input_report() with " 544 "buffer %s\n", usb_debug_str_buffer(buffer, actual_size, 0)); 446 //usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 447 // NULL); 448 /*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size" 449 " %zu\n", actual_size);*/ 450 //dump_buffer("bufffer: ", buffer, actual_size); 545 451 546 452 int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, … … 556 462 /* HID/KBD structure manipulation */ 557 463 /*----------------------------------------------------------------------------*/ 558 /** 559 * Creates a new USB/HID keyboard structure. 560 * 561 * The structure returned by this function is not initialized. Use 562 * usbhid_kbd_init() to initialize it prior to polling. 563 * 564 * @return New uninitialized structure for representing a USB/HID keyboard or 565 * NULL if not successful (memory error). 566 */ 464 567 465 static usbhid_kbd_t *usbhid_kbd_new(void) 568 466 { … … 590 488 591 489 /*----------------------------------------------------------------------------*/ 592 /** 593 * Properly destroys the USB/HID keyboard structure. 594 * 595 * @param kbd_dev Pointer to the structure to be destroyed. 596 */ 490 597 491 static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev) 598 492 { … … 609 503 } 610 504 611 if ((*kbd_dev)->repeat_mtx != NULL) {612 /* TODO: replace by some check and wait */613 assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));614 free((*kbd_dev)->repeat_mtx);615 }616 617 505 free(*kbd_dev); 618 506 *kbd_dev = NULL; … … 620 508 621 509 /*----------------------------------------------------------------------------*/ 622 /** 623 * Initialization of the USB/HID keyboard structure. 624 * 625 * This functions initializes required structures from the device's descriptors. 626 * 627 * During initialization, the keyboard is switched into boot protocol, the idle 628 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 629 * when a key is pressed or released. Finally, the LED lights are turned on 630 * according to the default setup of lock keys. 631 * 632 * @note By default, the keyboards is initialized with Num Lock turned on and 633 * other locks turned off. 634 * 635 * @param kbd_dev Keyboard device structure to be initialized. 636 * @param dev DDF device structure of the keyboard. 637 * 638 * @retval EOK if successful. 639 * @retval EINVAL if some parameter is not given. 640 * @return Other value inherited from function usbhid_dev_init(). 641 */ 510 642 511 static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev) 643 512 { … … 674 543 675 544 // save the size of the report (boot protocol report by default) 676 kbd_dev->key _count = BOOTP_REPORT_SIZE;677 kbd_dev->key s = (uint8_t *)calloc(678 kbd_dev->key _count, sizeof(uint8_t));679 680 if (kbd_dev->key s == NULL) {545 kbd_dev->keycode_count = BOOTP_REPORT_SIZE; 546 kbd_dev->keycodes = (uint8_t *)calloc( 547 kbd_dev->keycode_count, sizeof(uint8_t)); 548 549 if (kbd_dev->keycodes == NULL) { 681 550 usb_log_fatal("No memory!\n"); 682 return ENOMEM;551 return rc; 683 552 } 684 553 … … 687 556 kbd_dev->lock_keys = 0; 688 557 689 kbd_dev->repeat.key_new = 0;690 kbd_dev->repeat.key_repeated = 0;691 kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;692 kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;693 694 kbd_dev->repeat_mtx = (fibril_mutex_t *)(695 malloc(sizeof(fibril_mutex_t)));696 if (kbd_dev->repeat_mtx == NULL) {697 usb_log_fatal("No memory!\n");698 free(kbd_dev->keys);699 return ENOMEM;700 }701 702 fibril_mutex_initialize(kbd_dev->repeat_mtx);703 704 558 /* 705 559 * Set boot protocol. 706 560 * Set LEDs according to initial setup. 707 * Set Idle rate708 561 */ 709 562 assert(kbd_dev->hid_dev != NULL); … … 713 566 usbhid_kbd_set_led(kbd_dev); 714 567 715 usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);716 717 568 kbd_dev->initialized = 1; 718 569 usb_log_info("HID/KBD device structure initialized.\n"); … … 724 575 /* HID/KBD polling */ 725 576 /*----------------------------------------------------------------------------*/ 726 /** 727 * Main keyboard polling function. 728 * 729 * This function uses the Interrupt In pipe of the keyboard to poll for events. 730 * The keyboard is initialized in a way that it reports only when a key is 731 * pressed or released, so there is no actual need for any sleeping between 732 * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()). 733 * 734 * @param kbd_dev Initialized keyboard structure representing the device to 735 * poll. 736 * 737 * @sa usbhid_kbd_process_data() 738 */ 577 739 578 static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev) 740 579 { … … 759 598 usb_log_warning("Failed to start a session: %s.\n", 760 599 str_error(sess_rc)); 761 break;600 continue; 762 601 } 763 602 … … 771 610 usb_log_warning("Error polling the keyboard: %s.\n", 772 611 str_error(rc)); 773 break;612 continue; 774 613 } 775 614 … … 777 616 usb_log_warning("Error closing session: %s.\n", 778 617 str_error(sess_rc)); 779 break;618 continue; 780 619 } 781 620 … … 795 634 usbhid_kbd_process_data(kbd_dev, buffer, actual_size); 796 635 797 // disabled for now, no reason to sleep 798 //async_usleep(kbd_dev->hid_dev->poll_interval); 799 } 800 } 801 802 /*----------------------------------------------------------------------------*/ 803 /** 804 * Function executed by the main driver fibril. 805 * 806 * Just starts polling the keyboard for events. 807 * 808 * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 809 * representing the device. 810 * 811 * @retval EOK if the fibril finished polling the device. 812 * @retval EINVAL if no device was given in the argument. 813 * 814 * @sa usbhid_kbd_poll() 815 * 816 * @todo Change return value - only case when the fibril finishes is in case 817 * of some error, so the error should probably be propagated from function 818 * usbhid_kbd_poll() to here and up. 819 */ 636 async_usleep(kbd_dev->hid_dev->poll_interval); 637 } 638 639 // not reached 640 assert(0); 641 } 642 643 /*----------------------------------------------------------------------------*/ 644 820 645 static int usbhid_kbd_fibril(void *arg) 821 646 { … … 839 664 /* API functions */ 840 665 /*----------------------------------------------------------------------------*/ 841 /** 842 * Function for adding a new device of type USB/HID/keyboard. 843 * 844 * This functions initializes required structures from the device's descriptors 845 * and starts new fibril for polling the keyboard for events and another one for 846 * handling auto-repeat of keys. 847 * 848 * During initialization, the keyboard is switched into boot protocol, the idle 849 * rate is set to 0 (infinity), resulting in the keyboard only reporting event 850 * when a key is pressed or released. Finally, the LED lights are turned on 851 * according to the default setup of lock keys. 852 * 853 * @note By default, the keyboards is initialized with Num Lock turned on and 854 * other locks turned off. 855 * @note Currently supports only boot-protocol keyboards. 856 * 857 * @param dev Device to add. 858 * 859 * @retval EOK if successful. 860 * @retval ENOMEM if there 861 * @return Other error code inherited from one of functions usbhid_kbd_init(), 862 * ddf_fun_bind() and ddf_fun_add_to_class(). 863 * 864 * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril() 865 */ 666 866 667 int usbhid_kbd_try_add_device(ddf_dev_t *dev) 867 668 { … … 885 686 "structure.\n"); 886 687 ddf_fun_destroy(kbd_fun); 887 return E NOMEM; // TODO: some other code??688 return EINVAL; // TODO: some other code?? 888 689 } 889 690 … … 934 735 } 935 736 fibril_add_ready(fid); 936 937 /*938 * Create new fibril for auto-repeat939 */940 fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);941 if (fid == 0) {942 usb_log_error("Failed to start fibril for KBD auto-repeat");943 return ENOMEM;944 }945 fibril_add_ready(fid);946 737 947 738 (void)keyboard_ops; -
uspace/drv/usbhid/kbddev.h
r72af8da r3e7b7cd 39 39 #include <stdint.h> 40 40 41 #include <fibril_synch.h>42 43 41 #include <usb/classes/hid.h> 44 42 #include <ddf/driver.h> … … 48 46 49 47 /*----------------------------------------------------------------------------*/ 48 50 49 /** 51 * Structure for keeping information needed for auto-repeat of keys.50 * @brief USB/HID keyboard device type. 52 51 */ 53 52 typedef struct { 54 /** Last pressed key. */55 unsigned int key_new;56 /** Key to be repeated. */57 unsigned int key_repeated;58 /** Delay before first repeat in microseconds. */59 unsigned int delay_before;60 /** Delay between repeats in microseconds. */61 unsigned int delay_between;62 } usbhid_kbd_repeat_t;63 64 /**65 * USB/HID keyboard device type.66 *67 * Holds a reference to generic USB/HID device structure and keyboard-specific68 * data, such as currently pressed keys, modifiers and lock keys.69 *70 * Also holds a IPC phone to the console (since there is now no other way to71 * communicate with it).72 *73 * @note Storing active lock keys in this structure results in their setting74 * being device-specific.75 */76 typedef struct {77 /** Structure holding generic USB/HID device information. */78 53 usbhid_dev_t *hid_dev; 79 54 80 /** Currently pressed keys (not translated to key codes). */ 81 uint8_t *keys; 82 /** Count of stored keys (i.e. number of keys in the report). */ 83 size_t key_count; 84 /** Currently pressed modifiers (bitmap). */ 55 uint8_t *keycodes; 56 size_t keycode_count; 85 57 uint8_t modifiers; 86 58 87 /** Currently active modifiers including locks. Sent to the console. */88 59 unsigned mods; 89 90 /** Currently active lock keys. */91 60 unsigned lock_keys; 92 61 93 /** IPC phone to the console device (for sending key events). */94 62 int console_phone; 95 63 96 /** Information for auto-repeat of keys. */97 usbhid_kbd_repeat_t repeat;98 99 /** Mutex for accessing the information about auto-repeat. */100 fibril_mutex_t *repeat_mtx;101 102 /** State of the structure (for checking before use). */103 64 int initialized; 104 65 } usbhid_kbd_t; … … 108 69 int usbhid_kbd_try_add_device(ddf_dev_t *dev); 109 70 110 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);111 112 71 #endif /* USBHID_KBDDEV_H_ */ 113 72 -
uspace/drv/usbhid/main.c
r72af8da r3e7b7cd 47 47 48 48 /*----------------------------------------------------------------------------*/ 49 /** 50 * Callback for passing a new device to the driver. 51 * 52 * @note Currently, only boot-protocol keyboards are supported by this driver. 53 * 54 * @param dev Structure representing the new device. 55 * 56 * @retval EOK if successful. 57 * @retval EREFUSED if the device is not supported. 58 */ 49 59 50 static int usbhid_add_device(ddf_dev_t *dev) 60 51 { … … 89 80 int main(int argc, char *argv[]) 90 81 { 91 usb_log_enable(USB_LOG_LEVEL_ DEBUG, NAME);82 usb_log_enable(USB_LOG_LEVEL_INFO, NAME); 92 83 return ddf_driver_main(&kbd_driver); 93 84 } -
uspace/drv/usbhub/usbhub.c
r72af8da r3e7b7cd 118 118 dprintf(USB_LOG_LEVEL_ERROR, 119 119 "could not initialize connection to device endpoint, errno %d",opResult); 120 return opResult; 121 } 122 123 opResult = usb_endpoint_pipe_probe_default_control(&hub->endpoints.control); 124 if (opResult != EOK) { 125 dprintf(USB_LOG_LEVEL_ERROR, "failed probing endpoint 0, %d", opResult); 126 return opResult; 127 } 128 129 return EOK; 120 } 121 return opResult; 130 122 } 131 123 … … 241 233 dprintf(USB_LOG_LEVEL_DEBUG, "starting control transaction"); 242 234 usb_endpoint_pipe_start_session(&result->endpoints.control); 243 opResult = usb_request_set_configuration(&result->endpoints.control, 1);244 assert(opResult == EOK);245 246 235 opResult = usb_request_get_descriptor(&result->endpoints.control, 247 236 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, … … 438 427 &new_device_pipe, 439 428 &new_device_connection); 440 usb_endpoint_pipe_probe_default_control(&new_device_pipe);441 429 /// \TODO get highspeed info 442 430 usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL; -
uspace/drv/usbmid/main.c
r72af8da r3e7b7cd 44 44 #include "usbmid.h" 45 45 46 /** Callback when new MID device is attached to the host.47 *48 * @param gen_dev Generic DDF device representing the new device.49 * @return Error code.50 */51 46 static int usbmid_add_device(ddf_dev_t *gen_dev) 52 47 { … … 91 86 } 92 87 93 /** USB MID driver ops. */94 88 static driver_ops_t mid_driver_ops = { 95 89 .add_device = usbmid_add_device, 96 90 }; 97 91 98 /** USB MID driver. */99 92 static driver_t mid_driver = { 100 93 .name = NAME, -
uspace/drv/usbmid/usbmid.c
r72af8da r3e7b7cd 67 67 } 68 68 69 /** DDF interface of the child - interface function. */70 69 static usb_iface_t child_usb_iface = { 71 70 .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl, … … 74 73 }; 75 74 76 /** Operations for children - interface functions. */ 75 77 76 static ddf_dev_ops_t child_device_ops = { 78 77 .interfaces[USB_DEV_IFACE] = &child_usb_iface 79 78 }; 80 79 81 /** Operations of the device itself. */82 80 static ddf_dev_ops_t mid_device_ops = { 83 81 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl … … 116 114 return NULL; 117 115 } 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 }125 116 126 117 mid->dev = dev; … … 132 123 /** Create new interface for USB MID device. 133 124 * 134 * @param fun Backing generic DDF device function(representing interface).125 * @param dev Backing generic DDF child device (representing interface). 135 126 * @param iface_no Interface number. 136 127 * @return New interface. -
uspace/drv/usbmid/usbmid.h
r72af8da r3e7b7cd 44 44 #define NAME "usbmid" 45 45 46 /** USB MID device container. */47 46 typedef struct { 48 47 /** Device container. */ … … 55 54 } usbmid_device_t; 56 55 57 58 /** Container for single interface in a MID device. */59 56 typedef struct { 60 57 /** Function container. */ -
uspace/drv/usbmouse/init.c
r72af8da r3e7b7cd 42 42 43 43 /** Mouse polling endpoint description for boot protocol subclass. */ 44 usb_endpoint_description_t poll_endpoint_description = {44 static usb_endpoint_description_t poll_endpoint_description = { 45 45 .transfer_type = USB_TRANSFER_INTERRUPT, 46 46 .direction = USB_DIRECTION_IN, … … 51 51 }; 52 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_interface 81 } 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 53 102 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *); 54 /** Device ops for USB mouse. */55 103 static ddf_dev_ops_t mouse_ops = { 56 104 .default_handler = default_connection_handler … … 59 107 /** Default handler for IPC methods not handled by DDF. 60 108 * 61 * @param fun Device functionhandling the call.109 * @param dev Device handling the call. 62 110 * @param icallid Call id. 63 111 * @param icall Call data. … … 87 135 } 88 136 89 /** Create USB mouse device. 90 * 91 * The mouse device is stored into <code>dev->driver_data</code>. 92 * 93 * @param dev Generic device. 94 * @return Error code. 95 */ 96 int usb_mouse_create(usb_device_t *dev) 137 138 int usb_mouse_create(ddf_dev_t *dev) 97 139 { 98 140 usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t)); … … 100 142 return ENOMEM; 101 143 } 102 mouse->dev = dev;144 mouse->device = dev; 103 145 mouse->console_phone = -1; 104 146 105 147 int rc; 106 148 149 /* Initialize the backing connection. */ 150 rc = usb_device_connection_initialize_from_device(&mouse->wire, dev); 151 if (rc != EOK) { 152 goto leave; 153 } 154 155 /* Initialize the default control pipe. */ 156 rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe, 157 &mouse->wire); 158 if (rc != EOK) { 159 goto leave; 160 } 161 162 rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe); 163 if (rc != EOK) { 164 goto leave; 165 } 166 167 rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev)); 168 169 /* We can ignore error here. */ 170 usb_endpoint_pipe_end_session(&mouse->ctrl_pipe); 171 172 if (rc != EOK) { 173 goto leave; 174 } 175 107 176 /* Create DDF function. */ 108 mouse->mouse_fun = ddf_fun_create(dev ->ddf_dev, fun_exposed, "mouse");177 mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse"); 109 178 if (mouse->mouse_fun == NULL) { 110 179 rc = ENOMEM; -
uspace/drv/usbmouse/main.c
r72af8da r3e7b7cd 39 39 #include <str_error.h> 40 40 41 /** Callback when new mouse device is attached and recognised by DDF. 42 * 43 * @param dev Representation of a generic DDF device. 44 * @return Error code. 45 */ 46 static int usbmouse_add_device(usb_device_t *dev) 41 static int usbmouse_add_device(ddf_dev_t *dev) 47 42 { 48 43 int rc = usb_mouse_create(dev); … … 53 48 } 54 49 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; 50 fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev); 51 if (poll_fibril == 0) { 52 usb_log_error("Failed to initialize polling fibril.\n"); 53 /* FIXME: free allocated resources. */ 54 return ENOMEM; 65 55 } 66 56 57 fibril_add_ready(poll_fibril); 58 67 59 usb_log_info("controlling new mouse (handle %llu).\n", 68 dev-> ddf_dev->handle);60 dev->handle); 69 61 70 62 return EOK; 71 63 } 72 64 73 /** USB mouse driver ops. */ 74 static usb_driver_ops_t mouse_driver_ops = { 65 static driver_ops_t mouse_driver_ops = { 75 66 .add_device = usbmouse_add_device, 76 67 }; 77 68 78 static usb_endpoint_description_t *endpoints[] = { 79 &poll_endpoint_description, 80 NULL 81 }; 82 83 /** USB mouse driver. */ 84 static usb_driver_t mouse_driver = { 69 static driver_t mouse_driver = { 85 70 .name = NAME, 86 .ops = &mouse_driver_ops, 87 .endpoints = endpoints 71 .driver_ops = &mouse_driver_ops 88 72 }; 89 73 … … 92 76 usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME); 93 77 94 return usb_driver_main(&mouse_driver);78 return ddf_driver_main(&mouse_driver); 95 79 } 96 80 -
uspace/drv/usbmouse/mouse.c
r72af8da r3e7b7cd 37 37 #include <usb/debug.h> 38 38 #include <errno.h> 39 #include <str_error.h>40 39 #include <ipc/mouse.h> 41 40 42 /** Mouse polling callback. 43 * 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 */ 50 bool usb_mouse_polling_callback(usb_device_t *dev, 51 uint8_t *buffer, size_t buffer_size, void *arg) 41 int usb_mouse_polling_fibril(void *arg) 52 42 { 53 usb_mouse_t *mouse = (usb_mouse_t *) arg; 43 assert(arg != NULL); 44 ddf_dev_t *dev = (ddf_dev_t *) arg; 45 usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data; 54 46 55 usb_log_debug2("got buffer: %s.\n", 56 usb_debug_str_buffer(buffer, buffer_size, 0)); 47 assert(mouse); 57 48 58 uint8_t butt = buffer[0]; 59 char str_buttons[4] = { 60 butt & 1 ? '#' : '.', 61 butt & 2 ? '#' : '.', 62 butt & 4 ? '#' : '.', 63 0 64 }; 49 size_t buffer_size = mouse->poll_pipe.max_packet_size; 65 50 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; 51 if (buffer_size < 4) { 52 usb_log_error("Weird mouse, results will be skewed.\n"); 53 buffer_size = 4; 78 54 } 79 55 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 } 56 uint8_t *buffer = malloc(buffer_size); 57 if (buffer == NULL) { 58 usb_log_error("Out of memory, poll fibril aborted.\n"); 59 return ENOMEM; 94 60 } 95 61 96 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n",97 str_buttons, shift_x, shift_y, wheel);62 while (true) { 63 async_usleep(mouse->poll_interval_us); 98 64 99 /* Guess. */ 100 async_usleep(1000); 65 size_t actual_size; 101 66 102 return true; 67 /* FIXME: check for errors. */ 68 usb_endpoint_pipe_start_session(&mouse->poll_pipe); 69 70 usb_endpoint_pipe_read(&mouse->poll_pipe, 71 buffer, buffer_size, &actual_size); 72 73 usb_endpoint_pipe_end_session(&mouse->poll_pipe); 74 75 uint8_t butt = buffer[0]; 76 char str_buttons[4] = { 77 butt & 1 ? '#' : '.', 78 butt & 2 ? '#' : '.', 79 butt & 4 ? '#' : '.', 80 0 81 }; 82 83 int shift_x = ((int) buffer[1]) - 127; 84 int shift_y = ((int) buffer[2]) - 127; 85 int wheel = ((int) buffer[3]) - 127; 86 87 if (buffer[1] == 0) { 88 shift_x = 0; 89 } 90 if (buffer[2] == 0) { 91 shift_y = 0; 92 } 93 if (buffer[3] == 0) { 94 wheel = 0; 95 } 96 97 if (mouse->console_phone >= 0) { 98 if ((shift_x != 0) || (shift_y != 0)) { 99 /* FIXME: guessed for QEMU */ 100 async_req_2_0(mouse->console_phone, 101 MEVENT_MOVE, 102 - shift_x / 10, - shift_y / 10); 103 } 104 if (butt) { 105 /* FIXME: proper button clicking. */ 106 async_req_2_0(mouse->console_phone, 107 MEVENT_BUTTON, 1, 1); 108 async_req_2_0(mouse->console_phone, 109 MEVENT_BUTTON, 1, 0); 110 } 111 } 112 113 usb_log_debug("buttons=%s dX=%+3d dY=%+3d wheel=%+3d\n", 114 str_buttons, shift_x, shift_y, wheel); 115 } 116 117 return EOK; 103 118 } 104 119 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 to109 * 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;116 117 async_hangup(mouse->console_phone);118 mouse->console_phone = -1;119 }120 120 121 121 /** -
uspace/drv/usbmouse/mouse.h
r72af8da r3e7b7cd 37 37 #define USBMOUSE_MOUSE_H_ 38 38 39 #include < usb/devdrv.h>39 #include <ddf/driver.h> 40 40 #include <usb/pipes.h> 41 41 #include <time.h> … … 43 43 #define NAME "usbmouse" 44 44 45 /** Container for USB mouse device. */46 45 typedef struct { 47 /** Generic device container. */ 48 usb_device_t *dev; 49 /** Function representing the device. */ 46 ddf_dev_t *device; 50 47 ddf_fun_t *mouse_fun; 51 /** Polling interval in microseconds. */ 48 usb_device_connection_t wire; 49 usb_endpoint_pipe_t ctrl_pipe; 50 usb_endpoint_pipe_t poll_pipe; 52 51 suseconds_t poll_interval_us; 53 /** IPC phone to console (consumer). */54 52 int console_phone; 55 53 } usb_mouse_t; 56 54 57 #define POLL_PIPE(dev) ((dev)->pipes[0].pipe) 55 int usb_mouse_create(ddf_dev_t *); 58 56 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 *); 57 int usb_mouse_polling_fibril(void *); 65 58 66 59 #endif -
uspace/drv/vhc/conndev.c
r72af8da r3e7b7cd 110 110 /** Callback for DDF when client disconnects. 111 111 * 112 * @param fun Device functionthe client was connected to.112 * @param d Device the client was connected to. 113 113 */ 114 114 void on_client_close(ddf_fun_t *fun) -
uspace/lib/block/libblock.c
r72af8da r3e7b7cd 411 411 l = hash_table_find(&cache->block_hash, &key); 412 412 if (l) { 413 found:414 413 /* 415 414 * We found the block in the cache. … … 494 493 fibril_mutex_unlock(&b->lock); 495 494 goto retry; 496 }497 l = hash_table_find(&cache->block_hash, &key);498 if (l) {499 /*500 * Someone else must have already501 * instantiated the block while we were502 * not holding the cache lock.503 * Leave the recycled block on the504 * freelist and continue as if we505 * found the block of interest during506 * the first try.507 */508 fibril_mutex_unlock(&b->lock);509 goto found;510 495 } 511 496 -
uspace/lib/drv/generic/remote_usbhc.c
r72af8da r3e7b7cd 55 55 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 56 56 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 57 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);58 static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);59 57 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 60 58 … … 75 73 76 74 remote_usbhc_control_write, 77 remote_usbhc_control_read, 78 79 remote_usbhc_register_endpoint, 80 remote_usbhc_unregister_endpoint 75 remote_usbhc_control_read 81 76 }; 82 77 … … 527 522 528 523 529 void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,530 ipc_callid_t callid, ipc_call_t *call)531 {532 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;533 534 if (!usb_iface->register_endpoint) {535 async_answer_0(callid, ENOTSUP);536 return;537 }538 539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \540 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \542 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256543 544 INIT_FROM_HIGH_DATA(usb_address_t, address, 1);545 INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1);546 INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2);547 INIT_FROM_LOW_DATA(usb_direction_t, direction, 2);548 549 #undef INIT_FROM_HIGH_DATA550 #undef INIT_FROM_LOW_DATA551 552 size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call);553 unsigned int interval = (unsigned int) DEV_IPC_GET_ARG4(*call);554 555 int rc = usb_iface->register_endpoint(fun, address, endpoint,556 transfer_type, direction, max_packet_size, interval);557 558 async_answer_0(callid, rc);559 }560 561 562 void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,563 ipc_callid_t callid, ipc_call_t *call)564 {565 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;566 567 if (!usb_iface->unregister_endpoint) {568 async_answer_0(callid, ENOTSUP);569 return;570 }571 572 usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);573 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);574 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);575 576 int rc = usb_iface->unregister_endpoint(fun,577 address, endpoint, direction);578 579 async_answer_0(callid, rc);580 }581 582 524 583 525 /** -
uspace/lib/drv/include/usbhc_iface.h
r72af8da r3e7b7cd 167 167 IPC_M_USBHC_CONTROL_READ, 168 168 169 /** Register endpoint attributes at host controller. 170 * This is used to reserve portion of USB bandwidth. 171 * Parameters: 172 * - USB address + endpoint number (ADDR * 256 + EP) 173 * - transfer type + direction (TYPE * 256 + DIR) 174 * - maximum packet size 175 * - interval (in milliseconds) 176 * Answer: 177 * - EOK - reservation successful 178 * - ELIMIT - not enough bandwidth to satisfy the request 179 */ 180 IPC_M_USBHC_REGISTER_ENDPOINT, 181 182 /** Revert endpoint registration. 183 * Parameters: 184 * - USB address 185 * - endpoint number 186 * - data direction 187 * Answer: 188 * - EOK - endpoint unregistered 189 * - ENOENT - unknown endpoint 190 */ 191 IPC_M_USBHC_UNREGISTER_ENDPOINT 169 /* IPC_M_USB_ */ 192 170 } usbhc_iface_funcs_t; 193 171 … … 222 200 int (*release_address)(ddf_fun_t *, usb_address_t); 223 201 224 int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,225 usb_transfer_type_t, usb_direction_t, size_t, unsigned int);226 int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,227 usb_direction_t);228 229 202 usbhc_iface_transfer_out_t interrupt_out; 230 203 usbhc_iface_transfer_in_t interrupt_in; -
uspace/lib/usb/Makefile
r72af8da r3e7b7cd 37 37 src/ddfiface.c \ 38 38 src/debug.c \ 39 src/devdrv.c \40 src/devpoll.c \41 39 src/dp.c \ 42 40 src/dump.c \ … … 49 47 src/request.c \ 50 48 src/usb.c \ 51 src/usbdevice.c 49 src/usbdevice.c \ 50 src/usbmem.c 52 51 53 52 include $(USPACE_PREFIX)/Makefile.common -
uspace/lib/usb/include/usb/classes/classes.h
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * USB device classes (generic constants and functions).33 * @brief USB device classes and subclasses. 34 34 */ 35 35 #ifndef LIBUSB_CLASSES_H_ -
uspace/lib/usb/include/usb/debug.h
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * Debugging related functions.33 * @brief Debugging related functions. 34 34 */ 35 35 #ifndef LIBUSB_DEBUG_H_ … … 39 39 #include <assert.h> 40 40 41 void usb_dprintf(const char *tag, int level, const char *format, ...); 42 void usb_dprintf_enable(const char *tag, int level); 43 41 44 void usb_dump_standard_descriptor(FILE *, const char *, const char *, 42 45 const uint8_t *, size_t); … … 44 47 /** Logging level. */ 45 48 typedef enum { 46 /** Fatal, unrecoverable, error.47 * Such error prevents the driver from working at all.48 */49 49 USB_LOG_LEVEL_FATAL, 50 51 /** Serious but recoverable error52 * Shall be used for errors fatal for single device but not for53 * driver itself.54 */55 50 USB_LOG_LEVEL_ERROR, 56 57 /** Warning.58 * Problems from which the driver is able to recover gracefully.59 */60 51 USB_LOG_LEVEL_WARNING, 61 62 /** Information message.63 * This should be the last level that is printed by default to64 * the screen.65 * Typical usage is to inform that new device was found and what66 * are its capabilities.67 * Do not use for repetitive actions (such as device polling).68 */69 52 USB_LOG_LEVEL_INFO, 70 71 /** Debugging message. */72 53 USB_LOG_LEVEL_DEBUG, 73 74 /** More detailed debugging message. */75 54 USB_LOG_LEVEL_DEBUG2, 76 77 /** Terminating constant for logging levels. */78 55 USB_LOG_LEVEL_MAX 79 56 } usb_log_level_t; … … 84 61 void usb_log_printf(usb_log_level_t, const char *, ...); 85 62 86 /** Log fatal error. */87 63 #define usb_log_fatal(format, ...) \ 88 64 usb_log_printf(USB_LOG_LEVEL_FATAL, format, ##__VA_ARGS__) 89 65 90 /** Log normal (recoverable) error. */91 66 #define usb_log_error(format, ...) \ 92 67 usb_log_printf(USB_LOG_LEVEL_ERROR, format, ##__VA_ARGS__) 93 68 94 /** Log warning. */95 69 #define usb_log_warning(format, ...) \ 96 70 usb_log_printf(USB_LOG_LEVEL_WARNING, format, ##__VA_ARGS__) 97 71 98 /** Log informational message. */99 72 #define usb_log_info(format, ...) \ 100 73 usb_log_printf(USB_LOG_LEVEL_INFO, format, ##__VA_ARGS__) 101 74 102 /** Log debugging message. */103 75 #define usb_log_debug(format, ...) \ 104 76 usb_log_printf(USB_LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) 105 77 106 /** Log verbose debugging message. */107 78 #define usb_log_debug2(format, ...) \ 108 79 usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__) 109 80 110 const char *usb_debug_str_buffer(const uint8_t *, size_t, size_t);111 81 112 82 -
uspace/lib/usb/include/usb/descriptor.h
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * Standard USB descriptors.33 * @brief Standard USB descriptors. 34 34 */ 35 35 #ifndef LIBUSB_DESCRIPTOR_H_ … … 83 83 /** Product descriptor index. */ 84 84 uint8_t str_product; 85 /** Device serial number des criptor index. */85 /** Device serial number desriptor index. */ 86 86 uint8_t str_serial_number; 87 87 /** Number of possible configurations. */ … … 167 167 } __attribute__ ((packed)) usb_standard_endpoint_descriptor_t; 168 168 169 170 /* TODO: string descriptors. */ 171 169 172 #endif 170 173 /** -
uspace/lib/usb/include/usb/dp.h
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * USB descriptor parser.33 * @brief USB descriptor parser. 34 34 */ 35 35 #ifndef LIBUSB_DP_H_ … … 40 40 #include <usb/descriptor.h> 41 41 42 /** USB descriptors nesting.43 * The nesting describes the logical tree USB descriptors form44 * (e.g. that endpoint descriptor belongs to interface or that45 * interface belongs to configuration).46 *47 * See usb_descriptor_type_t for descriptor constants.48 */49 42 typedef struct { 50 /** Child descriptor id. */51 43 int child; 52 /** Parent descriptor id. */53 44 int parent; 54 45 } usb_dp_descriptor_nesting_t; … … 56 47 extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[]; 57 48 58 /** Descriptor parser structure. */59 49 typedef struct { 60 /** Used descriptor nesting. */61 50 usb_dp_descriptor_nesting_t *nesting; 62 51 } usb_dp_parser_t; 63 52 64 /** Descriptor parser data. */65 53 typedef struct { 66 /** Data to be parsed. */67 54 uint8_t *data; 68 /** Size of input data in bytes. */69 55 size_t size; 70 /** Custom argument. */71 56 void *arg; 72 57 } usb_dp_parser_data_t; -
uspace/lib/usb/include/usb/hub.h
r72af8da r3e7b7cd 32 32 /** @file 33 33 * Functions needed by hub drivers. 34 *35 * For class specific requests, see usb/classes/hub.h.36 34 */ 37 35 #ifndef LIBUSB_HUB_H_ -
uspace/lib/usb/include/usb/pipes.h
r72af8da r3e7b7cd 43 43 #include <ddf/driver.h> 44 44 45 /** Abstraction of a physical connection to the device. 45 /** 46 * Abstraction of a physical connection to the device. 46 47 * This type is an abstraction of the USB wire that connects the host and 47 48 * the function (device). … … 54 55 } usb_device_connection_t; 55 56 56 /** Abstraction of a logical connection to USB device endpoint. 57 /** 58 * Abstraction of a logical connection to USB device endpoint. 57 59 * It encapsulates endpoint attributes (transfer type etc.) as well 58 60 * as information about currently running sessions. … … 106 108 const usb_endpoint_description_t *description; 107 109 /** Interface number the endpoint must belong to (-1 for any). */ 108 int interface_no;110 const int interface_no; 109 111 /** Found descriptor fitting the description. */ 110 112 usb_standard_endpoint_descriptor_t *descriptor; 111 /** Interface descriptorthe endpoint belongs to. */113 /** Interface the endpoint belongs to. */ 112 114 usb_standard_interface_descriptor_t *interface; 113 115 /** Whether the endpoint was actually found. */ … … 129 131 int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *, 130 132 usb_device_connection_t *); 131 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *);132 133 int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 133 134 size_t, uint8_t *, size_t, usb_device_connection_t *); 134 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *, unsigned int, 135 usb_hc_connection_t *); 136 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *, usb_hc_connection_t *); 135 137 136 138 137 int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *); -
uspace/lib/usb/include/usb/request.h
r72af8da r3e7b7cd 72 72 union { 73 73 uint16_t value; 74 /* FIXME: add #ifdefs according to host endian ness */74 /* FIXME: add #ifdefs according to host endianess */ 75 75 struct { 76 76 uint8_t value_low; -
uspace/lib/usb/include/usb/usb.h
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * Common USB types and functions.33 * @brief Base USB types. 34 34 */ 35 35 #ifndef LIBUSB_USB_H_ … … 121 121 } usb_target_t; 122 122 123 /** Compare USB targets (addresses and endpoints).124 *125 * @param a First target.126 * @param b Second target.127 * @return Whether @p a and @p b points to the same pipe on the same device.128 */129 123 static inline int usb_target_same(usb_target_t a, usb_target_t b) 130 124 { -
uspace/lib/usb/src/ddfiface.c
r72af8da r3e7b7cd 56 56 /** Get host controller handle, interface implementation for hub driver. 57 57 * 58 * @param[in] fun Device functionthe operation is running on.58 * @param[in] device Device the operation is running on. 59 59 * @param[out] handle Storage for the host controller handle. 60 60 * @return Error code. … … 69 69 * a hub driver. 70 70 * 71 * @param[in] fun Device functionthe operation is running on.71 * @param[in] device Device the operation is running on. 72 72 * @param[out] handle Storage for the host controller handle. 73 73 * @return Error code. … … 88 88 IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle); 89 89 90 async_hangup(parent_phone);91 92 90 if (rc != EOK) { 93 91 return rc; … … 101 99 /** Get host controller handle, interface implementation for HC driver. 102 100 * 103 * @param[in] fun Device functionthe operation is running on.101 * @param[in] device Device the operation is running on. 104 102 * @param[out] handle Storage for the host controller handle. 105 103 * @return Always EOK. … … 118 116 /** Get USB device address, interface implementation for hub driver. 119 117 * 120 * @param[in] fun Device functionthe operation is running on.118 * @param[in] device Device the operation is running on. 121 119 * @param[in] handle Devman handle of USB device we want address of. 122 120 * @param[out] address Storage for USB address of device with handle @p handle. … … 153 151 * a hub driver. 154 152 * 155 * @param[in] fun Device functionthe operation is running on.153 * @param[in] device Device the operation is running on. 156 154 * @param[in] handle Devman handle of USB device we want address of. 157 155 * @param[out] address Storage for USB address of device with handle @p handle. -
uspace/lib/usb/src/debug.c
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * Debugging and logging support.33 * @brief Debugging support. 34 34 */ 35 35 #include <adt/list.h> … … 40 40 #include <usb/debug.h> 41 41 42 /** Debugging tag. */ 43 typedef struct { 44 /** Linked list member. */ 45 link_t link; 46 /** Tag name. 47 * We always have a private copy of the name. 48 */ 49 char *tag; 50 /** Enabled level of debugging. */ 51 int level; 52 } usb_debug_tag_t; 53 54 /** Get instance of usb_debug_tag_t from link_t. */ 55 #define USB_DEBUG_TAG_INSTANCE(iterator) \ 56 list_get_instance(iterator, usb_debug_tag_t, link) 57 58 /** List of all known tags. */ 59 static LIST_INITIALIZE(tag_list); 60 /** Mutex guard for the list of all tags. */ 61 static FIBRIL_MUTEX_INITIALIZE(tag_list_guard); 62 42 63 /** Level of logging messages. */ 43 64 static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING; 44 45 65 /** Prefix for logging messages. */ 46 66 static const char *log_prefix = "usb"; 47 48 67 /** Serialization mutex for logging functions. */ 49 68 static FIBRIL_MUTEX_INITIALIZE(log_serializer); 50 51 /** File where to store the log. */52 69 static FILE *log_stream = NULL; 53 70 71 /** Find or create new tag with given name. 72 * 73 * @param tagname Tag name. 74 * @return Debug tag structure. 75 * @retval NULL Out of memory. 76 */ 77 static usb_debug_tag_t *get_tag(const char *tagname) 78 { 79 link_t *link; 80 for (link = tag_list.next; \ 81 link != &tag_list; \ 82 link = link->next) { 83 usb_debug_tag_t *tag = USB_DEBUG_TAG_INSTANCE(link); 84 if (str_cmp(tag->tag, tagname) == 0) { 85 return tag; 86 } 87 } 88 89 /* 90 * Tag not found, we will create a new one. 91 */ 92 usb_debug_tag_t *new_tag = malloc(sizeof(usb_debug_tag_t)); 93 int rc = asprintf(&new_tag->tag, "%s", tagname); 94 if (rc < 0) { 95 free(new_tag); 96 return NULL; 97 } 98 list_initialize(&new_tag->link); 99 new_tag->level = 1; 100 101 /* 102 * Append it to the end of known tags. 103 */ 104 list_append(&new_tag->link, &tag_list); 105 106 return new_tag; 107 } 108 109 /** Print debugging information. 110 * If the tag is used for the first time, its structures are automatically 111 * created and initial verbosity level is set to 1. 112 * 113 * @param tagname Tag name. 114 * @param level Level (verbosity) of the message. 115 * @param format Formatting string for printf(). 116 */ 117 void usb_dprintf(const char *tagname, int level, const char *format, ...) 118 { 119 fibril_mutex_lock(&tag_list_guard); 120 usb_debug_tag_t *tag = get_tag(tagname); 121 if (tag == NULL) { 122 printf("USB debug: FATAL ERROR - failed to create tag.\n"); 123 goto leave; 124 } 125 126 if (tag->level < level) { 127 goto leave; 128 } 129 130 va_list args; 131 va_start(args, format); 132 133 printf("[%s:%d]: ", tagname, level); 134 vprintf(format, args); 135 136 va_end(args); 137 138 leave: 139 fibril_mutex_unlock(&tag_list_guard); 140 } 141 142 /** Enable debugging prints for given tag. 143 * 144 * Setting level to <i>n</i> will cause that only printing messages 145 * with level lower or equal to <i>n</i> will be printed. 146 * 147 * @param tagname Tag name. 148 * @param level Enabled level. 149 */ 150 void usb_dprintf_enable(const char *tagname, int level) 151 { 152 fibril_mutex_lock(&tag_list_guard); 153 usb_debug_tag_t *tag = get_tag(tagname); 154 if (tag == NULL) { 155 printf("USB debug: FATAL ERROR - failed to create tag.\n"); 156 goto leave; 157 } 158 159 tag->level = level; 160 161 leave: 162 fibril_mutex_unlock(&tag_list_guard); 163 } 54 164 55 165 /** Enable logging. … … 72 182 } 73 183 74 /** Get log level name prefix. 75 * 76 * @param level Log level. 77 * @return String prefix for the message. 78 */ 184 79 185 static const char *log_level_name(usb_log_level_t level) 80 186 { … … 146 252 } 147 253 148 149 #define REMAINDER_STR_FMT " (%zu)..."150 /* string + terminator + number width (enough for 4GB)*/151 #define REMAINDER_STR_LEN (5 + 1 + 10)152 153 /** How many bytes to group together. */154 #define BUFFER_DUMP_GROUP_SIZE 4155 156 /** Size of the string for buffer dumps. */157 #define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */158 159 /** Fibril local storage for the dumped buffer. */160 static fibril_local char buffer_dump[BUFFER_DUMP_LEN];161 162 /** Dump buffer into string.163 *164 * The function dumps given buffer into hexadecimal format and stores it165 * in a static fibril local string.166 * That means that you do not have to deallocate the string (actually, you167 * can not do that) and you do not have to guard it against concurrent168 * calls to it.169 * The only limitation is that each call rewrites the buffer again.170 * Thus, it is necessary to copy the buffer elsewhere (that includes printing171 * to screen or writing to file).172 * Since this function is expected to be used for debugging prints only,173 * that is not a big limitation.174 *175 * @warning You cannot use this function twice in the same printf176 * (see detailed explanation).177 *178 * @param buffer Buffer to be printed (can be NULL).179 * @param size Size of the buffer in bytes (can be zero).180 * @param dumped_size How many bytes to actually dump (zero means all).181 * @return Dumped buffer as a static (but fibril local) string.182 */183 const char *usb_debug_str_buffer(const uint8_t *buffer, size_t size,184 size_t dumped_size)185 {186 /*187 * Remove previous string (that might also reveal double usage of188 * this function).189 */190 bzero(buffer_dump, BUFFER_DUMP_LEN);191 192 if (buffer == NULL) {193 return "(null)";194 }195 if (size == 0) {196 return "(empty)";197 }198 if ((dumped_size == 0) || (dumped_size > size)) {199 dumped_size = size;200 }201 202 /* How many bytes are available in the output buffer. */203 size_t buffer_remaining_size = BUFFER_DUMP_LEN - 1 - REMAINDER_STR_LEN;204 char *it = buffer_dump;205 206 size_t index = 0;207 208 while (index < size) {209 /* Determine space before the number. */210 const char *space_before;211 if (index == 0) {212 space_before = "";213 } else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {214 space_before = " ";215 } else {216 space_before = " ";217 }218 219 /*220 * Add the byte as a hexadecimal number plus the space.221 * We do it into temporary buffer to ensure that always222 * the whole byte is printed.223 */224 int val = buffer[index];225 char current_byte[16];226 int printed = snprintf(current_byte, 16,227 "%s%02x", space_before, val);228 if (printed < 0) {229 break;230 }231 232 if ((size_t) printed > buffer_remaining_size) {233 break;234 }235 236 /* We can safely add 1, because space for end 0 is reserved. */237 str_append(it, buffer_remaining_size + 1, current_byte);238 239 buffer_remaining_size -= printed;240 /* Point at the terminator 0. */241 it += printed;242 index++;243 244 if (index >= dumped_size) {245 break;246 }247 }248 249 /* Add how many bytes were not printed. */250 if (index < size) {251 snprintf(it, REMAINDER_STR_LEN,252 REMAINDER_STR_FMT, size - index);253 }254 255 return buffer_dump;256 }257 258 259 254 /** 260 255 * @} -
uspace/lib/usb/src/dp.c
r72af8da r3e7b7cd 32 32 /** 33 33 * @file 34 * USB descriptor parser (implementation). 35 * 36 * The descriptor parser is a generic parser for structure, where individual 37 * items are stored in single buffer and each item begins with length followed 38 * by type. These types are organized into tree hierarchy. 39 * 40 * The parser is able of only two actions: find first child and find next 41 * sibling. 34 * @brief USB descriptor parser (implementation). 42 35 */ 43 36 #include <stdio.h> -
uspace/lib/usb/src/dump.c
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * Descriptor dumping.33 * @brief Descriptor dumping. 34 34 */ 35 35 #include <adt/list.h> … … 43 43 #include <usb/classes/hid.h> 44 44 45 /** Mapping between descriptor id and dumping function. */46 45 typedef struct { 47 /** Descriptor id. */48 46 int id; 49 /** Dumping function. */50 47 void (*dump)(FILE *, const char *, const char *, 51 48 const uint8_t *, size_t); … … 69 66 const uint8_t *, size_t); 70 67 71 /** Descriptor dumpers mapping. */72 68 static descriptor_dump_t descriptor_dumpers[] = { 73 69 { USB_DESCTYPE_DEVICE, usb_dump_descriptor_device }, … … 277 273 const uint8_t *descriptor, size_t descriptor_length) 278 274 { 279 /* TODO */280 275 } 281 276 … … 284 279 const uint8_t *descriptor, size_t descriptor_length) 285 280 { 286 /* TODO */287 281 } 288 282 -
uspace/lib/usb/src/hub.c
r72af8da r3e7b7cd 57 57 * 58 58 * @param connection Opened connection to host controller. 59 * @param speed Speed of the device that will respond on the default address.60 59 * @return Error code. 61 60 */ … … 87 86 * 88 87 * @param connection Opened connection to host controller. 89 * @param speed Speed of the new device (device that will be assigned90 * the returned address).91 88 * @return Assigned USB address or negative error code. 92 89 */ … … 147 144 /** Wrapper for registering attached device to the hub. 148 145 * 149 * The @p enable_port function is expected to enable si gnaling on given146 * The @p enable_port function is expected to enable singalling on given 150 147 * port. 151 148 * The two arguments to it can have arbitrary meaning … … 155 152 * 156 153 * If the @p enable_port fails (i.e. does not return EOK), the device 157 * addition is cancel ed.154 * addition is cancelled. 158 155 * The return value is then returned (it is good idea to use different 159 156 * error codes than those listed as return codes by this function itself). 160 157 * 161 * @param [in]parent Parent device (i.e. the hub device).162 * @param [in]connection Opened connection to host controller.163 * @param [in]dev_speed New device speed.164 * @param [in] enable_port Function for enabling signaling through the port the158 * @param parent Parent device (i.e. the hub device). 159 * @param connection Opened connection to host controller. 160 * @param dev_speed New device speed. 161 * @param enable_port Function for enabling signalling through the port the 165 162 * device is attached to. 166 * @param [in]port_no Port number (passed through to @p enable_port).167 * @param [in]arg Any data argument to @p enable_port.163 * @param port_no Port number (passed through to @p enable_port). 164 * @param arg Any data argument to @p enable_port. 168 165 * @param[out] assigned_address USB address of the device. 169 166 * @param[out] assigned_handle Devman handle of the new device. 170 * @param[in] dev_ops Child device ops.171 * @param[in] new_dev_data Arbitrary pointer to be stored in the child172 * as @c driver_data.173 * @param[out] new_fun Storage where pointer to allocated child function174 * will be written.175 167 * @return Error code. 176 168 * @retval ENOENT Connection to HC not opened. … … 209 201 210 202 /* 211 * Enable the port (i.e. allow signal ing through this port).203 * Enable the port (i.e. allow signalling through this port). 212 204 */ 213 205 rc = enable_port(port_no, arg); … … 231 223 rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe, 232 224 &dev_conn); 233 if (rc != EOK) {234 rc = ENOTCONN;235 goto leave_release_default_address;236 }237 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);238 225 if (rc != EOK) { 239 226 rc = ENOTCONN; -
uspace/lib/usb/src/pipes.c
r72af8da r3e7b7cd 99 99 * 100 100 * @param connection Connection structure to be initialized. 101 * @param dev Generic device backing the USB device.101 * @param device Generic device backing the USB device. 102 102 * @return Error code. 103 103 */ -
uspace/lib/usb/src/pipesinit.c
r72af8da r3e7b7cd 37 37 #include <usb/pipes.h> 38 38 #include <usb/dp.h> 39 #include <usb/request.h>40 #include <usbhc_iface.h>41 39 #include <errno.h> 42 40 #include <assert.h> 43 44 #define CTRL_PIPE_MIN_PACKET_SIZE 845 #define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 746 41 47 42 … … 374 369 375 370 int rc = usb_endpoint_pipe_initialize(pipe, connection, 376 0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, 377 USB_DIRECTION_BOTH); 371 0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH); 378 372 379 373 return rc; 380 }381 382 /** Probe default control pipe for max packet size.383 *384 * The function tries to get the correct value of max packet size several385 * time before giving up.386 *387 * The session on the pipe shall not be started.388 *389 * @param pipe Default control pipe.390 * @return Error code.391 */392 int usb_endpoint_pipe_probe_default_control(usb_endpoint_pipe_t *pipe)393 {394 assert(pipe);395 assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);396 397 if ((pipe->direction != USB_DIRECTION_BOTH) ||398 (pipe->transfer_type != USB_TRANSFER_CONTROL) ||399 (pipe->endpoint_no != 0)) {400 return EINVAL;401 }402 403 #define TRY_LOOP(attempt_var) \404 for (attempt_var = 0; attempt_var < 3; attempt_var++)405 406 size_t failed_attempts;407 int rc;408 409 TRY_LOOP(failed_attempts) {410 rc = usb_endpoint_pipe_start_session(pipe);411 if (rc == EOK) {412 break;413 }414 }415 if (rc != EOK) {416 return rc;417 }418 419 420 uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];421 size_t transferred_size;422 TRY_LOOP(failed_attempts) {423 rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,424 USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,425 0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,426 &transferred_size);427 if (rc == EOK) {428 if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {429 rc = ELIMIT;430 continue;431 }432 break;433 }434 }435 usb_endpoint_pipe_end_session(pipe);436 if (rc != EOK) {437 return rc;438 }439 440 pipe->max_packet_size441 = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];442 443 return EOK;444 }445 446 /** Register endpoint with the host controller.447 *448 * @param pipe Pipe to be registered.449 * @param interval Polling interval.450 * @param hc_connection Connection to the host controller (must be opened).451 * @return Error code.452 */453 int usb_endpoint_pipe_register(usb_endpoint_pipe_t *pipe,454 unsigned int interval,455 usb_hc_connection_t *hc_connection)456 {457 assert(pipe);458 assert(hc_connection);459 460 if (!usb_hc_connection_is_opened(hc_connection)) {461 return EBADF;462 }463 464 #define _PACK(high, low) ((high) * 256 + (low))465 466 return async_req_5_0(hc_connection->hc_phone,467 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,468 _PACK(pipe->wire->address, pipe->endpoint_no),469 _PACK(pipe->transfer_type, pipe->direction),470 pipe->max_packet_size, interval);471 472 #undef _PACK473 }474 475 /** Revert endpoint registration with the host controller.476 *477 * @param pipe Pipe to be unregistered.478 * @param hc_connection Connection to the host controller (must be opened).479 * @return Error code.480 */481 int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *pipe,482 usb_hc_connection_t *hc_connection)483 {484 assert(pipe);485 assert(hc_connection);486 487 if (!usb_hc_connection_is_opened(hc_connection)) {488 return EBADF;489 }490 491 return async_req_4_0(hc_connection->hc_phone,492 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT,493 pipe->wire->address, pipe->endpoint_no, pipe->direction);494 374 } 495 375 -
uspace/lib/usb/src/pipesio.c
r72af8da r3e7b7cd 115 115 116 116 if (data_request_rc != EOK) { 117 /* Prefer the return code of the opening request. */ 118 if (opening_request_rc != EOK) { 119 return (int) opening_request_rc; 120 } else { 121 return (int) data_request_rc; 122 } 117 return (int) data_request_rc; 123 118 } 124 119 if (opening_request_rc != EOK) { … … 336 331 337 332 if (data_request_rc != EOK) { 338 /* Prefer the return code of the opening request. */ 339 if (opening_request_rc != EOK) { 340 return (int) opening_request_rc; 341 } else { 342 return (int) data_request_rc; 343 } 333 return (int) data_request_rc; 344 334 } 345 335 if (opening_request_rc != EOK) { -
uspace/lib/usb/src/recognise.c
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * Functions for recognitionof attached devices.33 * @brief Functions for recognising kind of attached devices. 34 34 */ 35 35 #include <sys/types.h> … … 44 44 #include <assert.h> 45 45 46 /** Index to append after device name for uniqueness. */47 46 static size_t device_name_index = 0; 48 /** Mutex guard for device_name_index. */49 47 static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex); 50 48 51 /** DDF operations of child devices. */52 49 ddf_dev_ops_t child_ops = { 53 50 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl 54 51 }; 55 52 56 /** Get integer part from BCD coded number. */57 53 #define BCD_INT(a) (((unsigned int)(a)) / 256) 58 /** Get fraction part from BCD coded number (as an integer, no less). */59 54 #define BCD_FRAC(a) (((unsigned int)(a)) % 256) 60 55 61 /** Format for BCD coded number to be used in printf. */62 56 #define BCD_FMT "%x.%x" 63 /** Arguments to printf for BCD coded number. */64 57 #define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a)) 65 58 … … 120 113 } 121 114 122 /** Add match id to list or return with error code.123 *124 * @param match_ids List of match ids.125 * @param score Match id score.126 * @param format Format of the matching string127 * @param ... Arguments for the format.128 */129 115 #define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \ 130 116 do { \ … … 138 124 /** Create device match ids based on its interface. 139 125 * 140 * @param[in] desc_device Device descriptor. 141 * @param[in] desc_interface Interface descriptor. 126 * @param[in] descriptor Interface descriptor. 142 127 * @param[out] matches Initialized list of match ids. 143 128 * @return Error code (the two mentioned are not the only ones). 144 129 * @retval EINVAL Invalid input parameters (expects non NULL pointers). 145 * @retval ENOENT Device class is not "use interface".130 * @retval ENOENT Interface does not specify class. 146 131 */ 147 132 int usb_device_create_match_ids_from_interface( … … 334 319 * @param[in] parent Parent device. 335 320 * @param[out] child_handle Handle of the child device. 336 * @param[in] dev_ops Child device ops.337 * @param[in] dev_data Arbitrary pointer to be stored in the child338 * as @c driver_data.339 * @param[out] child_fun Storage where pointer to allocated child function340 * will be written.341 321 * @return Error code. 342 322 */ … … 369 349 goto failure; 370 350 } 371 rc = usb_endpoint_pipe_probe_default_control(&ctrl_pipe);372 if (rc != EOK) {373 goto failure;374 }375 351 376 352 /* … … 378 354 * naming etc., something more descriptive could be created. 379 355 */ 380 rc = asprintf(&child_name, "usb%02zu_a%d", 381 this_device_name_index, address); 356 rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index); 382 357 if (rc < 0) { 383 358 goto failure; -
uspace/lib/usb/src/request.c
r72af8da r3e7b7cd 110 110 * (must be in USB endianness). 111 111 * @param data Buffer where to store data accepted during the DATA stage. 112 * (they will come in USB endian ness).112 * (they will come in USB endianess). 113 113 * @param data_size Size of the @p data buffer 114 114 * (in native endianness). … … 161 161 * the new address. 162 162 * 163 * @see usb_drv_reserve_default_address 164 * @see usb_drv_release_default_address 165 * @see usb_drv_request_address 166 * @see usb_drv_release_address 167 * @see usb_drv_bind_address 168 * 163 169 * @param pipe Control endpoint pipe (session must be already started). 164 170 * @param new_address New USB address to be set (in native endianness). … … 195 201 * @param[in] pipe Control endpoint pipe (session must be already started). 196 202 * @param[in] request_type Request type (standard/class/vendor). 197 * @param[in] recipient Request recipient (device/interface/endpoint).198 203 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...). 199 204 * @param[in] descriptor_index Descriptor index. … … 230 235 * @param[in] pipe Control endpoint pipe (session must be already started). 231 236 * @param[in] request_type Request type (standard/class/vendor). 232 * @param[in] recipient Request recipient (device/interface/endpoint).233 237 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...). 234 238 * @param[in] descriptor_index Descriptor index. … … 524 528 return EEMPTY; 525 529 } 526 /* Sub tract first 2 bytes (length and descriptor type). */530 /* Substract first 2 bytes (length and descriptor type). */ 527 531 string_descriptor_size -= 2; 528 532 … … 544 548 size_t i; 545 549 for (i = 0; i < langs_count; i++) { 546 /* Language code from the descriptor is in USB endian ness. */550 /* Language code from the descriptor is in USB endianess. */ 547 551 /* FIXME: is this really correct? */ 548 552 uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8) … … 565 569 * 566 570 * @param[in] pipe Control endpoint pipe (session must be already started). 567 * @param[in] index String index (in native endian ness),571 * @param[in] index String index (in native endianess), 568 572 * first index has number 1 (index from descriptors can be used directly). 569 * @param[in] lang String language (in native endian ness).573 * @param[in] lang String language (in native endianess). 570 574 * @param[out] string_ptr Where to store allocated string in native encoding. 571 575 * @return Error code. … … 609 613 goto leave; 610 614 } 611 /* Sub tract first 2 bytes (length and descriptor type). */615 /* Substract first 2 bytes (length and descriptor type). */ 612 616 string_size -= 2; 613 617 -
uspace/lib/usb/src/usb.c
r72af8da r3e7b7cd 31 31 */ 32 32 /** @file 33 * Common USB functions.33 * @brief Base USB types. 34 34 */ 35 35 #include <usb/usb.h> … … 37 37 38 38 39 /** String representation for USB transfer type. 40 * 41 * @param t Transfer type. 42 * @return Transfer type as a string (in English). 43 */ 39 /** String representation for USB transfer type. */ 44 40 const char * usb_str_transfer_type(usb_transfer_type_t t) 45 41 { -
uspace/srv/hw/irc/apic/apic.c
r72af8da r3e7b7cd 54 54 #define NAME "apic" 55 55 56 static bool apic_found = false;57 58 56 static int apic_enable_irq(sysarg_t irq) 59 57 { … … 81 79 callid = async_get_call(&call); 82 80 83 sysarg_t method = IPC_GET_IMETHOD(call); 84 if (method == IPC_M_PHONE_HUNGUP) { 85 return; 86 } 87 88 if (!apic_found) { 89 async_answer_0(callid, ENOTSUP); 90 break; 91 } 92 93 switch (method) { 81 switch (IPC_GET_IMETHOD(call)) { 94 82 case IRC_ENABLE_INTERRUPT: 95 83 async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call))); … … 109 97 * 110 98 */ 111 static voidapic_init(void)99 static bool apic_init(void) 112 100 { 113 101 sysarg_t apic; 114 102 115 apic_found = sysinfo_get_value("apic", &apic) && apic;116 if (!apic_found) {117 printf(NAME ": Warning: no APIC found\n");103 if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) { 104 printf(NAME ": No APIC found\n"); 105 return false; 118 106 } 119 107 120 108 async_set_client_connection(apic_connection); 121 109 service_register(SERVICE_APIC); 110 111 return true; 122 112 } 123 113 … … 126 116 printf(NAME ": HelenOS APIC driver\n"); 127 117 128 apic_init(); 129 118 if (!apic_init()) 119 return -1; 120 130 121 printf(NAME ": Accepting connections\n"); 131 122 async_manager();
Note:
See TracChangeset
for help on using the changeset viewer.
