00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <errno.h>
00036 #include <usb/classes/hub.h>
00037 #include <usbvirt/device.h>
00038 #include "virthub.h"
00039 #include "hub.h"
00040
00042 static void on_state_change(usbvirt_device_t *dev,
00043 usbvirt_device_state_t old_state, usbvirt_device_state_t new_state)
00044 {
00045 hub_t *hub = (hub_t *)dev->device_data;
00046
00047 hub_acquire(hub);
00048
00049 switch (new_state) {
00050 case USBVIRT_STATE_CONFIGURED:
00051 hub_set_port_state_all(hub, HUB_PORT_STATE_POWERED_OFF);
00052 break;
00053 case USBVIRT_STATE_ADDRESS:
00054 hub_set_port_state_all(hub, HUB_PORT_STATE_NOT_CONFIGURED);
00055 break;
00056 default:
00057 break;
00058 }
00059
00060 hub_release(hub);
00061 }
00062
00064 static int req_on_status_change_pipe(usbvirt_device_t *dev,
00065 usb_endpoint_t endpoint, usb_transfer_type_t tr_type,
00066 void *buffer, size_t buffer_size, size_t *actual_size)
00067 {
00068 if (endpoint != HUB_STATUS_CHANGE_PIPE) {
00069 return ESTALL;
00070 }
00071 if (tr_type != USB_TRANSFER_INTERRUPT) {
00072 return ESTALL;
00073 }
00074
00075 hub_t *hub = dev->device_data;
00076
00077 hub_acquire(hub);
00078
00079 if (!hub->signal_changes) {
00080 hub_release(hub);
00081
00082 return ENAK;
00083 }
00084
00085
00086 uint8_t change_map = hub_get_status_change_bitmap(hub);
00087
00088 uint8_t *b = (uint8_t *) buffer;
00089 if (buffer_size > 0) {
00090 *b = change_map;
00091 *actual_size = 1;
00092 } else {
00093 *actual_size = 0;
00094 }
00095
00096 hub->signal_changes = false;
00097
00098 hub_release(hub);
00099
00100 return EOK;
00101 }
00102
00110 static int req_clear_hub_feature(usbvirt_device_t *dev,
00111 const usb_device_request_setup_packet_t *request, uint8_t *data,
00112 size_t *act_size)
00113 {
00114 return ENOTSUP;
00115 }
00116
00124 static int req_clear_port_feature(usbvirt_device_t *dev,
00125 const usb_device_request_setup_packet_t *request, uint8_t *data,
00126 size_t *act_size)
00127 {
00128 int rc;
00129 size_t port = request->index - 1;
00130 usb_hub_class_feature_t feature = request->value;
00131 hub_t *hub = (hub_t *) dev->device_data;
00132
00133 hub_acquire(hub);
00134
00135 hub_port_state_t port_state = hub_get_port_state(hub, port);
00136
00137 switch (feature) {
00138 case USB_HUB_FEATURE_PORT_ENABLE:
00139 if ((port_state != HUB_PORT_STATE_NOT_CONFIGURED)
00140 && (port_state != HUB_PORT_STATE_POWERED_OFF)) {
00141 hub_set_port_state(hub, port, HUB_PORT_STATE_DISABLED);
00142 }
00143 rc = EOK;
00144 break;
00145
00146 case USB_HUB_FEATURE_PORT_SUSPEND:
00147 if (port_state != HUB_PORT_STATE_SUSPENDED) {
00148 rc = EOK;
00149 break;
00150 }
00151 hub_set_port_state(hub, port, HUB_PORT_STATE_RESUMING);
00152 rc = EOK;
00153 break;
00154
00155 case USB_HUB_FEATURE_PORT_POWER:
00156 if (port_state != HUB_PORT_STATE_NOT_CONFIGURED) {
00157 hub_set_port_state(hub, port, HUB_PORT_STATE_POWERED_OFF);
00158 }
00159 rc = EOK;
00160 break;
00161
00162 case USB_HUB_FEATURE_C_PORT_CONNECTION:
00163 hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_CONNECTION);
00164 rc = EOK;
00165 break;
00166
00167 case USB_HUB_FEATURE_C_PORT_ENABLE:
00168 hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_ENABLE);
00169 rc = EOK;
00170 break;
00171
00172 case USB_HUB_FEATURE_C_PORT_SUSPEND:
00173 hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_SUSPEND);
00174 rc = EOK;
00175 break;
00176
00177 case USB_HUB_FEATURE_C_PORT_OVER_CURRENT:
00178 hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_OVER_CURRENT);
00179 rc = EOK;
00180 break;
00181
00182 case USB_HUB_FEATURE_C_PORT_RESET:
00183 hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_RESET);
00184 rc = EOK;
00185 break;
00186
00187 default:
00188 rc = ENOTSUP;
00189 break;
00190 }
00191
00192 hub_release(hub);
00193
00194 return rc;
00195 }
00196
00204 static int req_get_bus_state(usbvirt_device_t *dev,
00205 const usb_device_request_setup_packet_t *request, uint8_t *data,
00206 size_t *act_size)
00207 {
00208 return ENOTSUP;
00209 }
00210
00218 static int req_get_descriptor(usbvirt_device_t *dev,
00219 const usb_device_request_setup_packet_t *request, uint8_t *data,
00220 size_t *act_size)
00221 {
00222 if (request->value_high == USB_DESCTYPE_HUB) {
00223 usbvirt_control_reply_helper(request, data, act_size,
00224 &hub_descriptor, hub_descriptor.length);
00225
00226 return EOK;
00227 }
00228
00229 return EFORWARD;
00230 }
00231
00239 static int req_get_hub_status(usbvirt_device_t *dev,
00240 const usb_device_request_setup_packet_t *request, uint8_t *data,
00241 size_t *act_size)
00242 {
00243 uint32_t hub_status = 0;
00244
00245 usbvirt_control_reply_helper(request, data, act_size,
00246 &hub_status, sizeof(hub_status));
00247
00248 return EOK;
00249 }
00250
00258 static int req_get_port_status(usbvirt_device_t *dev,
00259 const usb_device_request_setup_packet_t *request, uint8_t *data,
00260 size_t *act_size)
00261 {
00262 hub_t *hub = (hub_t *) dev->device_data;
00263
00264 hub_acquire(hub);
00265
00266 uint32_t status = hub_get_port_status(hub, request->index - 1);
00267
00268 hub_release(hub);
00269
00270 usbvirt_control_reply_helper(request, data, act_size,
00271 &status, sizeof(status));
00272
00273 return EOK;
00274 }
00275
00283 static int req_set_hub_feature(usbvirt_device_t *dev,
00284 const usb_device_request_setup_packet_t *request, uint8_t *data,
00285 size_t *act_size)
00286 {
00287 return ENOTSUP;
00288 }
00289
00297 static int req_set_port_feature(usbvirt_device_t *dev,
00298 const usb_device_request_setup_packet_t *request, uint8_t *data,
00299 size_t *act_size)
00300 {
00301 int rc;
00302 size_t port = request->index - 1;
00303 usb_hub_class_feature_t feature = request->value;
00304 hub_t *hub = (hub_t *) dev->device_data;
00305
00306 hub_acquire(hub);
00307
00308 hub_port_state_t port_state = hub_get_port_state(hub, port);
00309
00310 switch (feature) {
00311 case USB_HUB_FEATURE_PORT_RESET:
00312 if (port_state != HUB_PORT_STATE_POWERED_OFF) {
00313 hub_set_port_state(hub, port, HUB_PORT_STATE_RESETTING);
00314 }
00315 rc = EOK;
00316 break;
00317
00318 case USB_HUB_FEATURE_PORT_SUSPEND:
00319 if (port_state == HUB_PORT_STATE_ENABLED) {
00320 hub_set_port_state(hub, port, HUB_PORT_STATE_SUSPENDED);
00321 }
00322 rc = EOK;
00323 break;
00324
00325 case USB_HUB_FEATURE_PORT_POWER:
00326 if (port_state == HUB_PORT_STATE_POWERED_OFF) {
00327 hub_set_port_state(hub, port, HUB_PORT_STATE_DISCONNECTED);
00328 }
00329 rc = EOK;
00330 break;
00331
00332 default:
00333 break;
00334 }
00335
00336 hub_release(hub);
00337
00338 return rc;
00339 }
00340
00341
00343 #define CLASS_REQ_IN(recipient) \
00344 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \
00345 USBVIRT_REQUEST_TYPE_CLASS, recipient)
00346
00347 #define CLASS_REQ_OUT(recipient) \
00348 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \
00349 USBVIRT_REQUEST_TYPE_CLASS, recipient)
00350
00352 #define REC_OTHER USB_REQUEST_RECIPIENT_OTHER
00353
00354 #define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE
00355
00356 #define DIR_IN USB_DIRECTION_IN
00357
00358 #define DIR_OUT USB_DIRECTION_OUT
00359
00360
00367 #define CLASS_REQ(direction, recipient, req) \
00368 .req_direction = direction, \
00369 .req_recipient = recipient, \
00370 .req_type = USB_REQUEST_TYPE_CLASS, \
00371 .request = req
00372
00379 #define STD_REQ(direction, recipient, req) \
00380 .req_direction = direction, \
00381 .req_recipient = recipient, \
00382 .req_type = USB_REQUEST_TYPE_STANDARD, \
00383 .request = req
00384
00386 static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
00387 {
00388 STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
00389 .name = "GetDescriptor",
00390 .callback = req_get_descriptor
00391 },
00392 {
00393 CLASS_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
00394 .name = "GetDescriptor",
00395 .callback = req_get_descriptor
00396 },
00397 {
00398 CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
00399 .name = "GetPortStatus",
00400 .callback = req_get_port_status
00401 },
00402 {
00403 CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
00404 .name = "ClearHubFeature",
00405 .callback = req_clear_hub_feature
00406 },
00407 {
00408 CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
00409 .name = "ClearPortFeature",
00410 .callback = req_clear_port_feature
00411 },
00412 {
00413 CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATE),
00414 .name = "GetBusState",
00415 .callback = req_get_bus_state
00416 },
00417 {
00418 CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
00419 .name = "GetHubDescriptor",
00420 .callback = req_get_descriptor
00421 },
00422 {
00423 CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),
00424 .name = "GetHubStatus",
00425 .callback = req_get_hub_status
00426 },
00427 {
00428 CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
00429 .name = "GetPortStatus",
00430 .callback = req_get_port_status
00431 },
00432 {
00433 CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
00434 .name = "SetHubFeature",
00435 .callback = req_set_hub_feature
00436 },
00437 {
00438 CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),
00439 .name = "SetPortFeature",
00440 .callback = req_set_port_feature
00441 },
00442 {
00443 .callback = NULL
00444 }
00445 };
00446
00447
00449 usbvirt_device_ops_t hub_ops = {
00450 .control = endpoint_zero_handlers,
00451 .data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe,
00452 .state_changed = on_state_change,
00453 };
00454