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

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

Fixed: use proper device enumeration procedure

  • Property mode set to 100644
File size: 4.1 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 uhci_port_new_device(port_instance);
40 } else {
41 uhci_port_remove_device(port_instance);
42 }
43 }
44 async_usleep(port_instance->wait_period_usec);
45 }
46 return EOK;
47}
48/*----------------------------------------------------------------------------*/
49static int uhci_port_new_device(uhci_port_t *port)
50{
51 assert(port);
52 assert(port->hc);
53
54 uhci_print_info("Adding new device on port %d.\n", port->number);
55
56 uhci_t *uhci_instance = (uhci_t*)(port->hc->driver_data);
57
58 /* get default address */
59 usb_address_keeping_reserve_default(&uhci_instance->address_manager);
60
61 const usb_address_t usb_address =
62 usb_address_keeping_request(&uhci_instance->address_manager);
63
64 if (usb_address <= 0) {
65 return usb_address;
66 }
67 /*
68 * the host then waits for at least 100 ms to allow completion of
69 * an insertion process and for power at the device to become stable.
70 */
71 async_usleep(100000);
72
73 /* enable port */
74 uhci_port_set_enabled(port, true);
75
76 /* The hub maintains the reset signal to that port for 10 ms
77 * (See Section 11.5.1.5)
78 */
79 port_status_t port_status =
80 port_status_read(port->address);
81 port_status |= STATUS_IN_RESET;
82 port_status_write(port->address, port_status);
83 async_usleep(10000);
84 port_status =
85 port_status_read(port->address);
86 port_status &= ~STATUS_IN_RESET;
87 port_status_write(port->address, port_status);
88
89 /* assign address to device */
90 int ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
91
92
93 if (ret != EOK) { /* address assigning went wrong */
94 uhci_print_error("Failed(%d) to assign address to the device.\n", ret);
95 uhci_port_set_enabled(port, false);
96 usb_address_keeping_release_default(&uhci_instance->address_manager);
97 return ENOMEM;
98 }
99
100 /* release default address */
101 usb_address_keeping_release_default(&uhci_instance->address_manager);
102
103 /* communicate and possibly report to devman */
104 assert(port->attached_device == 0);
105
106 ret = usb_drv_register_child_in_devman(port->hc_phone, port->hc, usb_address,
107 &port->attached_device);
108
109 if (ret != EOK) { /* something went wrong */
110 uhci_print_error("Failed(%d) in usb_drv_register_child.\n", ret);
111 uhci_port_set_enabled(port, false);
112 return ENOMEM;
113 }
114
115 return EOK;
116}
117/*----------------------------------------------------------------------------*/
118static int uhci_port_remove_device(uhci_port_t *port)
119{
120 uhci_print_error("Don't know how to remove device %#x.\n",
121 port->attached_device);
122 uhci_port_set_enabled(port, false);
123 return EOK;
124}
125/*----------------------------------------------------------------------------*/
126static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
127{
128 assert(port);
129
130 /* read register value */
131 port_status_t port_status
132 = port_status_read(port->address);
133
134 /* enable port: register write */
135 if (enabled) {
136 port_status |= STATUS_ENABLED;
137 } else {
138 port_status &= ~STATUS_ENABLED;
139 }
140 port_status_write(port->address, port_status);
141
142 uhci_print_info("%s port %d.\n",
143 enabled ? "Enabled" : "Disabled", port->number);
144 return EOK;
145}
146/*----------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.