source: mainline/uspace/drv/uhci/root_hub/port.c@ f0e25e8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f0e25e8 was f0e25e8, checked in by Jan Vesely <jano.vesely@…>, 15 years ago

Fixed: reset port after detecting a new device

  • Property mode set to 100644
File size: 3.8 KB
Line 
1
2#include <errno.h>
3//#include <usb/devreq.h> /* for usb_device_request_setup_packet_t */
4#include <usb/usb.h>
5#include <usb/usbdrv.h>
6
7#include "debug.h"
8#include "uhci.h"
9#include "port.h"
10#include "port_status.h"
11
12static int uhci_port_new_device(uhci_port_t *port);
13static int uhci_port_remove_device(uhci_port_t *port);
14static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
15
16/*----------------------------------------------------------------------------*/
17int uhci_port_check(void *port)
18{
19 uhci_port_t *port_instance = port;
20 assert(port_instance);
21 port_instance->hc_phone = devman_device_connect(port_instance->hc->handle, 0);
22
23 while (1) {
24 uhci_print_info("Port(%d) status address %p:\n",
25 port_instance->number, port_instance->address);
26
27 /* read register value */
28 port_status_t port_status =
29 port_status_read(port_instance->address);
30
31 /* debug print */
32 uhci_print_info("Port(%d) status %#.4x:\n",
33 port_instance->number, port_status);
34 print_port_status(port_status);
35
36 if (port_status & STATUS_CONNECTED_CHANGED) {
37 if (port_status & STATUS_CONNECTED) {
38 /* new device */
39 port_status |= STATUS_IN_RESET;
40 port_status_write(port_instance->address, port_status);
41 async_usleep(1000);
42 port_status =
43 port_status_read(port_instance->address);
44 port_status &= ~STATUS_IN_RESET;
45 port_status_write(port_instance->address, port_status);
46 uhci_port_new_device(port_instance);
47 } else {
48 uhci_port_remove_device(port_instance);
49 }
50 }
51 async_usleep(port_instance->wait_period_usec);
52 }
53 return EOK;
54}
55/*----------------------------------------------------------------------------*/
56static int uhci_port_new_device(uhci_port_t *port)
57{
58 assert(port);
59 assert(port->hc);
60
61 uhci_print_info("Adding new device on port %d.\n", port->number);
62
63 uhci_t *uhci_instance = (uhci_t*)(port->hc->driver_data);
64
65 /* get default address */
66 usb_address_keeping_reserve_default(&uhci_instance->address_manager);
67
68 const usb_address_t usb_address =
69 usb_address_keeping_request(&uhci_instance->address_manager);
70
71 if (usb_address <= 0) {
72 return usb_address;
73 }
74
75 /* enable port */
76 uhci_port_set_enabled(port, true);
77
78 /* assign address to device */
79 int ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
80
81
82 if (ret != EOK) { /* address assigning went wrong */
83 uhci_print_error("Failed(%d) to assign address to the device.\n", ret);
84 uhci_port_set_enabled(port, false);
85 usb_address_keeping_release_default(&uhci_instance->address_manager);
86 return ENOMEM;
87 }
88
89 /* release default address */
90 usb_address_keeping_release_default(&uhci_instance->address_manager);
91
92 /* communicate and possibly report to devman */
93 assert(port->attached_device == 0);
94
95 ret = usb_drv_register_child_in_devman(port->hc_phone, port->hc, usb_address,
96 &port->attached_device);
97
98 if (ret != EOK) { /* something went wrong */
99 uhci_print_error("Failed(%d) in usb_drv_register_child.\n", ret);
100 uhci_port_set_enabled(port, false);
101 return ENOMEM;
102 }
103
104 return EOK;
105}
106/*----------------------------------------------------------------------------*/
107static int uhci_port_remove_device(uhci_port_t *port)
108{
109 uhci_print_error("Don't know how to remove device %#x.\n",
110 port->attached_device);
111 uhci_port_set_enabled(port, false);
112 return EOK;
113}
114/*----------------------------------------------------------------------------*/
115static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
116{
117 assert(port);
118
119 /* read register value */
120 port_status_t port_status
121 = port_status_read(port->address);
122
123 /* enable port: register write */
124 if (enabled) {
125 port_status |= STATUS_ENABLED;
126 } else {
127 port_status &= ~STATUS_ENABLED;
128 }
129 port_status_write(port->address, port_status);
130
131 uhci_print_info("%s port %d.\n",
132 enabled ? "Enabled" : "Disabled", port->number);
133 return EOK;
134}
135/*----------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.