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

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

Refactoring move usb generics to usb_device.c

  • Property mode set to 100644
File size: 5.0 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
6#include "debug.h"
7#include "uhci.h"
8#include "port.h"
9#include "port_status.h"
10#include "utils/hc_synchronizer.h"
11#include "utils/usb_device.h"
12
13static int uhci_port_new_device(uhci_port_t *port);
14static int uhci_port_remove_device(uhci_port_t *port);
15static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
16static usb_address_t assign_address_to_zero_device(device_t *hc);
17
18/*----------------------------------------------------------------------------*/
19int uhci_port_check(void *port)
20{
21 uhci_port_t *port_instance = port;
22 assert(port_instance);
23
24 while (1) {
25 uhci_print_info("Port(%d) status address %p:\n",
26 port_instance->number, port_instance->address);
27
28 /* read register value */
29 port_status_t port_status =
30 port_status_read(port_instance->address);
31
32 /* debug print */
33 uhci_print_info("Port(%d) status %#.4x:\n",
34 port_instance->number, port_status);
35 print_port_status( port_status );
36
37 if (port_status & STATUS_CONNECTED_CHANGED) {
38 if (port_status & STATUS_CONNECTED) {
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 /* enable port */
62 uhci_port_set_enabled( port, true );
63
64 /* assign address to device */
65 usb_address_t address = assign_address_to_zero_device(port->hc);
66
67
68 if (address <= 0) { /* address assigning went wrong */
69 uhci_print_error("Failed to assign address to the device.\n");
70 uhci_port_set_enabled(port, false);
71 usb_address_keeping_release_default(&uhci_instance->address_manager);
72 return ENOMEM;
73 }
74
75 /* release default address */
76 usb_address_keeping_release_default(&uhci_instance->address_manager);
77
78 /* communicate and possibly report to devman */
79 assert(port->attached_device == 0);
80
81#define CHECK_RET_DELETE_CHILD_RETURN(ret, child, message, args...)\
82 if (ret < 0) { \
83 uhci_print_error("Failed(%d) to "message, ret, ##args); \
84 if (child) { \
85 delete_device(child); \
86 } \
87 uhci_port_set_enabled(port, false); \
88 usb_address_keeping_release(&uhci_instance->address_manager, address); \
89 return ret; \
90 } else (void)0
91
92 device_t *child = create_device();
93
94 int ret = child ? EOK : ENOMEM;
95 CHECK_RET_DELETE_CHILD_RETURN(ret, child, "create device.\n" );
96
97 ret = usb_device_init(child, port->hc, address, port->number );
98 CHECK_RET_DELETE_CHILD_RETURN(ret, child, "init usb device.\n" );
99
100 ret = child_device_register(child, port->hc);
101 CHECK_RET_DELETE_CHILD_RETURN(ret, child, "register usb device.\n" );
102
103 /* store device and bind address, can not fail */
104 port->attached_device = child->handle;
105 usb_address_keeping_devman_bind(&uhci_instance->address_manager,
106 address, port->attached_device);
107
108 return EOK;
109}
110/*----------------------------------------------------------------------------*/
111static int uhci_port_remove_device(uhci_port_t *port)
112{
113 uhci_print_error( "Don't know how to remove device %#x.\n",
114 port->attached_device);
115 uhci_port_set_enabled(port, false);
116 return EOK;
117}
118/*----------------------------------------------------------------------------*/
119static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
120{
121 assert(port);
122
123 /* read register value */
124 port_status_t port_status
125 = port_status_read(port->address);
126
127 /* enable port: register write */
128 if (enabled) {
129 port_status |= STATUS_ENABLED;
130 } else {
131 port_status &= ~STATUS_ENABLED;
132 }
133 port_status_write( port->address, port_status );
134
135 uhci_print_info( "%s port %d.\n",
136 enabled ? "Enabled" : "Disabled", port->number );
137 return EOK;
138}
139/*----------------------------------------------------------------------------*/
140static usb_address_t assign_address_to_zero_device( device_t *hc )
141{
142 assert( hc );
143 assert( hc->driver_data );
144
145 uhci_t *uhci_instance = (uhci_t*)hc->driver_data;
146
147 /* get new address */
148 const usb_address_t usb_address =
149 usb_address_keeping_request(&uhci_instance->address_manager);
150
151 if (usb_address <= 0) {
152 return usb_address;
153 }
154
155 /* assign new address */
156 usb_target_t new_device = { USB_ADDRESS_DEFAULT, 0 };
157 usb_device_request_setup_packet_t data =
158 {
159 .request_type = 0,
160 .request = USB_DEVREQ_SET_ADDRESS,
161 { .value = usb_address },
162 .index = 0,
163 .length = 0
164 };
165
166 sync_value_t sync;
167 uhci_setup_sync(hc, new_device,
168 USB_TRANSFER_CONTROL, &data, sizeof(data), &sync);
169
170 if (sync.result != USB_OUTCOME_OK) {
171 uhci_print_error(
172 "Failed to assign address to the connected device.\n");
173 usb_address_keeping_release(&uhci_instance->address_manager,
174 usb_address);
175 return -1;
176 }
177
178 uhci_print_info("Assigned address %#x.\n", usb_address);
179 return usb_address;
180}
Note: See TracBrowser for help on using the repository browser.