Changes in / [4069f5c:27eddb52] in mainline
- Files:
-
- 4 added
- 7 deleted
- 47 edited
Legend:
- Unmodified
- Added
- Removed
-
HelenOS.config
r4069f5c r27eddb52 573 573 ! CONFIG_RUN_VIRTUAL_USB_HC (n/y) 574 574 575 % OHCI root hub port power switching 576 @ "no" All root hub ports are always powered. 577 @ "ganged" Root hub ports are all powered or all off. 578 @ "per_port" Powered status of every root hub port is independent. 579 ![PLATFORM=ia32|PLATFORM=amd64] OHCI_POWER_SWITCH (choice) 575 % Polling UHCI & OHCI (no interrupts) 576 ! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_USBHC_NO_INTERRUPTS (n/y) 577 -
defaults/amd64/Makefile.config
r4069f5c r27eddb52 65 65 CONFIG_MOUNT_DATA = n 66 66 67 # OHCI root hub power switch, ganged is enough68 OHCI_POWER_SWITCH = ganged -
defaults/ia32/Makefile.config
r4069f5c r27eddb52 71 71 CONFIG_MOUNT_DATA = n 72 72 73 # OHCI root hub power switch, ganged is enough74 OHCI_POWER_SWITCH = ganged -
uspace/app/bdsh/Makefile
r4069f5c r27eddb52 54 54 cmds/mod_cmds.c \ 55 55 cmds/builtin_cmds.c \ 56 compl.c \57 56 errors.c \ 58 57 input.c \ -
uspace/app/bdsh/config.h
r4069f5c r27eddb52 40 40 #endif 41 41 42 /* Work around for getenv() */ 43 #define PATH "/srv:/app" 44 #define PATH_DELIM ":" 45 42 46 /* Used in many places */ 43 47 #define SMALL_BUFLEN 256 -
uspace/app/bdsh/exec.c
r4069f5c r27eddb52 52 52 static int try_access(const char *); 53 53 54 const char *search_dir[] = { "app", "srv", NULL };55 56 54 /* work-around for access() */ 57 55 static int try_access(const char *f) … … 71 69 static char *find_command(char *cmd) 72 70 { 73 size_t i; 71 char *path_tok; 72 char *path[PATH_MAX]; 73 int n = 0, i = 0; 74 size_t x = str_size(cmd) + 2; 74 75 75 76 found = (char *)malloc(PATH_MAX); … … 80 81 } 81 82 83 path_tok = str_dup(PATH); 84 85 /* Extract the PATH env to a path[] array */ 86 path[n] = strtok(path_tok, PATH_DELIM); 87 while (NULL != path[n]) { 88 if ((str_size(path[n]) + x ) > PATH_MAX) { 89 cli_error(CL_ENOTSUP, 90 "Segment %d of path is too large, search ends at segment %d", 91 n, n-1); 92 break; 93 } 94 path[++n] = strtok(NULL, PATH_DELIM); 95 } 96 82 97 /* We now have n places to look for the command */ 83 for (i = 0; search_dir[i] != NULL; i++) {98 for (i=0; path[i]; i++) { 84 99 memset(found, 0, sizeof(found)); 85 snprintf(found, PATH_MAX, "%s/%s", search_dir[i], cmd);100 snprintf(found, PATH_MAX, "%s/%s", path[i], cmd); 86 101 if (-1 != try_access(found)) { 102 free(path_tok); 87 103 return (char *) found; 88 104 } … … 90 106 91 107 /* We didn't find it, just give it back as-is. */ 108 free(path_tok); 92 109 return (char *) cmd; 93 110 } -
uspace/app/bdsh/exec.h
r4069f5c r27eddb52 33 33 #include "scli.h" 34 34 35 extern const char *search_dir[];36 37 35 extern unsigned int try_exec(char *, char **, iostate_t *); 38 36 -
uspace/app/bdsh/input.c
r4069f5c r27eddb52 1 1 /* 2 2 * Copyright (c) 2008 Tim Post 3 * Copyright (c) 2011 Jiri Svoboda4 3 * All rights reserved. 5 4 * … … 44 43 45 44 #include "config.h" 46 #include "compl.h"47 45 #include "util.h" 48 46 #include "scli.h" … … 228 226 int rc; 229 227 230 tinput_set_prompt(tinput, usr->prompt); 228 console_flush(tinput->console); 229 console_set_style(tinput->console, STYLE_EMPHASIS); 230 printf("%s", usr->prompt); 231 console_flush(tinput->console); 232 console_set_style(tinput->console, STYLE_NORMAL); 231 233 232 234 rc = tinput_read(tinput, &str); … … 261 263 } 262 264 263 tinput_set_compl_ops(tinput, &compl_ops);264 265 265 return 0; 266 266 } -
uspace/app/bdsh/scli.h
r4069f5c r27eddb52 32 32 #include "config.h" 33 33 #include <stdint.h> 34 #include <stdio.h>35 34 36 35 typedef struct { -
uspace/app/sbi/src/input.c
r4069f5c r27eddb52 176 176 int input_get_line(input_t *input, char **line) 177 177 { 178 const char *prompt;179 178 const char *sp; 180 179 char *dp; … … 213 212 /* Interactive mode */ 214 213 if (input->line_no == 0) 215 pr ompt = "sbi> ";214 printf("sbi> "); 216 215 else 217 pr ompt = "... ";216 printf("... "); 218 217 219 218 fflush(stdout); 220 if (os_input_line( prompt,&line_p) != EOK)219 if (os_input_line(&line_p) != EOK) 221 220 return EIO; 222 221 -
uspace/app/sbi/src/os/helenos.c
r4069f5c r27eddb52 210 210 * @param ptr Place to store pointer to new string. 211 211 */ 212 int os_input_line(c onst char *prompt, char **ptr)212 int os_input_line(char **ptr) 213 213 { 214 214 char *line; … … 219 219 if (tinput == NULL) 220 220 return EIO; 221 222 tinput_set_prompt(tinput, prompt);223 221 } 224 222 -
uspace/app/sbi/src/os/os.h
r4069f5c r27eddb52 38 38 char *os_chr_to_astr(wchar_t chr); 39 39 void os_input_disp_help(void); 40 int os_input_line(c onst char *prompt, char **ptr);40 int os_input_line(char **ptr); 41 41 int os_exec(char * const cmd[]); 42 42 -
uspace/app/sbi/src/os/posix.c
r4069f5c r27eddb52 193 193 * @param ptr Place to store pointer to new string. 194 194 */ 195 int os_input_line(const char *prompt, char **ptr) 196 { 197 printf("%s", prompt); 198 195 int os_input_line(char **ptr) 196 { 199 197 if (fgets(os_input_buffer, OS_INPUT_BUFFER_SIZE, stdin) == NULL) 200 198 os_input_buffer[0] = '\0'; -
uspace/drv/bus/isa/isa.c
r4069f5c r27eddb52 352 352 str_error(rc)); 353 353 } 354 355 free(id);356 354 } 357 355 -
uspace/drv/bus/pci/pciintel/pci.c
r4069f5c r27eddb52 342 342 } 343 343 344 free(match_id_str);345 346 344 /* TODO add more ids (with subsys ids, using class id etc.) */ 347 345 } -
uspace/drv/bus/usb/ohci/hc.c
r4069f5c r27eddb52 46 46 #define OHCI_USED_INTERRUPTS \ 47 47 (I_SO | I_WDH | I_UE | I_RHSC) 48 49 static const irq_cmd_t ohci_irq_commands[] = 50 { 51 { .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ }, 52 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS }, 53 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 }, 54 { .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ }, 55 { .cmd = CMD_ACCEPT }, 56 }; 57 48 static int interrupt_emulator(hc_t *instance); 58 49 static void hc_gain_control(hc_t *instance); 59 static void hc_start(hc_t *instance);60 50 static int hc_init_transfer_lists(hc_t *instance); 61 51 static int hc_init_memory(hc_t *instance); 62 static int interrupt_emulator(hc_t *instance);63 64 /*----------------------------------------------------------------------------*/65 /** Get number of commands used in IRQ code.66 * @return Number of commands.67 */68 size_t hc_irq_cmd_count(void)69 {70 return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);71 }72 /*----------------------------------------------------------------------------*/73 /** Generate IRQ code commands.74 * @param[out] cmds Place to store the commands.75 * @param[in] cmd_size Size of the place (bytes).76 * @param[in] regs Physical address of device's registers.77 * @param[in] reg_size Size of the register area (bytes).78 *79 * @return Error code.80 */81 int hc_get_irq_commands(82 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)83 {84 if (cmd_size < sizeof(ohci_irq_commands)85 || reg_size < sizeof(ohci_regs_t))86 return EOVERFLOW;87 88 /* Create register mapping to use in IRQ handler.89 * This mapping should be present in kernel only.90 * Remove it from here when kernel knows how to create mappings91 * and accepts physical addresses in IRQ code.92 * TODO: remove */93 ohci_regs_t *registers;94 const int ret = pio_enable((void*)regs, reg_size, (void**)®isters);95 if (ret != EOK)96 return ret;97 98 /* Some bogus access to force create mapping. DO NOT remove,99 * unless whole virtual addresses in irq is replaced100 * NOTE: Compiler won't remove this as ohci_regs_t members101 * are declared volatile.102 *103 * Introducing CMD_MEM set of IRQ code commands broke104 * assumption that IRQ code does not cause page faults.105 * If this happens during idling (THREAD == NULL)106 * it causes kernel panic.107 */108 registers->revision;109 110 memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));111 112 void *address = (void*)®isters->interrupt_status;113 cmds[0].addr = address;114 cmds[3].addr = address;115 return EOK;116 }117 52 /*----------------------------------------------------------------------------*/ 118 53 /** Announce OHCI root hub to the DDF … … 148 83 int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL, 149 84 USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0); 150 CHECK_RET_RELEASE(ret, 151 "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret)); 152 153 ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100); 154 CHECK_RET_RELEASE(ret, 155 "Failed to add root hub match-id: %s.\n", str_error(ret)); 85 CHECK_RET_RELEASE(ret, "Failed(%d) to add OHCI rh endpoint 0.\n", ret); 86 87 char *match_str = NULL; 88 /* DDF needs heap allocated string */ 89 ret = asprintf(&match_str, "usb&class=hub"); 90 ret = ret > 0 ? 0 : ret; 91 CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret); 92 93 ret = ddf_fun_add_match_id(hub_fun, match_str, 100); 94 CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret); 156 95 157 96 ret = ddf_fun_bind(hub_fun); 158 CHECK_RET_RELEASE(ret, 159 "Failed to bind root hub function: %s.\n", str_error(ret)); 97 CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret); 160 98 161 99 return EOK; … … 174 112 { 175 113 assert(instance); 176 114 int ret = EOK; 177 115 #define CHECK_RET_RETURN(ret, message...) \ 178 116 if (ret != EOK) { \ … … 181 119 } else (void)0 182 120 183 int ret = 184 pio_enable((void*)regs, reg_size, (void**)&instance->registers); 121 ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers); 185 122 CHECK_RET_RETURN(ret, 186 "Failed to gain access to device registers: %s.\n", str_error(ret)); 123 "Failed(%d) to gain access to device registers: %s.\n", 124 ret, str_error(ret)); 187 125 188 126 list_initialize(&instance->pending_batches); 189 127 usb_device_keeper_init(&instance->manager); 190 191 128 ret = usb_endpoint_manager_init(&instance->ep_manager, 192 129 BANDWIDTH_AVAILABLE_USB11); … … 200 137 201 138 fibril_mutex_initialize(&instance->guard); 202 203 139 hc_gain_control(instance); 140 141 rh_init(&instance->rh, instance->registers); 204 142 205 143 if (!interrupts) { … … 209 147 } 210 148 211 rh_init(&instance->rh, instance->registers);212 hc_start(instance);213 214 149 return EOK; 215 150 } 216 151 /*----------------------------------------------------------------------------*/ 217 /** Create and register endpoint structures.152 /** Create end register endpoint structures 218 153 * 219 154 * @param[in] instance OHCI driver structure. … … 233 168 size_t mps, size_t size, unsigned interval) 234 169 { 235 endpoint_t *ep = 236 endpoint_get(address, endpoint, direction, type, speed, mps); 170 endpoint_t *ep = malloc(sizeof(endpoint_t)); 237 171 if (ep == NULL) 238 172 return ENOMEM; 173 int ret = 174 endpoint_init(ep, address, endpoint, direction, type, speed, mps); 175 if (ret != EOK) { 176 free(ep); 177 return ret; 178 } 239 179 240 180 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); … … 244 184 } 245 185 246 int ret = 247 usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 186 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 248 187 if (ret != EOK) { 249 188 hcd_endpoint_clear(ep); … … 273 212 &instance->lists[ep->transfer_type], hcd_ep); 274 213 instance->registers->control |= C_PLE | C_IE; 214 break; 215 default: 275 216 break; 276 217 } … … 371 312 /* Check for root hub communication */ 372 313 if (batch->ep->address == instance->rh.address) { 373 rh_request(&instance->rh, batch); 374 return EOK; 314 return rh_request(&instance->rh, batch); 375 315 } 376 316 … … 434 374 435 375 if (status & I_UE) { 436 hc_start (instance);376 hc_start_hw(instance); 437 377 } 438 378 … … 459 399 /** Turn off any (BIOS)driver that might be in control of the device. 460 400 * 461 * This function implements routines described in chapter 5.1.1.3 of the OHCI462 * specification (page 40, pdf page 54).463 *464 401 * @param[in] instance OHCI hc driver structure. 465 402 */ … … 467 404 { 468 405 assert(instance); 469 470 406 usb_log_debug("Requesting OHCI control.\n"); 471 if (instance->registers->revision & R_LEGACY_FLAG) { 472 /* Turn off legacy emulation, it should be enough to zero 473 * the lowest bit, but it caused problems. Thus clear all 474 * except GateA20 (causes restart on some hw). 475 * See page 145 of the specs for details. 476 */ 477 volatile uint32_t *ohci_emulation_reg = 478 (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET); 479 usb_log_debug("OHCI legacy register %p: %x.\n", 480 ohci_emulation_reg, *ohci_emulation_reg); 481 /* Zero everything but A20State */ 482 *ohci_emulation_reg &= 0x100; 483 usb_log_debug( 484 "OHCI legacy register (should be 0 or 0x100) %p: %x.\n", 485 ohci_emulation_reg, *ohci_emulation_reg); 486 } 407 /* Turn off legacy emulation */ 408 volatile uint32_t *ohci_emulation_reg = 409 (uint32_t*)((char*)instance->registers + 0x100); 410 usb_log_debug("OHCI legacy register %p: %x.\n", 411 ohci_emulation_reg, *ohci_emulation_reg); 412 /* Do not change A20 state */ 413 *ohci_emulation_reg &= 0x100; 414 usb_log_debug("OHCI legacy register %p: %x.\n", 415 ohci_emulation_reg, *ohci_emulation_reg); 487 416 488 417 /* Interrupt routing enabled => smm driver is active */ … … 490 419 usb_log_debug("SMM driver: request ownership change.\n"); 491 420 instance->registers->command_status |= CS_OCR; 492 /* Hope that SMM actually knows its stuff or we can hang here */493 421 while (instance->registers->control & C_IR) { 494 422 async_usleep(1000); 495 423 } 496 424 usb_log_info("SMM driver: Ownership taken.\n"); 497 C_HCFS_SET(instance->registers->control, C_HCFS_RESET);425 instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT); 498 426 async_usleep(50000); 499 427 return; 500 428 } 501 429 502 const unsigned hc_status = C_HCFS_GET(instance->registers->control); 430 const unsigned hc_status = 431 (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK; 503 432 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 504 433 if (hc_status != C_HCFS_RESET) { … … 508 437 return; 509 438 } 510 /* HC is suspended assert resume for 20ms ,*/511 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);439 /* HC is suspended assert resume for 20ms */ 440 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT); 512 441 async_usleep(20000); 513 442 usb_log_info("BIOS driver: HC resumed.\n"); … … 525 454 * @param[in] instance OHCI hc driver structure. 526 455 */ 527 void hc_start (hc_t *instance)456 void hc_start_hw(hc_t *instance) 528 457 { 529 458 /* OHCI guide page 42 */ … … 587 516 instance->registers->periodic_start, frame_length); 588 517 589 C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);518 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT); 590 519 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 591 520 instance->registers->control); … … 605 534 int ret = endpoint_list_init(&instance->lists[type], name); \ 606 535 if (ret != EOK) { \ 607 usb_log_error("Failed to setup %s endpoint list: %s.\n", \608 name, str_error(ret)); \536 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 537 ret, name); \ 609 538 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\ 610 539 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \ … … 658 587 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 659 588 589 /* Init interrupt code */ 590 instance->interrupt_code.cmds = instance->interrupt_commands; 591 instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS; 592 { 593 /* Read status register */ 594 instance->interrupt_commands[0].cmd = CMD_MEM_READ_32; 595 instance->interrupt_commands[0].dstarg = 1; 596 instance->interrupt_commands[0].addr = 597 (void*)&instance->registers->interrupt_status; 598 599 /* Test whether we are the interrupt cause */ 600 instance->interrupt_commands[1].cmd = CMD_BTEST; 601 instance->interrupt_commands[1].value = 602 OHCI_USED_INTERRUPTS; 603 instance->interrupt_commands[1].srcarg = 1; 604 instance->interrupt_commands[1].dstarg = 2; 605 606 /* Predicate cleaning and accepting */ 607 instance->interrupt_commands[2].cmd = CMD_PREDICATE; 608 instance->interrupt_commands[2].value = 2; 609 instance->interrupt_commands[2].srcarg = 2; 610 611 /* Write-clean status register */ 612 instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32; 613 instance->interrupt_commands[3].srcarg = 1; 614 instance->interrupt_commands[3].addr = 615 (void*)&instance->registers->interrupt_status; 616 617 /* Accept interrupt */ 618 instance->interrupt_commands[4].cmd = CMD_ACCEPT; 619 } 620 660 621 return EOK; 661 622 } 662 663 623 /** 664 624 * @} -
uspace/drv/bus/usb/ohci/hc.h
r4069f5c r27eddb52 51 51 #include "hw_struct/hcca.h" 52 52 53 /** Main OHCI driver structure */ 53 #define OHCI_NEEDED_IRQ_COMMANDS 5 54 55 /** Main OHCI drier structure */ 54 56 typedef struct hc { 55 57 /** USB bus driver, devices and addresses */ … … 74 76 fibril_mutex_t guard; 75 77 78 /** Code to be executed in kernel interrupt handler */ 79 irq_code_t interrupt_code; 80 81 /** Commands that form interrupt code */ 82 irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS]; 83 76 84 /** USB hub emulation structure */ 77 85 rh_t rh; 78 86 } hc_t; 79 87 80 size_t hc_irq_cmd_count(void); 81 int hc_get_irq_commands( 82 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size); 88 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun); 83 89 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts); 84 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);90 void hc_start_hw(hc_t *instance); 85 91 86 92 /** Safely dispose host controller internal structures -
uspace/drv/bus/usb/ohci/ohci.c
r4069f5c r27eddb52 58 58 { 59 59 assert(dev); 60 assert(dev->driver_data); 60 61 return dev->driver_data; 61 62 } 63 62 64 /** IRQ handling callback, identifies device 63 65 * … … 68 70 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 69 71 { 70 assert(dev); 71 72 ohci_t *ohci = dev_to_ohci(dev); 73 if (!ohci) { 74 usb_log_warning("Interrupt on device that is not ready.\n"); 75 return; 76 } 72 hc_t *hc = &dev_to_ohci(dev)->hc; 73 assert(hc); 77 74 const uint16_t status = IPC_GET_ARG1(*call); 78 hc_interrupt( &ohci->hc, status);75 hc_interrupt(hc, status); 79 76 } 80 77 /*----------------------------------------------------------------------------*/ … … 169 166 } \ 170 167 free(instance); \ 171 device->driver_data = NULL; \172 168 usb_log_error(message); \ 173 169 return ret; \ … … 177 173 instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc"); 178 174 int ret = instance->hc_fun ? EOK : ENOMEM; 179 CHECK_RET_DEST_FREE_RETURN(ret, 180 "Failed to create OHCI HC function: %s.\n", str_error(ret)); 175 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n"); 181 176 instance->hc_fun->ops = &hc_ops; 182 177 instance->hc_fun->driver_data = &instance->hc; … … 184 179 instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh"); 185 180 ret = instance->rh_fun ? EOK : ENOMEM; 186 CHECK_RET_DEST_FREE_RETURN(ret, 187 "Failed to create OHCI RH function: %s.\n", str_error(ret)); 181 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n"); 188 182 instance->rh_fun->ops = &rh_ops; 189 183 … … 199 193 (void *) reg_base, reg_size, irq); 200 194 201 const size_t cmd_count = hc_irq_cmd_count();202 irq_cmd_t irq_cmds[cmd_count];203 ret =204 hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);205 CHECK_RET_DEST_FREE_RETURN(ret,206 "Failed to generate IRQ commands: %s.\n", str_error(ret));207 208 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };209 210 /* Register handler to avoid interrupt lockup */211 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);212 CHECK_RET_DEST_FREE_RETURN(ret,213 "Failed to register interrupt handler: %s.\n", str_error(ret));214 215 /* Try to enable interrupts */216 195 bool interrupts = false; 196 #ifdef CONFIG_USBHC_NO_INTERRUPTS 197 usb_log_warning("Interrupts disabled in OS config, " 198 "falling back to polling.\n"); 199 #else 217 200 ret = pci_enable_interrupts(device); 218 201 if (ret != EOK) { 219 usb_log_warning("Failed to enable interrupts: %s. "220 " Falling back to polling\n",str_error(ret));221 /* We don't need that handler */222 unregister_interrupt_handler(device, irq);202 usb_log_warning("Failed to enable interrupts: %s.\n", 203 str_error(ret)); 204 usb_log_info("HW interrupts not available, " 205 "falling back to polling.\n"); 223 206 } else { 224 207 usb_log_debug("Hw interrupts enabled.\n"); 225 208 interrupts = true; 226 209 } 210 #endif 227 211 228 212 ret = hc_init(&instance->hc, reg_base, reg_size, interrupts); 229 CHECK_RET_DEST_FREE_RETURN(ret, 230 "Failed to init ohci_hcd: %s.\n", str_error(ret)); 231 232 device->driver_data = instance; 213 CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret); 233 214 234 215 #define CHECK_RET_FINI_RETURN(ret, message...) \ 235 216 if (ret != EOK) { \ 236 unregister_interrupt_handler(device, irq); \237 217 hc_fini(&instance->hc); \ 238 218 CHECK_RET_DEST_FREE_RETURN(ret, message); \ 239 219 } else (void)0 240 220 221 /* It does no harm if we register this on polling */ 222 ret = register_interrupt_handler(device, irq, irq_handler, 223 &instance->hc.interrupt_code); 224 CHECK_RET_FINI_RETURN(ret, 225 "Failed(%d) to register interrupt handler.\n", ret); 241 226 242 227 ret = ddf_fun_bind(instance->hc_fun); 243 228 CHECK_RET_FINI_RETURN(ret, 244 "Failed to bind OHCI device function: %s.\n", str_error(ret)); 229 "Failed(%d) to bind OHCI device function: %s.\n", 230 ret, str_error(ret)); 245 231 246 232 ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME); … … 248 234 "Failed to add OHCI to HC class: %s.\n", str_error(ret)); 249 235 236 device->driver_data = instance; 237 238 hc_start_hw(&instance->hc); 250 239 hc_register_hub(&instance->hc, instance->rh_fun); 251 240 return EOK; -
uspace/drv/bus/usb/ohci/ohci_regs.h
r4069f5c r27eddb52 34 34 #ifndef DRV_OHCI_OHCI_REGS_H 35 35 #define DRV_OHCI_OHCI_REGS_H 36 #include <sys/types.h> 37 38 #define LEGACY_REGS_OFFSET 0x100 36 #include <stdint.h> 39 37 40 38 /** OHCI memory mapped registers structure */ 41 39 typedef struct ohci_regs { 42 const ioport32_t revision; 43 #define R_REVISION_MASK (0x3f) 44 #define R_REVISION_SHIFT (0) 45 #define R_LEGACY_FLAG (0x80) 46 47 ioport32_t control; 48 #define C_CBSR_MASK (0x3) /* Control-bulk service ratio */ 49 #define C_CBSR_1_1 (0x0) 50 #define C_CBSR_1_2 (0x1) 51 #define C_CBSR_1_3 (0x2) 52 #define C_CBSR_1_4 (0x3) 53 #define C_CBSR_SHIFT (0) 40 const volatile uint32_t revision; 41 volatile uint32_t control; 42 #define C_CSBR_MASK (0x3) /* Control-bulk service ratio */ 43 #define C_CSBR_1_1 (0x0) 44 #define C_CSBR_1_2 (0x1) 45 #define C_CSBR_1_3 (0x2) 46 #define C_CSBR_1_4 (0x3) 47 #define C_CSBR_SHIFT (0) 54 48 55 49 #define C_PLE (1 << 2) /* Periodic list enable */ … … 65 59 #define C_HCFS_SHIFT (6) 66 60 67 #define C_HCFS_GET(reg) \68 ((reg >> C_HCFS_SHIFT) & C_HCFS_MASK)69 #define C_HCFS_SET(reg, hcfs_state) \70 do { \71 reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \72 | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \73 } while (0)74 75 76 61 #define C_IR (1 << 8) /* Interrupt routing, make sure it's 0 */ 77 62 #define C_RWC (1 << 9) /* Remote wakeup connected, host specific */ 78 63 #define C_RWE (1 << 10) /* Remote wakeup enable */ 79 64 80 ioport32_t command_status;65 volatile uint32_t command_status; 81 66 #define CS_HCR (1 << 0) /* Host controller reset */ 82 67 #define CS_CLF (1 << 1) /* Control list filled */ … … 90 75 * writing causes enable/disable, 91 76 * status is write-clean (writing 1 clears the bit*/ 92 ioport32_t interrupt_status;93 ioport32_t interrupt_enable;94 ioport32_t interrupt_disable;77 volatile uint32_t interrupt_status; 78 volatile uint32_t interrupt_enable; 79 volatile uint32_t interrupt_disable; 95 80 #define I_SO (1 << 0) /* Scheduling overrun */ 96 81 #define I_WDH (1 << 1) /* Done head write-back */ … … 104 89 105 90 /** HCCA pointer (see hw_struct hcca.h) */ 106 ioport32_t hcca;91 volatile uint32_t hcca; 107 92 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */ 108 93 109 94 /** Currently executed periodic endpoint */ 110 const ioport32_t periodic_current;95 const volatile uint32_t periodic_current; 111 96 112 97 /** The first control endpoint */ 113 ioport32_t control_head;98 volatile uint32_t control_head; 114 99 115 100 /** Currently executed control endpoint */ 116 ioport32_t control_current;101 volatile uint32_t control_current; 117 102 118 103 /** The first bulk endpoint */ 119 ioport32_t bulk_head;104 volatile uint32_t bulk_head; 120 105 121 106 /** Currently executed bulk endpoint */ 122 ioport32_t bulk_current;107 volatile uint32_t bulk_current; 123 108 124 109 /** Done TD list, this value is periodically written to HCCA */ 125 const ioport32_t done_head;110 const volatile uint32_t done_head; 126 111 127 112 /** Frame time and max packet size for all transfers */ 128 ioport32_t fm_interval;113 volatile uint32_t fm_interval; 129 114 #define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/ 130 115 #define FMI_FI_SHIFT (0) … … 134 119 135 120 /** Bit times remaining in current frame */ 136 const ioport32_t fm_remaining;121 const volatile uint32_t fm_remaining; 137 122 #define FMR_FR_MASK FMI_FI_MASK 138 123 #define FMR_FR_SHIFT FMI_FI_SHIFT … … 140 125 141 126 /** Frame number */ 142 const ioport32_t fm_number;127 const volatile uint32_t fm_number; 143 128 #define FMN_NUMBER_MASK (0xffff) 144 129 145 130 /** Remaining bit time in frame to start periodic transfers */ 146 ioport32_t periodic_start;131 volatile uint32_t periodic_start; 147 132 #define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */ 148 133 149 134 /** Threshold for starting LS transaction */ 150 ioport32_t ls_threshold;135 volatile uint32_t ls_threshold; 151 136 #define LST_LST_MASK (0x7fff) 152 137 153 138 /** The first root hub control register */ 154 ioport32_t rh_desc_a;139 volatile uint32_t rh_desc_a; 155 140 #define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */ 156 141 #define RHDA_NDS_SHIFT (0) … … 159 144 #define RHDA_DT_FLAG (1 << 10) /* 1-Compound device, must be 0 */ 160 145 #define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */ 161 #define RHDA_NOCP _FLAG(1 << 12) /* OC control: 0-use OCPM, 1-OC off */146 #define RHDA_NOCP (1 << 12) /* OC control: 0-use OCPM, 1-OC off */ 162 147 #define RHDA_POTPGT_MASK (0xff) /* Power on to power good time */ 163 148 #define RHDA_POTPGT_SHIFT (24) 164 149 165 150 /** The other root hub control register */ 166 ioport32_t rh_desc_b;151 volatile uint32_t rh_desc_b; 167 152 #define RHDB_DR_MASK (0xffff) /* Device removable mask */ 168 153 #define RHDB_DR_SHIFT (0) … … 176 161 177 162 /** Root hub status register */ 178 ioport32_t rh_status;163 volatile uint32_t rh_status; 179 164 #define RHS_LPS_FLAG (1 << 0)/* read: 0, 180 165 * write: 0-no effect, … … 182 167 * specified in PPCM(RHDB), or all ports, 183 168 * if power is set globally */ 184 #define RHS_CLEAR_ GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */169 #define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */ 185 170 #define RHS_OCI_FLAG (1 << 1)/* Over-current indicator, if per-port: 0 */ 186 171 #define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC … … 193 178 * specified in PPCM(RHDB), or all ports, 194 179 * if power is set globally */ 195 #define RHS_SET_ GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */180 #define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */ 196 181 #define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change */ 197 182 #define RHS_CLEAR_DRWE (1 << 31) 198 183 199 184 /** Root hub per port status */ 200 ioport32_t rh_port_status[];185 volatile uint32_t rh_port_status[]; 201 186 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status, 202 187 * w: 1-clear port enable, 0-nothing */ -
uspace/drv/bus/usb/ohci/root_hub.c
r4069f5c r27eddb52 40 40 #include "root_hub.h" 41 41 #include <usb/classes/classes.h> 42 #include <usb/classes/hub.h>43 42 #include <usb/dev/driver.h> 44 43 #include "ohci_regs.h" … … 57 56 .device_subclass = 0, 58 57 .device_version = 0, 59 .length = sizeof (usb_standard_device_descriptor_t),60 .max_packet_size = 64,61 .vendor_id = 0x16db, /* HelenOS does not have USB vendor ID assigned.*/58 .length = sizeof (usb_standard_device_descriptor_t), 59 .max_packet_size = 8, 60 .vendor_id = 0x16db, 62 61 .product_id = 0x0001, 63 62 .str_serial_number = 0, … … 74 73 .descriptor_type = USB_DESCTYPE_CONFIGURATION, 75 74 .interface_count = 1, 76 .length = sizeof (usb_standard_configuration_descriptor_t),77 .max_power = 0, /* root hubs don't need no power */75 .length = sizeof (usb_standard_configuration_descriptor_t), 76 .max_power = 100, 78 77 .str_configuration = 0, 79 78 }; … … 90 89 .interface_protocol = 0, 91 90 .interface_subclass = 0, 92 .length = sizeof (usb_standard_interface_descriptor_t),91 .length = sizeof (usb_standard_interface_descriptor_t), 93 92 .str_interface = 0, 94 93 }; … … 101 100 .descriptor_type = USB_DESCTYPE_ENDPOINT, 102 101 .endpoint_address = 1 + (1 << 7), 103 .length = sizeof (usb_standard_endpoint_descriptor_t),104 .max_packet_size = 2,102 .length = sizeof (usb_standard_endpoint_descriptor_t), 103 .max_packet_size = 8, 105 104 .poll_interval = 255, 106 105 }; 107 106 108 static void create_serialized_hub_descriptor(rh_t *instance); 109 static void rh_init_descriptors(rh_t *instance); 110 static uint16_t create_interrupt_mask(rh_t *instance); 111 static int get_status(rh_t *instance, usb_transfer_batch_t *request); 112 static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request); 113 static int set_feature(rh_t *instance, usb_transfer_batch_t *request); 114 static int clear_feature(rh_t *instance, usb_transfer_batch_t *request); 115 static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port); 116 static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port); 117 static int control_request(rh_t *instance, usb_transfer_batch_t *request); 118 static inline void interrupt_request( 119 usb_transfer_batch_t *request, uint16_t mask, size_t size) 120 { 121 assert(request); 122 123 memcpy(request->data_buffer, &mask, size); 124 request->transfered_size = size; 125 usb_transfer_batch_finish_error(request, EOK); 126 } 127 128 #define TRANSFER_OK(bytes) \ 129 do { \ 130 request->transfered_size = bytes; \ 131 return EOK; \ 132 } while (0) 133 134 /** Root Hub driver structure initialization. 135 * 136 * Reads info registers and prepares descriptors. Sets power mode. 137 */ 138 void rh_init(rh_t *instance, ohci_regs_t *regs) 139 { 107 /** 108 * bitmask of hub features that are valid to be cleared 109 */ 110 static const uint32_t hub_clear_feature_valid_mask = 111 RHS_OCIC_FLAG | 112 RHS_CLEAR_PORT_POWER; 113 114 /** 115 * bitmask of hub features that are cleared by writing 1 (and not 0) 116 */ 117 static const uint32_t hub_clear_feature_by_writing_one_mask = 118 RHS_CLEAR_PORT_POWER; 119 120 /** 121 * bitmask of hub features that are valid to be set 122 */ 123 static const uint32_t hub_set_feature_valid_mask = 124 RHS_LPSC_FLAG | 125 RHS_OCIC_FLAG; 126 127 /** 128 * bitmask of hub features that are set by writing 1 and cleared by writing 0 129 */ 130 static const uint32_t hub_set_feature_direct_mask = 131 RHS_SET_PORT_POWER; 132 133 /** 134 * bitmask of port features that are valid to be set 135 */ 136 static const uint32_t port_set_feature_valid_mask = 137 RHPS_SET_PORT_ENABLE | 138 RHPS_SET_PORT_SUSPEND | 139 RHPS_SET_PORT_RESET | 140 RHPS_SET_PORT_POWER; 141 142 /** 143 * bitmask of port features that can be cleared 144 */ 145 static const uint32_t port_clear_feature_valid_mask = 146 RHPS_CCS_FLAG | 147 RHPS_SET_PORT_SUSPEND | 148 RHPS_POCI_FLAG | 149 RHPS_SET_PORT_POWER | 150 RHPS_CSC_FLAG | 151 RHPS_PESC_FLAG | 152 RHPS_PSSC_FLAG | 153 RHPS_OCIC_FLAG | 154 RHPS_PRSC_FLAG; 155 156 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into 157 //USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request 158 159 /** 160 * bitmask with port status changes 161 */ 162 static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK; 163 164 static int create_serialized_hub_descriptor(rh_t *instance); 165 166 static int rh_init_descriptors(rh_t *instance); 167 168 static int process_get_port_status_request(rh_t *instance, uint16_t port, 169 usb_transfer_batch_t * request); 170 171 static int process_get_hub_status_request(rh_t *instance, 172 usb_transfer_batch_t * request); 173 174 static int process_get_status_request(rh_t *instance, 175 usb_transfer_batch_t * request); 176 177 static void create_interrupt_mask_in_instance(rh_t *instance); 178 179 static int process_get_descriptor_request(rh_t *instance, 180 usb_transfer_batch_t *request); 181 182 static int process_get_configuration_request(rh_t *instance, 183 usb_transfer_batch_t *request); 184 185 static int process_hub_feature_set_request(rh_t *instance, uint16_t feature); 186 187 static int process_hub_feature_clear_request(rh_t *instance, 188 uint16_t feature); 189 190 static int process_port_feature_set_request(rh_t *instance, 191 uint16_t feature, uint16_t port); 192 193 static int process_port_feature_clear_request(rh_t *instance, 194 uint16_t feature, uint16_t port); 195 196 static int process_address_set_request(rh_t *instance, 197 uint16_t address); 198 199 static int process_request_with_output(rh_t *instance, 200 usb_transfer_batch_t *request); 201 202 static int process_request_with_input(rh_t *instance, 203 usb_transfer_batch_t *request); 204 205 static int process_request_without_data(rh_t *instance, 206 usb_transfer_batch_t *request); 207 208 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 209 210 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request); 211 212 static bool is_zeros(void * buffer, size_t size); 213 214 /** Root hub initialization 215 * @return Error code. 216 */ 217 int rh_init(rh_t *instance, ohci_regs_t *regs) { 140 218 assert(instance); 141 assert(regs);142 143 219 instance->registers = regs; 144 220 instance->port_count = 145 221 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 146 if (instance->port_count > 15) { 147 usb_log_warning("OHCI specification does not allow more than 15" 148 " ports. Max 15 ports will be used"); 149 instance->port_count = 15; 150 } 151 152 /* Don't forget the hub status bit and round up */ 153 instance->interrupt_mask_size = 1 + (instance->port_count / 8); 222 int opResult = rh_init_descriptors(instance); 223 if (opResult != EOK) { 224 return opResult; 225 } 226 // set port power mode to no-power-switching 227 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 154 228 instance->unfinished_interrupt_transfer = NULL; 155 156 #ifdef OHCI_POWER_SWITCH_no 157 /* Set port power mode to no power-switching. (always on) */ 158 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 159 /* Set to no over-current reporting */ 160 instance->registers->rh_desc_a |= RHDA_NOCP_FLAG; 161 #elif defined OHCI_POWER_SWITCH_ganged 162 /* Set port power mode to no ganged power-switching. */ 163 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 164 instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG; 165 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 166 /* Set to global over-current */ 167 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; 168 instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG; 169 #else 170 /* Set port power mode to no per port power-switching. */ 171 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 172 instance->registers->rh_desc_a |= RHDA_PSM_FLAG; 173 174 /* Control all ports by global switch and turn them off */ 175 instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT); 176 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 177 /* Return control to per port state */ 178 instance->registers->rh_desc_b |= 179 ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT; 180 /* Set per port over-current */ 181 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; 182 instance->registers->rh_desc_a |= RHDA_OCPM_FLAG; 183 #endif 184 185 rh_init_descriptors(instance); 229 instance->interrupt_mask_size = (instance->port_count + 8) / 8; 230 instance->interrupt_buffer = malloc(instance->interrupt_mask_size); 231 if (!instance->interrupt_buffer) 232 return ENOMEM; 186 233 187 234 usb_log_info("Root hub (%zu ports) initialized.\n", 188 235 instance->port_count); 189 } 190 /*----------------------------------------------------------------------------*/ 191 /** 192 * Process root hub request. 193 * 194 * @param instance Root hub instance 195 * @param request Structure containing both request and response information 196 * @return Error code 197 */ 198 void rh_request(rh_t *instance, usb_transfer_batch_t *request) 199 { 236 237 return EOK; 238 } 239 /*----------------------------------------------------------------------------*/ 240 241 /** 242 * process root hub request 243 * 244 * @param instance root hub instance 245 * @param request structure containing both request and response information 246 * @return error code 247 */ 248 int rh_request(rh_t *instance, usb_transfer_batch_t *request) { 200 249 assert(instance); 201 250 assert(request); 202 203 switch (request->ep->transfer_type) 204 { 205 case USB_TRANSFER_CONTROL: 251 int opResult; 252 if (request->ep->transfer_type == USB_TRANSFER_CONTROL) { 206 253 usb_log_debug("Root hub got CONTROL packet\n"); 207 const int ret = control_request(instance, request); 208 usb_transfer_batch_finish_error(request, ret); 209 break; 210 case USB_TRANSFER_INTERRUPT: 254 opResult = process_ctrl_request(instance, request); 255 usb_transfer_batch_finish_error(request, opResult); 256 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 211 257 usb_log_debug("Root hub got INTERRUPT packet\n"); 212 const uint16_t mask = create_interrupt_mask(instance); 213 if (mask == 0) { 258 create_interrupt_mask_in_instance(instance); 259 if (is_zeros(instance->interrupt_buffer, 260 instance->interrupt_mask_size)) { 214 261 usb_log_debug("No changes..\n"); 215 assert(instance->unfinished_interrupt_transfer == NULL);216 262 instance->unfinished_interrupt_transfer = request; 217 break; 218 } 219 usb_log_debug("Processing changes...\n"); 220 interrupt_request(request, mask, instance->interrupt_mask_size); 221 break; 222 223 default: 224 usb_log_error("Root hub got unsupported request.\n"); 225 usb_transfer_batch_finish_error(request, EINVAL); 226 } 227 } 228 /*----------------------------------------------------------------------------*/ 229 /** 230 * Process interrupt on a hub device. 263 //will be finished later 264 } else { 265 usb_log_debug("Processing changes..\n"); 266 process_interrupt_mask_in_instance(instance, request); 267 } 268 opResult = EOK; 269 } else { 270 271 opResult = EINVAL; 272 usb_transfer_batch_finish_error(request, opResult); 273 } 274 return EOK; 275 } 276 277 /*----------------------------------------------------------------------------*/ 278 279 /** 280 * process interrupt on a hub 231 281 * 232 282 * If there is no pending interrupt transfer, nothing happens. 233 283 * @param instance 234 284 */ 235 void rh_interrupt(rh_t *instance) 236 { 237 assert(instance); 238 239 if (!instance->unfinished_interrupt_transfer) 285 void rh_interrupt(rh_t *instance) { 286 if (!instance->unfinished_interrupt_transfer) { 240 287 return; 241 288 } 242 289 usb_log_debug("Finalizing interrupt transfer\n"); 243 const uint16_t mask = create_interrupt_mask(instance); 244 interrupt_request(instance->unfinished_interrupt_transfer, 245 mask, instance->interrupt_mask_size); 246 247 instance->unfinished_interrupt_transfer = NULL; 248 } 249 /*----------------------------------------------------------------------------*/ 250 /** 251 * Create hub descriptor. 252 * 253 * For descriptor format see USB hub specification (chapter 11.15.2.1, pg. 263) 254 * 255 * @param instance Root hub instance 256 * @return Error code 257 */ 258 void create_serialized_hub_descriptor(rh_t *instance) 259 { 260 assert(instance); 261 262 /* 7 bytes + 2 port bit fields (port count + global bit) */ 263 const size_t size = 7 + (instance->interrupt_mask_size * 2); 264 assert(size <= HUB_DESCRIPTOR_MAX_SIZE); 265 instance->hub_descriptor_size = size; 266 267 const uint32_t hub_desc = instance->registers->rh_desc_a; 268 const uint32_t port_desc = instance->registers->rh_desc_b; 269 270 /* bDescLength */ 271 instance->descriptors.hub[0] = size; 272 /* bDescriptorType */ 273 instance->descriptors.hub[1] = USB_DESCTYPE_HUB; 274 /* bNmbrPorts */ 275 instance->descriptors.hub[2] = instance->port_count; 276 /* wHubCharacteristics */ 277 instance->descriptors.hub[3] = 0 | 278 /* The lowest 2 bits indicate power switching mode */ 279 (((hub_desc & RHDA_PSM_FLAG) ? 1 : 0) << 0) | 280 (((hub_desc & RHDA_NPS_FLAG) ? 1 : 0) << 1) | 281 /* Bit 3 indicates device type (compound device) */ 282 (((hub_desc & RHDA_DT_FLAG) ? 1 : 0) << 2) | 283 /* Bits 4,5 indicate over-current protection mode */ 284 (((hub_desc & RHDA_OCPM_FLAG) ? 1 : 0) << 3) | 285 (((hub_desc & RHDA_NOCP_FLAG) ? 1 : 0) << 4); 286 287 /* Reserved */ 288 instance->descriptors.hub[4] = 0; 289 /* bPwrOn2PwrGood */ 290 instance->descriptors.hub[5] = 291 (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK; 292 /* bHubContrCurrent, root hubs don't need no power. */ 293 instance->descriptors.hub[6] = 0; 294 295 /* Device Removable and some legacy 1.0 stuff*/ 296 instance->descriptors.hub[7] = 297 (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff; 298 instance->descriptors.hub[8] = 0xff; 299 if (instance->interrupt_mask_size == 2) { 300 instance->descriptors.hub[8] = 301 (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8; 302 instance->descriptors.hub[9] = 0xff; 303 instance->descriptors.hub[10] = 0xff; 304 } 305 } 306 /*----------------------------------------------------------------------------*/ 307 /** Initialize hub descriptors. 308 * 309 * A full configuration descriptor is assembled. The configuration and endpoint 310 * descriptors have local modifications. 311 * @param instance Root hub instance 312 * @return Error code 313 */ 314 void rh_init_descriptors(rh_t *instance) 315 { 316 assert(instance); 317 318 instance->descriptors.configuration = ohci_rh_conf_descriptor; 319 instance->descriptors.interface = ohci_rh_iface_descriptor; 320 instance->descriptors.endpoint = ohci_rh_ep_descriptor; 321 create_serialized_hub_descriptor(instance); 322 323 instance->descriptors.endpoint.max_packet_size = 324 instance->interrupt_mask_size; 325 326 instance->descriptors.configuration.total_length = 327 sizeof(usb_standard_configuration_descriptor_t) + 328 sizeof(usb_standard_endpoint_descriptor_t) + 329 sizeof(usb_standard_interface_descriptor_t) + 330 instance->hub_descriptor_size; 331 } 332 /*----------------------------------------------------------------------------*/ 333 /** 334 * Create bitmap of changes to answer status interrupt. 290 create_interrupt_mask_in_instance(instance); 291 process_interrupt_mask_in_instance(instance, 292 instance->unfinished_interrupt_transfer); 293 } 294 /*----------------------------------------------------------------------------*/ 295 296 /** 297 * Create hub descriptor used in hub-driver <-> hub communication 298 * 299 * This means creating byt array from data in root hub registers. For more 300 * info see usb hub specification. 301 * 302 * @param instance root hub instance 303 * @return error code 304 */ 305 static int create_serialized_hub_descriptor(rh_t *instance) { 306 size_t size = 7 + 307 ((instance->port_count + 7) / 8) * 2; 308 size_t var_size = (instance->port_count + 7) / 8; 309 uint8_t * result = (uint8_t*) malloc(size); 310 if (!result) return ENOMEM; 311 312 bzero(result, size); 313 //size 314 result[0] = size; 315 //descriptor type 316 result[1] = USB_DESCTYPE_HUB; 317 result[2] = instance->port_count; 318 uint32_t hub_desc_reg = instance->registers->rh_desc_a; 319 result[3] = 320 ((hub_desc_reg >> 8) % 2) + 321 (((hub_desc_reg >> 9) % 2) << 1) + 322 (((hub_desc_reg >> 10) % 2) << 2) + 323 (((hub_desc_reg >> 11) % 2) << 3) + 324 (((hub_desc_reg >> 12) % 2) << 4); 325 result[4] = 0; 326 result[5] = /*descriptor->pwr_on_2_good_time*/ 50; 327 result[6] = 50; 328 329 size_t port; 330 for (port = 1; port <= instance->port_count; ++port) { 331 uint8_t is_non_removable = 332 instance->registers->rh_desc_b >> port % 2; 333 result[7 + port / 8] += 334 is_non_removable << (port % 8); 335 } 336 size_t i; 337 for (i = 0; i < var_size; ++i) { 338 result[7 + var_size + i] = 255; 339 } 340 instance->hub_descriptor = result; 341 instance->descriptor_size = size; 342 343 return EOK; 344 } 345 /*----------------------------------------------------------------------------*/ 346 347 /** initialize hub descriptors 348 * 349 * Initialized are device and full configuration descriptor. These need to 350 * be initialized only once per hub. 351 * @instance root hub instance 352 * @return error code 353 */ 354 static int rh_init_descriptors(rh_t *instance) { 355 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 356 sizeof (ohci_rh_device_descriptor) 357 ); 358 usb_standard_configuration_descriptor_t descriptor; 359 memcpy(&descriptor, &ohci_rh_conf_descriptor, 360 sizeof (ohci_rh_conf_descriptor)); 361 362 int opResult = create_serialized_hub_descriptor(instance); 363 if (opResult != EOK) { 364 return opResult; 365 } 366 descriptor.total_length = 367 sizeof (usb_standard_configuration_descriptor_t) + 368 sizeof (usb_standard_endpoint_descriptor_t) + 369 sizeof (usb_standard_interface_descriptor_t) + 370 instance->descriptor_size; 371 372 uint8_t * full_config_descriptor = 373 (uint8_t*) malloc(descriptor.total_length); 374 if (!full_config_descriptor) { 375 return ENOMEM; 376 } 377 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor)); 378 memcpy(full_config_descriptor + sizeof (descriptor), 379 &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor)); 380 memcpy(full_config_descriptor + sizeof (descriptor) + 381 sizeof (ohci_rh_iface_descriptor), 382 &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor)); 383 memcpy(full_config_descriptor + sizeof (descriptor) + 384 sizeof (ohci_rh_iface_descriptor) + 385 sizeof (ohci_rh_ep_descriptor), 386 instance->hub_descriptor, instance->descriptor_size); 387 388 instance->descriptors.configuration = full_config_descriptor; 389 instance->descriptors.configuration_size = descriptor.total_length; 390 391 return EOK; 392 } 393 /*----------------------------------------------------------------------------*/ 394 395 /** 396 * create answer to port status_request 397 * 398 * Copy content of corresponding port status register to answer buffer. The 399 * format of the port status register and port status data is the same ( 400 * see OHCI root hub and USB hub documentation). 401 * 402 * @param instance root hub instance 403 * @param port port number, counted from 1 404 * @param request structure containing both request and response information 405 * @return error code 406 */ 407 static int process_get_port_status_request(rh_t *instance, uint16_t port, 408 usb_transfer_batch_t * request) { 409 if (port < 1 || port > instance->port_count) 410 return EINVAL; 411 request->transfered_size = 4; 412 uint32_t data = instance->registers->rh_port_status[port - 1]; 413 memcpy(request->data_buffer, &data, 4); 414 return EOK; 415 } 416 /*----------------------------------------------------------------------------*/ 417 418 /** 419 * create answer to port status_request 420 * 421 * This copies flags in hub status register into the buffer. The format of the 422 * status register and status message is the same, according to USB hub 423 * specification and OHCI root hub specification. 424 * 425 * @param instance root hub instance 426 * @param request structure containing both request and response information 427 * @return error code 428 */ 429 static int process_get_hub_status_request(rh_t *instance, 430 usb_transfer_batch_t * request) { 431 request->transfered_size = 4; 432 //bits, 0,1,16,17 433 uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17); 434 uint32_t data = mask & instance->registers->rh_status; 435 memcpy(request->data_buffer, &data, 4); 436 437 return EOK; 438 } 439 /*----------------------------------------------------------------------------*/ 440 441 /** 442 * create answer to status request 443 * 444 * This might be either hub status or port status request. If neither, 445 * ENOTSUP is returned. 446 * @param instance root hub instance 447 * @param request structure containing both request and response information 448 * @return error code 449 */ 450 static int process_get_status_request(rh_t *instance, 451 usb_transfer_batch_t * request) { 452 size_t buffer_size = request->buffer_size; 453 usb_device_request_setup_packet_t * request_packet = 454 (usb_device_request_setup_packet_t*) 455 request->setup_buffer; 456 457 usb_hub_bm_request_type_t request_type = request_packet->request_type; 458 if (buffer_size < 4) { 459 usb_log_warning("Requested more data than buffer size\n"); 460 return EINVAL; 461 } 462 463 if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) 464 return process_get_hub_status_request(instance, request); 465 if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) 466 return process_get_port_status_request(instance, 467 request_packet->index, 468 request); 469 470 return ENOTSUP; 471 } 472 /*----------------------------------------------------------------------------*/ 473 474 /** 475 * create answer to status interrupt consisting of change bitmap 335 476 * 336 477 * Result contains bitmap where bit 0 indicates change on hub and … … 338 479 * Hub and Port status bitmap specification in USB specification 339 480 * (chapter 11.13.4). 340 * @param instance root hub instance 341 * @return Mask of changes. 342 */ 343 uint16_t create_interrupt_mask(rh_t *instance) 344 { 345 assert(instance); 346 uint16_t mask = 0; 347 348 /* Only local power source change and over-current change can happen */ 349 if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) { 350 mask |= 1; 351 } 352 size_t port = 1; 353 for (; port <= instance->port_count; ++port) { 354 /* Write-clean bits are those that indicate change */ 355 if (RHPS_CHANGE_WC_MASK 356 & instance->registers->rh_port_status[port - 1]) { 357 358 mask |= (1 << port); 359 } 360 } 361 /* USB is little endian */ 362 return host2uint32_t_le(mask); 363 } 364 /*----------------------------------------------------------------------------*/ 365 /** 366 * Create answer to status request. 367 * 368 * This might be either hub status or port status request. If neither, 369 * ENOTSUP is returned. 370 * @param instance root hub instance 371 * @param request structure containing both request and response information 372 * @return error code 373 */ 374 int get_status(rh_t *instance, usb_transfer_batch_t *request) 375 { 376 assert(instance); 377 assert(request); 378 379 const usb_device_request_setup_packet_t *request_packet = 380 (usb_device_request_setup_packet_t*)request->setup_buffer; 381 382 if (request->buffer_size < 4) { 383 usb_log_error("Buffer too small for get status request.\n"); 384 return EOVERFLOW; 385 } 386 387 /* Hub status: just filter relevant info from rh_status reg */ 388 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) { 389 const uint32_t data = instance->registers->rh_status & 390 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 391 memcpy(request->data_buffer, &data, 4); 392 TRANSFER_OK(4); 393 } 394 395 /* Copy appropriate rh_port_status register, OHCI designers were 396 * kind enough to make those bit values match USB specification */ 397 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) { 398 const unsigned port = request_packet->index; 399 if (port < 1 || port > instance->port_count) 400 return EINVAL; 401 402 const uint32_t data = 403 instance->registers->rh_port_status[port - 1]; 404 memcpy(request->data_buffer, &data, 4); 405 TRANSFER_OK(4); 406 } 407 408 return ENOTSUP; 409 } 410 /*----------------------------------------------------------------------------*/ 411 /** 412 * Create answer to a descriptor request. 481 * Uses instance`s interrupt buffer to store the interrupt information. 482 * @param instance root hub instance 483 */ 484 static void create_interrupt_mask_in_instance(rh_t * instance) { 485 uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer); 486 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 487 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 488 bzero(bitmap, instance->interrupt_mask_size); 489 if ((instance->registers->rh_status & mask) != 0) { 490 bitmap[0] = 1; 491 } 492 size_t port; 493 mask = port_status_change_mask; 494 for (port = 1; port <= instance->port_count; ++port) { 495 if ((mask & instance->registers->rh_port_status[port - 1]) != 0) { 496 497 bitmap[(port) / 8] += 1 << (port % 8); 498 } 499 } 500 } 501 /*----------------------------------------------------------------------------*/ 502 503 /** 504 * create answer to a descriptor request 413 505 * 414 506 * This might be a request for standard (configuration, device, endpoint or 415 507 * interface) or device specific (hub) descriptor. 416 * @param instance Root hub instance 417 * @param request Structure containing both request and response information 418 * @return Error code 419 */ 420 int get_descriptor(rh_t *instance, usb_transfer_batch_t *request) 421 { 422 assert(instance); 423 assert(request); 424 425 const usb_device_request_setup_packet_t *setup_request = 426 (usb_device_request_setup_packet_t *) request->setup_buffer; 508 * @param instance root hub instance 509 * @param request structure containing both request and response information 510 * @return error code 511 */ 512 static int process_get_descriptor_request(rh_t *instance, 513 usb_transfer_batch_t *request) { 514 usb_device_request_setup_packet_t * setup_request = 515 (usb_device_request_setup_packet_t*) request->setup_buffer; 427 516 size_t size; 428 const void * descriptor = NULL;517 const void * result_descriptor = NULL; 429 518 const uint16_t setup_request_value = setup_request->value_high; 430 519 //(setup_request->value_low << 8); 431 switch (setup_request_value) 432 { 433 case USB_DESCTYPE_HUB: 434 usb_log_debug2("USB_DESCTYPE_HUB\n"); 435 /* Hub descriptor was generated locally */ 436 descriptor = instance->descriptors.hub; 437 size = instance->hub_descriptor_size; 438 break; 439 440 case USB_DESCTYPE_DEVICE: 441 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 442 /* Device descriptor is shared (No one should ask for it)*/ 443 descriptor = &ohci_rh_device_descriptor; 444 size = sizeof(ohci_rh_device_descriptor); 445 break; 446 447 case USB_DESCTYPE_CONFIGURATION: 448 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 449 /* Start with configuration and add others depending on 450 * request size */ 451 descriptor = &instance->descriptors; 452 size = instance->descriptors.configuration.total_length; 453 break; 454 455 case USB_DESCTYPE_INTERFACE: 456 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 457 /* Use local interface descriptor. There is one and it 458 * might be modified */ 459 descriptor = &instance->descriptors.interface; 460 size = sizeof(instance->descriptors.interface); 461 break; 462 463 case USB_DESCTYPE_ENDPOINT: 464 /* Use local endpoint descriptor. There is one 465 * it might have max_packet_size field modified*/ 466 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 467 descriptor = &instance->descriptors.endpoint; 468 size = sizeof(instance->descriptors.endpoint); 469 break; 470 471 default: 472 usb_log_debug2("USB_DESCTYPE_EINVAL %d \n" 473 "\ttype %d\n\trequest %d\n\tvalue " 474 "%d\n\tindex %d\n\tlen %d\n ", 475 setup_request->value, 476 setup_request->request_type, setup_request->request, 477 setup_request_value, setup_request->index, 478 setup_request->length); 479 return EINVAL; 520 switch (setup_request_value) { 521 case USB_DESCTYPE_HUB: 522 { 523 usb_log_debug2("USB_DESCTYPE_HUB\n"); 524 result_descriptor = instance->hub_descriptor; 525 size = instance->descriptor_size; 526 break; 527 } 528 case USB_DESCTYPE_DEVICE: 529 { 530 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 531 result_descriptor = &ohci_rh_device_descriptor; 532 size = sizeof (ohci_rh_device_descriptor); 533 break; 534 } 535 case USB_DESCTYPE_CONFIGURATION: 536 { 537 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 538 result_descriptor = instance->descriptors.configuration; 539 size = instance->descriptors.configuration_size; 540 break; 541 } 542 case USB_DESCTYPE_INTERFACE: 543 { 544 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 545 result_descriptor = &ohci_rh_iface_descriptor; 546 size = sizeof (ohci_rh_iface_descriptor); 547 break; 548 } 549 case USB_DESCTYPE_ENDPOINT: 550 { 551 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 552 result_descriptor = &ohci_rh_ep_descriptor; 553 size = sizeof (ohci_rh_ep_descriptor); 554 break; 555 } 556 default: 557 { 558 usb_log_debug2("USB_DESCTYPE_EINVAL %d \n", 559 setup_request->value); 560 usb_log_debug2("\ttype %d\n\trequest %d\n\tvalue " 561 "%d\n\tindex %d\n\tlen %d\n ", 562 setup_request->request_type, 563 setup_request->request, 564 setup_request_value, 565 setup_request->index, 566 setup_request->length 567 ); 568 return EINVAL; 569 } 480 570 } 481 571 if (request->buffer_size < size) { 482 572 size = request->buffer_size; 483 573 } 484 485 memcpy(request->data_buffer, descriptor, size); 486 TRANSFER_OK(size); 487 } 488 /*----------------------------------------------------------------------------*/ 574 request->transfered_size = size; 575 memcpy(request->data_buffer, result_descriptor, size); 576 577 return EOK; 578 } 579 /*----------------------------------------------------------------------------*/ 580 581 /** 582 * answer to get configuration request 583 * 584 * Root hub works independently on the configuration. 585 * @param instance root hub instance 586 * @param request structure containing both request and response information 587 * @return error code 588 */ 589 static int process_get_configuration_request(rh_t *instance, 590 usb_transfer_batch_t *request) { 591 //set and get configuration requests do not have any meaning, only dummy 592 //values are returned 593 if (request->buffer_size != 1) 594 return EINVAL; 595 request->data_buffer[0] = 1; 596 request->transfered_size = 1; 597 598 return EOK; 599 } 600 /*----------------------------------------------------------------------------*/ 601 602 /** 603 * process feature-enabling request on hub 604 * 605 * @param instance root hub instance 606 * @param feature feature selector 607 * @return error code 608 */ 609 static int process_hub_feature_set_request(rh_t *instance, 610 uint16_t feature) { 611 if (!((1 << feature) & hub_set_feature_valid_mask)) 612 return EINVAL; 613 if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER) 614 feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16; 615 instance->registers->rh_status = 616 (instance->registers->rh_status | (1 << feature)) 617 & (~hub_clear_feature_by_writing_one_mask); 618 619 return EOK; 620 } 621 /*----------------------------------------------------------------------------*/ 622 623 /** 624 * process feature-disabling request on hub 625 * 626 * @param instance root hub instance 627 * @param feature feature selector 628 * @return error code 629 */ 630 static int process_hub_feature_clear_request(rh_t *instance, 631 uint16_t feature) { 632 if (!((1 << feature) & hub_clear_feature_valid_mask)) 633 return EINVAL; 634 //is the feature cleared directly? 635 if ((1 << feature) & hub_set_feature_direct_mask) { 636 instance->registers->rh_status = 637 (instance->registers->rh_status & (~(1 << feature))) 638 & (~hub_clear_feature_by_writing_one_mask); 639 } else {//the feature is cleared by writing '1' 640 641 instance->registers->rh_status = 642 (instance->registers->rh_status 643 & (~hub_clear_feature_by_writing_one_mask)) 644 | (1 << feature); 645 } 646 return EOK; 647 } 648 /*----------------------------------------------------------------------------*/ 649 489 650 /** 490 651 * process feature-enabling request on hub … … 496 657 * @return error code 497 658 */ 498 int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port) 499 {500 assert(instance);501 659 static int process_port_feature_set_request(rh_t *instance, 660 uint16_t feature, uint16_t port) { 661 if (!((1 << feature) & port_set_feature_valid_mask)) 662 return EINVAL; 502 663 if (port < 1 || port > instance->port_count) 503 664 return EINVAL; 504 505 switch (feature) 506 { 507 case USB_HUB_FEATURE_PORT_POWER: //8 508 /* No power switching */ 509 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 510 return EOK; 511 /* Ganged power switching */ 512 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 513 instance->registers->rh_status = RHS_SET_GLOBAL_POWER; 514 return EOK; 515 } 516 case USB_HUB_FEATURE_PORT_ENABLE: //1 517 case USB_HUB_FEATURE_PORT_SUSPEND: //2 518 case USB_HUB_FEATURE_PORT_RESET: //4 519 /* Nice thing is that these shifts correspond to the position 520 * of control bits in register */ 521 instance->registers->rh_port_status[port - 1] = (1 << feature); 522 return EOK; 523 default: 524 return ENOTSUP; 525 } 526 } 527 /*----------------------------------------------------------------------------*/ 528 /** 529 * Process feature clear request. 665 instance->registers->rh_port_status[port - 1] = 666 (instance->registers->rh_port_status[port - 1] | (1 << feature)) 667 & (~port_clear_feature_valid_mask); 668 return EOK; 669 } 670 /*----------------------------------------------------------------------------*/ 671 672 /** 673 * process feature-disabling request on hub 530 674 * 531 675 * @param instance root hub instance … … 535 679 * @return error code 536 680 */ 537 int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port) 538 {539 assert(instance);540 681 static int process_port_feature_clear_request(rh_t *instance, 682 uint16_t feature, uint16_t port) { 683 if (!((1 << feature) & port_clear_feature_valid_mask)) 684 return EINVAL; 541 685 if (port < 1 || port > instance->port_count) 542 686 return EINVAL; 543 544 /* Enabled features to clear: see page 269 of USB specs */ 545 switch (feature) 546 { 547 case USB_HUB_FEATURE_PORT_POWER: //8 548 /* No power switching */ 549 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 550 return ENOTSUP; 551 /* Ganged power switching */ 552 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 553 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 554 return EOK; 555 } 556 instance->registers->rh_port_status[port - 1] = 557 RHPS_CLEAR_PORT_POWER; 687 if (feature == USB_HUB_FEATURE_PORT_POWER) 688 feature = USB_HUB_FEATURE_PORT_LOW_SPEED; 689 if (feature == USB_HUB_FEATURE_PORT_SUSPEND) 690 feature = USB_HUB_FEATURE_PORT_OVER_CURRENT; 691 instance->registers->rh_port_status[port - 1] = 692 (instance->registers->rh_port_status[port - 1] 693 & (~port_clear_feature_valid_mask)) 694 | (1 << feature); 695 696 return EOK; 697 } 698 /*----------------------------------------------------------------------------*/ 699 700 /** 701 * register address to this device 702 * 703 * @param instance root hub instance 704 * @param address new address 705 * @return error code 706 */ 707 static int process_address_set_request(rh_t *instance, 708 uint16_t address) { 709 return ENOTSUP; 710 } 711 /*----------------------------------------------------------------------------*/ 712 713 /** 714 * process one of requests that requere output data 715 * 716 * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or 717 * USB_DEVREQ_GET_CONFIGURATION. 718 * @param instance root hub instance 719 * @param request structure containing both request and response information 720 * @return error code 721 */ 722 static int process_request_with_output(rh_t *instance, 723 usb_transfer_batch_t *request) { 724 usb_device_request_setup_packet_t * setup_request = 725 (usb_device_request_setup_packet_t*) request->setup_buffer; 726 if (setup_request->request == USB_DEVREQ_GET_STATUS) { 727 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 728 return process_get_status_request(instance, request); 729 } 730 if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) { 731 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 732 return process_get_descriptor_request(instance, request); 733 } 734 if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) { 735 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 736 737 return process_get_configuration_request(instance, request); 738 } 739 return ENOTSUP; 740 } 741 /*----------------------------------------------------------------------------*/ 742 743 /** 744 * process one of requests that carry input data 745 * 746 * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or 747 * USB_DEVREQ_SET_CONFIGURATION. 748 * @param instance root hub instance 749 * @param request structure containing both request and response information 750 * @return error code 751 */ 752 static int process_request_with_input(rh_t *instance, 753 usb_transfer_batch_t *request) { 754 usb_device_request_setup_packet_t * setup_request = 755 (usb_device_request_setup_packet_t*) request->setup_buffer; 756 request->transfered_size = 0; 757 if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) { 758 return ENOTSUP; 759 } 760 if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) { 761 //set and get configuration requests do not have any meaning, 762 //only dummy values are returned 763 558 764 return EOK; 559 560 case USB_HUB_FEATURE_PORT_ENABLE: //1 561 instance->registers->rh_port_status[port - 1] = 562 RHPS_CLEAR_PORT_ENABLE; 563 return EOK; 564 565 case USB_HUB_FEATURE_PORT_SUSPEND: //2 566 instance->registers->rh_port_status[port - 1] = 567 RHPS_CLEAR_PORT_SUSPEND; 568 return EOK; 569 570 case USB_HUB_FEATURE_C_PORT_CONNECTION: //16 571 case USB_HUB_FEATURE_C_PORT_ENABLE: //17 572 case USB_HUB_FEATURE_C_PORT_SUSPEND: //18 573 case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19 574 case USB_HUB_FEATURE_C_PORT_RESET: //20 575 /* Nice thing is that these shifts correspond to the position 576 * of control bits in register */ 577 instance->registers->rh_port_status[port - 1] = (1 << feature); 578 return EOK; 579 580 default: 581 return ENOTSUP; 582 } 583 } 584 /*----------------------------------------------------------------------------*/ 765 } 766 return ENOTSUP; 767 } 768 /*----------------------------------------------------------------------------*/ 769 585 770 /** 586 771 * process one of requests that do not request nor carry additional data … … 592 777 * @return error code 593 778 */ 594 int set_feature(rh_t *instance, usb_transfer_batch_t *request) 595 { 596 assert(instance); 597 assert(request); 598 599 const usb_device_request_setup_packet_t *setup_request = 600 (usb_device_request_setup_packet_t *) request->setup_buffer; 601 switch (setup_request->request_type) 602 { 603 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 604 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 605 return set_feature_port(instance, 606 setup_request->value, setup_request->index); 607 608 case USB_HUB_REQ_TYPE_SET_HUB_FEATURE: 609 /* Chapter 11.16.2 specifies that hub can be recipient 610 * only for C_HUB_LOCAL_POWER and C_HUB_OVER_CURRENT 611 * features. It makes no sense to SET either. */ 612 usb_log_error("Invalid HUB set feature request.\n"); 613 return ENOTSUP; 614 default: 615 usb_log_error("Invalid set feature request type: %d\n", 779 static int process_request_without_data(rh_t *instance, 780 usb_transfer_batch_t *request) { 781 usb_device_request_setup_packet_t * setup_request = 782 (usb_device_request_setup_packet_t*) request->setup_buffer; 783 request->transfered_size = 0; 784 if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) { 785 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) { 786 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 787 return process_hub_feature_clear_request(instance, 788 setup_request->value); 789 } 790 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) { 791 usb_log_debug2("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 792 return process_port_feature_clear_request(instance, 793 setup_request->value, 794 setup_request->index); 795 } 796 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n", 616 797 setup_request->request_type); 617 798 return EINVAL; 618 799 } 619 } 620 /*----------------------------------------------------------------------------*/ 621 /** 622 * process one of requests that do not request nor carry additional data 623 * 624 * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or 625 * USB_DEVREQ_SET_ADDRESS. 626 * @param instance root hub instance 627 * @param request structure containing both request and response information 628 * @return error code 629 */ 630 int clear_feature(rh_t *instance, usb_transfer_batch_t *request) 631 { 632 assert(instance); 633 assert(request); 634 635 const usb_device_request_setup_packet_t *setup_request = 636 (usb_device_request_setup_packet_t *) request->setup_buffer; 637 request->transfered_size = 0; 638 switch (setup_request->request_type) 639 { 640 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 641 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 642 return clear_feature_port(instance, 643 setup_request->value, setup_request->index); 644 645 case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE: 646 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE\n"); 647 /* 648 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and 649 * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented 650 * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported 651 * as root hubs do not support local power status feature. 652 * (OHCI pg. 127) */ 653 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 654 instance->registers->rh_status = RHS_OCIC_FLAG; 655 TRANSFER_OK(0); 656 } 657 default: 658 usb_log_error("Invalid clear feature request type: %d\n", 800 if (setup_request->request == USB_DEVREQ_SET_FEATURE) { 801 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) { 802 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 803 return process_hub_feature_set_request(instance, 804 setup_request->value); 805 } 806 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) { 807 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 808 return process_port_feature_set_request(instance, 809 setup_request->value, 810 setup_request->index); 811 } 812 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n", 659 813 setup_request->request_type); 660 814 return EINVAL; 661 815 } 662 } 663 /*----------------------------------------------------------------------------*/ 664 /** 665 * Process hub control request. 816 if (setup_request->request == USB_DEVREQ_SET_ADDRESS) { 817 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 818 return process_address_set_request(instance, 819 setup_request->value); 820 } 821 usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n", 822 setup_request->request_type); 823 824 return ENOTSUP; 825 } 826 /*----------------------------------------------------------------------------*/ 827 828 /** 829 * process hub control request 666 830 * 667 831 * If needed, writes answer into the request structure. … … 680 844 * @return error code 681 845 */ 682 int control_request(rh_t *instance, usb_transfer_batch_t *request) 683 { 684 assert(instance); 685 assert(request); 686 846 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) { 687 847 if (!request->setup_buffer) { 688 usb_log_error(" Root hub received empty transaction!");689 return EINVAL; 690 } 691 692 if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {848 usb_log_error("root hub received empty transaction?"); 849 return EINVAL; 850 } 851 int opResult; 852 if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) { 693 853 usb_log_error("Setup packet too small\n"); 694 return EOVERFLOW; 695 } 696 697 usb_log_debug2("CTRL packet: %s.\n", 698 usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8)); 699 const usb_device_request_setup_packet_t *setup_request = 700 (usb_device_request_setup_packet_t *) request->setup_buffer; 701 switch (setup_request->request) 702 { 703 case USB_DEVREQ_GET_STATUS: 704 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 705 return get_status(instance, request); 706 707 case USB_DEVREQ_GET_DESCRIPTOR: 708 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 709 return get_descriptor(instance, request); 710 711 case USB_DEVREQ_GET_CONFIGURATION: 712 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 713 if (request->buffer_size != 1) 714 return EINVAL; 715 request->data_buffer[0] = 1; 716 TRANSFER_OK(1); 717 718 case USB_DEVREQ_CLEAR_FEATURE: 719 usb_log_debug2("Processing request without " 720 "additional data\n"); 721 return clear_feature(instance, request); 722 case USB_DEVREQ_SET_FEATURE: 723 usb_log_debug2("Processing request without " 724 "additional data\n"); 725 return set_feature(instance, request); 726 727 case USB_DEVREQ_SET_ADDRESS: 728 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 729 instance->address = setup_request->value; 730 TRANSFER_OK(0); 731 732 case USB_DEVREQ_SET_CONFIGURATION: 733 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n"); 734 /* We don't need to do anything */ 735 TRANSFER_OK(0); 736 737 case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */ 738 default: 739 usb_log_error("Received unsupported request: %d.\n", 740 setup_request->request); 741 return ENOTSUP; 742 } 854 return EINVAL; 855 } 856 usb_log_debug("CTRL packet: %s.\n", 857 usb_debug_str_buffer( 858 (const uint8_t *) request->setup_buffer, 8, 8)); 859 usb_device_request_setup_packet_t * setup_request = 860 (usb_device_request_setup_packet_t*) 861 request->setup_buffer; 862 switch (setup_request->request) { 863 case USB_DEVREQ_GET_STATUS: 864 case USB_DEVREQ_GET_DESCRIPTOR: 865 case USB_DEVREQ_GET_CONFIGURATION: 866 usb_log_debug2("Processing request with output\n"); 867 opResult = process_request_with_output( 868 instance, request); 869 break; 870 case USB_DEVREQ_CLEAR_FEATURE: 871 case USB_DEVREQ_SET_FEATURE: 872 case USB_DEVREQ_SET_ADDRESS: 873 usb_log_debug2("Processing request without " 874 "additional data\n"); 875 opResult = process_request_without_data( 876 instance, request); 877 break; 878 case USB_DEVREQ_SET_DESCRIPTOR: 879 case USB_DEVREQ_SET_CONFIGURATION: 880 usb_log_debug2("Processing request with input\n"); 881 opResult = process_request_with_input( 882 instance, request); 883 884 break; 885 default: 886 usb_log_warning("Received unsupported request: %d.\n", 887 setup_request->request); 888 opResult = ENOTSUP; 889 } 890 return opResult; 891 } 892 /*----------------------------------------------------------------------------*/ 893 894 /** 895 * process hanging interrupt request 896 * 897 * If an interrupt transfer has been received and there was no change, 898 * the driver stores the transfer information and waits for change to occcur. 899 * This routine is called when that happens and it finalizes the interrupt 900 * transfer. 901 * 902 * @param instance hub instance 903 * @param request batch request to be processed 904 * 905 * @return 906 */ 907 static int process_interrupt_mask_in_instance(rh_t *instance, 908 usb_transfer_batch_t * request) { 909 memcpy(request->data_buffer, instance->interrupt_buffer, 910 instance->interrupt_mask_size); 911 request->transfered_size = instance->interrupt_mask_size; 912 instance->unfinished_interrupt_transfer = NULL; 913 usb_transfer_batch_finish_error(request, EOK); 914 915 return EOK; 916 } 917 918 /*----------------------------------------------------------------------------*/ 919 920 /** 921 * return whether the buffer is full of zeros 922 * 923 * Convenience function. 924 * @param buffer 925 * @param size 926 * @return 927 */ 928 static bool is_zeros(void *buffer, size_t size) { 929 if (!buffer) return true; 930 if (!size) return true; 931 size_t i; 932 for (i = 0; i < size; ++i) { 933 if (((char*) buffer)[i]) 934 return false; 935 } 936 return true; 743 937 } 744 938 -
uspace/drv/bus/usb/ohci/root_hub.h
r4069f5c r27eddb52 41 41 #include "batch.h" 42 42 43 #define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)44 45 43 /** 46 44 * ohci root hub representation … … 53 51 /** hub port count */ 54 52 size_t port_count; 53 /** hubs descriptors */ 54 usb_device_descriptors_t descriptors; 55 55 /** interrupt transfer waiting for an actual interrupt to occur */ 56 usb_transfer_batch_t *unfinished_interrupt_transfer; 56 usb_transfer_batch_t * unfinished_interrupt_transfer; 57 /** pre-allocated interrupt mask 58 * 59 * This is allocated when initializing instance, so that memory 60 * allocation is not needed when processing request. Buffer is used for 61 * interrupt bitmask. 62 */ 63 uint8_t * interrupt_buffer; 57 64 /** size of interrupt buffer */ 58 65 size_t interrupt_mask_size; 59 /** Descriptors */ 60 struct { 61 usb_standard_configuration_descriptor_t configuration; 62 usb_standard_interface_descriptor_t interface; 63 usb_standard_endpoint_descriptor_t endpoint; 64 uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE]; 65 } __attribute__ ((packed)) descriptors; 66 /** instance`s descriptor*/ 67 uint8_t * hub_descriptor; 66 68 /** size of hub descriptor */ 67 size_t hub_descriptor_size; 69 size_t descriptor_size; 70 68 71 69 72 } rh_t; 70 73 71 voidrh_init(rh_t *instance, ohci_regs_t *regs);74 int rh_init(rh_t *instance, ohci_regs_t *regs); 72 75 73 voidrh_request(rh_t *instance, usb_transfer_batch_t *request);76 int rh_request(rh_t *instance, usb_transfer_batch_t *request); 74 77 75 78 void rh_interrupt(rh_t *instance); -
uspace/drv/bus/usb/uhci/hc.c
r4069f5c r27eddb52 47 47 (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT) 48 48 49 static const irq_cmd_t uhci_irq_commands[] =50 {51 { .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},52 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,53 .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS },54 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },55 { .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/},56 { .cmd = CMD_ACCEPT },57 };58 49 59 50 static int hc_init_transfer_lists(hc_t *instance); … … 63 54 static int hc_interrupt_emulator(void *arg); 64 55 static int hc_debug_checker(void *arg); 65 66 /*----------------------------------------------------------------------------*/67 /** Get number of commands used in IRQ code.68 * @return Number of commands.69 */70 size_t hc_irq_cmd_count(void)71 {72 return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);73 }74 /*----------------------------------------------------------------------------*/75 /** Generate IRQ code commands.76 * @param[out] cmds Place to store the commands.77 * @param[in] cmd_size Size of the place (bytes).78 * @param[in] regs Physical address of device's registers.79 * @param[in] reg_size Size of the register area (bytes).80 *81 * @return Error code.82 */83 int hc_get_irq_commands(84 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)85 {86 if (cmd_size < sizeof(uhci_irq_commands)87 || reg_size < sizeof(uhci_regs_t))88 return EOVERFLOW;89 90 uhci_regs_t *registers = (uhci_regs_t*)regs;91 92 memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));93 94 cmds[0].addr = (void*)®isters->usbsts;95 cmds[3].addr = (void*)®isters->usbsts;96 return EOK;97 }98 56 /*----------------------------------------------------------------------------*/ 99 57 /** Initialize UHCI hc driver structure … … 111 69 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts) 112 70 { 113 assert(reg_size >= sizeof( uhci_regs_t));71 assert(reg_size >= sizeof(regs_t)); 114 72 int ret; 115 73 … … 124 82 125 83 /* allow access to hc control registers */ 126 uhci_regs_t *io;84 regs_t *io; 127 85 ret = pio_enable(regs, reg_size, (void **)&io); 128 CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n", 129 io, str_error(ret)); 86 CHECK_RET_RETURN(ret, 87 "Failed(%d) to gain access to registers at %p: %s.\n", 88 ret, io, str_error(ret)); 130 89 instance->registers = io; 131 usb_log_debug( 132 "Device registers at %p (%zuB) accessible.\n",io, reg_size);90 usb_log_debug("Device registers at %p (%zuB) accessible.\n", 91 io, reg_size); 133 92 134 93 ret = hc_init_mem_structures(instance); 135 94 CHECK_RET_RETURN(ret, 136 "Failed to initialize UHCI memory structures: %s.\n",137 str_error(ret));95 "Failed(%d) to initialize UHCI memory structures: %s.\n", 96 ret, str_error(ret)); 138 97 139 98 hc_init_hw(instance); … … 157 116 { 158 117 assert(instance); 159 uhci_regs_t *registers = instance->registers;118 regs_t *registers = instance->registers; 160 119 161 120 /* Reset everything, who knows what touched it before us */ 162 121 pio_write_16(®isters->usbcmd, UHCI_CMD_GLOBAL_RESET); 163 async_usleep( 50000); /* 50ms according to USB spec(root hub reset)*/122 async_usleep(10000); /* 10ms according to USB spec */ 164 123 pio_write_16(®isters->usbcmd, 0); 165 124 166 /* Reset hc, all states and counters . Hope that hw is not broken*/125 /* Reset hc, all states and counters */ 167 126 pio_write_16(®isters->usbcmd, UHCI_CMD_HCRESET); 168 127 do { async_usleep(10); } … … 182 141 } 183 142 184 const uint16_t cmd= pio_read_16(®isters->usbcmd);185 if ( cmd!= 0)186 usb_log_warning("Previous command value: %x.\n", cmd);143 const uint16_t status = pio_read_16(®isters->usbcmd); 144 if (status != 0) 145 usb_log_warning("Previous command value: %x.\n", status); 187 146 188 147 /* Start the hc with large(64B) packet FSBR */ … … 211 170 } else (void) 0 212 171 172 /* Init interrupt code */ 173 instance->interrupt_code.cmds = instance->interrupt_commands; 174 { 175 /* Read status register */ 176 instance->interrupt_commands[0].cmd = CMD_PIO_READ_16; 177 instance->interrupt_commands[0].dstarg = 1; 178 instance->interrupt_commands[0].addr = 179 &instance->registers->usbsts; 180 181 /* Test whether we are the interrupt cause */ 182 instance->interrupt_commands[1].cmd = CMD_BTEST; 183 instance->interrupt_commands[1].value = 184 UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS; 185 instance->interrupt_commands[1].srcarg = 1; 186 instance->interrupt_commands[1].dstarg = 2; 187 188 /* Predicate cleaning and accepting */ 189 instance->interrupt_commands[2].cmd = CMD_PREDICATE; 190 instance->interrupt_commands[2].value = 2; 191 instance->interrupt_commands[2].srcarg = 2; 192 193 /* Write clean status register */ 194 instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16; 195 instance->interrupt_commands[3].srcarg = 1; 196 instance->interrupt_commands[3].addr = 197 &instance->registers->usbsts; 198 199 /* Accept interrupt */ 200 instance->interrupt_commands[4].cmd = CMD_ACCEPT; 201 202 instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS; 203 } 204 213 205 /* Init transfer lists */ 214 206 int ret = hc_init_transfer_lists(instance); 215 CHECK_RET_RETURN(ret, "Failed to init ializetransfer lists.\n");207 CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n"); 216 208 usb_log_debug("Initialized transfer lists.\n"); 209 210 /* Init USB frame list page*/ 211 instance->frame_list = get_page(); 212 ret = instance->frame_list ? EOK : ENOMEM; 213 CHECK_RET_RETURN(ret, "Failed to get frame list page.\n"); 214 usb_log_debug("Initialized frame list at %p.\n", instance->frame_list); 215 216 /* Set all frames to point to the first queue head */ 217 const uint32_t queue = LINK_POINTER_QH( 218 addr_to_phys(instance->transfers_interrupt.queue_head)); 219 220 unsigned i = 0; 221 for(; i < UHCI_FRAME_LIST_COUNT; ++i) { 222 instance->frame_list[i] = queue; 223 } 217 224 218 225 /* Init device keeper */ 219 226 usb_device_keeper_init(&instance->manager); 220 usb_log_debug("Initialized device keeper.\n");227 usb_log_debug("Initialized device manager.\n"); 221 228 222 229 ret = usb_endpoint_manager_init(&instance->ep_manager, … … 225 232 str_error(ret)); 226 233 227 /* Init USB frame list page*/228 instance->frame_list = get_page();229 if (!instance->frame_list) {230 usb_log_error("Failed to get frame list page.\n");231 usb_endpoint_manager_destroy(&instance->ep_manager);232 return ENOMEM;233 }234 usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);235 236 /* Set all frames to point to the first queue head */237 const uint32_t queue = LINK_POINTER_QH(238 addr_to_phys(instance->transfers_interrupt.queue_head));239 unsigned i = 0;240 for(; i < UHCI_FRAME_LIST_COUNT; ++i) {241 instance->frame_list[i] = queue;242 }243 244 234 return EOK; 245 235 #undef CHECK_RET_RETURN … … 262 252 int ret = transfer_list_init(&instance->transfers_##type, name); \ 263 253 if (ret != EOK) { \ 264 usb_log_error("Failed to setup %s transfer list: %s.\n", \265 name, str_error(ret)); \254 usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \ 255 ret, name, str_error(ret)); \ 266 256 transfer_list_fini(&instance->transfers_bulk_full); \ 267 257 transfer_list_fini(&instance->transfers_control_full); \ -
uspace/drv/bus/usb/uhci/hc.h
r4069f5c r27eddb52 84 84 /** SOF modification to match external timers */ 85 85 uint8_t sofmod; 86 } uhci_regs_t;86 } regs_t; 87 87 88 88 #define UHCI_FRAME_LIST_COUNT 1024 … … 100 100 101 101 /** Addresses of I/O registers */ 102 uhci_regs_t *registers;102 regs_t *registers; 103 103 104 104 /** Frame List contains 1024 link pointers */ … … 116 116 /** Pointer table to the above lists, helps during scheduling */ 117 117 transfer_list_t *transfers[2][4]; 118 119 /** Code to be executed in kernel interrupt handler */ 120 irq_code_t interrupt_code; 121 122 /** Commands that form interrupt code */ 123 irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS]; 124 118 125 /** Fibril periodically checking status register*/ 119 126 fid_t interrupt_emulator; 127 120 128 /** Indicator of hw interrupts availability */ 121 129 bool hw_interrupts; … … 124 132 unsigned hw_failures; 125 133 } hc_t; 126 size_t hc_irq_cmd_count(void); 127 int hc_get_irq_commands( 128 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size); 134 129 135 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts); 136 130 137 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch); 138 131 139 void hc_interrupt(hc_t *instance, uint16_t status); 132 140 -
uspace/drv/bus/usb/uhci/root_hub.c
r4069f5c r27eddb52 50 50 int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size) 51 51 { 52 int ret;53 54 52 assert(fun); 55 53 56 ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100); 54 char *match_str = NULL; 55 int ret = asprintf(&match_str, "usb&uhci&root-hub"); 56 if (ret < 0) { 57 usb_log_error( 58 "Failed(%d) to create root hub match string: %s.\n", 59 ret, str_error(ret)); 60 return ret; 61 } 62 assert(match_str); 63 64 ret = ddf_fun_add_match_id(fun, match_str, 100); 57 65 if (ret != EOK) { 58 usb_log_error("Failed to add root hub match id: %s\n", 59 str_error(ret)); 66 free(match_str); 67 usb_log_error("Failed(%d) to add root hub match id: %s\n", 68 ret, str_error(ret)); 60 69 return ret; 61 70 } -
uspace/drv/bus/usb/uhci/uhci.c
r4069f5c r27eddb52 64 64 { 65 65 assert(dev); 66 assert(dev->driver_data); 66 67 return dev->driver_data; 67 68 } … … 77 78 assert(dev); 78 79 uhci_t *uhci = dev_to_uhci(dev); 79 if (!uhci) { 80 usb_log_error("Interrupt on not yet initialized device.\n"); 81 return; 82 } 80 hc_t *hc = &uhci->hc; 83 81 const uint16_t status = IPC_GET_ARG1(*call); 84 hc_interrupt(&uhci->hc, status); 82 assert(hc); 83 hc_interrupt(hc, status); 85 84 } 86 85 /*----------------------------------------------------------------------------*/ … … 193 192 } \ 194 193 free(instance); \ 195 device->driver_data = NULL; \196 194 usb_log_error(message); \ 197 195 return ret; \ … … 224 222 ret = pci_disable_legacy(device); 225 223 CHECK_RET_DEST_FREE_RETURN(ret, 226 "Failed to disable legacy USB: %s.\n", str_error(ret)); 227 228 const size_t cmd_count = hc_irq_cmd_count(); 229 irq_cmd_t irq_cmds[cmd_count]; 230 ret = 231 hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size); 232 CHECK_RET_DEST_FREE_RETURN(ret, 233 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 234 235 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds }; 236 237 /* Register handler to avoid interrupt lockup */ 238 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 239 CHECK_RET_DEST_FREE_RETURN(ret, 240 "Failed to register interrupt handler: %s.\n", str_error(ret)); 224 "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret)); 241 225 242 226 bool interrupts = false; 227 #ifdef CONFIG_USBHC_NO_INTERRUPTS 228 usb_log_warning("Interrupts disabled in OS config, " \ 229 "falling back to polling.\n"); 230 #else 243 231 ret = pci_enable_interrupts(device); 244 232 if (ret != EOK) { 245 usb_log_warning("Failed to enable interrupts: %s." 246 " Falling back to polling.\n", str_error(ret)); 233 usb_log_warning("Failed to enable interrupts: %s.\n", 234 str_error(ret)); 235 usb_log_info("HW interrupts not available, " \ 236 "falling back to polling.\n"); 247 237 } else { 248 238 usb_log_debug("Hw interrupts enabled.\n"); 249 239 interrupts = true; 250 240 } 241 #endif 242 251 243 252 244 ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts); 253 245 CHECK_RET_DEST_FREE_RETURN(ret, 254 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 255 256 device->driver_data = instance; 246 "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret)); 257 247 258 248 #define CHECK_RET_FINI_RETURN(ret, message...) \ … … 263 253 } else (void)0 264 254 255 /* It does no harm if we register this on polling */ 256 ret = register_interrupt_handler(device, irq, irq_handler, 257 &instance->hc.interrupt_code); 258 CHECK_RET_FINI_RETURN(ret, 259 "Failed(%d) to register interrupt handler: %s.\n", 260 ret, str_error(ret)); 261 265 262 ret = ddf_fun_bind(instance->hc_fun); 266 CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n", 267 str_error(ret)); 263 CHECK_RET_FINI_RETURN(ret, 264 "Failed(%d) to bind UHCI device function: %s.\n", 265 ret, str_error(ret)); 268 266 269 267 ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME); … … 274 272 (uintptr_t)instance->hc.registers + 0x10, 4); 275 273 CHECK_RET_FINI_RETURN(ret, 276 "Failed to setup UHCI root hub: %s.\n", str_error(ret));274 "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret)); 277 275 278 276 ret = ddf_fun_bind(instance->rh_fun); 279 277 CHECK_RET_FINI_RETURN(ret, 280 "Failed to register UHCI root hub: %s.\n", str_error(ret)); 281 278 "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret)); 279 280 device->driver_data = instance; 282 281 return EOK; 283 282 #undef CHECK_RET_FINI_RETURN -
uspace/drv/bus/usb/usbhub/usbhub.c
r4069f5c r27eddb52 220 220 * @return error code 221 221 */ 222 int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) 223 { 222 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) { 224 223 // get hub descriptor 225 usb_log_debug(" Retrievingdescriptor\n");224 usb_log_debug("Creating serialized descriptor\n"); 226 225 uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE]; 226 usb_hub_descriptor_t * descriptor; 227 227 int opResult; 228 228 … … 234 234 235 235 if (opResult != EOK) { 236 usb_log_error("Failed to receive hub descriptor: %s.\n", 237 str_error(opResult)); 236 usb_log_error("Failed when receiving hub descriptor, " 237 "%s\n", 238 str_error(opResult)); 239 free(serialized_descriptor); 238 240 return opResult; 239 241 } 240 usb_log_debug2("Parsing descriptor\n"); 241 usb_hub_descriptor_t descriptor; 242 opResult = usb_deserialize_hub_desriptor( 243 serialized_descriptor, received_size, &descriptor); 244 if (opResult != EOK) { 245 usb_log_error("Could not parse descriptor: %s\n", 246 str_error(opResult)); 247 return opResult; 248 } 249 usb_log_debug("Setting port count to %d.\n", descriptor.ports_count); 250 hub_info->port_count = descriptor.ports_count; 251 252 hub_info->ports = 253 malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1)); 242 usb_log_debug2("Deserializing descriptor\n"); 243 descriptor = usb_create_deserialized_hub_desriptor( 244 serialized_descriptor); 245 if (descriptor == NULL) { 246 usb_log_warning("could not deserialize descriptor \n"); 247 return ENOMEM; 248 } 249 usb_log_debug("setting port count to %d\n", descriptor->ports_count); 250 hub_info->port_count = descriptor->ports_count; 251 bool is_power_switched = 252 ((descriptor->hub_characteristics & 1) == 0); 253 bool has_individual_port_powering = 254 ((descriptor->hub_characteristics & 1) != 0); 255 hub_info->ports = malloc( 256 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 254 257 if (!hub_info->ports) { 255 258 return ENOMEM; 256 259 } 257 258 260 size_t port; 259 261 for (port = 0; port < hub_info->port_count + 1; ++port) { 260 262 usb_hub_port_init(&hub_info->ports[port]); 261 263 } 262 263 const bool is_power_switched =264 !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);265 264 if (is_power_switched) { 266 265 usb_log_debug("Hub power switched\n"); 267 const bool per_port_power = descriptor.hub_characteristics 268 & HUB_CHAR_POWER_PER_PORT_FLAG; 266 267 if (!has_individual_port_powering) { 268 //this setting actually makes no difference 269 usb_log_debug("Hub has global powering\n"); 270 } 269 271 270 272 for (port = 1; port <= hub_info->port_count; ++port) { 271 273 usb_log_debug("Powering port %zu.\n", port); 272 opResult = usb_hub_set_port_feature( 273 hub_info->control_pipe, 274 opResult = usb_hub_set_port_feature(hub_info->control_pipe, 274 275 port, USB_HUB_FEATURE_PORT_POWER); 275 276 if (opResult != EOK) { 276 277 usb_log_error("Cannot power on port %zu: %s.\n", 277 278 port, str_error(opResult)); 278 } else {279 if (!per_port_power) {280 usb_log_debug(281 "Ganged power switching mode, "282 "one port is enough.\n");283 break;284 }285 279 } 286 280 } … … 289 283 usb_log_debug("Power not switched, not going to be powered\n"); 290 284 } 285 usb_log_debug2("Freeing data\n"); 286 free(descriptor); 291 287 return EOK; 292 288 } -
uspace/drv/bus/usb/usbhub/usbhub_private.h
r4069f5c r27eddb52 171 171 void * serialized_descriptor); 172 172 173 int usb_deserialize_hub_desriptor( 174 void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor); 173 usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor( 174 void * serialized_descriptor); 175 176 void usb_deserialize_hub_desriptor(void * serialized_descriptor, 177 usb_hub_descriptor_t * descriptor); 175 178 176 179 -
uspace/drv/bus/usb/usbhub/utils.c
r4069f5c r27eddb52 110 110 } 111 111 112 /*----------------------------------------------------------------------------*/113 112 /** 114 * Deserialize descriptor into given pointer113 * create deserialized desriptor structure out of serialized descriptor 115 114 * 115 * The serialized descriptor must be proper usb hub descriptor, 116 * otherwise an eerror might occur. 117 * 118 * @param sdescriptor serialized descriptor 119 * @return newly created deserialized descriptor pointer 120 */ 121 usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor( 122 void *serialized_descriptor) { 123 uint8_t * sdescriptor = serialized_descriptor; 124 125 if (sdescriptor[1] != USB_DESCTYPE_HUB) { 126 usb_log_warning("trying to deserialize wrong descriptor %x\n", 127 sdescriptor[1]); 128 return NULL; 129 } 130 131 usb_hub_descriptor_t * result = malloc(sizeof (usb_hub_descriptor_t)); 132 if (result) 133 usb_deserialize_hub_desriptor(serialized_descriptor, result); 134 return result; 135 } 136 137 /** 138 * deserialize descriptor into given pointer 139 * 116 140 * @param serialized_descriptor 117 141 * @param descriptor 118 142 * @return 119 143 */ 120 int usb_deserialize_hub_desriptor( 121 void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor) 122 { 144 void usb_deserialize_hub_desriptor( 145 void * serialized_descriptor, usb_hub_descriptor_t *descriptor) { 123 146 uint8_t * sdescriptor = serialized_descriptor; 124 125 if (sdescriptor[1] != USB_DESCTYPE_HUB) {126 usb_log_error("Trying to deserialize wrong descriptor %x\n",127 sdescriptor[1]);128 return EINVAL;129 }130 if (size < 7) {131 usb_log_error("Serialized descriptor too small.\n");132 return EOVERFLOW;133 }134 135 147 descriptor->ports_count = sdescriptor[2]; 136 descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4]; 148 /// @fixme handling of endianness?? 149 descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3]; 137 150 descriptor->pwr_on_2_good_time = sdescriptor[5]; 138 151 descriptor->current_requirement = sdescriptor[6]; 139 constsize_t var_size = (descriptor->ports_count + 7) / 8;152 size_t var_size = (descriptor->ports_count + 7) / 8; 140 153 //descriptor->devices_removable = (uint8_t*) malloc(var_size); 141 154 142 if (size < (7 + var_size)) { 143 usb_log_error("Serialized descriptor too small.\n"); 144 return EOVERFLOW; 145 } 146 size_t i = 0; 147 for (; i < var_size; ++i) { 155 size_t i; 156 for (i = 0; i < var_size; ++i) { 148 157 descriptor->devices_removable[i] = sdescriptor[7 + i]; 149 158 } 150 return EOK;151 159 } 152 /*----------------------------------------------------------------------------*/ 160 153 161 /** 154 162 * @} -
uspace/drv/bus/usb/usbmast/Makefile
r4069f5c r27eddb52 44 44 45 45 SOURCES = \ 46 bo_trans.c \ 47 cmdw.c \ 46 cmds.c \ 48 47 main.c \ 48 mast.c \ 49 49 scsi_ms.c 50 50 -
uspace/drv/bus/usb/usbmast/main.c
r4069f5c r27eddb52 45 45 #include <errno.h> 46 46 #include <str_error.h> 47 #include "cmd w.h"48 #include " bo_trans.h"47 #include "cmds.h" 48 #include "mast.h" 49 49 #include "scsi_ms.h" 50 #include "usbmast.h"51 50 52 51 #define NAME "usbmast" … … 78 77 }; 79 78 80 static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun); 79 /** Mass storage function. 80 * 81 * Serves as soft state for function/LUN. 82 */ 83 typedef struct { 84 /** DDF function */ 85 ddf_fun_t *ddf_fun; 86 /** Total number of blocks. */ 87 uint64_t nblocks; 88 /** Block size in bytes. */ 89 size_t block_size; 90 /** USB device function belongs to */ 91 usb_device_t *usb_dev; 92 } usbmast_fun_t; 93 81 94 static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall, 82 95 void *arg); … … 90 103 { 91 104 int rc; 92 usbmast_dev_t *mdev = NULL; 93 unsigned i; 105 const char *fun_name = "a"; 106 ddf_fun_t *fun = NULL; 107 usbmast_fun_t *msfun = NULL; 94 108 95 109 /* Allocate softstate */ 96 m dev = calloc(1, sizeof(usbmast_dev_t));97 if (m dev== NULL) {110 msfun = calloc(1, sizeof(usbmast_fun_t)); 111 if (msfun == NULL) { 98 112 usb_log_error("Failed allocating softstate.\n"); 99 113 rc = ENOMEM; … … 101 115 } 102 116 103 mdev->ddf_dev = dev->ddf_dev; 104 mdev->usb_dev = dev; 117 fun = ddf_fun_create(dev->ddf_dev, fun_exposed, fun_name); 118 if (fun == NULL) { 119 usb_log_error("Failed to create DDF function %s.\n", fun_name); 120 rc = ENOMEM; 121 goto error; 122 } 123 124 /* Set up a connection handler. */ 125 fun->conn_handler = usbmast_bd_connection; 126 fun->driver_data = msfun; 105 127 106 128 usb_log_info("Initializing mass storage `%s'.\n", … … 114 136 115 137 usb_log_debug("Get LUN count...\n"); 116 mdev->luns = usb_masstor_get_lun_count(mdev); 117 118 for (i = 0; i < mdev->luns; i++) { 119 rc = usbmast_fun_create(mdev, i); 120 if (rc != EOK) 121 goto error; 122 } 123 124 return EOK; 125 error: 126 /* XXX Destroy functions */ 127 if (mdev != NULL) 128 free(mdev); 129 return rc; 130 } 131 132 /** Create mass storage function. 133 * 134 * Called once for each LUN. 135 * 136 * @param mdev Mass storage device 137 * @param lun LUN 138 * @return EOK on success or negative error code. 139 */ 140 static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun) 141 { 142 int rc; 143 char *fun_name = NULL; 144 ddf_fun_t *fun = NULL; 145 usbmast_fun_t *mfun = NULL; 146 147 /* Allocate softstate */ 148 mfun = calloc(1, sizeof(usbmast_fun_t)); 149 if (mfun == NULL) { 150 usb_log_error("Failed allocating softstate.\n"); 151 rc = ENOMEM; 152 goto error; 153 } 154 155 mfun->mdev = mdev; 156 mfun->lun = lun; 157 158 if (asprintf(&fun_name, "l%u", lun) < 0) { 159 usb_log_error("Out of memory.\n"); 160 rc = ENOMEM; 161 goto error; 162 } 163 164 fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name); 165 if (fun == NULL) { 166 usb_log_error("Failed to create DDF function %s.\n", fun_name); 167 rc = ENOMEM; 168 goto error; 169 } 170 171 free(fun_name); 172 fun_name = NULL; 173 174 /* Set up a connection handler. */ 175 fun->conn_handler = usbmast_bd_connection; 176 fun->driver_data = mfun; 138 size_t lun_count = usb_masstor_get_lun_count(dev); 139 140 /* XXX Handle more than one LUN properly. */ 141 if (lun_count > 1) { 142 usb_log_warning ("Mass storage has %zu LUNs. Ignoring all " 143 "but first.\n", lun_count); 144 } 177 145 178 146 usb_log_debug("Inquire...\n"); 179 147 usbmast_inquiry_data_t inquiry; 180 rc = usbmast_inquiry( mfun, &inquiry);148 rc = usbmast_inquiry(dev, &inquiry); 181 149 if (rc != EOK) { 182 150 usb_log_warning("Failed to inquire device `%s': %s.\n", 183 mdev->ddf_dev->name, str_error(rc));151 dev->ddf_dev->name, str_error(rc)); 184 152 rc = EIO; 185 153 goto error; 186 154 } 187 155 188 usb_log_info("Mass storage `%s' LUN %u: " \ 189 "%s by %s rev. %s is %s (%s).\n", 190 mdev->ddf_dev->name, 191 lun, 156 usb_log_info("Mass storage `%s': " \ 157 "%s by %s rev. %s is %s (%s), %zu LUN(s).\n", 158 dev->ddf_dev->name, 192 159 inquiry.product, 193 160 inquiry.vendor, 194 161 inquiry.revision, 195 162 usbmast_scsi_dev_type_str(inquiry.device_type), 196 inquiry.removable ? "removable" : "non-removable"); 163 inquiry.removable ? "removable" : "non-removable", 164 lun_count); 197 165 198 166 uint32_t nblocks, block_size; 199 167 200 rc = usbmast_read_capacity( mfun, &nblocks, &block_size);168 rc = usbmast_read_capacity(dev, &nblocks, &block_size); 201 169 if (rc != EOK) { 202 170 usb_log_warning("Failed to read capacity, device `%s': %s.\n", 203 mdev->ddf_dev->name, str_error(rc));171 dev->ddf_dev->name, str_error(rc)); 204 172 rc = EIO; 205 173 goto error; … … 209 177 "block_size=%" PRIu32 "\n", nblocks, block_size); 210 178 211 mfun->nblocks = nblocks; 212 mfun->block_size = block_size; 179 msfun->nblocks = nblocks; 180 msfun->block_size = block_size; 181 msfun->usb_dev = dev; 213 182 214 183 rc = ddf_fun_bind(fun); … … 225 194 if (fun != NULL) 226 195 ddf_fun_destroy(fun); 227 if (fun_name != NULL) 228 free(fun_name); 229 if (mfun != NULL) 230 free(mfun); 196 if (msfun != NULL) 197 free(msfun); 231 198 return rc; 232 199 } … … 236 203 void *arg) 237 204 { 238 usbmast_fun_t *m fun;205 usbmast_fun_t *msfun; 239 206 void *comm_buf = NULL; 240 207 size_t comm_size; … … 262 229 (void) async_share_out_finalize(callid, comm_buf); 263 230 264 m fun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;231 msfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data; 265 232 266 233 while (true) { … … 276 243 switch (method) { 277 244 case BD_GET_BLOCK_SIZE: 278 async_answer_1(callid, EOK, m fun->block_size);245 async_answer_1(callid, EOK, msfun->block_size); 279 246 break; 280 247 case BD_GET_NUM_BLOCKS: 281 async_answer_2(callid, EOK, LOWER32(m fun->nblocks),282 UPPER32(m fun->nblocks));248 async_answer_2(callid, EOK, LOWER32(msfun->nblocks), 249 UPPER32(msfun->nblocks)); 283 250 break; 284 251 case BD_READ_BLOCKS: 285 252 ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 286 253 cnt = IPC_GET_ARG3(call); 287 retval = usbmast_read(mfun, ba, cnt, comm_buf); 254 retval = usbmast_read(msfun->usb_dev, ba, cnt, 255 msfun->block_size, comm_buf); 288 256 async_answer_0(callid, retval); 289 257 break; … … 291 259 ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 292 260 cnt = IPC_GET_ARG3(call); 293 retval = usbmast_write(mfun, ba, cnt, comm_buf); 261 retval = usbmast_write(msfun->usb_dev, ba, cnt, 262 msfun->block_size, comm_buf); 294 263 async_answer_0(callid, retval); 295 264 break; -
uspace/drv/bus/usb/usbmast/scsi_ms.c
r4069f5c r27eddb52 46 46 #include <scsi/sbc.h> 47 47 #include <scsi/spc.h> 48 #include "cmd w.h"49 #include " bo_trans.h"48 #include "cmds.h" 49 #include "mast.h" 50 50 #include "scsi_ms.h" 51 #include "usbmast.h"52 51 53 52 /** Get string representation for SCSI peripheral device type. … … 63 62 /** Perform SCSI Inquiry command on USB mass storage device. 64 63 * 65 * @param mfun Mass storage function66 * @param inquiry_result Where to store parsed inquiry result 67 * @return Error code 68 */ 69 int usbmast_inquiry(usb mast_fun_t *mfun, usbmast_inquiry_data_t *inq_res)64 * @param dev USB device. 65 * @param inquiry_result Where to store parsed inquiry result. 66 * @return Error code. 67 */ 68 int usbmast_inquiry(usb_device_t *dev, usbmast_inquiry_data_t *inq_res) 70 69 { 71 70 scsi_std_inquiry_data_t inq_data; … … 78 77 cdb.alloc_len = host2uint16_t_be(sizeof(inq_data)); 79 78 80 rc = usb_massstor_data_in( mfun, 0xDEADBEEF, (uint8_t *) &cdb,79 rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb, 81 80 sizeof(cdb), &inq_data, sizeof(inq_data), &response_len); 82 81 83 82 if (rc != EOK) { 84 83 usb_log_error("Inquiry failed, device %s: %s.\n", 85 mfun->mdev->ddf_dev->name, str_error(rc));84 dev->ddf_dev->name, str_error(rc)); 86 85 return rc; 87 86 } … … 119 118 /** Perform SCSI Request Sense command on USB mass storage device. 120 119 * 121 * @param mfun Mass storage function120 * @param dev USB device 122 121 * @param buf Destination buffer 123 122 * @param size Size of @a buf … … 125 124 * @return Error code. 126 125 */ 127 int usbmast_request_sense(usb mast_fun_t *mfun, void *buf, size_t size)126 int usbmast_request_sense(usb_device_t *dev, void *buf, size_t size) 128 127 { 129 128 scsi_cdb_request_sense_t cdb; … … 135 134 cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE); 136 135 137 rc = usb_massstor_data_in( mfun, 0xDEADBEEF, (uint8_t *) &cdb,136 rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb, 138 137 sizeof(cdb), buf, size, &data_len); 139 138 140 139 if (rc != EOK) { 141 140 usb_log_error("Request Sense failed, device %s: %s.\n", 142 mfun->mdev->ddf_dev->name, str_error(rc));141 dev->ddf_dev->name, str_error(rc)); 143 142 return rc; 144 143 } … … 155 154 /** Perform SCSI Read Capacity command on USB mass storage device. 156 155 * 157 * @param mfun Mass storage function158 * @param nblocks Output, number of blocks 159 * @param block_size Output, block size in bytes 160 * 161 * @return Error code. 162 */ 163 int usbmast_read_capacity(usb mast_fun_t *mfun, uint32_t *nblocks,156 * @param dev USB device. 157 * @param nblocks Output, number of blocks. 158 * @param block_size Output, block size in bytes. 159 * 160 * @return Error code. 161 */ 162 int usbmast_read_capacity(usb_device_t *dev, uint32_t *nblocks, 164 163 uint32_t *block_size) 165 164 { … … 172 171 cdb.op_code = SCSI_CMD_READ_CAPACITY_10; 173 172 174 rc = usb_massstor_data_in( mfun, 0xDEADBEEF, (uint8_t *) &cdb,173 rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb, 175 174 sizeof(cdb), &data, sizeof(data), &data_len); 176 175 177 176 if (rc != EOK) { 178 177 usb_log_error("Read Capacity (10) failed, device %s: %s.\n", 179 mfun->mdev->ddf_dev->name, str_error(rc));178 dev->ddf_dev->name, str_error(rc)); 180 179 return rc; 181 180 } … … 195 194 /** Perform SCSI Read command on USB mass storage device. 196 195 * 197 * @param mfun Mass storage function 198 * @param ba Address of first block 199 * @param nblocks Number of blocks to read 200 * 201 * @return Error code 202 */ 203 int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf) 196 * @param dev USB device. 197 * @param ba Address of first block. 198 * @param nblocks Number of blocks to read. 199 * @param bsize Block size. 200 * 201 * @return Error code. 202 */ 203 int usbmast_read(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize, 204 void *buf) 204 205 { 205 206 scsi_cdb_read_12_t cdb; … … 212 213 return ELIMIT; 213 214 214 if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)215 if ((uint64_t)nblocks * bsize > UINT32_MAX) 215 216 return ELIMIT; 216 217 … … 220 221 cdb.xfer_len = host2uint32_t_be(nblocks); 221 222 222 rc = usb_massstor_data_in( mfun, 0xDEADBEEF, (uint8_t *) &cdb,223 sizeof(cdb), buf, nblocks * mfun->block_size, &data_len);223 rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb, 224 sizeof(cdb), buf, nblocks * bsize, &data_len); 224 225 225 226 if (rc != EOK) { 226 227 usb_log_error("Read (12) failed, device %s: %s.\n", 227 mfun->mdev->ddf_dev->name, str_error(rc));228 return rc; 229 } 230 231 if (data_len < nblocks * mfun->block_size) {228 dev->ddf_dev->name, str_error(rc)); 229 return rc; 230 } 231 232 if (data_len < nblocks * bsize) { 232 233 usb_log_error("SCSI Read response too short (%zu).\n", 233 234 data_len); … … 240 241 /** Perform SCSI Write command on USB mass storage device. 241 242 * 242 * @param mfun Mass storage function243 * @param dev USB device 243 244 * @param ba Address of first block 244 245 * @param nblocks Number of blocks to read 246 * @param bsize Block size 245 247 * @param data Data to write 246 248 * 247 249 * @return Error code 248 250 */ 249 int usbmast_write(usb mast_fun_t *mfun, uint64_t ba, size_t nblocks,251 int usbmast_write(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize, 250 252 const void *data) 251 253 { … … 254 256 int rc; 255 257 258 /* XXX Need softstate to store block size. */ 259 256 260 if (ba > UINT32_MAX) 257 261 return ELIMIT; 258 262 259 if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)263 if ((uint64_t)nblocks * bsize > UINT32_MAX) 260 264 return ELIMIT; 261 265 … … 265 269 cdb.xfer_len = host2uint32_t_be(nblocks); 266 270 267 rc = usb_massstor_data_out( mfun, 0xDEADBEEF, (uint8_t *) &cdb,268 sizeof(cdb), data, nblocks * mfun->block_size, &sent_len);271 rc = usb_massstor_data_out(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb, 272 sizeof(cdb), data, nblocks * bsize, &sent_len); 269 273 270 274 if (rc != EOK) { 271 275 usb_log_error("Write (12) failed, device %s: %s.\n", 272 mfun->mdev->ddf_dev->name, str_error(rc));273 return rc; 274 } 275 276 if (sent_len < nblocks * mfun->block_size) {276 dev->ddf_dev->name, str_error(rc)); 277 return rc; 278 } 279 280 if (sent_len < nblocks * bsize) { 277 281 usb_log_error("SCSI Write not all bytes transferred (%zu).\n", 278 282 sent_len); -
uspace/drv/bus/usb/usbmast/scsi_ms.h
r4069f5c r27eddb52 59 59 } usbmast_inquiry_data_t; 60 60 61 extern int usbmast_inquiry(usbmast_fun_t *, usbmast_inquiry_data_t *); 62 extern int usbmast_request_sense(usbmast_fun_t *, void *, size_t); 63 extern int usbmast_read_capacity(usbmast_fun_t *, uint32_t *, uint32_t *); 64 extern int usbmast_read(usbmast_fun_t *, uint64_t, size_t, void *); 65 extern int usbmast_write(usbmast_fun_t *, uint64_t, size_t, const void *); 61 extern int usbmast_inquiry(usb_device_t *, usbmast_inquiry_data_t *); 62 extern int usbmast_request_sense(usb_device_t *, void *, size_t); 63 extern int usbmast_read_capacity(usb_device_t *, uint32_t *, uint32_t *); 64 extern int usbmast_read(usb_device_t *, uint64_t, size_t, size_t, void *); 65 extern int usbmast_write(usb_device_t *, uint64_t, size_t, size_t, 66 const void *); 66 67 extern const char *usbmast_scsi_dev_type_str(unsigned); 67 68 -
uspace/drv/bus/usb/vhc/connhost.c
r4069f5c r27eddb52 141 141 size_t max_packet_size, unsigned int interval) 142 142 { 143 /* TODO: Use usb_endpoint_manager_add_ep */ 144 VHC_DATA(vhc, fun); 145 146 endpoint_t *ep = endpoint_get( 147 address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1); 143 VHC_DATA(vhc, fun); 144 145 endpoint_t *ep = malloc(sizeof(endpoint_t)); 148 146 if (ep == NULL) { 149 147 return ENOMEM; 150 148 } 151 149 152 int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 150 int rc = endpoint_init(ep, address, endpoint, direction, transfer_type, 151 USB_SPEED_FULL, 1); 152 if (rc != EOK) { 153 free(ep); 154 return rc; 155 } 156 157 rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 153 158 if (rc != EOK) { 154 159 endpoint_destroy(ep); -
uspace/drv/infrastructure/root/root.c
r4069f5c r27eddb52 176 176 } 177 177 178 free(match_id);179 180 178 rc = ddf_fun_bind(fun); 181 179 if (rc != EOK) { -
uspace/drv/test/test1/test1.c
r4069f5c r27eddb52 74 74 } 75 75 76 rc = ddf_fun_add_match_id(fun, match_id, match_score);76 rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score); 77 77 if (rc != EOK) { 78 78 ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s", -
uspace/lib/c/generic/io/io.c
r4069f5c r27eddb52 714 714 off64_t ftell(FILE *stream) 715 715 { 716 _fflushbuf(stream);717 716 return lseek(stream->fd, 0, SEEK_CUR); 718 717 } -
uspace/lib/clui/tinput.c
r4069f5c r27eddb52 1 1 /* 2 * Copyright (c) 201 1Jiri Svoboda2 * Copyright (c) 2010 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 #include <sort.h>30 29 #include <stdio.h> 31 30 #include <stdlib.h> … … 43 42 #include <tinput.h> 44 43 45 #define LIN_TO_COL(ti, lpos) ((lpos) % ((ti)->con_cols))46 #define LIN_TO_ROW(ti, lpos) ((lpos) / ((ti)->con_cols))47 48 44 /** Seek direction */ 49 45 typedef enum { … … 65 61 static void tinput_post_seek(tinput_t *, bool); 66 62 67 static void tinput_console_set_lpos(tinput_t *ti, unsigned lpos)68 {69 console_set_pos(ti->console, LIN_TO_COL(ti, lpos),70 LIN_TO_ROW(ti, lpos));71 }72 73 63 /** Create a new text input field. */ 74 64 tinput_t *tinput_new(void) … … 76 66 tinput_t *ti; 77 67 78 ti = calloc(1,sizeof(tinput_t));68 ti = malloc(sizeof(tinput_t)); 79 69 if (ti == NULL) 80 70 return NULL; … … 87 77 void tinput_destroy(tinput_t *ti) 88 78 { 89 if (ti->prompt != NULL)90 free(ti->prompt);91 79 free(ti); 92 }93 94 static void tinput_display_prompt(tinput_t *ti)95 {96 tinput_console_set_lpos(ti, ti->prompt_coord);97 98 console_set_style(ti->console, STYLE_EMPHASIS);99 printf("%s", ti->prompt);100 console_flush(ti->console);101 console_set_style(ti->console, STYLE_NORMAL);102 80 } 103 81 … … 110 88 tinput_sel_get_bounds(ti, &sa, &sb); 111 89 112 tinput_console_set_lpos(ti, ti->text_coord + start); 90 console_set_pos(ti->console, (ti->col0 + start) % ti->con_cols, 91 ti->row0 + (ti->col0 + start) / ti->con_cols); 113 92 console_set_style(ti->console, STYLE_NORMAL); 114 93 … … 155 134 static void tinput_position_caret(tinput_t *ti) 156 135 { 157 tinput_console_set_lpos(ti, ti->text_coord + ti->pos); 158 } 159 160 /** Update text_coord, prompt_coord in case the screen could have scrolled. */ 136 console_set_pos(ti->console, (ti->col0 + ti->pos) % ti->con_cols, 137 ti->row0 + (ti->col0 + ti->pos) / ti->con_cols); 138 } 139 140 /** Update row0 in case the screen could have scrolled. */ 161 141 static void tinput_update_origin(tinput_t *ti) 162 142 { 163 unsigned end_coord = ti->text_coord + ti->nc; 164 unsigned end_row = LIN_TO_ROW(ti, end_coord); 165 166 unsigned scroll_rows; 167 168 /* Update coords if the screen scrolled. */ 169 if (end_row >= ti->con_rows) { 170 scroll_rows = end_row - ti->con_rows + 1; 171 ti->text_coord -= ti->con_cols * scroll_rows; 172 ti->prompt_coord -= ti->con_cols * scroll_rows; 173 } 174 } 175 176 static void tinput_jump_after(tinput_t *ti) 177 { 178 tinput_console_set_lpos(ti, ti->text_coord + ti->nc); 179 console_flush(ti->console); 180 putchar('\n'); 181 } 182 183 static int tinput_display(tinput_t *ti) 184 { 185 sysarg_t col0, row0; 186 187 if (console_get_pos(ti->console, &col0, &row0) != EOK) 188 return EIO; 189 190 ti->prompt_coord = row0 * ti->con_cols + col0; 191 ti->text_coord = ti->prompt_coord + str_length(ti->prompt); 192 193 tinput_display_prompt(ti); 194 tinput_display_tail(ti, 0, 0); 195 tinput_position_caret(ti); 196 197 return EOK; 143 sysarg_t width = ti->col0 + ti->nc; 144 sysarg_t rows = (width / ti->con_cols) + 1; 145 146 /* Update row0 if the screen scrolled. */ 147 if (ti->row0 + rows > ti->con_rows) 148 ti->row0 = ti->con_rows - rows; 198 149 } 199 150 … … 203 154 return; 204 155 205 unsigned new_width = LIN_TO_COL(ti, ti->text_coord)+ ti->nc + 1;156 sysarg_t new_width = ti->col0 + ti->nc + 1; 206 157 if (new_width % ti->con_cols == 0) { 207 158 /* Advancing to new line. */ … … 234 185 return; 235 186 236 unsigned new_width = LIN_TO_COL(ti, ti->text_coord)+ ti->nc + ilen;237 unsignednew_height = (new_width / ti->con_cols) + 1;187 sysarg_t new_width = ti->col0 + ti->nc + ilen; 188 sysarg_t new_height = (new_width / ti->con_cols) + 1; 238 189 if (new_height >= ti->con_rows) { 239 190 /* Disallow text longer than 1 page for now. */ … … 560 511 } 561 512 562 /** Compare two entries in array of completions. */563 static int compl_cmp(void *va, void *vb, void *arg)564 {565 const char *a = *(const char **) va;566 const char *b = *(const char **) vb;567 568 return str_cmp(a, b);569 }570 571 static size_t common_pref_len(const char *a, const char *b)572 {573 size_t i;574 size_t a_off, b_off;575 wchar_t ca, cb;576 577 i = 0;578 a_off = 0;579 b_off = 0;580 581 while (true) {582 ca = str_decode(a, &a_off, STR_NO_LIMIT);583 cb = str_decode(b, &b_off, STR_NO_LIMIT);584 585 if (ca == '\0' || cb == '\0' || ca != cb)586 break;587 ++i;588 }589 590 return i;591 }592 593 static void tinput_text_complete(tinput_t *ti)594 {595 void *state;596 size_t cstart;597 char *ctmp;598 char **compl; /* Array of completions */599 size_t compl_len; /* Current length of @c compl array */600 size_t cnum;601 size_t i;602 int rc;603 604 if (ti->compl_ops == NULL)605 return;606 607 /*608 * Obtain list of all possible completions (growing array).609 */610 611 rc = (*ti->compl_ops->init)(ti->buffer, ti->pos, &cstart, &state);612 if (rc != EOK)613 return;614 615 cnum = 0;616 617 compl_len = 1;618 compl = malloc(compl_len * sizeof(char *));619 if (compl == NULL) {620 printf("Error: Out of memory.\n");621 return;622 }623 624 while (true) {625 rc = (*ti->compl_ops->get_next)(state, &ctmp);626 if (rc != EOK)627 break;628 629 if (cnum >= compl_len) {630 /* Extend array */631 compl_len = 2 * compl_len;632 compl = realloc(compl, compl_len * sizeof(char *));633 if (compl == NULL) {634 printf("Error: Out of memory.\n");635 break;636 }637 }638 639 compl[cnum] = str_dup(ctmp);640 if (compl[cnum] == NULL) {641 printf("Error: Out of memory.\n");642 break;643 }644 cnum++;645 }646 647 (*ti->compl_ops->fini)(state);648 649 if (cnum > 1) {650 /*651 * More than one match. Determine maximum common prefix.652 */653 size_t cplen;654 655 cplen = str_length(compl[0]);656 for (i = 1; i < cnum; i++)657 cplen = min(cplen, common_pref_len(compl[0], compl[i]));658 659 /* Compute how many bytes we should skip. */660 size_t istart = str_lsize(compl[0], ti->pos - cstart);661 662 if (cplen > istart) {663 /* Insert common prefix. */664 665 /* Copy remainder of common prefix. */666 char *cpref = str_ndup(compl[0] + istart,667 str_lsize(compl[0], cplen - istart));668 669 /* Insert it. */670 tinput_insert_string(ti, cpref);671 free(cpref);672 } else {673 /* No common prefix. Sort and display all entries. */674 675 qsort(compl, cnum, sizeof(char *), compl_cmp, NULL);676 677 tinput_jump_after(ti);678 for (i = 0; i < cnum; i++)679 printf("%s\n", compl[i]);680 tinput_display(ti);681 }682 } else if (cnum == 1) {683 /*684 * We have exactly one match. Insert it.685 */686 687 /* Compute how many bytes of completion string we should skip. */688 size_t istart = str_lsize(compl[0], ti->pos - cstart);689 690 /* Insert remainder of completion string at current position. */691 tinput_insert_string(ti, compl[0] + istart);692 }693 694 for (i = 0; i < cnum; i++)695 free(compl[i]);696 free(compl);697 }698 699 513 /** Initialize text input field. 700 514 * … … 707 521 ti->hpos = 0; 708 522 ti->history[0] = NULL; 709 }710 711 /** Set prompt string.712 *713 * @param ti Text input714 * @param prompt Prompt string715 *716 * @return EOK on success, ENOMEM if out of memory.717 */718 int tinput_set_prompt(tinput_t *ti, const char *prompt)719 {720 if (ti->prompt != NULL)721 free(ti->prompt);722 723 ti->prompt = str_dup(prompt);724 if (ti->prompt == NULL)725 return ENOMEM;726 727 return EOK;728 }729 730 /** Set completion ops.731 *732 * Set pointer to completion ops structure that will be used for text733 * completion.734 */735 void tinput_set_compl_ops(tinput_t *ti, tinput_compl_ops_t *compl_ops)736 {737 ti->compl_ops = compl_ops;738 523 } 739 524 … … 754 539 return EIO; 755 540 541 if (console_get_pos(ti->console, &ti->col0, &ti->row0) != EOK) 542 return EIO; 543 756 544 ti->pos = 0; 757 545 ti->sel_start = 0; … … 761 549 ti->exit_clui = false; 762 550 763 if (tinput_display(ti) != EOK)764 return EIO;765 766 551 while (!ti->done) { 767 552 console_flush(ti->console); … … 929 714 tinput_history_seek(ti, -1); 930 715 break; 931 case KC_TAB:932 tinput_text_complete(ti);933 break;934 716 default: 935 717 break; -
uspace/lib/clui/tinput.h
r4069f5c r27eddb52 1 1 /* 2 * Copyright (c) 201 1Jiri Svoboda2 * Copyright (c) 2010 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 37 37 #define LIBCLUI_TINPUT_H_ 38 38 39 #include < adt/list.h>39 #include <stdio.h> 40 40 #include <async.h> 41 41 #include <inttypes.h> 42 42 #include <io/console.h> 43 #include <stdio.h>44 43 45 44 #define HISTORY_LEN 10 46 45 #define INPUT_MAX_SIZE 1024 47 48 /** Begin enumeration of text completions.49 *50 * When user requests text completion, tinput will call this function to start51 * text completion operation. @a *cstart should be set to the position52 * (character index) of the first character of the 'word' that is being53 * completed. The resulting text is obtained by replacing the range of text54 * starting at @a *cstart and ending at @a pos with the completion text.55 *56 * The function can pass information to the get_next and fini functions57 * via @a state. The init function allocates the state object and stores58 * a pointer to it to @a *state. The fini function destroys the state object.59 *60 * @param text Current contents of edit buffer (null-terminated).61 * @param pos Current caret position.62 * @param cstart Output, position in text where completion begins from.63 * @param state Output, pointer to a client state object.64 *65 * @return EOK on success, negative error code on failure.66 */67 typedef int (*tinput_compl_init_fn)(wchar_t *text, size_t pos, size_t *cstart,68 void **state);69 70 /** Obtain one text completion alternative.71 *72 * Upon success the function sets @a *compl to point to a string, the73 * completion text. The caller (Tinput) should not modify or free the text.74 * The pointer is only valid until the next invocation of any completion75 * function.76 *77 * @param state Pointer to state object created by the init funtion.78 * @param compl Output, the completion text, ownership retained.79 *80 * @return EOK on success, negative error code on failure.81 */82 typedef int (*tinput_compl_get_next_fn)(void *state, char **compl);83 84 85 /** Finish enumeration of text completions.86 *87 * The function must deallocate any state information allocated by the init88 * function or temporary data allocated by the get_next function.89 *90 * @param state Pointer to state object created by the init funtion.91 */92 typedef void (*tinput_compl_fini_fn)(void *state);93 94 /** Text completion ops. */95 typedef struct {96 tinput_compl_init_fn init;97 tinput_compl_get_next_fn get_next;98 tinput_compl_fini_fn fini;99 } tinput_compl_ops_t;100 46 101 47 /** Text input field (command line). … … 107 53 console_ctrl_t *console; 108 54 109 /** Prompt string */110 char *prompt;111 112 /** Completion ops. */113 tinput_compl_ops_t *compl_ops;114 115 55 /** Buffer holding text currently being edited */ 116 56 wchar_t buffer[INPUT_MAX_SIZE + 1]; 117 57 118 /** Linear position on screen where the prompt starts */ 119 unsigned prompt_coord; 120 /** Linear position on screen where the text field starts */ 121 unsigned text_coord; 58 /** Screen coordinates of the top-left corner of the text field */ 59 sysarg_t col0; 60 sysarg_t row0; 122 61 123 62 /** Screen dimensions */ … … 151 90 152 91 extern tinput_t *tinput_new(void); 153 extern int tinput_set_prompt(tinput_t *, const char *);154 extern void tinput_set_compl_ops(tinput_t *, tinput_compl_ops_t *);155 92 extern void tinput_destroy(tinput_t *); 156 93 extern int tinput_read(tinput_t *, char **); -
uspace/lib/drv/generic/driver.c
r4069f5c r27eddb52 620 620 return ENOMEM; 621 621 622 match_id->id = str_dup(match_id_str);622 match_id->id = match_id_str; 623 623 match_id->score = 90; 624 624 -
uspace/lib/usb/include/usb/classes/hub.h
r4069f5c r27eddb52 119 119 */ 120 120 uint16_t hub_characteristics; 121 #define HUB_CHAR_POWER_PER_PORT_FLAG (1 << 0)122 #define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)123 121 124 122 /** -
uspace/lib/usbhost/include/usb/host/endpoint.h
r4069f5c r27eddb52 61 61 } endpoint_t; 62 62 63 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,64 usb_ direction_t direction, usb_transfer_type_t type, usb_speed_t speed,65 size_t max_packet_size);63 int endpoint_init(endpoint_t *instance, usb_address_t address, 64 usb_endpoint_t endpoint, usb_direction_t direction, 65 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size); 66 66 67 67 void endpoint_destroy(endpoint_t *instance); -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
r4069f5c r27eddb52 82 82 size_t data_size) 83 83 { 84 endpoint_t *ep = endpoint_get( 85 address, endpoint, direction, type, speed, max_packet_size); 86 if (!ep) 84 endpoint_t *ep = malloc(sizeof(endpoint_t)); 85 if (ep == NULL) 87 86 return ENOMEM; 88 87 89 const int ret = 90 usb_endpoint_manager_register_ep(instance, ep, data_size); 88 int ret = endpoint_init(ep, address, endpoint, direction, type, speed, 89 max_packet_size); 90 if (ret != EOK) { 91 free(ep); 92 return ret; 93 } 94 95 ret = usb_endpoint_manager_register_ep(instance, ep, data_size); 91 96 if (ret != EOK) { 92 97 endpoint_destroy(ep); 98 return ret; 93 99 } 94 return ret;100 return EOK; 95 101 } 96 102 #endif -
uspace/lib/usbhost/src/batch.c
r4069f5c r27eddb52 109 109 assert(instance); 110 110 assert(instance->ep); 111 assert(instance->next_step);112 111 endpoint_release(instance->ep); 113 112 instance->next_step(instance); -
uspace/lib/usbhost/src/endpoint.c
r4069f5c r27eddb52 39 39 #include <usb/host/endpoint.h> 40 40 41 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,42 usb_ direction_t direction, usb_transfer_type_t type, usb_speed_t speed,43 size_t max_packet_size)41 int endpoint_init(endpoint_t *instance, usb_address_t address, 42 usb_endpoint_t endpoint, usb_direction_t direction, 43 usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size) 44 44 { 45 endpoint_t *instance = malloc(sizeof(endpoint_t)); 46 if (instance) { 47 instance->address = address; 48 instance->endpoint = endpoint; 49 instance->direction = direction; 50 instance->transfer_type = type; 51 instance->speed = speed; 52 instance->max_packet_size = max_packet_size; 53 instance->toggle = 0; 54 instance->active = false; 55 fibril_mutex_initialize(&instance->guard); 56 fibril_condvar_initialize(&instance->avail); 57 endpoint_clear_hc_data(instance); 58 } 59 return instance; 45 assert(instance); 46 instance->address = address; 47 instance->endpoint = endpoint; 48 instance->direction = direction; 49 instance->transfer_type = type; 50 instance->speed = speed; 51 instance->max_packet_size = max_packet_size; 52 instance->toggle = 0; 53 instance->active = false; 54 fibril_mutex_initialize(&instance->guard); 55 fibril_condvar_initialize(&instance->avail); 56 endpoint_clear_hc_data(instance); 57 return EOK; 60 58 } 61 59 /*----------------------------------------------------------------------------*/ -
uspace/srv/hid/input/ctl/stty.c
r4069f5c r27eddb52 34 34 * @file 35 35 * @brief Serial TTY-like keyboard controller driver. 36 *37 * Keyboard emulation on a serial terminal.38 36 */ 39 37 … … 65 63 #include <stdio.h> 66 64 67 /**68 * Sequnece definitions are primarily for Xterm. Additionally we define69 * sequences that are unique to Gnome terminal -- most are the same but70 * some differ.71 */72 65 static int seq_defs[] = { 73 66 /* Not shifted */ … … 88 81 0, KC_MINUS, 0x2d, GSP_END, 89 82 0, KC_EQUALS, 0x3d, GSP_END, 90 91 83 0, KC_BACKSPACE, 0x08, GSP_END, 92 84 … … 224 216 0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END, 225 217 226 /*227 * Sequences specific to Gnome terminal228 */229 0, KC_BACKSPACE, 0x7f, GSP_END, /* ASCII DEL */230 0, KC_HOME, 0x1b, 0x4f, 0x48, GSP_END,231 0, KC_END, 0x1b, 0x4f, 0x46, GSP_END,232 233 218 0, 0 234 219 }; -
uspace/srv/hid/input/generic/gsp.c
r4069f5c r27eddb52 104 104 if (key == 0) break; 105 105 106 /* Insert one sequence. */ 106 /* Insert one sequence. */ 107 107 rc = gsp_insert_seq(p, dp, mods, key); 108 108 if (rc != 0) … … 197 197 198 198 if (t == NULL) { 199 printf("gsp_step: not found, state=%d, input=0x%x\n", 200 state, input); 199 printf("gsp_step: not found\n"); 201 200 *mods = 0; 202 201 *key = 0; … … 206 205 *mods = t->out_mods; 207 206 *key = t->out_key; 208 209 207 return t->new_state; 210 208 } -
uspace/srv/hid/input/generic/input.c
r4069f5c r27eddb52 410 410 #endif 411 411 #if defined(MACHINE_msim) 412 kbd_add_dev(&msim_port, & stty_ctl);412 kbd_add_dev(&msim_port, &pc_ctl); 413 413 #endif 414 414 #if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
Note:
See TracChangeset
for help on using the changeset viewer.