Changes in / [dc4c19e:a49e171] in mainline
- Location:
- uspace
- Files:
-
- 6 deleted
- 54 edited
-
app/usbinfo/dev.c (modified) (4 diffs)
-
doc/doxygroups.h (modified) (2 diffs)
-
drv/ehci-hcd/hc_iface.c (modified) (14 diffs)
-
drv/ohci/Makefile (modified) (1 diff)
-
drv/ohci/batch.c (modified) (9 diffs)
-
drv/ohci/batch.h (modified) (2 diffs)
-
drv/ohci/hc.c (modified) (11 diffs)
-
drv/ohci/hc.h (modified) (2 diffs)
-
drv/ohci/hw_struct/completion_codes.h (modified) (2 diffs)
-
drv/ohci/hw_struct/endpoint_descriptor.c (deleted)
-
drv/ohci/hw_struct/endpoint_descriptor.h (modified) (3 diffs)
-
drv/ohci/hw_struct/transfer_descriptor.c (deleted)
-
drv/ohci/hw_struct/transfer_descriptor.h (modified) (3 diffs)
-
drv/ohci/iface.c (modified) (20 diffs)
-
drv/ohci/ohci_regs.h (modified) (1 diff)
-
drv/ohci/root_hub.c (modified) (32 diffs)
-
drv/ohci/transfer_list.c (deleted)
-
drv/ohci/transfer_list.h (deleted)
-
drv/ohci/utils/malloc32.h (modified) (1 diff)
-
drv/uhci-hcd/batch.c (modified) (3 diffs)
-
drv/uhci-hcd/batch.h (modified) (1 diff)
-
drv/uhci-hcd/hc.c (modified) (3 diffs)
-
drv/uhci-hcd/iface.c (modified) (16 diffs)
-
drv/uhci-hcd/transfer_list.c (modified) (3 diffs)
-
drv/uhci-rhd/root_hub.h (modified) (1 diff)
-
drv/usbhub/Makefile (modified) (1 diff)
-
drv/usbhub/port_status.h (modified) (15 diffs)
-
drv/usbhub/ports.c (modified) (8 diffs)
-
drv/usbhub/ports.h (modified) (3 diffs)
-
drv/usbhub/usbhub.c (modified) (13 diffs)
-
drv/usbhub/usbhub.h (modified) (3 diffs)
-
drv/usbhub/usbhub_private.h (modified) (2 diffs)
-
drv/usbhub/utils.c (modified) (3 diffs)
-
drv/usbmid/main.c (modified) (2 diffs)
-
drv/vhc/connhost.c (modified) (6 diffs)
-
lib/drv/generic/remote_usbhc.c (modified) (12 diffs)
-
lib/drv/include/usbhc_iface.h (modified) (7 diffs)
-
lib/usb/Makefile (modified) (1 diff)
-
lib/usb/include/usb/classes/hub.h (modified) (2 diffs)
-
lib/usb/include/usb/devdrv.h (modified) (1 diff)
-
lib/usb/include/usb/host/batch.h (modified) (1 diff)
-
lib/usb/include/usb/host/device_keeper.h (modified) (2 diffs)
-
lib/usb/include/usb/host/endpoint.h (modified) (3 diffs)
-
lib/usb/include/usb/host/usb_endpoint_manager.h (modified) (1 diff)
-
lib/usb/include/usb/hub.h (modified) (1 diff)
-
lib/usb/include/usb/pipes.h (modified) (5 diffs)
-
lib/usb/include/usb/usb.h (modified) (1 diff)
-
lib/usb/src/devdrv.c (modified) (7 diffs)
-
lib/usb/src/devpoll.c (modified) (1 diff)
-
lib/usb/src/host/batch.c (modified) (3 diffs)
-
lib/usb/src/host/device_keeper.c (modified) (3 diffs)
-
lib/usb/src/host/endpoint.c (modified) (4 diffs)
-
lib/usb/src/host/usb_endpoint_manager.c (modified) (3 diffs)
-
lib/usb/src/hub.c (modified) (8 diffs)
-
lib/usb/src/pipepriv.c (deleted)
-
lib/usb/src/pipepriv.h (deleted)
-
lib/usb/src/pipes.c (modified) (6 diffs)
-
lib/usb/src/pipesinit.c (modified) (5 diffs)
-
lib/usb/src/pipesio.c (modified) (20 diffs)
-
lib/usb/src/recognise.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/usbinfo/dev.c
rdc4c19e ra49e171 50 50 51 51 int rc; 52 bool transfer_started = false;53 52 54 53 rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr); … … 77 76 } 78 77 79 rc = usb_pipe_start_ long_transfer(&dev->ctrl_pipe);78 rc = usb_pipe_start_session(&dev->ctrl_pipe); 80 79 if (rc != EOK) { 81 80 fprintf(stderr, 82 NAME ": failed to start transferon control pipe: %s.\n",81 NAME ": failed to start session on control pipe: %s.\n", 83 82 str_error(rc)); 84 83 goto leave; 85 84 } 86 transfer_started = true;87 85 88 86 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, … … 109 107 110 108 leave: 111 if ( transfer_started) {112 usb_pipe_end_ long_transfer(&dev->ctrl_pipe);109 if (usb_pipe_is_session_started(&dev->ctrl_pipe)) { 110 usb_pipe_end_session(&dev->ctrl_pipe); 113 111 } 114 112 … … 120 118 void destroy_device(usbinfo_device_t *dev) 121 119 { 122 usb_pipe_end_ long_transfer(&dev->ctrl_pipe);120 usb_pipe_end_session(&dev->ctrl_pipe); 123 121 free(dev); 124 122 } -
uspace/doc/doxygroups.h
rdc4c19e ra49e171 269 269 270 270 /** 271 * @defgroup drvusbohci OHCI driver272 * @ingroup usb273 * @brief Driver for OHCI host controller.274 */275 276 /**277 271 * @defgroup drvusbehci EHCI driver 278 272 * @ingroup usb … … 281 275 282 276 /** 283 * @defgroup drvusbfallback USB fallback driver 277 * @defgroup drvusbfallback USB fallback driver. 284 278 * @ingroup usb 285 279 * @brief Fallback driver for any USB device. -
uspace/drv/ehci-hcd/hc_iface.c
rdc4c19e ra49e171 123 123 * @param[in] fun Device function the action was invoked on. 124 124 * @param[in] address USB address of the device. 125 * @param[in] speed Endpoint speed (invalid means to use device one).126 125 * @param[in] endpoint Endpoint number. 127 126 * @param[in] transfer_type USB transfer type. … … 132 131 */ 133 132 static int register_endpoint(ddf_fun_t *fun, 134 usb_address_t address, usb_ speed_t speed, usb_endpoint_t endpoint,133 usb_address_t address, usb_endpoint_t endpoint, 135 134 usb_transfer_type_t transfer_type, usb_direction_t direction, 136 135 size_t max_packet_size, unsigned int interval) … … 166 165 * @param[in] fun Device function the action was invoked on. 167 166 * @param[in] target Target pipe (address and endpoint number) specification. 167 * @param[in] max_packet_size Max packet size for the transfer. 168 168 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 169 169 * by the caller). … … 174 174 */ 175 175 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 176 void *data, size_t size,176 size_t max_packet_size, void *data, size_t size, 177 177 usbhc_iface_transfer_out_callback_t callback, void *arg) 178 178 { … … 191 191 * @param[in] fun Device function the action was invoked on. 192 192 * @param[in] target Target pipe (address and endpoint number) specification. 193 * @param[in] max_packet_size Max packet size for the transfer. 193 194 * @param[in] data Buffer where to store the data (in USB endianess, 194 195 * allocated and deallocated by the caller). … … 199 200 */ 200 201 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 201 void *data, size_t size,202 size_t max_packet_size, void *data, size_t size, 202 203 usbhc_iface_transfer_in_callback_t callback, void *arg) 203 204 { … … 216 217 * @param[in] fun Device function the action was invoked on. 217 218 * @param[in] target Target pipe (address and endpoint number) specification. 219 * @param[in] max_packet_size Max packet size for the transfer. 218 220 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 219 221 * by the caller). … … 224 226 */ 225 227 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 226 void *data, size_t size,228 size_t max_packet_size, void *data, size_t size, 227 229 usbhc_iface_transfer_out_callback_t callback, void *arg) 228 230 { … … 241 243 * @param[in] fun Device function the action was invoked on. 242 244 * @param[in] target Target pipe (address and endpoint number) specification. 245 * @param[in] max_packet_size Max packet size for the transfer. 243 246 * @param[in] data Buffer where to store the data (in USB endianess, 244 247 * allocated and deallocated by the caller). … … 249 252 */ 250 253 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 251 void *data, size_t size,254 size_t max_packet_size, void *data, size_t size, 252 255 usbhc_iface_transfer_in_callback_t callback, void *arg) 253 256 { … … 266 269 * @param[in] fun Device function the action was invoked on. 267 270 * @param[in] target Target pipe (address and endpoint number) specification. 271 * @param[in] max_packet_size Max packet size for the transfer. 268 272 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 269 273 * and deallocated by the caller). … … 277 281 */ 278 282 static int control_write(ddf_fun_t *fun, usb_target_t target, 283 size_t max_packet_size, 279 284 void *setup_packet, size_t setup_packet_size, 280 285 void *data_buffer, size_t data_buffer_size, … … 295 300 * @param[in] fun Device function the action was invoked on. 296 301 * @param[in] target Target pipe (address and endpoint number) specification. 302 * @param[in] max_packet_size Max packet size for the transfer. 297 303 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 298 304 * and deallocated by the caller). … … 306 312 */ 307 313 static int control_read(ddf_fun_t *fun, usb_target_t target, 314 size_t max_packet_size, 308 315 void *setup_packet, size_t setup_packet_size, 309 316 void *data_buffer, size_t data_buffer_size, -
uspace/drv/ohci/Makefile
rdc4c19e ra49e171 33 33 34 34 SOURCES = \ 35 iface.c \ 35 36 batch.c \ 37 main.c \ 36 38 hc.c \ 37 iface.c \38 main.c \39 39 ohci.c \ 40 pci.c \41 40 root_hub.c \ 42 transfer_list.c \ 43 hw_struct/endpoint_descriptor.c \ 44 hw_struct/transfer_descriptor.c 45 41 pci.c 46 42 47 43 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/ohci/batch.c
rdc4c19e ra49e171 40 40 #include "batch.h" 41 41 #include "utils/malloc32.h" 42 #include "hw_struct/endpoint_descriptor.h"43 #include "hw_struct/transfer_descriptor.h"44 42 45 typedef struct ohci_batch {46 ed_t *ed;47 td_t *tds;48 size_t td_count;49 } ohci_batch_t;50 51 static void batch_control(usb_transfer_batch_t *instance,52 usb_direction_t data_dir, usb_direction_t status_dir);53 43 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance); 54 44 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance); 55 45 56 46 #define DEFAULT_ERROR_COUNT 3 57 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, 58 char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size, 47 usb_transfer_batch_t * batch_get( 48 ddf_fun_t *fun, 49 usb_target_t target, 50 usb_transfer_type_t transfer_type, 51 size_t max_packet_size, 52 usb_speed_t speed, 53 char *buffer, 54 size_t buffer_size, 55 char *setup_buffer, 56 size_t setup_size, 59 57 usbhc_iface_transfer_in_callback_t func_in, 60 usbhc_iface_transfer_out_callback_t func_out, void *arg) 58 usbhc_iface_transfer_out_callback_t func_out, 59 void *arg, 60 usb_device_keeper_t *manager 61 ) 61 62 { 62 63 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \ … … 72 73 CHECK_NULL_DISPOSE_RETURN(instance, 73 74 "Failed to allocate batch instance.\n"); 74 usb_target_t target = 75 { .address = ep->address, .endpoint = ep->endpoint }; 76 usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed, 77 ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size, 78 func_in, func_out, arg, fun, ep, NULL); 79 80 ohci_batch_t *data = malloc(sizeof(ohci_batch_t)); 81 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 82 bzero(data, sizeof(ohci_batch_t)); 83 instance->private_data = data; 84 85 /* we needs + 1 transfer descriptor as the last one won't be executed */ 86 data->td_count = 1 + 87 ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER); 88 if (ep->transfer_type == USB_TRANSFER_CONTROL) { 89 data->td_count += 2; 90 } 91 92 data->tds = malloc32(sizeof(td_t) * data->td_count); 93 CHECK_NULL_DISPOSE_RETURN(data->tds, 94 "Failed to allocate transfer descriptors.\n"); 95 bzero(data->tds, sizeof(td_t) * data->td_count); 96 97 data->ed = malloc32(sizeof(ed_t)); 98 CHECK_NULL_DISPOSE_RETURN(data->ed, 99 "Failed to allocate endpoint descriptor.\n"); 75 usb_transfer_batch_init(instance, target, transfer_type, speed, 76 max_packet_size, buffer, NULL, buffer_size, NULL, setup_size, 77 func_in, func_out, arg, fun, NULL, NULL); 100 78 101 79 if (buffer_size > 0) { … … 112 90 } 113 91 92 114 93 return instance; 115 94 } … … 118 97 { 119 98 assert(instance); 120 ohci_batch_t *data = instance->private_data; 121 assert(data); 122 free32(data->ed); 123 free32(data->tds); 99 free32(instance->transport_buffer); 124 100 free32(instance->setup_buffer); 125 free32(instance->transport_buffer);126 free(data);127 101 free(instance); 128 }129 /*----------------------------------------------------------------------------*/130 bool batch_is_complete(usb_transfer_batch_t *instance)131 {132 assert(instance);133 ohci_batch_t *data = instance->private_data;134 assert(data);135 size_t tds = data->td_count - 1;136 usb_log_debug2("Batch(%p) checking %d td(s) for completion.\n",137 instance, tds);138 size_t i = 0;139 for (; i < tds; ++i) {140 if (!td_is_finished(&data->tds[i]))141 return false;142 instance->error = td_error(&data->tds[i]);143 /* FIXME: calculate real transfered size */144 instance->transfered_size = instance->buffer_size;145 if (instance->error != EOK) {146 usb_log_debug("Batch(%p) found error TD(%d):%x.\n",147 instance, i, data->tds[i].status);148 return true;149 // endpoint_toggle_set(instance->ep,150 }151 }152 return true;153 102 } 154 103 /*----------------------------------------------------------------------------*/ … … 160 109 instance->buffer_size); 161 110 instance->next_step = batch_call_out_and_dispose; 162 batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);111 /* TODO: implement */ 163 112 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 164 113 } … … 168 117 assert(instance); 169 118 instance->next_step = batch_call_in_and_dispose; 170 batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);119 /* TODO: implement */ 171 120 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 172 121 } … … 175 124 { 176 125 assert(instance); 177 assert(instance->direction == USB_DIRECTION_IN);126 instance->direction = USB_DIRECTION_IN; 178 127 instance->next_step = batch_call_in_and_dispose; 179 128 /* TODO: implement */ … … 184 133 { 185 134 assert(instance); 186 assert(instance->direction == USB_DIRECTION_OUT);135 instance->direction = USB_DIRECTION_OUT; 187 136 /* We are data out, we are supposed to provide data */ 188 137 memcpy(instance->transport_buffer, instance->buffer, … … 211 160 } 212 161 /*----------------------------------------------------------------------------*/ 213 ed_t * batch_ed(usb_transfer_batch_t *instance)214 {215 assert(instance);216 ohci_batch_t *data = instance->private_data;217 assert(data);218 return data->ed;219 }220 /*----------------------------------------------------------------------------*/221 void batch_control(usb_transfer_batch_t *instance,222 usb_direction_t data_dir, usb_direction_t status_dir)223 {224 assert(instance);225 ohci_batch_t *data = instance->private_data;226 assert(data);227 ed_init(data->ed, instance->ep);228 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);229 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed,230 data->ed->status, data->ed->td_tail, data->ed->td_head,231 data->ed->next);232 int toggle = 0;233 /* setup stage */234 td_init(&data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,235 instance->setup_size, toggle);236 td_set_next(&data->tds[0], &data->tds[1]);237 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0].status,238 data->tds[0].cbp, data->tds[0].next, data->tds[0].be);239 240 /* data stage */241 size_t td_current = 1;242 size_t remain_size = instance->buffer_size;243 char *transfer_buffer = instance->transport_buffer;244 while (remain_size > 0) {245 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?246 OHCI_TD_MAX_TRANSFER : remain_size;247 toggle = 1 - toggle;248 249 td_init(&data->tds[td_current], data_dir, transfer_buffer,250 transfer_size, toggle);251 td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);252 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",253 data->tds[td_current].status, data->tds[td_current].cbp,254 data->tds[td_current].next, data->tds[td_current].be);255 256 transfer_buffer += transfer_size;257 remain_size -= transfer_size;258 assert(td_current < data->td_count - 2);259 ++td_current;260 }261 262 /* status stage */263 assert(td_current == data->td_count - 2);264 td_init(&data->tds[td_current], status_dir, NULL, 0, 1);265 usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",266 data->tds[td_current].status, data->tds[td_current].cbp,267 data->tds[td_current].next, data->tds[td_current].be);268 }269 /*----------------------------------------------------------------------------*/270 162 /** Helper function calls callback and correctly disposes of batch structure. 271 163 * -
uspace/drv/ohci/batch.h
rdc4c19e ra49e171 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusb uhcihc28 /** @addtogroup drvusbohci 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief UHCI driver USB transaction structure32 * @brief OHCI driver USB transaction structure 33 33 */ 34 #ifndef DRV_UHCI_BATCH_H 35 #define DRV_UHCI_BATCH_H 34 #ifndef DRV_OHCI_BATCH_H 35 #define DRV_OHCI_BATCH_H 36 36 37 37 38 #include <usbhc_iface.h> 38 39 #include <usb/usb.h> 39 40 #include <usb/host/device_keeper.h> 40 #include <usb/host/endpoint.h>41 41 #include <usb/host/batch.h> 42 42 43 #include "hw_struct/endpoint_descriptor.h"44 45 43 usb_transfer_batch_t * batch_get( 46 ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size, 47 char *setup_buffer, size_t setup_size, 44 ddf_fun_t *fun, 45 usb_target_t target, 46 usb_transfer_type_t transfer_type, 47 size_t max_packet_size, 48 usb_speed_t speed, 49 char *buffer, 50 size_t size, 51 char *setup_buffer, 52 size_t setup_size, 48 53 usbhc_iface_transfer_in_callback_t func_in, 49 54 usbhc_iface_transfer_out_callback_t func_out, 50 void *arg); 55 void *arg, 56 usb_device_keeper_t *manager 57 ); 51 58 52 59 void batch_dispose(usb_transfer_batch_t *instance); 53 54 bool batch_is_complete(usb_transfer_batch_t *instance);55 60 56 61 void batch_control_write(usb_transfer_batch_t *instance); … … 65 70 66 71 void batch_bulk_out(usb_transfer_batch_t *instance); 67 68 ed_t * batch_ed(usb_transfer_batch_t *instance);69 72 #endif 70 73 /** -
uspace/drv/ohci/hc.c
rdc4c19e ra49e171 47 47 static void hc_gain_control(hc_t *instance); 48 48 static void hc_init_hw(hc_t *instance); 49 static int hc_init_transfer_lists(hc_t *instance);50 static int hc_init_memory(hc_t *instance);51 49 /*----------------------------------------------------------------------------*/ 52 50 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun) … … 61 59 &instance->manager, hub_address, hub_fun->handle); 62 60 63 endpoint_t *ep = malloc(sizeof(endpoint_t));64 assert(ep);65 int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH,66 USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64);67 assert(ret == EOK);68 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0);69 assert(ret == EOK);70 71 61 char *match_str = NULL; 72 ret = asprintf(&match_str, "usb&class=hub");73 //ret = (match_str == NULL) ? ret : EOK;62 int ret = asprintf(&match_str, "usb&class=hub"); 63 ret = (match_str == NULL) ? ret : EOK; 74 64 if (ret < 0) { 75 usb_log_error( 76 "Failed(%d) to create root hub match-id string.\n", ret); 65 usb_log_error("Failed to create root hub match-id string.\n"); 77 66 return ret; 78 67 } … … 108 97 ret, str_error(ret)); 109 98 110 hc_gain_control(instance);111 ret = hc_init_memory(instance);112 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",113 ret, str_error(ret));114 hc_init_hw(instance);115 116 rh_init(&instance->rh, dev, instance->registers);117 118 99 if (!interrupts) { 119 100 instance->interrupt_emulator = … … 122 103 } 123 104 105 hc_gain_control(instance); 106 107 rh_init(&instance->rh, dev, instance->registers); 108 109 hc_init_hw(instance); 110 111 /* TODO: implement */ 124 112 return EOK; 125 113 } … … 129 117 assert(instance); 130 118 assert(batch); 131 132 /* check for root hub communication */133 119 if (batch->target.address == instance->rh.address) { 134 120 return rh_request(&instance->rh, batch); 135 121 } 136 137 transfer_list_add_batch( 138 instance->transfers[batch->transfer_type], batch); 139 140 switch (batch->transfer_type) { 141 case USB_TRANSFER_CONTROL: 142 instance->registers->control &= ~C_CLE; 143 instance->registers->command_status |= CS_CLF; 144 usb_log_debug2("Set control transfer filled: %x.\n", 145 instance->registers->command_status); 146 instance->registers->control |= C_CLE; 147 break; 148 case USB_TRANSFER_BULK: 149 instance->registers->command_status |= CS_BLF; 150 usb_log_debug2("Set bulk transfer filled: %x.\n", 151 instance->registers->command_status); 152 break; 153 default: 154 break; 155 } 156 return EOK; 122 /* TODO: implement */ 123 return ENOTSUP; 157 124 } 158 125 /*----------------------------------------------------------------------------*/ … … 160 127 { 161 128 assert(instance); 162 if ( (status & ~IS_SF) == 0) /* ignore sof status */129 if (status == 0) 163 130 return; 164 131 if (status & IS_RHSC) … … 167 134 usb_log_info("OHCI interrupt: %x.\n", status); 168 135 169 170 LIST_INITIALIZE(done); 171 transfer_list_remove_finished(&instance->transfers_interrupt, &done); 172 transfer_list_remove_finished(&instance->transfers_isochronous, &done); 173 transfer_list_remove_finished(&instance->transfers_control, &done); 174 transfer_list_remove_finished(&instance->transfers_bulk, &done); 175 176 while (!list_empty(&done)) { 177 link_t *item = done.next; 178 list_remove(item); 179 usb_transfer_batch_t *batch = 180 list_get_instance(item, usb_transfer_batch_t, link); 181 usb_transfer_batch_finish(batch); 182 } 136 /* TODO: Check for further interrupt causes */ 137 /* TODO: implement */ 183 138 } 184 139 /*----------------------------------------------------------------------------*/ … … 199 154 { 200 155 assert(instance); 201 /* Turn off legacy emulation */202 volatile uint32_t *ohci_emulation_reg =203 (uint32_t*)((char*)instance->registers + 0x100);204 usb_log_debug("OHCI legacy register %p: %x.\n",205 ohci_emulation_reg, *ohci_emulation_reg);206 *ohci_emulation_reg = 0;207 208 156 /* Interrupt routing enabled => smm driver is active */ 209 157 if (instance->registers->control & C_IR) { 210 usb_log_ debug("SMM driver: requestownership change.\n");158 usb_log_info("Found SMM driver requesting ownership change.\n"); 211 159 instance->registers->command_status |= CS_OCR; 212 160 while (instance->registers->control & C_IR) { 213 161 async_usleep(1000); 214 162 } 215 usb_log_info(" SMM driver: Ownership taken.\n");163 usb_log_info("Ownership taken from SMM driver.\n"); 216 164 return; 217 165 } … … 221 169 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 222 170 if (hc_status != C_HCFS_RESET) { 223 usb_log_ debug("BIOS driver found.\n");171 usb_log_info("Found BIOS driver.\n"); 224 172 if (hc_status == C_HCFS_OPERATIONAL) { 225 usb_log_info(" BIOS driver: HC operational.\n");173 usb_log_info("HC operational(BIOS).\n"); 226 174 return; 227 175 } … … 229 177 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT); 230 178 async_usleep(20000); 231 usb_log_info("BIOS driver: HC resumed.\n");232 179 return; 233 180 } … … 235 182 /* HC is in reset (hw startup) => no other driver 236 183 * maintain reset for at least the time specified in USB spec (50 ms)*/ 237 usb_log_info("HC found in reset.\n");238 184 async_usleep(50000); 185 186 /* turn off legacy emulation */ 187 volatile uint32_t *ohci_emulation_reg = 188 (uint32_t*)((char*)instance->registers + 0x100); 189 usb_log_info("OHCI legacy register status %p: %x.\n", 190 ohci_emulation_reg, *ohci_emulation_reg); 191 *ohci_emulation_reg = 0; 192 239 193 } 240 194 /*----------------------------------------------------------------------------*/ 241 195 void hc_init_hw(hc_t *instance) 242 196 { 243 /* OHCI guide page 42 */ 244 assert(instance); 245 usb_log_debug2("Started hc initialization routine.\n"); 246 247 /* Save contents of fm_interval register */ 197 assert(instance); 248 198 const uint32_t fm_interval = instance->registers->fm_interval; 249 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);250 251 /* Reset hc */252 usb_log_debug2("HC reset.\n");253 size_t time = 0;254 199 instance->registers->command_status = CS_HCR; 255 while (instance->registers->command_status & CS_HCR) { 256 async_usleep(10); 257 time += 10; 258 } 259 usb_log_debug2("HC reset complete in %zu us.\n", time); 260 261 /* Restore fm_interval */ 200 async_usleep(10); 262 201 instance->registers->fm_interval = fm_interval; 263 202 assert((instance->registers->command_status & CS_HCR) == 0); 264 265 203 /* hc is now in suspend state */ 266 usb_log_debug2("HC should be in suspend state(%x).\n", 267 instance->registers->control); 268 269 /* Enable queues */ 270 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); 271 usb_log_debug2("All queues enabled(%x).\n", 272 instance->registers->control); 273 274 /* Disable interrupts */ 275 instance->registers->interrupt_disable = I_SF | I_OC; 276 usb_log_debug2("Disabling interrupts: %x.\n", 277 instance->registers->interrupt_disable); 278 instance->registers->interrupt_disable = I_MI; 279 usb_log_debug2("Enabled interrupts: %x.\n", 280 instance->registers->interrupt_enable); 281 282 /* Set periodic start to 90% */ 283 uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK); 284 instance->registers->periodic_start = (frame_length / 10) * 9; 285 usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n", 286 instance->registers->periodic_start, 287 instance->registers->periodic_start, frame_length); 204 /* TODO: init HCCA block */ 205 /* TODO: init queues */ 206 /* TODO: enable queues */ 207 /* TODO: enable interrupts */ 208 /* TODO: set periodic start to 90% */ 288 209 289 210 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT); 290 usb_log_info("OHCI HC up and running(%x).\n", 291 instance->registers->control); 292 } 293 /*----------------------------------------------------------------------------*/ 294 int hc_init_transfer_lists(hc_t *instance) 295 { 296 assert(instance); 297 298 #define SETUP_TRANSFER_LIST(type, name) \ 299 do { \ 300 int ret = transfer_list_init(&instance->type, name); \ 301 if (ret != EOK) { \ 302 usb_log_error("Failed(%d) to setup %s transfer list.\n", \ 303 ret, name); \ 304 transfer_list_fini(&instance->transfers_isochronous); \ 305 transfer_list_fini(&instance->transfers_interrupt); \ 306 transfer_list_fini(&instance->transfers_control); \ 307 transfer_list_fini(&instance->transfers_bulk); \ 308 } \ 309 } while (0) 310 311 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 312 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 313 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 314 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 315 316 transfer_list_set_next(&instance->transfers_interrupt, 317 &instance->transfers_isochronous); 318 319 /* Assign pointers to be used during scheduling */ 320 instance->transfers[USB_TRANSFER_INTERRUPT] = 321 &instance->transfers_interrupt; 322 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 323 &instance->transfers_interrupt; 324 instance->transfers[USB_TRANSFER_CONTROL] = 325 &instance->transfers_control; 326 instance->transfers[USB_TRANSFER_BULK] = 327 &instance->transfers_bulk; 328 329 return EOK; 330 #undef CHECK_RET_CLEAR_RETURN 331 } 332 /*----------------------------------------------------------------------------*/ 333 int hc_init_memory(hc_t *instance) 334 { 335 assert(instance); 336 /* Init queues */ 337 hc_init_transfer_lists(instance); 338 339 /*Init HCCA */ 340 instance->hcca = malloc32(sizeof(hcca_t)); 341 if (instance->hcca == NULL) 342 return ENOMEM; 343 bzero(instance->hcca, sizeof(hcca_t)); 344 instance->registers->hcca = addr_to_phys(instance->hcca); 345 usb_log_debug2("OHCI HCCA initialized at %p(%p).\n", 346 instance->hcca, instance->registers->hcca); 347 348 /* Use queues */ 349 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 350 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 351 instance->transfers_bulk.list_head, 352 instance->transfers_bulk.list_head_pa); 353 354 instance->registers->control_head = 355 instance->transfers_control.list_head_pa; 356 usb_log_debug2("Control HEAD set to: %p(%p).\n", 357 instance->transfers_control.list_head, 358 instance->transfers_control.list_head_pa); 359 360 unsigned i = 0; 361 for (; i < 32; ++i) { 362 instance->hcca->int_ep[i] = 363 instance->transfers_interrupt.list_head_pa; 364 } 365 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 366 instance->transfers_interrupt.list_head, 367 instance->transfers_interrupt.list_head_pa); 368 369 return EOK; 211 usb_log_info("OHCI HC up and running.\n"); 370 212 } 371 213 /** -
uspace/drv/ohci/hc.h
rdc4c19e ra49e171 48 48 #include "ohci_regs.h" 49 49 #include "root_hub.h" 50 #include "transfer_list.h"51 50 #include "hw_struct/hcca.h" 52 51 … … 55 54 usb_address_t rh_address; 56 55 rh_t rh; 57 58 hcca_t *hcca;59 60 transfer_list_t transfers_isochronous;61 transfer_list_t transfers_interrupt;62 transfer_list_t transfers_control;63 transfer_list_t transfers_bulk;64 65 transfer_list_t *transfers[4];66 67 56 ddf_fun_t *ddf_instance; 68 57 usb_device_keeper_t manager; -
uspace/drv/ohci/hw_struct/completion_codes.h
rdc4c19e ra49e171 35 35 #define DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H 36 36 37 #include <errno.h>38 39 37 #define CC_NOERROR (0x0) 40 38 #define CC_CRC (0x1) … … 52 50 #define CC_NOACCESS2 (0xf) 53 51 54 inline static int cc_to_rc(int cc)55 {56 switch (cc) {57 case CC_NOERROR:58 return EOK;59 60 case CC_CRC:61 return EBADCHECKSUM;62 63 case CC_PIDUNEXPECTED:64 case CC_PIDFAIL:65 case CC_BITSTUFF:66 return EIO;67 68 case CC_TOGGLE:69 case CC_STALL:70 return ESTALL;71 72 case CC_NORESPONSE:73 return ETIMEOUT;74 75 case CC_DATAOVERRRUN:76 case CC_DATAUNDERRRUN:77 case CC_BUFFEROVERRRUN:78 case CC_BUFFERUNDERRUN:79 return EOVERFLOW;80 81 case CC_NOACCESS1:82 case CC_NOACCESS2:83 default:84 return ENOTSUP;85 }86 }87 88 52 #endif 89 53 /** -
uspace/drv/ohci/hw_struct/endpoint_descriptor.h
rdc4c19e ra49e171 35 35 #define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H 36 36 37 #include <assert.h>38 37 #include <stdint.h> 39 40 #include <usb/host/endpoint.h>41 42 #include "utils/malloc32.h"43 #include "transfer_descriptor.h"44 38 45 39 #include "completion_codes.h" … … 50 44 #define ED_STATUS_FA_SHIFT (0) 51 45 #define ED_STATUS_EN_MASK (0xf) /* USB endpoint address */ 52 #define ED_STATUS_EN_SHIFT ( 7)46 #define ED_STATUS_EN_SHIFT (6) 53 47 #define ED_STATUS_D_MASK (0x3) /* direction */ 54 #define ED_STATUS_D_SHIFT (1 1)48 #define ED_STATUS_D_SHIFT (10) 55 49 #define ED_STATUS_D_IN (0x1) 56 50 #define ED_STATUS_D_OUT (0x2) 57 #define ED_STATUS_D_TRANSFER (0x3)58 51 59 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag : 1 = low*/52 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag */ 60 53 #define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */ 61 54 #define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/ … … 78 71 #define ED_NEXT_PTR_SHIFT (0) 79 72 } __attribute__((packed)) ed_t; 80 81 void ed_init(ed_t *instance, endpoint_t *ep);82 83 static inline void ed_add_tds(ed_t *instance, td_t *head, td_t *tail)84 {85 assert(instance);86 instance->td_head = addr_to_phys(head) & ED_TDHEAD_PTR_MASK;87 instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK;88 }89 90 static inline void ed_append_ed(ed_t *instance, ed_t *next)91 {92 assert(instance);93 assert(next);94 uint32_t pa = addr_to_phys(next);95 assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);96 instance->next = pa;97 }98 99 73 #endif 100 74 /** -
uspace/drv/ohci/hw_struct/transfer_descriptor.h
rdc4c19e ra49e171 35 35 #define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H 36 36 37 #include <bool.h>38 37 #include <stdint.h> 39 #include "utils/malloc32.h"40 38 41 39 #include "completion_codes.h" 42 43 /* OHCI TDs can handle up to 8KB buffers */44 #define OHCI_TD_MAX_TRANSFER (8 * 1024)45 40 46 41 typedef struct td { … … 57 52 #define TD_STATUS_T_MASK (0x3) /* data toggle 1x = use ED toggle carry */ 58 53 #define TD_STATUS_T_SHIFT (24) 59 #define TD_STATUS_T_0 (0x2)60 #define TD_STATUS_T_1 (0x3)61 54 #define TD_STATUS_EC_MASK (0x3) /* error count */ 62 55 #define TD_STATUS_EC_SHIFT (26) … … 71 64 volatile uint32_t be; /* buffer end, address of the last byte */ 72 65 } __attribute__((packed)) td_t; 73 74 void td_init(75 td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);76 77 inline static void td_set_next(td_t *instance, td_t *next)78 {79 assert(instance);80 instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;81 }82 83 inline static bool td_is_finished(td_t *instance)84 {85 assert(instance);86 int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;87 /* something went wrong, error code is set */88 if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {89 return true;90 }91 /* everything done */92 if (cc == CC_NOERROR && instance->cbp == 0) {93 return true;94 }95 return false;96 }97 98 static inline int td_error(td_t *instance)99 {100 assert(instance);101 int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;102 return cc_to_rc(cc);103 }104 66 #endif 105 67 /** -
uspace/drv/ohci/iface.c
rdc4c19e ra49e171 1 1 /* 2 * Copyright (c) 2011 Vojtech Horky , Jan Vesely2 * Copyright (c) 2011 Vojtech Horky 3 3 * All rights reserved. 4 4 * … … 30 30 */ 31 31 /** @file 32 * @brief OHCI driver hc interface implementation32 * USB-HC interface implementation. 33 33 */ 34 34 #include <ddf/driver.h> … … 36 36 37 37 #include <usb/debug.h> 38 #include <usb/host/endpoint.h>39 38 40 39 #include "iface.h" 41 40 #include "hc.h" 42 41 43 static inline int setup_batch( 44 ddf_fun_t *fun, usb_target_t target, usb_direction_t direction, 45 void *data, size_t size, void * setup_data, size_t setup_size, 46 usbhc_iface_transfer_in_callback_t in, 47 usbhc_iface_transfer_out_callback_t out, void *arg, const char* name, 48 hc_t **hc, usb_transfer_batch_t **batch) 49 { 50 assert(hc); 51 assert(batch); 52 assert(fun); 53 *hc = fun_to_hc(fun); 54 assert(*hc); 55 56 size_t res_bw; 57 endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager, 58 target.address, target.endpoint, direction, &res_bw); 59 if (ep == NULL) { 60 usb_log_error("Endpoint(%d:%d) not registered for %s.\n", 61 target.address, target.endpoint, name); 62 return ENOENT; 63 } 64 65 usb_log_debug("%s %d:%d %zu(%zu).\n", 66 name, target.address, target.endpoint, size, ep->max_packet_size); 67 68 const size_t bw = bandwidth_count_usb11( 69 ep->speed, ep->transfer_type, size, ep->max_packet_size); 70 if (res_bw < bw) { 71 usb_log_error("Endpoint(%d:%d) %s needs %zu bw " 72 "but only %zu is reserved.\n", 73 target.address, target.endpoint, name, bw, res_bw); 74 return ENOSPC; 75 } 76 77 *batch = batch_get( 78 fun, ep, data, size, setup_data, setup_size, in, out, arg); 79 if (!*batch) 80 return ENOMEM; 42 #define UNSUPPORTED(methodname) \ 43 usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \ 44 methodname, __FILE__, __LINE__) 45 46 /** Reserve default address. 47 * 48 * This function may block the caller. 49 * 50 * @param[in] fun Device function the action was invoked on. 51 * @param[in] speed Speed of the device for which the default address is 52 * reserved. 53 * @return Error code. 54 */ 55 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) 56 { 57 assert(fun); 58 hc_t *hc = fun_to_hc(fun); 59 assert(hc); 60 usb_log_debug("Default address request with speed %d.\n", speed); 61 usb_device_keeper_reserve_default_address(&hc->manager, speed); 81 62 return EOK; 82 63 } 83 64 /*----------------------------------------------------------------------------*/ 84 /** Request address interface function 85 * 86 * @param[in] fun DDF function that was called. 87 * @param[in] speed Speed to associate with the new default address. 88 * @param[out] address Place to write a new address. 65 /** Release default address. 66 * 67 * @param[in] fun Device function the action was invoked on. 68 * @return Error code. 69 */ 70 static int release_default_address(ddf_fun_t *fun) 71 { 72 assert(fun); 73 hc_t *hc = fun_to_hc(fun); 74 assert(hc); 75 usb_log_debug("Default address release.\n"); 76 usb_device_keeper_release_default_address(&hc->manager); 77 return EOK; 78 } 79 /*----------------------------------------------------------------------------*/ 80 /** Found free USB address. 81 * 82 * @param[in] fun Device function the action was invoked on. 83 * @param[in] speed Speed of the device that will get this address. 84 * @param[out] address Non-null pointer where to store the free address. 89 85 * @return Error code. 90 86 */ … … 105 101 } 106 102 /*----------------------------------------------------------------------------*/ 107 /** Bind address interface function108 * 109 * @param[in] fun D DF function that was called.110 * @param[in] address Address of the device111 * @param[in] handle Devman handle of the device driver.103 /** Bind USB address with device devman handle. 104 * 105 * @param[in] fun Device function the action was invoked on. 106 * @param[in] address USB address of the device. 107 * @param[in] handle Devman handle of the device. 112 108 * @return Error code. 113 109 */ 114 110 static int bind_address( 115 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)111 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle) 116 112 { 117 113 assert(fun); … … 123 119 } 124 120 /*----------------------------------------------------------------------------*/ 125 /** Release address interface function126 * 127 * @param[in] fun D DF function that was called.121 /** Release previously requested address. 122 * 123 * @param[in] fun Device function the action was invoked on. 128 124 * @param[in] address USB address to be released. 129 125 * @return Error code. … … 143 139 * @param[in] fun Device function the action was invoked on. 144 140 * @param[in] address USB address of the device. 145 * @param[in] ep_speed Endpoint speed (invalid means to use device one).146 141 * @param[in] endpoint Endpoint number. 147 142 * @param[in] transfer_type USB transfer type. … … 151 146 * @return Error code. 152 147 */ 153 static int register_endpoint( ddf_fun_t *fun,154 usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,148 static int register_endpoint( 149 ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint, 155 150 usb_transfer_type_t transfer_type, usb_direction_t direction, 156 151 size_t max_packet_size, unsigned int interval) 157 152 { 158 hc_t *hc = fun_to_hc(fun);159 assert(hc);160 161 usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);162 if (speed >= USB_SPEED_MAX) {163 speed = ep_speed;164 }153 assert(fun); 154 hc_t *hc = fun_to_hc(fun); 155 assert(hc); 156 if (address == hc->rh.address) 157 return EOK; 158 const usb_speed_t speed = 159 usb_device_keeper_get_speed(&hc->manager, address); 165 160 const size_t size = max_packet_size; 166 int ret;167 168 161 usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n", 169 162 address, endpoint, usb_str_transfer_type(transfer_type), 170 163 usb_str_speed(speed), direction, size, max_packet_size, interval); 171 172 endpoint_t *ep = malloc(sizeof(endpoint_t)); 173 if (ep == NULL) 174 return ENOMEM; 175 ret = endpoint_init(ep, address, endpoint, direction, 176 transfer_type, speed, max_packet_size); 177 if (ret != EOK) { 178 free(ep); 179 return ret; 180 } 181 182 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size); 183 if (ret != EOK) { 184 endpoint_destroy(ep); 185 } 186 return ret; 187 } 188 /*----------------------------------------------------------------------------*/ 164 // TODO use real endpoint here! 165 return usb_endpoint_manager_register_ep(&hc->ep_manager,NULL, 0); 166 } 167 /*----------------------------------------------------------------------------*/ 168 /** Unregister endpoint (free some bandwidth reservation). 169 * 170 * @param[in] fun Device function the action was invoked on. 171 * @param[in] address USB address of the device. 172 * @param[in] endpoint Endpoint number. 173 * @param[in] direction Endpoint data direction. 174 * @return Error code. 175 */ 189 176 static int unregister_endpoint( 190 177 ddf_fun_t *fun, usb_address_t address, 191 178 usb_endpoint_t endpoint, usb_direction_t direction) 192 179 { 180 assert(fun); 193 181 hc_t *hc = fun_to_hc(fun); 194 182 assert(hc); … … 208 196 * @param[in] fun Device function the action was invoked on. 209 197 * @param[in] target Target pipe (address and endpoint number) specification. 198 * @param[in] max_packet_size Max packet size for the transfer. 210 199 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 211 200 * by the caller). … … 216 205 */ 217 206 static int interrupt_out( 218 ddf_fun_t *fun, usb_target_t target, void *data,207 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 219 208 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 220 209 { 221 usb_transfer_batch_t *batch = NULL; 222 hc_t *hc = NULL; 223 int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size, 224 NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch); 225 if (ret != EOK) 226 return ret; 210 assert(fun); 211 hc_t *hc = fun_to_hc(fun); 212 assert(hc); 213 usb_speed_t speed = 214 usb_device_keeper_get_speed(&hc->manager, target.address); 215 216 usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n", 217 target.address, target.endpoint, size, max_packet_size); 218 219 usb_transfer_batch_t *batch = 220 batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size, 221 speed, data, size, NULL, 0, NULL, callback, arg, &hc->manager); 222 if (!batch) 223 return ENOMEM; 227 224 batch_interrupt_out(batch); 228 ret = hc_schedule(hc, batch);225 const int ret = hc_schedule(hc, batch); 229 226 if (ret != EOK) { 230 227 batch_dispose(batch); … … 242 239 * @param[in] fun Device function the action was invoked on. 243 240 * @param[in] target Target pipe (address and endpoint number) specification. 241 * @param[in] max_packet_size Max packet size for the transfer. 244 242 * @param[in] data Buffer where to store the data (in USB endianess, 245 243 * allocated and deallocated by the caller). … … 250 248 */ 251 249 static int interrupt_in( 252 ddf_fun_t *fun, usb_target_t target, void *data,250 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 253 251 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 254 252 { 255 usb_transfer_batch_t *batch = NULL; 256 hc_t *hc = NULL; 257 int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size, 258 NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch); 259 if (ret != EOK) 260 return ret; 253 assert(fun); 254 hc_t *hc = fun_to_hc(fun); 255 assert(hc); 256 usb_speed_t speed = 257 usb_device_keeper_get_speed(&hc->manager, target.address); 258 usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n", 259 target.address, target.endpoint, size, max_packet_size); 260 261 usb_transfer_batch_t *batch = 262 batch_get(fun, target, USB_TRANSFER_INTERRUPT, max_packet_size, 263 speed, data, size, NULL, 0, callback, NULL, arg, &hc->manager); 264 if (!batch) 265 return ENOMEM; 261 266 batch_interrupt_in(batch); 262 ret = hc_schedule(hc, batch);267 const int ret = hc_schedule(hc, batch); 263 268 if (ret != EOK) { 264 269 batch_dispose(batch); … … 276 281 * @param[in] fun Device function the action was invoked on. 277 282 * @param[in] target Target pipe (address and endpoint number) specification. 283 * @param[in] max_packet_size Max packet size for the transfer. 278 284 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 279 285 * by the caller). … … 284 290 */ 285 291 static int bulk_out( 286 ddf_fun_t *fun, usb_target_t target, void *data,292 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 287 293 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 288 294 { 289 usb_transfer_batch_t *batch = NULL; 290 hc_t *hc = NULL; 291 int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size, 292 NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch); 293 if (ret != EOK) 294 return ret; 295 assert(fun); 296 hc_t *hc = fun_to_hc(fun); 297 assert(hc); 298 usb_speed_t speed = 299 usb_device_keeper_get_speed(&hc->manager, target.address); 300 301 usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n", 302 target.address, target.endpoint, size, max_packet_size); 303 304 usb_transfer_batch_t *batch = 305 batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed, 306 data, size, NULL, 0, NULL, callback, arg, &hc->manager); 307 if (!batch) 308 return ENOMEM; 295 309 batch_bulk_out(batch); 296 ret = hc_schedule(hc, batch);310 const int ret = hc_schedule(hc, batch); 297 311 if (ret != EOK) { 298 312 batch_dispose(batch); … … 310 324 * @param[in] fun Device function the action was invoked on. 311 325 * @param[in] target Target pipe (address and endpoint number) specification. 326 * @param[in] max_packet_size Max packet size for the transfer. 312 327 * @param[in] data Buffer where to store the data (in USB endianess, 313 328 * allocated and deallocated by the caller). … … 318 333 */ 319 334 static int bulk_in( 320 ddf_fun_t *fun, usb_target_t target, void *data,335 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 321 336 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 322 337 { 323 usb_transfer_batch_t *batch = NULL; 324 hc_t *hc = NULL; 325 int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size, 326 NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch); 327 if (ret != EOK) 328 return ret; 338 assert(fun); 339 hc_t *hc = fun_to_hc(fun); 340 assert(hc); 341 usb_speed_t speed = 342 usb_device_keeper_get_speed(&hc->manager, target.address); 343 usb_log_debug("Bulk IN %d:%d %zu(%zu).\n", 344 target.address, target.endpoint, size, max_packet_size); 345 346 usb_transfer_batch_t *batch = 347 batch_get(fun, target, USB_TRANSFER_BULK, max_packet_size, speed, 348 data, size, NULL, 0, callback, NULL, arg, &hc->manager); 349 if (!batch) 350 return ENOMEM; 329 351 batch_bulk_in(batch); 330 ret = hc_schedule(hc, batch);352 const int ret = hc_schedule(hc, batch); 331 353 if (ret != EOK) { 332 354 batch_dispose(batch); … … 344 366 * @param[in] fun Device function the action was invoked on. 345 367 * @param[in] target Target pipe (address and endpoint number) specification. 368 * @param[in] max_packet_size Max packet size for the transfer. 346 369 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 347 370 * and deallocated by the caller). … … 355 378 */ 356 379 static int control_write( 357 ddf_fun_t *fun, usb_target_t target, 380 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, 358 381 void *setup_data, size_t setup_size, void *data, size_t size, 359 382 usbhc_iface_transfer_out_callback_t callback, void *arg) 360 383 { 361 usb_transfer_batch_t *batch = NULL; 362 hc_t *hc = NULL; 363 int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size, 364 setup_data, setup_size, NULL, callback, arg, "Control WRITE", 365 &hc, &batch); 366 if (ret != EOK) 367 return ret; 368 usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data); 384 assert(fun); 385 hc_t *hc = fun_to_hc(fun); 386 assert(hc); 387 usb_speed_t speed = 388 usb_device_keeper_get_speed(&hc->manager, target.address); 389 usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n", 390 speed, target.address, target.endpoint, size, max_packet_size); 391 392 if (setup_size != 8) 393 return EINVAL; 394 395 usb_transfer_batch_t *batch = 396 batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, 397 speed, data, size, setup_data, setup_size, NULL, callback, arg, 398 &hc->manager); 399 if (!batch) 400 return ENOMEM; 401 usb_device_keeper_reset_if_need(&hc->manager, target, setup_data); 369 402 batch_control_write(batch); 370 ret = hc_schedule(hc, batch);403 const int ret = hc_schedule(hc, batch); 371 404 if (ret != EOK) { 372 405 batch_dispose(batch); … … 384 417 * @param[in] fun Device function the action was invoked on. 385 418 * @param[in] target Target pipe (address and endpoint number) specification. 419 * @param[in] max_packet_size Max packet size for the transfer. 386 420 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 387 421 * and deallocated by the caller). … … 395 429 */ 396 430 static int control_read( 397 ddf_fun_t *fun, usb_target_t target, 431 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, 398 432 void *setup_data, size_t setup_size, void *data, size_t size, 399 433 usbhc_iface_transfer_in_callback_t callback, void *arg) 400 434 { 401 usb_transfer_batch_t *batch = NULL; 402 hc_t *hc = NULL; 403 int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size, 404 setup_data, setup_size, callback, NULL, arg, "Control READ", 405 &hc, &batch); 406 if (ret != EOK) 407 return ret; 435 assert(fun); 436 hc_t *hc = fun_to_hc(fun); 437 assert(hc); 438 usb_speed_t speed = 439 usb_device_keeper_get_speed(&hc->manager, target.address); 440 441 usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n", 442 speed, target.address, target.endpoint, size, max_packet_size); 443 usb_transfer_batch_t *batch = 444 batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, 445 speed, data, size, setup_data, setup_size, callback, NULL, arg, 446 &hc->manager); 447 if (!batch) 448 return ENOMEM; 408 449 batch_control_read(batch); 409 ret = hc_schedule(hc, batch); 410 if (ret != EOK) { 411 batch_dispose(batch); 412 } 413 return ret; 414 } 415 /*----------------------------------------------------------------------------*/ 450 const int ret = hc_schedule(hc, batch); 451 if (ret != EOK) { 452 batch_dispose(batch); 453 } 454 return ret; 455 } 456 /*----------------------------------------------------------------------------*/ 457 /** Host controller interface implementation for OHCI. */ 416 458 usbhc_iface_t hc_iface = { 459 .reserve_default_address = reserve_default_address, 460 .release_default_address = release_default_address, 417 461 .request_address = request_address, 418 462 .bind_address = bind_address, … … 431 475 .control_read = control_read, 432 476 }; 477 433 478 /** 434 479 * @} -
uspace/drv/ohci/ohci_regs.h
rdc4c19e ra49e171 41 41 const volatile uint32_t revision; 42 42 volatile uint32_t control; 43 #define C_CSBR_MASK (0x3) /* Control-bulk service ratio */ 44 #define C_CSBR_1_1 (0x0) 45 #define C_CSBR_1_2 (0x1) 46 #define C_CSBR_1_3 (0x2) 47 #define C_CSBR_1_4 (0x3) 43 #define C_CSBR_MASK (0x3) 48 44 #define C_CSBR_SHIFT (0) 45 #define C_PLE (1 << 2) 46 #define C_IE (1 << 3) 47 #define C_CLE (1 << 4) 48 #define C_BLE (1 << 5) 49 49 50 #define C_PLE (1 << 2) /* Periodic list enable */ 51 #define C_IE (1 << 3) /* Isochronous enable */ 52 #define C_CLE (1 << 4) /* Control list enable */ 53 #define C_BLE (1 << 5) /* Bulk list enable */ 50 #define C_HCFS_MASK (0x3) 51 #define C_HCFS_SHIFT (6) 52 #define C_HCFS_RESET (0x0) 53 #define C_HCFS_OPERATIONAL (0x1) 54 #define C_HCFS_RESUME (0x2) 55 #define C_HCFS_SUSPEND (0x3) 54 56 55 #define C_HCFS_MASK (0x3) /* Host controller functional state */ 56 #define C_HCFS_RESET (0x0) 57 #define C_HCFS_OPERATIONAL (0x1) 58 #define C_HCFS_RESUME (0x2) 59 #define C_HCFS_SUSPEND (0x3) 60 #define C_HCFS_SHIFT (6) 61 62 #define C_IR (1 << 8) /* Interrupt routing, make sure it's 0 */ 63 #define C_RWC (1 << 9) /* Remote wakeup connected, host specific */ 64 #define C_RWE (1 << 10) /* Remote wakeup enable */ 57 #define C_IR (1 << 8) 58 #define C_RWC (1 << 9) 59 #define C_RWE (1 << 10) 65 60 66 61 volatile uint32_t command_status; 67 #define CS_HCR (1 << 0) /* Host controller reset */68 #define CS_CLF (1 << 1) /* Control list filled */69 #define CS_BLF (1 << 2) /* Bulk list filled */70 #define CS_OCR (1 << 3) /* Ownership change request */71 #define CS_SOC_MASK (0x3) /* Scheduling overrun count */62 #define CS_HCR (1 << 0) 63 #define CS_CLF (1 << 1) 64 #define CS_BLF (1 << 2) 65 #define CS_OCR (1 << 3) 66 #define CS_SOC_MASK (0x3) 72 67 #define CS_SOC_SHIFT (16) 73 68 74 69 volatile uint32_t interrupt_status; 75 #define IS_SO (1 << 0) /* Scheduling overrun */76 #define IS_WDH (1 << 1) /* Write-back done head */77 #define IS_SF (1 << 2) /* Start of frame */78 #define IS_RD (1 << 3) /* Resume detected */79 #define IS_UE (1 << 4) /* Unrecoverable error */80 #define IS_FNO (1 << 5) /* Frame number overflow */81 #define IS_RHSC (1 << 6) /* Root hub status change */82 #define IS_OC (1 << 30) /* Ownership change */70 #define IS_SO (1 << 0) 71 #define IS_WDH (1 << 1) 72 #define IS_SF (1 << 2) 73 #define IS_RD (1 << 3) 74 #define IS_UE (1 << 4) 75 #define IS_FNO (1 << 5) 76 #define IS_RHSC (1 << 6) 77 #define IS_OC (1 << 30) 83 78 84 /** Interupt enable/disable, reads give the same value, writing causes 85 * enable/disable */ 86 volatile uint32_t interrupt_enable; 79 volatile uint32_t interupt_enable; 80 #define IE_SO (1 << 0) 81 #define IE_WDH (1 << 1) 82 #define IE_SF (1 << 2) 83 #define IE_RD (1 << 3) 84 #define IE_UE (1 << 4) 85 #define IE_FNO (1 << 5) 86 #define IE_RHSC (1 << 6) 87 #define IE_OC (1 << 30) 88 #define IE_MIE (1 << 31) 89 87 90 volatile uint32_t interrupt_disable; 88 #define I_SO (1 << 0) /* Scheduling overrun */89 #define I_WDH (1 << 1) /* Done head write-back */90 #define I_SF (1 << 2) /* Start of frame */91 #define I_RD (1 << 3) /* Resume detect */92 #define I_UE (1 << 4) /* Unrecoverable error */93 #define I_FNO (1 << 5) /* Frame number overflow */94 #define I_RHSC (1 << 6) /* Root hub status change */95 #define I_OC (1 << 30) /* Ownership change */96 #define I_MI (1 << 31) /* Master interrupt (all/any interrupts) */97 98 /** HCCA pointer (see hw_struct hcca.h) */99 91 volatile uint32_t hcca; 100 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */ 101 102 /** Currently executed period endpoint */ 103 const volatile uint32_t period_current; 104 105 /** The first control endpoint */ 92 volatile uint32_t period_corrent; 106 93 volatile uint32_t control_head; 107 108 /** Currently executed control endpoint */109 94 volatile uint32_t control_current; 110 111 /** The first bulk endpoint */112 95 volatile uint32_t bulk_head; 113 114 /** Currently executed bulk endpoint */115 96 volatile uint32_t bulk_current; 116 117 /** Done TD list, this value is periodically written to HCCA */ 118 const volatile uint32_t done_head; 119 120 /** Frame time and max packet size for all transfers */ 97 volatile uint32_t done_head; 121 98 volatile uint32_t fm_interval; 122 #define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/ 123 #define FMI_FI_SHIFT (0) 124 #define FMI_FSMPS_MASK (0x7fff) /* Full speed max packet size */ 125 #define FMI_FSMPS_SHIFT (16) 126 #define FMI_TOGGLE_FLAG (1 << 31) 127 128 /** Bit times remaining in current frame */ 129 const volatile uint32_t fm_remaining; 130 #define FMR_FR_MASK FMI_FI_MASK 131 #define FMR_FR_SHIFT FMI_FI_SHIFT 132 #define FMR_TOGGLE_FLAG FMI_TOGGLE_FLAG 133 134 /** Frame number */ 135 const volatile uint32_t fm_number; 136 #define FMN_NUMBER_MASK (0xffff) 137 138 /** Remaining bit time in frame to start periodic transfers */ 99 volatile uint32_t fm_remaining; 100 volatile uint32_t fm_number; 139 101 volatile uint32_t periodic_start; 140 #define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */141 142 /** Threshold for starting LS transaction */143 102 volatile uint32_t ls_threshold; 144 #define LST_LST_MASK (0x7fff)145 146 /** The first root hub control register */147 103 volatile uint32_t rh_desc_a; 148 #define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */149 #define RHDA_NDS_SHIFT (0)150 #define RHDA_PSM_FLAG (1 << 8) /* Power switching mode: 0-global, 1-per port*/151 #define RHDA_NPS_FLAG (1 << 9) /* No power switch: 1-power on, 0-use PSM*/152 #define RHDA_DT_FLAG (1 << 10) /* 1-Compound device, must be 0 */153 #define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */154 #define RHDA_NOCP (1 << 12) /* OC control: 0-use OCPM, 1-OC off */155 #define RHDA_POTPGT_MASK (0xff) /* Power on to power good time */156 #define RHDA_POTPGT_SHIFT (24)157 158 /** The other root hub control register */159 104 volatile uint32_t rh_desc_b; 160 #define RHDB_DR_MASK (0xffff) /* Device removable mask */161 #define RHDB_DR_SHIFT (0)162 #define RHDB_PCC_MASK (0xffff) /* Power control mask */163 #define RHDB_PCC_SHIFT (16)164 165 /* Port device removable status */166 #define RHDB_DR_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)167 /* Port power control status: 1-per port power control, 0-global power switch */168 #define RHDB_PPC_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)169 170 /** Root hub status register */171 105 volatile uint32_t rh_status; 172 #define RHS_LPS_FLAG (1 << 0)/* read: 0,173 * write: 0-no effect,174 * 1-turn off port power for ports175 * specified in PPCM(RHDB), or all ports,176 * if power is set globally */177 #define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */178 #define RHS_OCI_FLAG (1 << 1)/* Over-current indicator, if per-port: 0 */179 #define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC180 * 1-connect status change wakes HC181 * write: 1-set DRWE, 0-no effect */182 #define RHS_SET_DRWE RHS_DRWE_FLAG183 #define RHS_LPSC_FLAG (1 << 16)/* read: 0,184 * write: 0-no effect185 * 1-turn on port power for ports186 * specified in PPCM(RHDB), or all ports,187 * if power is set globally */188 #define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */189 #define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change */190 #define RHS_CLEAR_DRWE (1 << 31)191 192 /** Root hub per port status */193 106 volatile uint32_t rh_port_status[]; 194 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,195 * w: 1-clear port enable, 0-nothing */196 #define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG197 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status198 * w: 1-set port enable, 0-nothing */199 #define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG200 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status201 * w: 1-set port suspend, 0-nothing */202 #define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG203 #define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port204 * w: 1-clear port suspend (start resume205 * if suspened)206 * 0-nothing */207 #define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG208 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status209 * w: 1-set port reset, 0-nothing */210 #define RHPS_SET_PORT_RESET RHPS_PRS_FLAG211 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status212 * w: 1-set port power, 0-nothing */213 #define RHPS_SET_PORT_POWER RHPS_PPS_FLAG214 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached215 * w: 1-clear port power, 0-nothing */216 #define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG217 #define RHPS_CSC_FLAG (1 << 16) /* connect status change Write-Clean */218 #define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */219 #define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */220 #define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */221 #define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */222 #define RHPS_CHANGE_WC_MASK 0x1f0000223 107 } __attribute__((packed)) ohci_regs_t; 224 108 #endif -
uspace/drv/ohci/root_hub.c
rdc4c19e ra49e171 47 47 * standart device descriptor for ohci root hub 48 48 */ 49 static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = { 50 .configuration_count = 1, 51 .descriptor_type = USB_DESCTYPE_DEVICE, 52 .device_class = USB_CLASS_HUB, 53 .device_protocol = 0, 54 .device_subclass = 0, 55 .device_version = 0, 56 .length = sizeof (usb_standard_device_descriptor_t), 57 /// \TODO this value is guessed 58 .max_packet_size = 8, 59 .vendor_id = 0x16db, 60 .product_id = 0x0001, 61 /// \TODO these values migt be different 62 .str_serial_number = 0, 63 .usb_spec_version = 0x110, 49 static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = 50 { 51 .configuration_count = 1, 52 .descriptor_type = USB_DESCTYPE_DEVICE, 53 .device_class = USB_CLASS_HUB, 54 .device_protocol = 0, 55 .device_subclass = 0, 56 .device_version = 0, 57 .length = sizeof(usb_standard_device_descriptor_t), 58 /// \TODO this value is guessed 59 .max_packet_size = 8, 60 .vendor_id = 0x16db, 61 .product_id = 0x0001, 62 /// \TODO these values migt be different 63 .str_serial_number = 0, 64 .usb_spec_version = 0x110, 64 65 }; 65 66 … … 68 69 * for ohci root hubs 69 70 */ 70 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = { 71 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = 72 { 71 73 /// \TODO some values are default or guessed 72 .attributes = 1 <<7,74 .attributes = 1<<7, 73 75 .configuration_number = 1, 74 76 .descriptor_type = USB_DESCTYPE_CONFIGURATION, 75 77 .interface_count = 1, 76 .length = sizeof (usb_standard_configuration_descriptor_t),78 .length = sizeof(usb_standard_configuration_descriptor_t), 77 79 .max_power = 100, 78 80 .str_configuration = 0, … … 82 84 * standart ohci root hub interface descriptor 83 85 */ 84 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = { 86 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = 87 { 85 88 .alternate_setting = 0, 86 89 .descriptor_type = USB_DESCTYPE_INTERFACE, … … 91 94 .interface_protocol = 0, 92 95 .interface_subclass = 0, 93 .length = sizeof (usb_standard_interface_descriptor_t),96 .length = sizeof(usb_standard_interface_descriptor_t), 94 97 .str_interface = 0, 95 98 }; … … 98 101 * standart ohci root hub endpoint descriptor 99 102 */ 100 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = { 103 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = 104 { 101 105 .attributes = USB_TRANSFER_INTERRUPT, 102 106 .descriptor_type = USB_DESCTYPE_ENDPOINT, 103 .endpoint_address = 1 + (1 <<7),104 .length = sizeof (usb_standard_endpoint_descriptor_t),107 .endpoint_address = 1 + (1<<7), 108 .length = sizeof(usb_standard_endpoint_descriptor_t), 105 109 .max_packet_size = 8, 106 110 .poll_interval = 255, … … 108 112 109 113 static const uint32_t hub_clear_feature_valid_mask = 110 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) |111 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);114 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) + 115 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 112 116 113 117 static const uint32_t hub_clear_feature_by_writing_one_mask = … … 115 119 116 120 static const uint32_t hub_set_feature_valid_mask = 117 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) | 118 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 119 120 121 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 122 123 121 124 static const uint32_t hub_set_feature_direct_mask = 122 125 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 123 126 124 127 static const uint32_t port_set_feature_valid_mask = 125 (1 << USB_HUB_FEATURE_PORT_ENABLE) |126 (1 << USB_HUB_FEATURE_PORT_SUSPEND) | 127 (1 << USB_HUB_FEATURE_PORT_RESET) | 128 (1 << USB_HUB_FEATURE_PORT_POWER);128 (1 << USB_HUB_FEATURE_PORT_ENABLE) + 129 (1 << USB_HUB_FEATURE_PORT_SUSPEND) + 130 (1 << USB_HUB_FEATURE_PORT_RESET) + 131 (1 << USB_HUB_FEATURE_PORT_POWER); 129 132 130 133 static const uint32_t port_clear_feature_valid_mask = 131 (1 << USB_HUB_FEATURE_PORT_CONNECTION) | 132 (1 << USB_HUB_FEATURE_PORT_SUSPEND) | 133 (1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) | 134 (1 << USB_HUB_FEATURE_PORT_POWER) | 135 (1 << USB_HUB_FEATURE_C_PORT_CONNECTION) | 136 (1 << USB_HUB_FEATURE_C_PORT_ENABLE) | 137 (1 << USB_HUB_FEATURE_C_PORT_SUSPEND) | 138 (1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) | 139 (1 << USB_HUB_FEATURE_C_PORT_RESET); 140 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into 141 //USB_HUB_FEATURE_PORT_LOW_SPEED 142 143 static const uint32_t port_status_change_mask = 144 (1<< USB_HUB_FEATURE_C_PORT_CONNECTION) | 145 (1<< USB_HUB_FEATURE_C_PORT_ENABLE) | 146 (1<< USB_HUB_FEATURE_C_PORT_OVER_CURRENT) | 147 (1<< USB_HUB_FEATURE_C_PORT_RESET) | 148 (1<< USB_HUB_FEATURE_C_PORT_SUSPEND); 149 150 151 static void usb_create_serialized_hub_descriptor(rh_t *instance, 152 uint8_t ** out_result, 153 size_t * out_size); 154 155 static void rh_init_descriptors(rh_t *instance); 156 157 static int process_get_port_status_request(rh_t *instance, uint16_t port, 158 usb_transfer_batch_t * request); 159 160 static int process_get_hub_status_request(rh_t *instance, 161 usb_transfer_batch_t * request); 162 163 static int process_get_status_request(rh_t *instance, 164 usb_transfer_batch_t * request); 165 166 static void create_interrupt_mask(rh_t *instance, void ** buffer, 167 size_t * buffer_size); 168 169 static int process_get_descriptor_request(rh_t *instance, 170 usb_transfer_batch_t *request); 171 172 static int process_get_configuration_request(rh_t *instance, 173 usb_transfer_batch_t *request); 174 175 static int process_hub_feature_set_request(rh_t *instance, uint16_t feature); 176 177 static int process_hub_feature_clear_request(rh_t *instance, 178 uint16_t feature); 179 180 static int process_port_feature_set_request(rh_t *instance, 181 uint16_t feature, uint16_t port); 182 183 static int process_port_feature_clear_request(rh_t *instance, 184 uint16_t feature, uint16_t port); 185 186 static int process_address_set_request(rh_t *instance, 187 uint16_t address); 188 189 static int process_request_with_output(rh_t *instance, 190 usb_transfer_batch_t *request); 191 192 static int process_request_with_input(rh_t *instance, 193 usb_transfer_batch_t *request); 194 195 static int process_request_without_data(rh_t *instance, 196 usb_transfer_batch_t *request); 197 198 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 199 200 201 202 203 204 /** Root hub initialization 205 * @return Error code. 206 */ 207 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) { 208 assert(instance); 209 //instance->address = -1; 210 instance->registers = regs; 211 instance->device = dev; 212 instance->port_count = 213 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 214 rh_init_descriptors(instance); 215 // set port power mode to no-power-switching 216 instance->registers->rh_desc_a = 217 instance->registers->rh_desc_a | (1<<9); 218 219 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 220 221 //start generic usb hub driver 222 223 /* TODO: implement */ 224 return EOK; 225 } 226 /*----------------------------------------------------------------------------*/ 227 228 /** 229 * process root hub request 230 * 231 * @param instance root hub instance 232 * @param request structure containing both request and response information 233 * @return error code 234 */ 235 int rh_request(rh_t *instance, usb_transfer_batch_t *request) { 236 assert(instance); 237 assert(request); 238 int opResult; 239 if (request->transfer_type == USB_TRANSFER_CONTROL) { 240 usb_log_info("Root hub got CONTROL packet\n"); 241 opResult = process_ctrl_request(instance, request); 242 } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) { 243 usb_log_info("Root hub got INTERRUPT packet\n"); 244 void * buffer; 245 create_interrupt_mask(instance, &buffer, 246 &(request->transfered_size)); 247 memcpy(request->transport_buffer, buffer, 248 request->transfered_size); 249 opResult = EOK; 250 } else { 251 opResult = EINVAL; 252 } 253 usb_transfer_batch_finish_error(request, opResult); 254 return EOK; 255 } 256 257 /*----------------------------------------------------------------------------*/ 258 259 260 void rh_interrupt(rh_t *instance) { 261 usb_log_info("Whoa whoa wait, I`m not supposed to receive any " 262 "interrupts, am I?\n"); 263 /* TODO: implement? */ 264 } 265 /*----------------------------------------------------------------------------*/ 134 (1 << USB_HUB_FEATURE_PORT_CONNECTION) + 135 (1 << USB_HUB_FEATURE_PORT_SUSPEND) + 136 (1 << USB_HUB_FEATURE_PORT_OVER_CURRENT) + 137 (1 << USB_HUB_FEATURE_PORT_POWER) + 138 (1 << USB_HUB_FEATURE_C_PORT_CONNECTION) + 139 (1 << USB_HUB_FEATURE_C_PORT_ENABLE) + 140 (1 << USB_HUB_FEATURE_C_PORT_SUSPEND) + 141 (1 << USB_HUB_FEATURE_C_PORT_OVER_CURRENT) + 142 (1 << USB_HUB_FEATURE_C_PORT_RESET); 143 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into USB_HUB_FEATURE_PORT_LOW_SPEED 144 145 146 266 147 267 148 /** … … 276 157 */ 277 158 static void usb_create_serialized_hub_descriptor(rh_t *instance, 278 uint8_t ** out_result,279 size_t * out_size) {159 uint8_t ** out_result, 160 size_t * out_size) { 280 161 //base size 281 162 size_t size = 7; 282 163 //variable size according to port count 283 164 size_t var_size = instance->port_count / 8 + 284 ((instance->port_count % 8 > 0) ? 1 : 0);165 ((instance->port_count % 8 > 0) ? 1 : 0); 285 166 size += 2 * var_size; 286 167 uint8_t * result = (uint8_t*) malloc(size); 287 bzero(result, size);168 bzero(result,size); 288 169 //size 289 170 result[0] = size; … … 293 174 uint32_t hub_desc_reg = instance->registers->rh_desc_a; 294 175 result[3] = 295 ((hub_desc_reg >> 8) %2) +296 (((hub_desc_reg >> 9) %2) << 1) +297 (((hub_desc_reg >> 10) %2) << 2) +298 (((hub_desc_reg >> 11) %2) << 3) +299 (((hub_desc_reg >> 12) %2) << 4);176 ((hub_desc_reg >> 8) %2) + 177 (((hub_desc_reg >> 9) %2) << 1) + 178 (((hub_desc_reg >> 10) %2) << 2) + 179 (((hub_desc_reg >> 11) %2) << 3) + 180 (((hub_desc_reg >> 12) %2) << 4); 300 181 result[4] = 0; 301 182 result[5] = /*descriptor->pwr_on_2_good_time*/ 50; … … 304 185 int port; 305 186 for (port = 1; port <= instance->port_count; ++port) { 306 uint8_t is_non_removable = 307 instance->registers->rh_desc_b >> port % 2; 308 result[7 + port / 8] += 309 is_non_removable << (port % 8); 187 result[7 + port/8] += 188 ((instance->registers->rh_desc_b >> port)%2) << (port%8); 310 189 } 311 190 size_t i; … … 316 195 (*out_size) = size; 317 196 } 318 /*----------------------------------------------------------------------------*/ 197 319 198 320 199 /** initialize hub descriptors … … 324 203 * @instance root hub instance 325 204 */ 326 static void rh_init_descriptors(rh_t *instance) {205 static void rh_init_descriptors(rh_t *instance){ 327 206 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 328 sizeof (ohci_rh_device_descriptor)329 );207 sizeof(ohci_rh_device_descriptor) 208 ); 330 209 usb_standard_configuration_descriptor_t descriptor; 331 memcpy(&descriptor, &ohci_rh_conf_descriptor,332 sizeof(ohci_rh_conf_descriptor));210 memcpy(&descriptor,&ohci_rh_conf_descriptor, 211 sizeof(ohci_rh_conf_descriptor)); 333 212 uint8_t * hub_descriptor; 334 213 size_t hub_desc_size; 335 214 usb_create_serialized_hub_descriptor(instance, &hub_descriptor, 336 &hub_desc_size);215 &hub_desc_size); 337 216 338 217 descriptor.total_length = 339 sizeof (usb_standard_configuration_descriptor_t)+340 sizeof (usb_standard_endpoint_descriptor_t)+341 sizeof (usb_standard_interface_descriptor_t)+342 hub_desc_size;343 218 sizeof(usb_standard_configuration_descriptor_t)+ 219 sizeof(usb_standard_endpoint_descriptor_t)+ 220 sizeof(usb_standard_interface_descriptor_t)+ 221 hub_desc_size; 222 344 223 uint8_t * full_config_descriptor = 345 (uint8_t*) malloc(descriptor.total_length);346 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));347 memcpy(full_config_descriptor + sizeof (descriptor),348 &ohci_rh_iface_descriptor, sizeof(ohci_rh_iface_descriptor));349 memcpy(full_config_descriptor + sizeof (descriptor) +350 sizeof(ohci_rh_iface_descriptor),351 &ohci_rh_ep_descriptor, sizeof(ohci_rh_ep_descriptor));352 memcpy(full_config_descriptor + sizeof (descriptor) +353 sizeof(ohci_rh_iface_descriptor) +354 sizeof(ohci_rh_ep_descriptor),355 hub_descriptor, hub_desc_size);356 224 (uint8_t*) malloc(descriptor.total_length); 225 memcpy(full_config_descriptor, &descriptor, sizeof(descriptor)); 226 memcpy(full_config_descriptor + sizeof(descriptor), 227 &ohci_rh_iface_descriptor, sizeof(ohci_rh_iface_descriptor)); 228 memcpy(full_config_descriptor + sizeof(descriptor) + 229 sizeof(ohci_rh_iface_descriptor), 230 &ohci_rh_ep_descriptor, sizeof(ohci_rh_ep_descriptor)); 231 memcpy(full_config_descriptor + sizeof(descriptor) + 232 sizeof(ohci_rh_iface_descriptor) + 233 sizeof(ohci_rh_ep_descriptor), 234 hub_descriptor, hub_desc_size); 235 357 236 instance->descriptors.configuration = full_config_descriptor; 358 237 instance->descriptors.configuration_size = descriptor.total_length; 359 238 } 239 240 /** Root hub initialization 241 * @return Error code. 242 */ 243 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) 244 { 245 assert(instance); 246 instance->address = -1; 247 instance->registers = regs; 248 instance->device = dev; 249 instance->port_count = instance->registers->rh_desc_a & 0xff; 250 rh_init_descriptors(instance); 251 /// \TODO set port power mode 252 253 254 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 255 256 //start generic usb hub driver 257 258 /* TODO: implement */ 259 return EOK; 260 } 360 261 /*----------------------------------------------------------------------------*/ 361 262 … … 371 272 */ 372 273 static int process_get_port_status_request(rh_t *instance, uint16_t port, 373 usb_transfer_batch_t * request){374 if (port < 1 || port >instance->port_count)375 return EINVAL; 376 uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;274 usb_transfer_batch_t * request){ 275 if(port<1 || port>instance->port_count) 276 return EINVAL; 277 uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer; 377 278 request->transfered_size = 4; 378 uint32_buffer[0] = instance->registers->rh_port_status[port - 1]; 379 #if 0 380 int i; 381 for (i = 0; i < instance->port_count; ++i) { 382 usb_log_debug("port status %d,x%x\n", 383 instance->registers->rh_port_status[i], 384 instance->registers->rh_port_status[i]); 385 } 386 #endif 387 return EOK; 388 } 389 /*----------------------------------------------------------------------------*/ 279 uint32_buffer[0] = instance->registers->rh_port_status[port -1]; 280 return EOK; 281 } 390 282 391 283 /** … … 399 291 */ 400 292 static int process_get_hub_status_request(rh_t *instance, 401 usb_transfer_batch_t * request) { 402 uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer; 293 usb_transfer_batch_t * request){ 294 uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer; 295 //bits, 0,1,16,17 403 296 request->transfered_size = 4; 404 //bits, 0,1,16,17 405 uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17); 297 uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17); 406 298 uint32_buffer[0] = mask & instance->registers->rh_status; 407 299 return EOK; 408 } 409 /*----------------------------------------------------------------------------*/ 300 301 } 302 303 410 304 411 305 /** … … 419 313 */ 420 314 static int process_get_status_request(rh_t *instance, 421 usb_transfer_batch_t * request) { 315 usb_transfer_batch_t * request) 316 { 422 317 size_t buffer_size = request->buffer_size; 423 318 usb_device_request_setup_packet_t * request_packet = 424 (usb_device_request_setup_packet_t*)425 request->setup_buffer;319 (usb_device_request_setup_packet_t*) 320 request->setup_buffer; 426 321 427 322 usb_hub_bm_request_type_t request_type = request_packet->request_type; 428 if (buffer_size < 4/*request_packet->length*/){///\TODO323 if(buffer_size<4/*request_packet->length*/){///\TODO 429 324 usb_log_warning("requested more data than buffer size\n"); 430 325 return EINVAL; 431 326 } 432 327 433 if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)328 if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) 434 329 return process_get_hub_status_request(instance, request); 435 if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) 436 return process_get_port_status_request(instance, 437 request_packet->index, 438 request); 330 if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) 331 return process_get_port_status_request(instance, request_packet->index, 332 request); 439 333 return ENOTSUP; 440 334 } 441 /*----------------------------------------------------------------------------*/442 335 443 336 /** … … 446 339 * Result contains bitmap where bit 0 indicates change on hub and 447 340 * bit i indicates change on i`th port (i>0). For more info see 448 * Hub and Port status bitmap specification in USB specification 449 * (chapter 11.13.4) 341 * Hub and Port status bitmap specification in USB specification. 450 342 * @param instance root hub instance 451 343 * @param@out buffer pointer to created interrupt mas … … 453 345 */ 454 346 static void create_interrupt_mask(rh_t *instance, void ** buffer, 455 size_t * buffer_size){347 size_t * buffer_size){ 456 348 int bit_count = instance->port_count + 1; 457 (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1); 458 349 (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1; 459 350 (*buffer) = malloc(*buffer_size); 460 uint8_t * bitmap = (uint8_t*) (*buffer); 461 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 462 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 463 bzero(bitmap, (*buffer_size)); 464 if (instance->registers->rh_status & mask) { 351 uint8_t * bitmap = (uint8_t*)(*buffer); 352 uint32_t mask = (1<<16) + (1<<17); 353 bzero(bitmap,(*buffer_size)); 354 if(instance->registers->rh_status & mask){ 465 355 bitmap[0] = 1; 466 356 } 467 357 int port; 468 mask = port_status_change_mask; 469 for (port = 1; port <= instance->port_count; ++port) { 470 if (mask & instance->registers->rh_port_status[port - 1]) { 471 bitmap[(port) / 8] += 1 << (port % 8); 472 } 473 } 474 } 475 /*----------------------------------------------------------------------------*/ 476 358 mask = 0; 359 int i; 360 for(i=16;i<=20;++i) 361 mask += 1<<i; 362 for(port = 1; port<=instance->port_count;++port){ 363 if(mask & instance->registers->rh_port_status[port-1]){ 364 bitmap[(port+1)/8] += 1<<(port%8); 365 } 366 } 367 } 368 477 369 /** 478 370 * create answer to a descriptor request … … 485 377 */ 486 378 static int process_get_descriptor_request(rh_t *instance, 487 usb_transfer_batch_t *request){379 usb_transfer_batch_t *request){ 488 380 usb_device_request_setup_packet_t * setup_request = 489 (usb_device_request_setup_packet_t*)request->setup_buffer;381 (usb_device_request_setup_packet_t*)request->setup_buffer; 490 382 size_t size; 491 383 const void * result_descriptor = NULL; 492 384 const uint16_t setup_request_value = setup_request->value_high; 493 //(setup_request->value_low << 8);385 //(setup_request->value_low << 8); 494 386 bool del = false; 495 switch (setup_request_value) {496 case USB_DESCTYPE_HUB:497 {387 switch (setup_request_value) 388 { 389 case USB_DESCTYPE_HUB: { 498 390 uint8_t * descriptor; 499 391 usb_create_serialized_hub_descriptor( 500 392 instance, &descriptor, &size); 501 393 result_descriptor = descriptor; 502 if (result_descriptor) del = true;394 if(result_descriptor) del = true; 503 395 break; 504 396 } 505 case USB_DESCTYPE_DEVICE: 506 { 397 case USB_DESCTYPE_DEVICE: { 507 398 usb_log_debug("USB_DESCTYPE_DEVICE\n"); 508 399 result_descriptor = &ohci_rh_device_descriptor; 509 size = sizeof (ohci_rh_device_descriptor);400 size = sizeof(ohci_rh_device_descriptor); 510 401 break; 511 402 } 512 case USB_DESCTYPE_CONFIGURATION: 513 { 403 case USB_DESCTYPE_CONFIGURATION: { 514 404 usb_log_debug("USB_DESCTYPE_CONFIGURATION\n"); 515 405 result_descriptor = instance->descriptors.configuration; … … 517 407 break; 518 408 } 519 case USB_DESCTYPE_INTERFACE: 520 { 409 case USB_DESCTYPE_INTERFACE: { 521 410 usb_log_debug("USB_DESCTYPE_INTERFACE\n"); 522 411 result_descriptor = &ohci_rh_iface_descriptor; 523 size = sizeof (ohci_rh_iface_descriptor);412 size = sizeof(ohci_rh_iface_descriptor); 524 413 break; 525 414 } 526 case USB_DESCTYPE_ENDPOINT: 527 { 415 case USB_DESCTYPE_ENDPOINT: { 528 416 usb_log_debug("USB_DESCTYPE_ENDPOINT\n"); 529 417 result_descriptor = &ohci_rh_ep_descriptor; 530 size = sizeof (ohci_rh_ep_descriptor);418 size = sizeof(ohci_rh_ep_descriptor); 531 419 break; 532 420 } 533 default: 534 { 535 usb_log_debug("USB_DESCTYPE_EINVAL %d \n", 536 setup_request->value); 537 usb_log_debug("\ttype %d\n\trequest %d\n\tvalue " 538 "%d\n\tindex %d\n\tlen %d\n ", 539 setup_request->request_type, 540 setup_request->request, 541 setup_request_value, 542 setup_request->index, 543 setup_request->length 544 ); 421 default: { 422 usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value); 423 usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ", 424 setup_request->request_type, 425 setup_request->request, 426 setup_request_value, 427 setup_request->index, 428 setup_request->length 429 ); 545 430 return EINVAL; 546 431 } 547 432 } 548 if (request->buffer_size < size){433 if(request->buffer_size < size){ 549 434 size = request->buffer_size; 550 435 } 551 436 request->transfered_size = size; 552 memcpy(request->transport_buffer, result_descriptor, size); 437 memcpy(request->transport_buffer,result_descriptor,size); 438 usb_log_debug("sent desctiptor: %s\n", 439 usb_debug_str_buffer((uint8_t*)request->transport_buffer,size,size)); 553 440 if (del) 554 441 free(result_descriptor); 555 442 return EOK; 556 443 } 557 /*----------------------------------------------------------------------------*/558 444 559 445 /** … … 565 451 * @return error code 566 452 */ 567 static int process_get_configuration_request(rh_t *instance, 568 usb_transfer_batch_t *request){453 static int process_get_configuration_request(rh_t *instance, 454 usb_transfer_batch_t *request){ 569 455 //set and get configuration requests do not have any meaning, only dummy 570 456 //values are returned 571 if (request->buffer_size != 1)457 if(request->buffer_size != 1) 572 458 return EINVAL; 573 459 request->transport_buffer[0] = 1; … … 575 461 return EOK; 576 462 } 577 /*----------------------------------------------------------------------------*/578 463 579 464 /** 580 465 * process feature-enabling request on hub 581 * 466 * 582 467 * @param instance root hub instance 583 468 * @param feature feature selector … … 585 470 */ 586 471 static int process_hub_feature_set_request(rh_t *instance, 587 uint16_t feature) { 588 if (!((1 << feature) & hub_set_feature_valid_mask)) 589 return EINVAL; 590 if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER) 591 feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16; 472 uint16_t feature){ 473 if(! ((1<<feature) & hub_set_feature_valid_mask)) 474 return EINVAL; 592 475 instance->registers->rh_status = 593 (instance->registers->rh_status | (1 << feature)) 594 & (~hub_clear_feature_by_writing_one_mask); 595 return EOK; 596 } 597 /*----------------------------------------------------------------------------*/ 476 (instance->registers->rh_status | (1<<feature)) 477 & (~ hub_clear_feature_by_writing_one_mask); 478 return EOK; 479 } 598 480 599 481 /** … … 605 487 */ 606 488 static int process_hub_feature_clear_request(rh_t *instance, 607 uint16_t feature){608 if (!((1 <<feature) & hub_clear_feature_valid_mask))489 uint16_t feature){ 490 if(! ((1<<feature) & hub_clear_feature_valid_mask)) 609 491 return EINVAL; 610 492 //is the feature cleared directly? 611 if ((1 << feature) & hub_set_feature_direct_mask){493 if ((1<<feature) & hub_set_feature_direct_mask){ 612 494 instance->registers->rh_status = 613 (instance->registers->rh_status & (~(1 <<feature)))614 & (~ hub_clear_feature_by_writing_one_mask);615 } else{//the feature is cleared by writing '1'495 (instance->registers->rh_status & (~(1<<feature))) 496 & (~ hub_clear_feature_by_writing_one_mask); 497 }else{//the feature is cleared by writing '1' 616 498 instance->registers->rh_status = 617 (instance->registers->rh_status 618 & (~hub_clear_feature_by_writing_one_mask)) 619 | (1 << feature); 620 } 621 return EOK; 622 } 623 /*----------------------------------------------------------------------------*/ 499 (instance->registers->rh_status 500 & (~ hub_clear_feature_by_writing_one_mask)) 501 | (1<<feature); 502 } 503 return EOK; 504 } 505 506 624 507 625 508 /** 626 509 * process feature-enabling request on hub 627 * 510 * 628 511 * @param instance root hub instance 629 512 * @param feature feature selector … … 633 516 */ 634 517 static int process_port_feature_set_request(rh_t *instance, 635 uint16_t feature, uint16_t port){636 if (!((1 <<feature) & port_set_feature_valid_mask))637 return EINVAL; 638 if (port < 1 || port >instance->port_count)518 uint16_t feature, uint16_t port){ 519 if(!((1<<feature) & port_set_feature_valid_mask)) 520 return EINVAL; 521 if(port<1 || port>instance->port_count) 639 522 return EINVAL; 640 523 instance->registers->rh_port_status[port - 1] = 641 (instance->registers->rh_port_status[port - 1] | (1 <<feature))642 & (~port_clear_feature_valid_mask);524 (instance->registers->rh_port_status[port - 1] | (1<<feature)) 525 & (~port_clear_feature_valid_mask); 643 526 /// \TODO any error? 644 527 return EOK; 645 528 } 646 /*----------------------------------------------------------------------------*/647 529 648 530 /** … … 656 538 */ 657 539 static int process_port_feature_clear_request(rh_t *instance, 658 uint16_t feature, uint16_t port){659 if (!((1 <<feature) & port_clear_feature_valid_mask))660 return EINVAL; 661 if (port < 1 || port >instance->port_count)662 return EINVAL; 663 if (feature == USB_HUB_FEATURE_PORT_POWER)540 uint16_t feature, uint16_t port){ 541 if(!((1<<feature) & port_clear_feature_valid_mask)) 542 return EINVAL; 543 if(port<1 || port>instance->port_count) 544 return EINVAL; 545 if(feature == USB_HUB_FEATURE_PORT_POWER) 664 546 feature = USB_HUB_FEATURE_PORT_LOW_SPEED; 665 if (feature == USB_HUB_FEATURE_PORT_SUSPEND)547 if(feature == USB_HUB_FEATURE_PORT_SUSPEND) 666 548 feature = USB_HUB_FEATURE_PORT_OVER_CURRENT; 667 549 instance->registers->rh_port_status[port - 1] = 668 (instance->registers->rh_port_status[port - 1]669 & (~port_clear_feature_valid_mask))670 | (1 <<feature);550 (instance->registers->rh_port_status[port - 1] 551 & (~port_clear_feature_valid_mask)) 552 | (1<<feature); 671 553 /// \TODO any error? 672 554 return EOK; 673 555 } 674 /*----------------------------------------------------------------------------*/ 556 675 557 676 558 /** 677 559 * register address to this device 678 * 560 * 679 561 * @param instance root hub instance 680 562 * @param address new address … … 682 564 */ 683 565 static int process_address_set_request(rh_t *instance, 684 uint16_t address){566 uint16_t address){ 685 567 instance->address = address; 686 568 return EOK; 687 569 } 688 /*----------------------------------------------------------------------------*/689 570 690 571 /** … … 698 579 */ 699 580 static int process_request_with_output(rh_t *instance, 700 usb_transfer_batch_t *request){581 usb_transfer_batch_t *request){ 701 582 usb_device_request_setup_packet_t * setup_request = 702 (usb_device_request_setup_packet_t*)request->setup_buffer;703 if (setup_request->request == USB_DEVREQ_GET_STATUS){583 (usb_device_request_setup_packet_t*)request->setup_buffer; 584 if(setup_request->request == USB_DEVREQ_GET_STATUS){ 704 585 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 705 586 return process_get_status_request(instance, request); 706 587 } 707 if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){588 if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){ 708 589 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 709 590 return process_get_descriptor_request(instance, request); 710 591 } 711 if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION){592 if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){ 712 593 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 713 594 return process_get_configuration_request(instance, request); … … 715 596 return ENOTSUP; 716 597 } 717 /*----------------------------------------------------------------------------*/718 598 719 599 /** … … 727 607 */ 728 608 static int process_request_with_input(rh_t *instance, 729 usb_transfer_batch_t *request){609 usb_transfer_batch_t *request){ 730 610 usb_device_request_setup_packet_t * setup_request = 731 (usb_device_request_setup_packet_t*)request->setup_buffer;611 (usb_device_request_setup_packet_t*)request->setup_buffer; 732 612 request->transfered_size = 0; 733 if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){613 if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){ 734 614 return ENOTSUP; 735 615 } 736 if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION){616 if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){ 737 617 //set and get configuration requests do not have any meaning, 738 618 //only dummy values are returned … … 741 621 return ENOTSUP; 742 622 } 743 /*----------------------------------------------------------------------------*/744 623 745 624 /** … … 753 632 */ 754 633 static int process_request_without_data(rh_t *instance, 755 usb_transfer_batch_t *request){634 usb_transfer_batch_t *request){ 756 635 usb_device_request_setup_packet_t * setup_request = 757 (usb_device_request_setup_packet_t*)request->setup_buffer;636 (usb_device_request_setup_packet_t*)request->setup_buffer; 758 637 request->transfered_size = 0; 759 if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE){760 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){638 if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE){ 639 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){ 761 640 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 762 641 return process_hub_feature_clear_request(instance, 763 setup_request->value);764 } 765 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){642 setup_request->value); 643 } 644 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){ 766 645 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 767 646 return process_port_feature_clear_request(instance, 768 setup_request->value,769 setup_request->index);647 setup_request->value, 648 setup_request->index); 770 649 } 771 650 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n", 772 setup_request->request_type);773 return EINVAL; 774 } 775 if (setup_request->request == USB_DEVREQ_SET_FEATURE){776 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){651 setup_request->request_type); 652 return EINVAL; 653 } 654 if(setup_request->request == USB_DEVREQ_SET_FEATURE){ 655 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){ 777 656 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 778 657 return process_hub_feature_set_request(instance, 779 setup_request->value);780 } 781 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){658 setup_request->value); 659 } 660 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){ 782 661 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 783 662 return process_port_feature_set_request(instance, 784 setup_request->value, 785 setup_request->index); 786 } 787 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n", 788 setup_request->request_type); 789 return EINVAL; 790 } 791 if (setup_request->request == USB_DEVREQ_SET_ADDRESS) { 663 setup_request->value, 664 setup_request->index); 665 } 666 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type); 667 return EINVAL; 668 } 669 if(setup_request->request == USB_DEVREQ_SET_ADDRESS){ 792 670 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 793 return process_address_set_request(instance, 794 setup_request->value); 795 } 796 usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n", 797 setup_request->request_type); 671 return process_address_set_request(instance, setup_request->value); 672 } 673 usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type); 798 674 return ENOTSUP; 799 675 } 800 /*----------------------------------------------------------------------------*/801 676 802 677 /** … … 818 693 * @return error code 819 694 */ 820 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) { 821 if (!request->setup_buffer) { 695 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request){ 696 int opResult; 697 if (request->setup_buffer) { 698 if(sizeof(usb_device_request_setup_packet_t)>request->setup_size){ 699 usb_log_error("setup packet too small\n"); 700 return EINVAL; 701 } 702 usb_log_info("CTRL packet: %s.\n", 703 usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8)); 704 usb_device_request_setup_packet_t * setup_request = 705 (usb_device_request_setup_packet_t*)request->setup_buffer; 706 if( 707 setup_request->request == USB_DEVREQ_GET_STATUS 708 || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR 709 || setup_request->request == USB_DEVREQ_GET_CONFIGURATION 710 ){ 711 usb_log_debug("processing request with output\n"); 712 opResult = process_request_with_output(instance,request); 713 }else if( 714 setup_request->request == USB_DEVREQ_CLEAR_FEATURE 715 || setup_request->request == USB_DEVREQ_SET_FEATURE 716 || setup_request->request == USB_DEVREQ_SET_ADDRESS 717 ){ 718 usb_log_debug("processing request without additional data\n"); 719 opResult = process_request_without_data(instance,request); 720 }else if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR 721 || setup_request->request == USB_DEVREQ_SET_CONFIGURATION 722 ){ 723 usb_log_debug("processing request with input\n"); 724 opResult = process_request_with_input(instance,request); 725 }else{ 726 usb_log_warning("received unsuported request: %d\n", 727 setup_request->request 728 ); 729 opResult = ENOTSUP; 730 } 731 }else{ 822 732 usb_log_error("root hub received empty transaction?"); 823 return EINVAL; 824 } 733 opResult = EINVAL; 734 } 735 return opResult; 736 } 737 738 /** 739 * process root hub request 740 * 741 * @param instance root hub instance 742 * @param request structure containing both request and response information 743 * @return error code 744 */ 745 int rh_request(rh_t *instance, usb_transfer_batch_t *request) 746 { 747 assert(instance); 748 assert(request); 825 749 int opResult; 826 if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) { 827 usb_log_error("setup packet too small\n"); 828 return EINVAL; 829 } 830 usb_log_info("CTRL packet: %s.\n", 831 usb_debug_str_buffer( 832 (const uint8_t *) request->setup_buffer, 8, 8)); 833 usb_device_request_setup_packet_t * setup_request = 834 (usb_device_request_setup_packet_t*) 835 request->setup_buffer; 836 switch (setup_request->request) { 837 case USB_DEVREQ_GET_STATUS: 838 case USB_DEVREQ_GET_DESCRIPTOR: 839 case USB_DEVREQ_GET_CONFIGURATION: 840 usb_log_debug("processing request with output\n"); 841 opResult = process_request_with_output( 842 instance, request); 843 break; 844 case USB_DEVREQ_CLEAR_FEATURE: 845 case USB_DEVREQ_SET_FEATURE: 846 case USB_DEVREQ_SET_ADDRESS: 847 usb_log_debug("processing request without " 848 "additional data\n"); 849 opResult = process_request_without_data( 850 instance, request); 851 break; 852 case USB_DEVREQ_SET_DESCRIPTOR: 853 case USB_DEVREQ_SET_CONFIGURATION: 854 usb_log_debug("processing request with " 855 "input\n"); 856 opResult = process_request_with_input( 857 instance, request); 858 break; 859 default: 860 usb_log_warning("received unsuported request: " 861 "%d\n", 862 setup_request->request 863 ); 864 opResult = ENOTSUP; 865 } 866 return opResult; 867 } 868 750 if(request->transfer_type == USB_TRANSFER_CONTROL){ 751 usb_log_info("Root hub got CONTROL packet\n"); 752 opResult = process_ctrl_request(instance,request); 753 }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){ 754 usb_log_info("Root hub got INTERRUPT packet\n"); 755 void * buffer; 756 create_interrupt_mask(instance, &buffer, 757 &(request->transfered_size)); 758 memcpy(request->transport_buffer,buffer, request->transfered_size); 759 opResult = EOK; 760 }else{ 761 opResult = EINVAL; 762 } 763 usb_transfer_batch_finish(request, opResult); 764 return EOK; 765 } 766 /*----------------------------------------------------------------------------*/ 767 768 769 void rh_interrupt(rh_t *instance) 770 { 771 usb_log_info("Whoa whoa wait, I`m not supposed to receive any interrupts, am I?\n"); 772 /* TODO: implement? */ 773 } 869 774 /** 870 775 * @} -
uspace/drv/ohci/utils/malloc32.h
rdc4c19e ra49e171 37 37 #include <assert.h> 38 38 #include <malloc.h> 39 #include <errno.h>40 39 #include <mem.h> 41 40 #include <as.h> -
uspace/drv/uhci-hcd/batch.c
rdc4c19e ra49e171 80 80 * transaction and callback. 81 81 */ 82 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, 83 char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size, 82 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 83 usb_transfer_type_t transfer_type, size_t max_packet_size, 84 usb_speed_t speed, char *buffer, size_t buffer_size, 85 char* setup_buffer, size_t setup_size, 84 86 usbhc_iface_transfer_in_callback_t func_in, 85 usbhc_iface_transfer_out_callback_t func_out, void *arg )86 { 87 assert(ep); 87 usbhc_iface_transfer_out_callback_t func_out, void *arg, endpoint_t *ep 88 ) 89 { 88 90 assert(func_in == NULL || func_out == NULL); 89 91 assert(func_in != NULL || func_out != NULL); … … 101 103 CHECK_NULL_DISPOSE_RETURN(instance, 102 104 "Failed to allocate batch instance.\n"); 103 usb_target_t target = 104 { .address = ep->address, .endpoint = ep->endpoint }; 105 usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed, 106 ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size, 107 func_in, func_out, arg, fun, ep, NULL); 105 usb_transfer_batch_init(instance, target, 106 transfer_type, speed, max_packet_size, 107 buffer, NULL, buffer_size, NULL, setup_size, func_in, 108 func_out, arg, fun, ep, NULL); 108 109 109 110 110 111 uhci_batch_t *data = malloc(sizeof(uhci_batch_t)); 111 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 112 CHECK_NULL_DISPOSE_RETURN(instance, 113 "Failed to allocate batch instance.\n"); 112 114 bzero(data, sizeof(uhci_batch_t)); 113 115 instance->private_data = data; 114 116 115 data->transfers = 116 (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size; 117 if (ep->transfer_type == USB_TRANSFER_CONTROL) { 117 data->transfers = (buffer_size + max_packet_size - 1) / max_packet_size; 118 if (transfer_type == USB_TRANSFER_CONTROL) { 118 119 data->transfers += 2; 119 120 } … … 177 178 instance, i, data->tds[i].status); 178 179 td_print_status(&data->tds[i]); 179 assert(instance->ep != NULL); 180 181 endpoint_toggle_set(instance->ep, 182 td_toggle(&data->tds[i])); 180 if (instance->ep != NULL) 181 endpoint_toggle_set(instance->ep, 182 td_toggle(&data->tds[i])); 183 183 if (i > 0) 184 184 goto substract_ret; -
uspace/drv/uhci-hcd/batch.h
rdc4c19e ra49e171 44 44 45 45 usb_transfer_batch_t * batch_get( 46 ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size, 47 char *setup_buffer, size_t setup_size, 46 ddf_fun_t *fun, 47 usb_target_t target, 48 usb_transfer_type_t transfer_type, 49 size_t max_packet_size, 50 usb_speed_t speed, 51 char *buffer, 52 size_t size, 53 char *setup_buffer, 54 size_t setup_size, 48 55 usbhc_iface_transfer_in_callback_t func_in, 49 56 usbhc_iface_transfer_out_callback_t func_out, 50 void *arg); 57 void *arg, 58 endpoint_t *ep 59 ); 51 60 52 61 void batch_dispose(usb_transfer_batch_t *instance); -
uspace/drv/uhci-hcd/hc.c
rdc4c19e ra49e171 240 240 usb_log_debug("Initialized device manager.\n"); 241 241 242 ret = usb_endpoint_manager_init(&instance->ep_manager, 243 BANDWIDTH_AVAILABLE_USB11); 242 ret = 243 usb_endpoint_manager_init(&instance->ep_manager, 244 BANDWIDTH_AVAILABLE_USB11); 244 245 assert(ret == EOK); 245 246 … … 331 332 instance->transfers[batch->speed][batch->transfer_type]; 332 333 assert(list); 334 if (batch->transfer_type == USB_TRANSFER_CONTROL) { 335 usb_device_keeper_use_control( 336 &instance->manager, batch->target); 337 } 333 338 transfer_list_add_batch(list, batch); 334 339 … … 368 373 usb_transfer_batch_t *batch = 369 374 list_get_instance(item, usb_transfer_batch_t, link); 370 usb_transfer_batch_finish(batch); 375 switch (batch->transfer_type) 376 { 377 case USB_TRANSFER_CONTROL: 378 usb_device_keeper_release_control( 379 &instance->manager, batch->target); 380 break; 381 case USB_TRANSFER_INTERRUPT: 382 case USB_TRANSFER_ISOCHRONOUS: { 383 /* 384 int ret = bandwidth_free(&instance->bandwidth, 385 batch->target.address, 386 batch->target.endpoint, 387 batch->direction); 388 if (ret != EOK) 389 usb_log_warning("Failed(%d) to free " 390 "reserved bw: %s.\n", ret, 391 str_error(ret)); 392 */ 393 } 394 default: 395 break; 396 } 397 batch->next_step(batch); 371 398 } 372 399 } -
uspace/drv/uhci-hcd/iface.c
rdc4c19e ra49e171 41 41 #include "hc.h" 42 42 43 static inline int setup_batch( 44 ddf_fun_t *fun, usb_target_t target, usb_direction_t direction, 45 void *data, size_t size, void * setup_data, size_t setup_size, 46 usbhc_iface_transfer_in_callback_t in, 47 usbhc_iface_transfer_out_callback_t out, void *arg, const char* name, 48 hc_t **hc, usb_transfer_batch_t **batch) 49 { 50 assert(hc); 51 assert(batch); 52 assert(fun); 53 *hc = fun_to_hc(fun); 54 assert(*hc); 55 56 size_t res_bw; 57 endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager, 58 target.address, target.endpoint, direction, &res_bw); 59 if (ep == NULL) { 60 usb_log_error("Endpoint(%d:%d) not registered for %s.\n", 61 target.address, target.endpoint, name); 62 return ENOENT; 63 } 64 65 usb_log_debug("%s %d:%d %zu(%zu).\n", 66 name, target.address, target.endpoint, size, ep->max_packet_size); 67 68 const size_t bw = bandwidth_count_usb11( 69 ep->speed, ep->transfer_type, size, ep->max_packet_size); 70 if (res_bw < bw) { 71 usb_log_error("Endpoint(%d:%d) %s needs %zu bw " 72 "but only %zu is reserved.\n", 73 target.address, target.endpoint, name, bw, res_bw); 74 return ENOSPC; 75 } 76 77 *batch = batch_get( 78 fun, ep, data, size, setup_data, setup_size, in, out, arg); 79 if (!*batch) 80 return ENOMEM; 43 /** Reserve default address interface function 44 * 45 * @param[in] fun DDF function that was called. 46 * @param[in] speed Speed to associate with the new default address. 47 * @return Error code. 48 */ 49 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) 50 { 51 assert(fun); 52 hc_t *hc = fun_to_hc(fun); 53 assert(hc); 54 usb_log_debug("Default address request with speed %d.\n", speed); 55 usb_device_keeper_reserve_default_address(&hc->manager, speed); 56 return EOK; 57 #if 0 58 endpoint_t *ep = malloc(sizeof(endpoint_t)); 59 if (ep == NULL) 60 return ENOMEM; 61 const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64; 62 endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size); 63 int ret; 64 try_retgister: 65 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, 66 USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0); 67 if (ret == EEXISTS) { 68 async_usleep(1000); 69 goto try_retgister; 70 } 71 if (ret != EOK) { 72 endpoint_destroy(ep); 73 } 74 return ret; 75 #endif 76 } 77 /*----------------------------------------------------------------------------*/ 78 /** Release default address interface function 79 * 80 * @param[in] fun DDF function that was called. 81 * @return Error code. 82 */ 83 static int release_default_address(ddf_fun_t *fun) 84 { 85 assert(fun); 86 hc_t *hc = fun_to_hc(fun); 87 assert(hc); 88 usb_log_debug("Default address release.\n"); 89 // return usb_endpoint_manager_unregister_ep(&hc->ep_manager, 90 // USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH); 91 usb_device_keeper_release_default_address(&hc->manager); 81 92 return EOK; 82 93 } … … 140 151 /*----------------------------------------------------------------------------*/ 141 152 static int register_endpoint( 142 ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed, 143 usb_endpoint_t endpoint, 153 ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint, 144 154 usb_transfer_type_t transfer_type, usb_direction_t direction, 145 155 size_t max_packet_size, unsigned int interval) … … 147 157 hc_t *hc = fun_to_hc(fun); 148 158 assert(hc); 149 const size_t size = max_packet_size; 159 const usb_speed_t speed = 160 usb_device_keeper_get_speed(&hc->manager, address); 161 const size_t size = 162 (transfer_type == USB_TRANSFER_INTERRUPT 163 || transfer_type == USB_TRANSFER_ISOCHRONOUS) ? 164 max_packet_size : 0; 150 165 int ret; 151 usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address); 152 if (speed >= USB_SPEED_MAX) { 153 speed = ep_speed; 154 } 166 167 endpoint_t *ep = malloc(sizeof(endpoint_t)); 168 if (ep == NULL) 169 return ENOMEM; 170 ret = endpoint_init(ep, address, endpoint, direction, 171 transfer_type, speed, max_packet_size); 172 if (ret != EOK) { 173 free(ep); 174 return ret; 175 } 176 155 177 usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n", 156 178 address, endpoint, usb_str_transfer_type(transfer_type), 157 179 usb_str_speed(speed), direction, size, max_packet_size, interval); 158 180 159 160 endpoint_t *ep = malloc(sizeof(endpoint_t));161 if (ep == NULL)162 return ENOMEM;163 ret = endpoint_init(ep, address, endpoint, direction,164 transfer_type, speed, max_packet_size);165 if (ret != EOK) {166 free(ep);167 return ret;168 }169 170 181 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size); 171 182 if (ret != EOK) { 172 183 endpoint_destroy(ep); 184 } else { 185 usb_device_keeper_add_ep(&hc->manager, address, ep); 173 186 } 174 187 return ret; … … 191 204 * @param[in] fun DDF function that was called. 192 205 * @param[in] target USB device to write to. 206 * @param[in] max_packet_size maximum size of data packet the device accepts 193 207 * @param[in] data Source of data. 194 208 * @param[in] size Size of data source. … … 198 212 */ 199 213 static int interrupt_out( 200 ddf_fun_t *fun, usb_target_t target, void *data,214 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 201 215 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 202 216 { 203 usb_transfer_batch_t *batch = NULL; 204 hc_t *hc = NULL; 205 int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size, 206 NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch); 207 if (ret != EOK) 208 return ret; 217 assert(fun); 218 hc_t *hc = fun_to_hc(fun); 219 assert(hc); 220 221 usb_log_debug("Interrupt OUT %d:%d %zu(%zu).\n", 222 target.address, target.endpoint, size, max_packet_size); 223 224 size_t res_bw; 225 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 226 target.address, target.endpoint, USB_DIRECTION_OUT, &res_bw); 227 if (ep == NULL) { 228 usb_log_error("Endpoint(%d:%d) not registered for INT OUT.\n", 229 target.address, target.endpoint); 230 return ENOENT; 231 } 232 const size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type, 233 size, ep->max_packet_size); 234 if (res_bw < bw) 235 { 236 usb_log_error("Endpoint(%d:%d) INT IN needs %zu bw " 237 "but only %zu is reserved.\n", 238 target.address, target.endpoint, bw, res_bw); 239 return ENOENT; 240 } 241 assert(ep->speed == 242 usb_device_keeper_get_speed(&hc->manager, target.address)); 243 assert(ep->max_packet_size == max_packet_size); 244 assert(ep->transfer_type == USB_TRANSFER_INTERRUPT); 245 246 usb_transfer_batch_t *batch = 247 batch_get(fun, target, ep->transfer_type, ep->max_packet_size, 248 ep->speed, data, size, NULL, 0, NULL, callback, arg, ep); 249 if (!batch) 250 return ENOMEM; 209 251 batch_interrupt_out(batch); 210 ret = hc_schedule(hc, batch);252 const int ret = hc_schedule(hc, batch); 211 253 if (ret != EOK) { 212 254 batch_dispose(batch); … … 219 261 * @param[in] fun DDF function that was called. 220 262 * @param[in] target USB device to write to. 263 * @param[in] max_packet_size maximum size of data packet the device accepts 221 264 * @param[out] data Data destination. 222 265 * @param[in] size Size of data source. … … 226 269 */ 227 270 static int interrupt_in( 228 ddf_fun_t *fun, usb_target_t target, void *data,271 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 229 272 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 230 273 { 231 usb_transfer_batch_t *batch = NULL; 232 hc_t *hc = NULL; 233 int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size, 234 NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch); 235 if (ret != EOK) 236 return ret; 274 assert(fun); 275 hc_t *hc = fun_to_hc(fun); 276 assert(hc); 277 278 usb_log_debug("Interrupt IN %d:%d %zu(%zu).\n", 279 target.address, target.endpoint, size, max_packet_size); 280 281 size_t res_bw; 282 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 283 target.address, target.endpoint, USB_DIRECTION_IN, &res_bw); 284 if (ep == NULL) { 285 usb_log_error("Endpoint(%d:%d) not registered for INT IN.\n", 286 target.address, target.endpoint); 287 return ENOENT; 288 } 289 const size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type, 290 size, ep->max_packet_size); 291 if (res_bw < bw) 292 { 293 usb_log_error("Endpoint(%d:%d) INT IN needs %zu bw " 294 "but only %zu bw is reserved.\n", 295 target.address, target.endpoint, bw, res_bw); 296 return ENOENT; 297 } 298 299 assert(ep->speed == 300 usb_device_keeper_get_speed(&hc->manager, target.address)); 301 assert(ep->max_packet_size == max_packet_size); 302 assert(ep->transfer_type == USB_TRANSFER_INTERRUPT); 303 304 usb_transfer_batch_t *batch = 305 batch_get(fun, target, ep->transfer_type, ep->max_packet_size, 306 ep->speed, data, size, NULL, 0, callback, NULL, arg, ep); 307 if (!batch) 308 return ENOMEM; 237 309 batch_interrupt_in(batch); 238 ret = hc_schedule(hc, batch);310 const int ret = hc_schedule(hc, batch); 239 311 if (ret != EOK) { 240 312 batch_dispose(batch); … … 247 319 * @param[in] fun DDF function that was called. 248 320 * @param[in] target USB device to write to. 321 * @param[in] max_packet_size maximum size of data packet the device accepts 249 322 * @param[in] data Source of data. 250 323 * @param[in] size Size of data source. … … 254 327 */ 255 328 static int bulk_out( 256 ddf_fun_t *fun, usb_target_t target, void *data,329 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 257 330 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 258 331 { 259 usb_transfer_batch_t *batch = NULL; 260 hc_t *hc = NULL; 261 int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size, 262 NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch); 263 if (ret != EOK) 264 return ret; 332 assert(fun); 333 hc_t *hc = fun_to_hc(fun); 334 assert(hc); 335 336 usb_log_debug("Bulk OUT %d:%d %zu(%zu).\n", 337 target.address, target.endpoint, size, max_packet_size); 338 339 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 340 target.address, target.endpoint, USB_DIRECTION_OUT, NULL); 341 if (ep == NULL) { 342 usb_log_error("Endpoint(%d:%d) not registered for BULK OUT.\n", 343 target.address, target.endpoint); 344 return ENOENT; 345 } 346 assert(ep->speed == 347 usb_device_keeper_get_speed(&hc->manager, target.address)); 348 assert(ep->max_packet_size == max_packet_size); 349 assert(ep->transfer_type == USB_TRANSFER_BULK); 350 351 usb_transfer_batch_t *batch = 352 batch_get(fun, target, ep->transfer_type, ep->max_packet_size, 353 ep->speed, data, size, NULL, 0, NULL, callback, arg, ep); 354 if (!batch) 355 return ENOMEM; 265 356 batch_bulk_out(batch); 266 ret = hc_schedule(hc, batch);357 const int ret = hc_schedule(hc, batch); 267 358 if (ret != EOK) { 268 359 batch_dispose(batch); … … 275 366 * @param[in] fun DDF function that was called. 276 367 * @param[in] target USB device to write to. 368 * @param[in] max_packet_size maximum size of data packet the device accepts 277 369 * @param[out] data Data destination. 278 370 * @param[in] size Size of data source. … … 282 374 */ 283 375 static int bulk_in( 284 ddf_fun_t *fun, usb_target_t target, void *data,376 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, void *data, 285 377 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 286 378 { 287 usb_transfer_batch_t *batch = NULL; 288 hc_t *hc = NULL; 289 int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size, 290 NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch); 291 if (ret != EOK) 292 return ret; 379 assert(fun); 380 hc_t *hc = fun_to_hc(fun); 381 assert(hc); 382 usb_log_debug("Bulk IN %d:%d %zu(%zu).\n", 383 target.address, target.endpoint, size, max_packet_size); 384 385 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 386 target.address, target.endpoint, USB_DIRECTION_IN, NULL); 387 if (ep == NULL) { 388 usb_log_error("Endpoint(%d:%d) not registered for BULK IN.\n", 389 target.address, target.endpoint); 390 return ENOENT; 391 } 392 assert(ep->speed == 393 usb_device_keeper_get_speed(&hc->manager, target.address)); 394 assert(ep->max_packet_size == max_packet_size); 395 assert(ep->transfer_type == USB_TRANSFER_BULK); 396 397 usb_transfer_batch_t *batch = 398 batch_get(fun, target, ep->transfer_type, ep->max_packet_size, 399 ep->speed, data, size, NULL, 0, callback, NULL, arg, ep); 400 if (!batch) 401 return ENOMEM; 293 402 batch_bulk_in(batch); 294 ret = hc_schedule(hc, batch);403 const int ret = hc_schedule(hc, batch); 295 404 if (ret != EOK) { 296 405 batch_dispose(batch); … … 303 412 * @param[in] fun DDF function that was called. 304 413 * @param[in] target USB device to write to. 414 * @param[in] max_packet_size maximum size of data packet the device accepts. 305 415 * @param[in] setup_data Data to send with SETUP transfer. 306 416 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B). … … 312 422 */ 313 423 static int control_write( 314 ddf_fun_t *fun, usb_target_t target, 424 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, 315 425 void *setup_data, size_t setup_size, void *data, size_t size, 316 426 usbhc_iface_transfer_out_callback_t callback, void *arg) 317 427 { 318 usb_transfer_batch_t *batch = NULL; 319 hc_t *hc = NULL; 320 int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size, 321 setup_data, setup_size, NULL, callback, arg, "Control WRITE", 322 &hc, &batch); 323 if (ret != EOK) 324 return ret; 325 usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data); 428 assert(fun); 429 hc_t *hc = fun_to_hc(fun); 430 assert(hc); 431 usb_speed_t speed = 432 usb_device_keeper_get_speed(&hc->manager, target.address); 433 usb_log_debug("Control WRITE (%d) %d:%d %zu(%zu).\n", 434 speed, target.address, target.endpoint, size, max_packet_size); 435 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 436 target.address, target.endpoint, USB_DIRECTION_BOTH, NULL); 437 if (ep == NULL) { 438 usb_log_warning("Endpoint(%d:%d) not registered for CONTROL.\n", 439 target.address, target.endpoint); 440 } 441 442 if (setup_size != 8) 443 return EINVAL; 444 445 usb_transfer_batch_t *batch = 446 batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed, 447 data, size, setup_data, setup_size, NULL, callback, arg, ep); 448 if (!batch) 449 return ENOMEM; 450 usb_device_keeper_reset_if_need(&hc->manager, target, setup_data); 326 451 batch_control_write(batch); 327 ret = hc_schedule(hc, batch);452 const int ret = hc_schedule(hc, batch); 328 453 if (ret != EOK) { 329 454 batch_dispose(batch); … … 336 461 * @param[in] fun DDF function that was called. 337 462 * @param[in] target USB device to write to. 463 * @param[in] max_packet_size maximum size of data packet the device accepts. 338 464 * @param[in] setup_data Data to send with SETUP packet. 339 465 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). … … 345 471 */ 346 472 static int control_read( 347 ddf_fun_t *fun, usb_target_t target, 473 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size, 348 474 void *setup_data, size_t setup_size, void *data, size_t size, 349 475 usbhc_iface_transfer_in_callback_t callback, void *arg) 350 476 { 351 usb_transfer_batch_t *batch = NULL; 352 hc_t *hc = NULL; 353 int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size, 354 setup_data, setup_size, callback, NULL, arg, "Control READ", 355 &hc, &batch); 356 if (ret != EOK) 357 return ret; 477 assert(fun); 478 hc_t *hc = fun_to_hc(fun); 479 assert(hc); 480 usb_speed_t speed = 481 usb_device_keeper_get_speed(&hc->manager, target.address); 482 483 usb_log_debug("Control READ(%d) %d:%d %zu(%zu).\n", 484 speed, target.address, target.endpoint, size, max_packet_size); 485 endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager, 486 target.address, target.endpoint, USB_DIRECTION_BOTH, NULL); 487 if (ep == NULL) { 488 usb_log_warning("Endpoint(%d:%d) not registered for CONTROL.\n", 489 target.address, target.endpoint); 490 } 491 usb_transfer_batch_t *batch = 492 batch_get(fun, target, USB_TRANSFER_CONTROL, max_packet_size, speed, 493 data, size, setup_data, setup_size, callback, NULL, arg, ep); 494 if (!batch) 495 return ENOMEM; 358 496 batch_control_read(batch); 359 ret = hc_schedule(hc, batch);497 const int ret = hc_schedule(hc, batch); 360 498 if (ret != EOK) { 361 499 batch_dispose(batch); … … 365 503 /*----------------------------------------------------------------------------*/ 366 504 usbhc_iface_t hc_iface = { 505 .reserve_default_address = reserve_default_address, 506 .release_default_address = release_default_address, 367 507 .request_address = request_address, 368 508 .bind_address = bind_address, -
uspace/drv/uhci-hcd/transfer_list.c
rdc4c19e ra49e171 132 132 } 133 133 /*----------------------------------------------------------------------------*/ 134 /** Create list for finished batches. 135 * 136 * @param[in] instance List to use. 137 * @param[in] done list to fill 134 /** Check list for finished batches. 135 * 136 * @param[in] instance List to use. 137 * @return Error code 138 * 139 * Creates a local list of finished batches and calls next_step on each and 140 * every one. This is safer because next_step may theoretically access 141 * this transfer list leading to the deadlock if its done inline. 138 142 */ 139 143 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done) … … 157 161 } 158 162 fibril_mutex_unlock(&instance->guard); 163 159 164 } 160 165 /*----------------------------------------------------------------------------*/ … … 171 176 list_get_instance(current, usb_transfer_batch_t, link); 172 177 transfer_list_remove_batch(instance, batch); 173 usb_transfer_batch_finish _error(batch, EIO);178 usb_transfer_batch_finish(batch, EIO); 174 179 } 175 180 fibril_mutex_unlock(&instance->guard); -
uspace/drv/uhci-rhd/root_hub.h
rdc4c19e ra49e171 40 40 41 41 #define UHCI_ROOT_HUB_PORT_COUNT 2 42 #define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */42 #define ROOT_HUB_WAIT_USEC 5000000 /* 5 seconds */ 43 43 44 44 typedef struct root_hub { -
uspace/drv/usbhub/Makefile
rdc4c19e ra49e171 34 34 SOURCES = \ 35 35 main.c \ 36 ports.c \ 36 37 utils.c \ 37 usbhub.c \ 38 ports.c 38 usbhub.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/usbhub/port_status.h
rdc4c19e ra49e171 49 49 50 50 /** 51 * structure holding hub status and changes flags.52 * should not be accessed directly, use supplied getter/setter methods.53 *54 * For more information refer to table 11.16.2.5 in55 * "Universal Serial Bus Specification Revision 1.1"56 *57 */58 typedef uint32_t usb_hub_status_t;59 60 /**61 51 * set values in request to be it a port status request 62 52 * @param request … … 64 54 */ 65 55 static inline void usb_hub_set_port_status_request( 66 usb_device_request_setup_packet_t * request, uint16_t port67 ){56 usb_device_request_setup_packet_t * request, uint16_t port 57 ){ 68 58 request->index = port; 69 59 request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS; … … 73 63 } 74 64 75 /**76 * set values in request to be it a port status request77 * @param request78 * @param port79 */80 static inline void usb_hub_set_hub_status_request(81 usb_device_request_setup_packet_t * request82 ) {83 request->index = 0;84 request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;85 request->request = USB_HUB_REQUEST_GET_STATUS;86 request->value = 0;87 request->length = 4;88 }89 65 90 66 /** … … 94 70 */ 95 71 static inline usb_device_request_setup_packet_t * 96 usb_hub_create_port_status_request(uint16_t port) {72 usb_hub_create_port_status_request(uint16_t port){ 97 73 usb_device_request_setup_packet_t * result = 98 malloc(sizeof(usb_device_request_setup_packet_t));99 usb_hub_set_port_status_request(result, port);74 usb_new(usb_device_request_setup_packet_t); 75 usb_hub_set_port_status_request(result,port); 100 76 return result; 101 77 } 102 78 79 103 80 /** 104 81 * set the device request to be a port feature enable request … … 108 85 */ 109 86 static inline void usb_hub_set_enable_port_feature_request( 110 usb_device_request_setup_packet_t * request, uint16_t port,111 uint16_t feature_selector112 ){87 usb_device_request_setup_packet_t * request, uint16_t port, 88 uint16_t feature_selector 89 ){ 113 90 request->index = port; 114 91 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 125 102 */ 126 103 static inline void usb_hub_set_disable_port_feature_request( 127 usb_device_request_setup_packet_t * request, uint16_t port,128 uint16_t feature_selector129 ){104 usb_device_request_setup_packet_t * request, uint16_t port, 105 uint16_t feature_selector 106 ){ 130 107 request->index = port; 131 108 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 141 118 */ 142 119 static inline void usb_hub_set_enable_port_request( 143 usb_device_request_setup_packet_t * request, uint16_t port144 ){120 usb_device_request_setup_packet_t * request, uint16_t port 121 ){ 145 122 request->index = port; 146 123 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 156 133 */ 157 134 static inline usb_device_request_setup_packet_t * 158 usb_hub_create_enable_port_request(uint16_t port) {135 usb_hub_create_enable_port_request(uint16_t port){ 159 136 usb_device_request_setup_packet_t * result = 160 malloc(sizeof(usb_device_request_setup_packet_t));161 usb_hub_set_enable_port_request(result, port);137 usb_new(usb_device_request_setup_packet_t); 138 usb_hub_set_enable_port_request(result,port); 162 139 return result; 163 140 } … … 169 146 */ 170 147 static inline void usb_hub_set_disable_port_request( 171 usb_device_request_setup_packet_t * request, uint16_t port172 ){148 usb_device_request_setup_packet_t * request, uint16_t port 149 ){ 173 150 request->index = port; 174 151 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 184 161 */ 185 162 static inline usb_device_request_setup_packet_t * 186 usb_hub_create_disable_port_request(uint16_t port) {163 usb_hub_create_disable_port_request(uint16_t port){ 187 164 usb_device_request_setup_packet_t * result = 188 malloc(sizeof(usb_device_request_setup_packet_t));189 usb_hub_set_disable_port_request(result, port);165 usb_new(usb_device_request_setup_packet_t); 166 usb_hub_set_disable_port_request(result,port); 190 167 return result; 191 168 } … … 197 174 */ 198 175 static inline void usb_hub_set_reset_port_request( 199 usb_device_request_setup_packet_t * request, uint16_t port200 ){176 usb_device_request_setup_packet_t * request, uint16_t port 177 ){ 201 178 request->index = port; 202 179 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 212 189 */ 213 190 static inline usb_device_request_setup_packet_t * 214 usb_hub_create_reset_port_request(uint16_t port) {191 usb_hub_create_reset_port_request(uint16_t port){ 215 192 usb_device_request_setup_packet_t * result = 216 malloc(sizeof(usb_device_request_setup_packet_t));217 usb_hub_set_reset_port_request(result, port);193 usb_new(usb_device_request_setup_packet_t); 194 usb_hub_set_reset_port_request(result,port); 218 195 return result; 219 196 } … … 225 202 */ 226 203 static inline void usb_hub_set_power_port_request( 227 usb_device_request_setup_packet_t * request, uint16_t port228 ){204 usb_device_request_setup_packet_t * request, uint16_t port 205 ){ 229 206 request->index = port; 230 207 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 240 217 */ 241 218 static inline void usb_hub_unset_power_port_request( 242 usb_device_request_setup_packet_t * request, uint16_t port243 ){219 usb_device_request_setup_packet_t * request, uint16_t port 220 ){ 244 221 request->index = port; 245 222 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 249 226 } 250 227 251 /** 252 * get i`th bit of port status 253 * 254 * @param status 255 * @param idx 256 * @return 257 */ 258 static inline bool usb_port_is_status(usb_port_status_t status, int idx) { 259 return (status&(1 << idx))!=0; 260 } 261 262 /** 263 * set i`th bit of port status 264 * 265 * @param status 266 * @param idx 267 * @param value 268 */ 269 static inline void usb_port_status_set_bit( 270 usb_port_status_t * status, int idx, bool value) { 271 (*status) = value ? 272 ((*status) | (1 << (idx))) : 273 ((*status)&(~(1 << (idx)))); 274 } 275 276 /** 277 * get i`th bit of hub status 278 * 279 * @param status 280 * @param idx 281 * @return 282 */ 283 static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) { 284 return (status&(1 << idx))!=0; 285 } 286 287 /** 288 * set i`th bit of hub status 289 * 290 * @param status 291 * @param idx 292 * @param value 293 */ 294 static inline void usb_hub_status_set_bit( 295 usb_hub_status_t * status, int idx, bool value) { 296 (*status) = value ? 297 ((*status) | (1 << (idx))) : 298 ((*status)&(~(1 << (idx)))); 299 } 300 301 302 #if 0 303 /** 304 * connection status geter for port status 305 * 306 * @param status 307 * @return true if there is something connected 308 */ 309 static inline bool usb_port_dev_connected(usb_port_status_t * status) { 310 return usb_port_get_bit(status, 0); 311 } 312 313 /** 314 * set device connected bit in port status 315 * 316 * @param status 317 * @param connected value of the bit 318 */ 319 static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) { 320 usb_port_set_bit(status, 0, connected); 228 229 /** get i`th bit of port status */ 230 static inline bool usb_port_get_bit(usb_port_status_t * status, int idx) 231 { 232 return (((*status)>>(idx))%2); 233 } 234 235 /** set i`th bit of port status */ 236 static inline void usb_port_set_bit( 237 usb_port_status_t * status, int idx, bool value) 238 { 239 (*status) = value? 240 ((*status)|(1<<(idx))): 241 ((*status)&(~(1<<(idx)))); 242 } 243 244 //device connnected on port 245 static inline bool usb_port_dev_connected(usb_port_status_t * status){ 246 return usb_port_get_bit(status,0); 247 } 248 249 static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){ 250 usb_port_set_bit(status,0,connected); 321 251 } 322 252 323 253 //port enabled 324 325 /** 326 * port enabled getter for port status 327 * 328 * @param status 329 * @return true if the port is enabled 330 */ 331 static inline bool usb_port_enabled(usb_port_status_t * status) { 332 return usb_port_get_bit(status, 1); 333 } 334 335 /** 336 * set port enabled bit in port status 337 * 338 * @param status 339 * @param enabled value of the bit 340 */ 341 static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) { 342 usb_port_set_bit(status, 1, enabled); 254 static inline bool usb_port_enabled(usb_port_status_t * status){ 255 return usb_port_get_bit(status,1); 256 } 257 258 static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){ 259 usb_port_set_bit(status,1,enabled); 343 260 } 344 261 345 262 //port suspended 346 /** 347 * port suspended getter for port status 348 * 349 * @param status 350 * @return true if port is suspended 351 */ 352 static inline bool usb_port_suspended(usb_port_status_t * status) { 353 return usb_port_get_bit(status, 2); 354 } 355 356 /** 357 * set port suspended bit in port status 358 * 359 * @param status 360 * @param suspended value of the bit 361 */ 362 static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) { 363 usb_port_set_bit(status, 2, suspended); 263 static inline bool usb_port_suspended(usb_port_status_t * status){ 264 return usb_port_get_bit(status,2); 265 } 266 267 static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){ 268 usb_port_set_bit(status,2,suspended); 364 269 } 365 270 366 271 //over currect 367 /** 368 * over current condition indicator getter for port status 369 * 370 * @param status 371 * @return true if there is opver-current condition on the hub 372 */ 373 static inline bool usb_port_over_current(usb_port_status_t * status) { 374 return usb_port_get_bit(status, 3); 375 } 376 377 /** 378 * set over current indicator bit in port status 379 * 380 * @param status 381 * @param value value of the bit 382 */ 383 static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) { 384 usb_port_set_bit(status, 3, value); 272 static inline bool usb_port_over_current(usb_port_status_t * status){ 273 return usb_port_get_bit(status,3); 274 } 275 276 static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){ 277 usb_port_set_bit(status,3,value); 385 278 } 386 279 387 280 //port reset 388 /** 389 * port reset indicator getter for port status 390 * 391 * @param status 392 * @return true if port is reset 393 */ 394 static inline bool usb_port_reset(usb_port_status_t * status) { 395 return usb_port_get_bit(status, 4); 396 } 397 398 /** 399 * set port reset bit in port status 400 * 401 * @param status 402 * @param value value of the bit 403 */ 404 static inline void usb_port_set_reset(usb_port_status_t * status, bool value) { 405 usb_port_set_bit(status, 4, value); 281 static inline bool usb_port_reset(usb_port_status_t * status){ 282 return usb_port_get_bit(status,4); 283 } 284 285 static inline void usb_port_set_reset(usb_port_status_t * status,bool value){ 286 usb_port_set_bit(status,4,value); 406 287 } 407 288 408 289 //powered 409 /** 410 * power state getter for port status 411 * 412 * @param status 413 * @return true if port is powered 414 */ 415 static inline bool usb_port_powered(usb_port_status_t * status) { 416 return usb_port_get_bit(status, 8); 417 } 418 419 /** 420 * set port powered bit in port status 421 * 422 * @param status 423 * @param powered value of the bit 424 */ 425 static inline void usb_port_set_powered(usb_port_status_t * status, bool powered) { 426 usb_port_set_bit(status, 8, powered); 427 } 428 429 #endif 290 static inline bool usb_port_powered(usb_port_status_t * status){ 291 return usb_port_get_bit(status,8); 292 } 293 294 static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){ 295 usb_port_set_bit(status,8,powered); 296 } 430 297 431 298 //low speed device attached 432 /** 433 * low speed device on the port indicator 434 * 435 * @param status 436 * @return true if low speed device is attached 437 */ 438 static inline bool usb_port_low_speed(usb_port_status_t status) { 439 return usb_port_is_status(status, 9); 440 } 441 442 /** 443 * set low speed device connected bit in port status 444 * 445 * @param status 446 * @param low_speed value of the bit 447 */ 448 static inline void usb_port_set_low_speed(usb_port_status_t * status, bool low_speed) { 449 usb_port_status_set_bit(status, 9, low_speed); 450 } 451 452 //high speed device attached 453 /** 454 * high speed device on the port indicator 455 * 456 * @param status 457 * @return true if high speed device is on port 458 */ 459 static inline bool usb_port_high_speed(usb_port_status_t status) { 460 return usb_port_is_status(status, 10); 461 } 462 463 /** 464 * set high speed device bit in port status 465 * 466 * @param status 467 * @param high_speed value of the bit 468 */ 469 static inline void usb_port_set_high_speed(usb_port_status_t * status, bool high_speed) { 470 usb_port_status_set_bit(status, 10, high_speed); 471 } 472 473 /** 474 * speed getter for port status 475 * 476 * @param status 477 * @return speed of usb device (for more see usb specification) 478 */ 479 static inline usb_speed_t usb_port_speed(usb_port_status_t status) { 480 if (usb_port_low_speed(status)) 299 static inline bool usb_port_low_speed(usb_port_status_t * status){ 300 return usb_port_get_bit(status,9); 301 } 302 303 static inline void usb_port_set_low_speed(usb_port_status_t * status,bool low_speed){ 304 usb_port_set_bit(status,9,low_speed); 305 } 306 307 //low speed device attached 308 static inline bool usb_port_high_speed(usb_port_status_t * status){ 309 return usb_port_get_bit(status,10); 310 } 311 312 static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){ 313 usb_port_set_bit(status,10,high_speed); 314 } 315 316 static inline usb_speed_t usb_port_speed(usb_port_status_t * status){ 317 if(usb_port_low_speed(status)) 481 318 return USB_SPEED_LOW; 482 if (usb_port_high_speed(status))319 if(usb_port_high_speed(status)) 483 320 return USB_SPEED_HIGH; 484 321 return USB_SPEED_FULL; 485 322 } 486 323 487 #if 0 324 488 325 //connect change 489 /** 490 * port connect change indicator 491 * 492 * @param status 493 * @return true if connection has changed 494 */ 495 static inline bool usb_port_connect_change(usb_port_status_t * status) { 496 return usb_port_get_bit(status, 16); 497 } 498 499 /** 500 * set connection change bit in port status 501 * @param status 502 * @param change value of the bit 503 */ 504 static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) { 505 usb_port_set_bit(status, 16, change); 326 static inline bool usb_port_connect_change(usb_port_status_t * status){ 327 return usb_port_get_bit(status,16); 328 } 329 330 static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){ 331 usb_port_set_bit(status,16,change); 506 332 } 507 333 508 334 //port enable change 509 /** 510 * port enable change for port status 511 * 512 * @param status 513 * @return true if the port has been enabled/disabled 514 */ 515 static inline bool usb_port_enabled_change(usb_port_status_t * status) { 516 return usb_port_get_bit(status, 17); 517 } 518 519 /** 520 * set port enable change bit in port status 521 * 522 * @param status 523 * @param change value of the bit 524 */ 525 static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) { 526 usb_port_set_bit(status, 17, change); 335 static inline bool usb_port_enabled_change(usb_port_status_t * status){ 336 return usb_port_get_bit(status,17); 337 } 338 339 static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){ 340 usb_port_set_bit(status,17,change); 527 341 } 528 342 529 343 //suspend change 530 /** 531 * port suspend change for port status 532 * 533 * @param status 534 * @return ture if suspend status has changed 535 */ 536 static inline bool usb_port_suspend_change(usb_port_status_t * status) { 537 return usb_port_get_bit(status, 18); 538 } 539 540 /** 541 * set port suspend change bit in port status 542 * 543 * @param status 544 * @param change value of the bit 545 */ 546 static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) { 547 usb_port_set_bit(status, 18, change); 344 static inline bool usb_port_suspend_change(usb_port_status_t * status){ 345 return usb_port_get_bit(status,18); 346 } 347 348 static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){ 349 usb_port_set_bit(status,18,change); 548 350 } 549 351 550 352 //over current change 551 /** 552 * over current change indicator 553 * 554 * @param status 555 * @return true if over-current condition on port has changed 556 */ 557 static inline bool usb_port_overcurrent_change(usb_port_status_t * status) { 558 return usb_port_get_bit(status, 19); 559 } 560 561 /** 562 * set port over current change bit in port status 563 * 564 * @param status 565 * @param change value of the bit 566 */ 567 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) { 568 usb_port_set_bit(status, 19, change); 353 static inline bool usb_port_overcurrent_change(usb_port_status_t * status){ 354 return usb_port_get_bit(status,19); 355 } 356 357 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){ 358 usb_port_set_bit(status,19,change); 569 359 } 570 360 571 361 //reset change 572 /** 573 * port reset change indicator 574 * @param status 575 * @return true if port has been reset 576 */ 577 static inline bool usb_port_reset_completed(usb_port_status_t * status) { 578 return usb_port_get_bit(status, 20); 579 } 580 581 /** 582 * set port reset completed bit in port status 583 * 584 * @param status 585 * @param change value of the bit 586 */ 587 static inline void usb_port_set_reset_completed(usb_port_status_t * status, bool completed) { 588 usb_port_set_bit(status, 20, completed); 589 } 590 591 //local power status 592 /** 593 * local power lost indicator for hub status 594 * 595 * @param status 596 * @return true if hub is not powered 597 */ 598 static inline bool usb_hub_local_power_lost(usb_hub_status_t * status) { 599 return usb_hub_get_bit(status, 0); 600 } 601 602 /** 603 * set hub power lost bit in hub status 604 * 605 * @param status 606 * @param change value of the bit 607 */ 608 static inline void usb_hub_set_local_power_lost(usb_port_status_t * status, 609 bool power_lost) { 610 usb_hub_set_bit(status, 0, power_lost); 611 } 612 613 //over current ocndition 614 /** 615 * hub over-current indicator 616 * 617 * @param status 618 * @return true if over-current condition occurred on hub 619 */ 620 static inline bool usb_hub_over_current(usb_hub_status_t * status) { 621 return usb_hub_get_bit(status, 1); 622 } 623 624 /** 625 * set hub over current bit in hub status 626 * 627 * @param status 628 * @param change value of the bit 629 */ 630 static inline void usb_hub_set_over_current(usb_port_status_t * status, 631 bool over_current) { 632 usb_hub_set_bit(status, 1, over_current); 633 } 634 635 //local power change 636 /** 637 * hub power change indicator 638 * 639 * @param status 640 * @return true if local power status has been changed - power has been 641 * dropped or re-established 642 */ 643 static inline bool usb_hub_local_power_change(usb_hub_status_t * status) { 644 return usb_hub_get_bit(status, 16); 645 } 646 647 /** 648 * set hub power change bit in hub status 649 * 650 * @param status 651 * @param change value of the bit 652 */ 653 static inline void usb_hub_set_local_power_change(usb_port_status_t * status, 654 bool change) { 655 usb_hub_set_bit(status, 16, change); 656 } 657 658 //local power status 659 /** 660 * hub over-current condition change indicator 661 * 662 * @param status 663 * @return true if over-current condition has changed 664 */ 665 static inline bool usb_hub_over_current_change(usb_hub_status_t * status) { 666 return usb_hub_get_bit(status, 17); 667 } 668 669 /** 670 * set hub over current change bit in hub status 671 * 672 * @param status 673 * @param change value of the bit 674 */ 675 static inline void usb_hub_set_over_current_change(usb_port_status_t * status, 676 bool change) { 677 usb_hub_set_bit(status, 17, change); 678 } 679 #endif 362 static inline bool usb_port_reset_completed(usb_port_status_t * status){ 363 return usb_port_get_bit(status,20); 364 } 365 366 static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){ 367 usb_port_set_bit(status,20,completed); 368 } 369 680 370 681 371 -
uspace/drv/usbhub/ports.c
rdc4c19e ra49e171 33 33 * Hub ports functions. 34 34 */ 35 36 #include < bool.h>35 #include "port_status.h" 36 #include <inttypes.h> 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h> 40 #include <fibril_synch.h> 41 39 #include <usb/request.h> 42 40 #include <usb/debug.h> 43 41 44 #include "ports.h" 45 #include "usbhub.h" 46 #include "usbhub_private.h" 47 #include "port_status.h" 48 42 /** Retrieve port status. 43 * 44 * @param[in] ctrl_pipe Control pipe to use. 45 * @param[in] port Port number (starting at 1). 46 * @param[out] status Where to store the port status. 47 * @return Error code. 48 */ 49 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port, 50 usb_port_status_t *status) 51 { 52 size_t recv_size; 53 usb_device_request_setup_packet_t request; 54 usb_port_status_t status_tmp; 55 56 usb_hub_set_port_status_request(&request, port); 57 int rc = usb_pipe_control_read(ctrl_pipe, 58 &request, sizeof(usb_device_request_setup_packet_t), 59 &status_tmp, sizeof(status_tmp), &recv_size); 60 if (rc != EOK) { 61 return rc; 62 } 63 64 if (recv_size != sizeof (status_tmp)) { 65 return ELIMIT; 66 } 67 68 if (status != NULL) { 69 *status = status_tmp; 70 } 71 72 return EOK; 73 } 49 74 50 75 /** Information for fibril for device discovery. */ … … 55 80 }; 56 81 57 static void usb_hub_removed_device(58 usb_hub_info_t * hub, uint16_t port);59 60 static void usb_hub_port_reset_completed(usb_hub_info_t * hub,61 uint16_t port, uint32_t status);62 63 static void usb_hub_port_over_current(usb_hub_info_t * hub,64 uint16_t port, uint32_t status);65 66 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,67 usb_port_status_t *status);68 69 static int enable_port_callback(int port_no, void *arg);70 71 static int add_device_phase1_worker_fibril(void *arg);72 73 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,74 usb_speed_t speed);75 76 /**77 * Process interrupts on given hub port78 *79 * Accepts connection, over current and port reset change.80 * @param hub hub representation81 * @param port port number, starting from 182 */83 void usb_hub_process_interrupt(usb_hub_info_t * hub,84 uint16_t port) {85 usb_log_debug("interrupt at port %d\n", port);86 //determine type of change87 //usb_pipe_t *pipe = hub->control_pipe;88 89 int opResult;90 91 usb_port_status_t status;92 opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);93 if (opResult != EOK) {94 usb_log_error("Failed to get port %zu status: %s.\n",95 port, str_error(opResult));96 return;97 }98 //connection change99 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {100 bool device_connected = usb_port_is_status(status,101 USB_HUB_FEATURE_PORT_CONNECTION);102 usb_log_debug("Connection change on port %zu: %s.\n", port,103 device_connected ? "device attached" : "device removed");104 105 if (device_connected) {106 opResult = create_add_device_fibril(hub, port,107 usb_port_speed(status));108 if (opResult != EOK) {109 usb_log_error(110 "Cannot handle change on port %zu: %s.\n",111 str_error(opResult));112 }113 } else {114 usb_hub_removed_device(hub, port);115 }116 }117 //over current118 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {119 //check if it was not auto-resolved120 usb_log_debug("overcurrent change on port\n");121 usb_hub_port_over_current(hub, port, status);122 }123 //port reset124 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {125 usb_hub_port_reset_completed(hub, port, status);126 }127 usb_log_debug("status x%x : %d\n ", status, status);128 129 usb_port_status_set_bit(130 &status, USB_HUB_FEATURE_C_PORT_CONNECTION,false);131 usb_port_status_set_bit(132 &status, USB_HUB_FEATURE_PORT_RESET,false);133 usb_port_status_set_bit(134 &status, USB_HUB_FEATURE_C_PORT_RESET,false);135 usb_port_status_set_bit(136 &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT,false);137 /// \TODO what about port power change?138 if (status >> 16) {139 usb_log_info("there was unsupported change on port %d: %X\n",140 port, status);141 142 }143 }144 145 146 /**147 * routine called when a device on port has been removed148 *149 * If the device on port had default address, it releases default address.150 * Otherwise does not do anything, because DDF does not allow to remove device151 * from it`s device tree.152 * @param hub hub representation153 * @param port port number, starting from 1154 */155 static void usb_hub_removed_device(156 usb_hub_info_t * hub, uint16_t port) {157 158 int opResult = usb_hub_clear_port_feature(hub->control_pipe,159 port, USB_HUB_FEATURE_C_PORT_CONNECTION);160 if (opResult != EOK) {161 usb_log_warning("could not clear port-change-connection flag\n");162 }163 /** \TODO remove device from device manager - not yet implemented in164 * devide manager165 */166 167 //close address168 //if (hub->attached_devs[port].address != 0) {169 if(hub->ports[port].attached_device.address >= 0){170 /*uncomment this code to use it when DDF allows device removal171 opResult = usb_hc_unregister_device(172 &hub->connection,173 hub->attached_devs[port].address);174 if(opResult != EOK) {175 dprintf(USB_LOG_LEVEL_WARNING, "could not release "176 "address of "177 "removed device: %d", opResult);178 }179 hub->attached_devs[port].address = 0;180 hub->attached_devs[port].handle = 0;181 */182 } else {183 // TODO: is this really reason to print a warning?184 usb_log_warning("Device removed before being registered.\n");185 186 /*187 * Device was removed before port reset completed.188 * We will announce a failed port reset to unblock the189 * port reset callback from new device wrapper.190 */191 usb_hub_port_t *the_port = hub->ports + port;192 fibril_mutex_lock(&the_port->reset_mutex);193 the_port->reset_completed = true;194 the_port->reset_okay = false;195 fibril_condvar_broadcast(&the_port->reset_cv);196 fibril_mutex_unlock(&the_port->reset_mutex);197 }198 }199 200 201 /**202 * Process port reset change203 *204 * After this change port should be enabled, unless some problem occured.205 * This functions triggers second phase of enabling new device.206 * @param hub207 * @param port208 * @param status209 */210 static void usb_hub_port_reset_completed(usb_hub_info_t * hub,211 uint16_t port, uint32_t status){212 usb_log_debug("Port %zu reset complete.\n", port);213 if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {214 /* Finalize device adding. */215 usb_hub_port_t *the_port = hub->ports + port;216 fibril_mutex_lock(&the_port->reset_mutex);217 the_port->reset_completed = true;218 the_port->reset_okay = true;219 fibril_condvar_broadcast(&the_port->reset_cv);220 fibril_mutex_unlock(&the_port->reset_mutex);221 } else {222 usb_log_warning(223 "Port %zu reset complete but port not enabled.\n",224 port);225 }226 }227 228 /**229 * Process over current condition on port.230 *231 * Turn off the power on the port.232 *233 * @param hub hub representation234 * @param port port number, starting from 1235 */236 static void usb_hub_port_over_current(usb_hub_info_t * hub,237 uint16_t port, uint32_t status) {238 int opResult;239 if(usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)){240 opResult = usb_hub_clear_port_feature(hub->control_pipe,241 port, USB_HUB_FEATURE_PORT_POWER);242 if (opResult != EOK) {243 usb_log_error("cannot power off port %d; %d\n",244 port, opResult);245 }246 }else{247 opResult = usb_hub_set_port_feature(hub->control_pipe,248 port, USB_HUB_FEATURE_PORT_POWER);249 if (opResult != EOK) {250 usb_log_error("cannot power on port %d; %d\n",251 port, opResult);252 }253 }254 }255 256 /** Retrieve port status.257 *258 * @param[in] ctrl_pipe Control pipe to use.259 * @param[in] port Port number (starting at 1).260 * @param[out] status Where to store the port status.261 * @return Error code.262 */263 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,264 usb_port_status_t *status)265 {266 size_t recv_size;267 usb_device_request_setup_packet_t request;268 usb_port_status_t status_tmp;269 270 usb_hub_set_port_status_request(&request, port);271 int rc = usb_pipe_control_read(ctrl_pipe,272 &request, sizeof(usb_device_request_setup_packet_t),273 &status_tmp, sizeof(status_tmp), &recv_size);274 if (rc != EOK) {275 return rc;276 }277 278 if (recv_size != sizeof (status_tmp)) {279 return ELIMIT;280 }281 282 if (status != NULL) {283 *status = status_tmp;284 }285 286 return EOK;287 }288 289 82 /** Callback for enabling a specific port. 290 83 * … … 298 91 static int enable_port_callback(int port_no, void *arg) 299 92 { 300 usb_hub_info_t *hub = arg;93 usb_hub_info_t *hub = (usb_hub_info_t *) arg; 301 94 int rc; 302 95 usb_device_request_setup_packet_t request; … … 329 122 } 330 123 331 if (my_port->reset_okay) { 332 return EOK; 333 } else { 334 return ESTALL; 335 } 124 return EOK; 336 125 } 337 126 … … 367 156 data->hub->ports[data->port].attached_device.address = new_address; 368 157 369 usb_log_info("Detected new device on `%s' (port %zu), " 158 usb_log_info("Detected new device on `%s' (port %zu), " \ 370 159 "address %d (handle %" PRIun ").\n", 371 160 data->hub->usb_device->ddf_dev->name, data->port, … … 377 166 return EOK; 378 167 } 379 380 168 381 169 /** Start device adding when connection change is detected. … … 388 176 * @return Error code. 389 177 */ 390 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,178 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port, 391 179 usb_speed_t speed) 392 180 { … … 425 213 } 426 214 215 /** Process change on a single port. 216 * 217 * @param hub Hub to which the port belongs. 218 * @param port Port index (starting at 1). 219 */ 220 static void process_port_change(usb_hub_info_t *hub, size_t port) 221 { 222 int rc; 223 224 usb_port_status_t port_status; 225 226 rc = get_port_status(&hub->usb_device->ctrl_pipe, port, &port_status); 227 if (rc != EOK) { 228 usb_log_error("Failed to get port %zu status: %s.\n", 229 port, str_error(rc)); 230 return; 231 } 232 233 /* 234 * Check exact nature of the change. 235 */ 236 usb_log_debug("Port %zu change status: %x.\n", port, 237 (unsigned int) port_status); 238 239 if (usb_port_connect_change(&port_status)) { 240 bool device_connected = usb_port_dev_connected(&port_status); 241 usb_log_debug("Connection change on port %zu: %s.\n", port, 242 device_connected ? "device attached" : "device removed"); 243 244 if (device_connected) { 245 rc = add_device_phase1_new_fibril(hub, port, 246 usb_port_speed(&port_status)); 247 if (rc != EOK) { 248 usb_log_error( 249 "Cannot handle change on port %zu: %s.\n", 250 str_error(rc)); 251 } 252 } else { 253 usb_hub_removed_device(hub, port); 254 } 255 } 256 257 if (usb_port_overcurrent_change(&port_status)) { 258 if (usb_port_over_current(&port_status)) { 259 usb_log_warning("Overcurrent on port %zu.\n", port); 260 usb_hub_over_current(hub, port); 261 } else { 262 usb_log_debug("Overcurrent on port %zu autoresolved.\n", 263 port); 264 } 265 } 266 267 if (usb_port_reset_completed(&port_status)) { 268 usb_log_debug("Port %zu reset complete.\n", port); 269 if (usb_port_enabled(&port_status)) { 270 /* Finalize device adding. */ 271 usb_hub_port_t *the_port = hub->ports + port; 272 fibril_mutex_lock(&the_port->reset_mutex); 273 the_port->reset_completed = true; 274 fibril_condvar_broadcast(&the_port->reset_cv); 275 fibril_mutex_unlock(&the_port->reset_mutex); 276 } else { 277 usb_log_warning( 278 "Port %zu reset complete but port not enabled.\n", 279 port); 280 } 281 } 282 283 usb_port_set_connect_change(&port_status, false); 284 usb_port_set_reset(&port_status, false); 285 usb_port_set_reset_completed(&port_status, false); 286 usb_port_set_dev_connected(&port_status, false); 287 if (port_status >> 16) { 288 usb_log_warning("Unsupported change on port %zu: %x.\n", 289 port, (unsigned int) port_status); 290 } 291 } 292 293 294 /** Callback for polling hub for port changes. 295 * 296 * @param dev Device where the change occured. 297 * @param change_bitmap Bitmap of changed ports. 298 * @param change_bitmap_size Size of the bitmap in bytes. 299 * @param arg Custom argument, points to @c usb_hub_info_t. 300 * @return Whether to continue polling. 301 */ 302 bool hub_port_changes_callback(usb_device_t *dev, 303 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) 304 { 305 usb_hub_info_t *hub = (usb_hub_info_t *) arg; 306 307 /* FIXME: check that we received enough bytes. */ 308 if (change_bitmap_size == 0) { 309 goto leave; 310 } 311 312 size_t port; 313 for (port = 1; port < hub->port_count + 1; port++) { 314 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2; 315 if (change) { 316 process_port_change(hub, port); 317 } 318 } 319 320 321 leave: 322 /* FIXME: proper interval. */ 323 async_usleep(1000 * 1000 * 10 ); 324 325 return true; 326 } 327 328 427 329 /** 428 330 * @} -
uspace/drv/usbhub/ports.h
rdc4c19e ra49e171 36 36 #define DRV_USBHUB_PORTS_H 37 37 38 #include <usb/devdrv.h> 38 #include <ipc/devman.h> 39 #include <usb/usb.h> 40 #include <ddf/driver.h> 41 #include <fibril_synch.h> 42 39 43 #include <usb/hub.h> 40 44 41 typedef struct usb_hub_info_t usb_hub_info_t; 45 #include <usb/pipes.h> 46 #include <usb/devdrv.h> 42 47 43 48 /** Information about single port on a hub. */ … … 51 56 */ 52 57 bool reset_completed; 53 /** Whether to announce the port reset as successful. */54 bool reset_okay;55 58 56 59 /** Information about attached device. */ … … 69 72 } 70 73 71 72 void usb_hub_process_interrupt(usb_hub_info_t * hub, 73 uint16_t port); 74 74 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *); 75 75 76 76 -
uspace/drv/usbhub/usbhub.c
rdc4c19e ra49e171 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h>40 39 41 40 #include <usb_iface.h> … … 54 53 #include "usb/classes/classes.h" 55 54 56 57 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev); 58 59 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info); 60 61 static int usb_hub_set_configuration(usb_hub_info_t * hub_info); 62 63 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info); 64 65 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 66 usb_hub_status_t status); 67 68 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 69 usb_hub_status_t status); 70 71 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info); 72 73 74 /// \TODO malloc checking 55 static int usb_hub_trigger_connecting_non_removable_devices( 56 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 57 75 58 76 59 //********************************************* … … 81 64 82 65 /** 83 * Initialize hub device driver fibril84 *85 * Creates hub representation and fibril that periodically checks hub`s status.86 * Hub representation is passed to the fibril.87 * @param usb_dev generic usb device information88 * @return error code89 */90 int usb_hub_add_device(usb_device_t * usb_dev) {91 if (!usb_dev) return EINVAL;92 usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);93 //create hc connection94 usb_log_debug("Initializing USB wire abstraction.\n");95 int opResult = usb_hc_connection_initialize_from_device(96 &hub_info->connection,97 hub_info->usb_device->ddf_dev);98 if (opResult != EOK) {99 usb_log_error("could not initialize connection to device, "100 "errno %d\n",101 opResult);102 free(hub_info);103 return opResult;104 }105 106 usb_pipe_start_session(hub_info->control_pipe);107 //set hub configuration108 opResult = usb_hub_set_configuration(hub_info);109 if (opResult != EOK) {110 usb_log_error("could not set hub configuration, errno %d\n",111 opResult);112 free(hub_info);113 return opResult;114 }115 //get port count and create attached_devs116 opResult = usb_hub_process_hub_specific_info(hub_info);117 if (opResult != EOK) {118 usb_log_error("could process hub specific info, errno %d\n",119 opResult);120 free(hub_info);121 return opResult;122 }123 usb_pipe_end_session(hub_info->control_pipe);124 125 /// \TODO what is this?126 usb_log_debug("Creating `hub' function.\n");127 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,128 fun_exposed, "hub");129 assert(hub_fun != NULL);130 hub_fun->ops = NULL;131 132 opResult = ddf_fun_bind(hub_fun);133 assert(opResult == EOK);134 opResult = ddf_fun_add_to_class(hub_fun, "hub");135 assert(opResult == EOK);136 137 opResult = usb_hub_start_hub_fibril(hub_info);138 if(opResult!=EOK)139 free(hub_info);140 return opResult;141 }142 143 144 /** Callback for polling hub for changes.145 *146 * @param dev Device where the change occured.147 * @param change_bitmap Bitmap of changed ports.148 * @param change_bitmap_size Size of the bitmap in bytes.149 * @param arg Custom argument, points to @c usb_hub_info_t.150 * @return Whether to continue polling.151 */152 bool hub_port_changes_callback(usb_device_t *dev,153 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {154 usb_hub_info_t *hub = (usb_hub_info_t *) arg;155 156 /* FIXME: check that we received enough bytes. */157 if (change_bitmap_size == 0) {158 goto leave;159 }160 161 bool change;162 change = ((uint8_t*) change_bitmap)[0] & 1;163 if (change) {164 usb_hub_process_global_interrupt(hub);165 }166 167 size_t port;168 for (port = 1; port < hub->port_count + 1; port++) {169 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;170 if (change) {171 usb_hub_process_interrupt(hub, port);172 }173 }174 leave:175 /* FIXME: proper interval. */176 async_usleep(1000 * 1000 * 10);177 178 return true;179 }180 181 182 //*********************************************183 //184 // support functions185 //186 //*********************************************187 188 /**189 66 * create usb_hub_info_t structure 190 67 * … … 194 71 */ 195 72 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) { 196 usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t));197 if (!result) return NULL;73 usb_hub_info_t * result = usb_new(usb_hub_info_t); 74 if(!result) return NULL; 198 75 result->usb_device = usb_dev; 199 76 result->status_change_pipe = usb_dev->pipes[0].pipe; … … 213 90 * @return error code 214 91 */ 215 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){ 216 93 // get hub descriptor 217 94 usb_log_debug("creating serialized descriptor\n"); 218 95 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE); 219 96 usb_hub_descriptor_t * descriptor; 220 int opResult; 221 97 98 /* this was one fix of some bug, should not be needed anymore 99 * these lines allow to reset hub once more, it can be used as 100 * brute-force initialization for non-removable devices 101 int opResult = usb_request_set_configuration(&result->endpoints.control, 1); 102 if(opResult!=EOK){ 103 usb_log_error("could not set default configuration, errno %d",opResult); 104 return opResult; 105 } 106 */ 222 107 size_t received_size; 223 opResult = usb_request_get_descriptor(hub_info->control_pipe, 224 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 225 USB_DESCTYPE_HUB, 0, 0, serialized_descriptor, 226 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 108 int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe, 109 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 110 USB_DESCTYPE_HUB, 111 0, 0, serialized_descriptor, 112 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 227 113 228 114 if (opResult != EOK) { 229 usb_log_error("failed when receiving hub descriptor, " 230 "badcode = %d\n", 231 opResult); 115 usb_log_error("failed when receiving hub descriptor, badcode = %d\n", 116 opResult); 232 117 free(serialized_descriptor); 233 118 return opResult; … … 235 120 usb_log_debug2("deserializing descriptor\n"); 236 121 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor); 237 if (descriptor == NULL){122 if(descriptor==NULL){ 238 123 usb_log_warning("could not deserialize descriptor \n"); 239 124 return opResult; 240 125 } 241 usb_log_debug("setting port count to %d\n", descriptor->ports_count);126 usb_log_debug("setting port count to %d\n",descriptor->ports_count); 242 127 hub_info->port_count = descriptor->ports_count; 243 /// \TODO this is not semantically correct 244 hub_info->ports = malloc( 245 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 128 hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1)); 246 129 size_t port; 247 130 for (port = 0; port < hub_info->port_count + 1; port++) { 248 131 usb_hub_port_init(&hub_info->ports[port]); 249 132 } 133 //handle non-removable devices 134 usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor); 250 135 usb_log_debug2("freeing data\n"); 251 136 free(serialized_descriptor); … … 254 139 return EOK; 255 140 } 256 257 141 /** 258 142 * Set configuration of hub … … 263 147 * @return error code 264 148 */ 265 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info){ 266 150 //device descriptor 267 151 usb_standard_device_descriptor_t *std_descriptor … … 269 153 usb_log_debug("hub has %d configurations\n", 270 154 std_descriptor->configuration_count); 271 if (std_descriptor->configuration_count < 1){155 if(std_descriptor->configuration_count<1){ 272 156 usb_log_error("there are no configurations available\n"); 273 157 return EINVAL; … … 289 173 } 290 174 usb_log_debug("\tused configuration %d\n", 291 config_descriptor->configuration_number);175 config_descriptor->configuration_number); 292 176 293 177 return EOK; … … 295 179 296 180 /** 297 * create and start fibril with hub control loop 298 * 299 * Before the fibril is started, the control pipe and host controller 300 * connection of the hub is open. 301 * 302 * @param hub_info hub representing structure 181 * Initialize hub device driver fibril 182 * 183 * Creates hub representation and fibril that periodically checks hub`s status. 184 * Hub representation is passed to the fibril. 185 * @param usb_dev generic usb device information 303 186 * @return error code 304 187 */ 305 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){ 188 int usb_hub_add_device(usb_device_t * usb_dev){ 189 if(!usb_dev) return EINVAL; 190 usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev); 191 //create hc connection 192 usb_log_debug("Initializing USB wire abstraction.\n"); 193 int opResult = usb_hc_connection_initialize_from_device( 194 &hub_info->connection, 195 hub_info->usb_device->ddf_dev); 196 if(opResult != EOK){ 197 usb_log_error("could not initialize connection to device, errno %d\n", 198 opResult); 199 free(hub_info); 200 return opResult; 201 } 202 203 usb_pipe_start_session(hub_info->control_pipe); 204 //set hub configuration 205 opResult = usb_hub_set_configuration(hub_info); 206 if(opResult!=EOK){ 207 usb_log_error("could not set hub configuration, errno %d\n",opResult); 208 free(hub_info); 209 return opResult; 210 } 211 //get port count and create attached_devs 212 opResult = usb_hub_process_hub_specific_info(hub_info); 213 if(opResult!=EOK){ 214 usb_log_error("could not set hub configuration, errno %d\n",opResult); 215 free(hub_info); 216 return opResult; 217 } 218 usb_pipe_end_session(hub_info->control_pipe); 219 220 221 /// \TODO what is this? 222 usb_log_debug("Creating `hub' function.\n"); 223 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev, 224 fun_exposed, "hub"); 225 assert(hub_fun != NULL); 226 hub_fun->ops = NULL; 227 228 int rc = ddf_fun_bind(hub_fun); 229 assert(rc == EOK); 230 rc = ddf_fun_add_to_class(hub_fun, "hub"); 231 assert(rc == EOK); 232 306 233 /* 307 234 * The processing will require opened control pipe and connection … … 312 239 * auto destruction, this could work better. 313 240 */ 314 int rc = usb_pipe_start_session(hub_info->control_pipe);241 rc = usb_pipe_start_session(&usb_dev->ctrl_pipe); 315 242 if (rc != EOK) { 316 243 usb_log_error("Failed to start session on control pipe: %s.\n", 317 244 str_error(rc)); 318 return rc;245 goto leave; 319 246 } 320 247 rc = usb_hc_connection_open(&hub_info->connection); 321 248 if (rc != EOK) { 322 usb_pipe_end_session( hub_info->control_pipe);249 usb_pipe_end_session(&usb_dev->ctrl_pipe); 323 250 usb_log_error("Failed to open connection to HC: %s.\n", 324 251 str_error(rc)); 325 return rc;252 goto leave; 326 253 } 327 254 328 255 rc = usb_device_auto_poll(hub_info->usb_device, 0, 329 hub_port_changes_callback, ((hub_info->port_count +1) / 8) + 1,256 hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1, 330 257 NULL, hub_info); 331 258 if (rc != EOK) { … … 339 266 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 340 267 return EOK; 341 } 268 269 leave: 270 free(hub_info); 271 272 return rc; 273 } 274 342 275 343 276 //********************************************* 344 277 // 345 // change handling functions278 // hub driver code, main loop and port handling 346 279 // 347 280 //********************************************* 348 281 349 350 /** 351 * process hub over current change352 * 353 * This means either to power off the hub or power iton.354 * @param hub _info hub instance355 * @param status hub status bitmask282 /** 283 * triggers actions to connect non0removable devices 284 * 285 * This will trigger operations leading to activated non-removable device. 286 * Control pipe of the hub must be open fo communication. 287 * @param hub hub representation 288 * @param descriptor usb hub descriptor 356 289 * @return error code 357 290 */ 358 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 359 usb_hub_status_t status) { 291 static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub, 292 usb_hub_descriptor_t * descriptor) 293 { 294 usb_log_info("attaching non-removable devices(if any)\n"); 295 usb_device_request_setup_packet_t request; 360 296 int opResult; 361 if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_OVER_CURRENT)){ 362 opResult = usb_hub_clear_feature(hub_info->control_pipe, 363 USB_HUB_FEATURE_HUB_LOCAL_POWER); 364 if (opResult != EOK) { 365 usb_log_error("cannot power off hub: %d\n", 366 opResult); 367 } 368 } else { 369 opResult = usb_hub_set_feature(hub_info->control_pipe, 370 USB_HUB_FEATURE_HUB_LOCAL_POWER); 371 if (opResult != EOK) { 372 usb_log_error("cannot power on hub: %d\n", 373 opResult); 374 } 375 } 376 return opResult; 377 } 378 379 /** 380 * process hub power change 381 * 382 * If the power has been lost, reestablish it. 383 * If it was reestablished, re-power all ports. 384 * @param hub_info hub instance 385 * @param status hub status bitmask 386 * @return error code 387 */ 388 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 389 usb_hub_status_t status) { 390 int opResult; 391 if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) { 392 //restart power on hub 393 opResult = usb_hub_set_feature(hub_info->control_pipe, 394 USB_HUB_FEATURE_HUB_LOCAL_POWER); 395 if (opResult != EOK) { 396 usb_log_error("cannot power on hub: %d\n", 397 opResult); 398 } 399 } else {//power reestablished on hub- restart ports 400 size_t port; 401 for (port = 0; port < hub_info->port_count; ++port) { 402 opResult = usb_hub_set_port_feature( 403 hub_info->control_pipe, 404 port, USB_HUB_FEATURE_PORT_POWER); 297 size_t rcvd_size; 298 usb_port_status_t status; 299 uint8_t * non_removable_dev_bitmap = descriptor->devices_removable; 300 int port; 301 for(port=1;port<=descriptor->ports_count;++port){ 302 bool is_non_removable = 303 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2; 304 if(is_non_removable){ 305 usb_log_debug("non-removable device on port %d\n",port); 306 usb_hub_set_port_status_request(&request, port); 307 opResult = usb_pipe_control_read( 308 hub->control_pipe, 309 &request, sizeof(usb_device_request_setup_packet_t), 310 &status, 4, &rcvd_size 311 ); 405 312 if (opResult != EOK) { 406 usb_log_error("cannot power on port %d; %d\n", 407 port, opResult); 313 usb_log_error("could not get port status of port %d errno:%d\n", 314 port, opResult); 315 return opResult; 316 } 317 //set the status change bit, so it will be noticed in driver loop 318 if(usb_port_dev_connected(&status)){ 319 usb_hub_set_disable_port_feature_request(&request, port, 320 USB_HUB_FEATURE_PORT_CONNECTION); 321 opResult = usb_pipe_control_read( 322 hub->control_pipe, 323 &request, sizeof(usb_device_request_setup_packet_t), 324 &status, 4, &rcvd_size 325 ); 326 if (opResult != EOK) { 327 usb_log_warning( 328 "could not clear port connection on port %d errno:%d\n", 329 port, opResult); 330 } 331 usb_log_debug("cleared port connection\n"); 332 usb_hub_set_enable_port_feature_request(&request, port, 333 USB_HUB_FEATURE_PORT_ENABLE); 334 opResult = usb_pipe_control_read( 335 hub->control_pipe, 336 &request, sizeof(usb_device_request_setup_packet_t), 337 &status, 4, &rcvd_size 338 ); 339 if (opResult != EOK) { 340 usb_log_warning( 341 "could not set port enabled on port %d errno:%d\n", 342 port, opResult); 343 } 344 usb_log_debug("port set to enabled - should lead to connection change\n"); 408 345 } 409 346 } 410 347 } 411 return opResult; 412 } 413 414 /** 415 * process hub interrupts 416 * 417 * The change can be either in the over-current condition or 418 * local-power lost condition. 419 * @param hub_info hub instance 420 */ 421 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info) { 422 usb_log_debug("global interrupt on a hub\n"); 423 usb_pipe_t *pipe = hub_info->control_pipe; 348 /// \TODO this is just a debug code 349 for(port=1;port<=descriptor->ports_count;++port){ 350 bool is_non_removable = 351 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2; 352 if(is_non_removable){ 353 usb_log_debug("port %d is non-removable\n",port); 354 usb_port_status_t status; 355 size_t rcvd_size; 356 usb_device_request_setup_packet_t request; 357 //int opResult; 358 usb_hub_set_port_status_request(&request, port); 359 //endpoint 0 360 opResult = usb_pipe_control_read( 361 hub->control_pipe, 362 &request, sizeof(usb_device_request_setup_packet_t), 363 &status, 4, &rcvd_size 364 ); 365 if (opResult != EOK) { 366 usb_log_error("could not get port status %d\n",opResult); 367 } 368 if (rcvd_size != sizeof (usb_port_status_t)) { 369 usb_log_error("received status has incorrect size\n"); 370 } 371 //something connected/disconnected 372 if (usb_port_connect_change(&status)) { 373 usb_log_debug("some connection changed\n"); 374 } 375 usb_log_debug("status: %s\n",usb_debug_str_buffer( 376 (uint8_t *)&status,4,4)); 377 } 378 } 379 return EOK; 380 } 381 382 383 /** 384 * release default address used by given hub 385 * 386 * Also unsets hub->is_default_address_used. Convenience wrapper function. 387 * @note hub->connection MUST be open for communication 388 * @param hub hub representation 389 * @return error code 390 */ 391 static int usb_hub_release_default_address(usb_hub_info_t * hub){ 392 int opResult = usb_hc_release_default_address(&hub->connection); 393 if(opResult!=EOK){ 394 usb_log_error("could not release default address, errno %d\n",opResult); 395 return opResult; 396 } 397 hub->is_default_address_used = false; 398 return EOK; 399 } 400 401 /** 402 * routine called when a device on port has been removed 403 * 404 * If the device on port had default address, it releases default address. 405 * Otherwise does not do anything, because DDF does not allow to remove device 406 * from it`s device tree. 407 * @param hub hub representation 408 * @param port port number, starting from 1 409 */ 410 void usb_hub_removed_device( 411 usb_hub_info_t * hub,uint16_t port) { 412 413 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 414 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 415 if(opResult != EOK){ 416 usb_log_warning("could not clear port-change-connection flag\n"); 417 } 418 /** \TODO remove device from device manager - not yet implemented in 419 * devide manager 420 */ 421 422 //close address 423 if(hub->ports[port].attached_device.address >= 0){ 424 /*uncomment this code to use it when DDF allows device removal 425 opResult = usb_hc_unregister_device( 426 &hub->connection, hub->attached_devs[port].address); 427 if(opResult != EOK) { 428 dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \ 429 "removed device: %d", opResult); 430 } 431 hub->attached_devs[port].address = 0; 432 hub->attached_devs[port].handle = 0; 433 */ 434 }else{ 435 usb_log_warning("this is strange, disconnected device had no address\n"); 436 //device was disconnected before it`s port was reset - return default address 437 usb_hub_release_default_address(hub); 438 } 439 } 440 441 442 /** 443 * Process over current condition on port. 444 * 445 * Turn off the power on the port. 446 * 447 * @param hub hub representation 448 * @param port port number, starting from 1 449 */ 450 void usb_hub_over_current( usb_hub_info_t * hub, 451 uint16_t port){ 424 452 int opResult; 425 426 usb_port_status_t status; 427 size_t rcvd_size; 428 usb_device_request_setup_packet_t request; 429 //int opResult; 430 usb_hub_set_hub_status_request(&request); 431 //endpoint 0 432 433 opResult = usb_pipe_control_read( 434 pipe, 435 &request, sizeof (usb_device_request_setup_packet_t), 436 &status, 4, &rcvd_size 437 ); 438 if (opResult != EOK) { 439 usb_log_error("could not get hub status\n"); 440 return; 441 } 442 if (rcvd_size != sizeof (usb_port_status_t)) { 443 usb_log_error("received status has incorrect size\n"); 444 return; 445 } 446 //port reset 447 if ( 448 usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) { 449 usb_process_hub_over_current(hub_info, status); 450 } 451 if ( 452 usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) { 453 usb_process_hub_power_change(hub_info, status); 454 } 455 } 453 opResult = usb_hub_clear_port_feature(hub->control_pipe, 454 port, USB_HUB_FEATURE_PORT_POWER); 455 if(opResult!=EOK){ 456 usb_log_error("cannot power off port %d; %d\n", 457 port, opResult); 458 } 459 } 460 456 461 457 462 /** -
uspace/drv/usbhub/usbhub.h
rdc4c19e ra49e171 37 37 38 38 #include <ipc/devman.h> 39 #include <usb/usb.h> 39 40 #include <ddf/driver.h> 40 41 42 #define NAME "usbhub" 43 41 44 #include <usb/hub.h> 42 #include <usb/classes/hub.h>43 45 44 46 #include <usb/pipes.h> 45 47 #include <usb/devdrv.h> 46 47 #include <fibril_synch.h>48 49 #define NAME "usbhub"50 48 51 49 #include "ports.h" … … 54 52 55 53 /** Information about attached hub. */ 56 struct usb_hub_info_t{54 typedef struct { 57 55 /** Number of ports. */ 58 56 size_t port_count; 59 57 60 /** attached device handles, for each port one*/58 /** Ports. */ 61 59 usb_hub_port_t *ports; 62 60 63 61 /** connection to hcd */ 64 62 usb_hc_connection_t connection; … … 89 87 /** generic usb device data*/ 90 88 usb_device_t * usb_device; 91 } ;89 } usb_hub_info_t; 92 90 93 //int usb_hub_control_loop(void * hub_info_param); 91 /** 92 * function running the hub-controlling loop. 93 * @param hub_info_param hub info pointer 94 */ 95 int usb_hub_control_loop(void * hub_info_param); 96 97 /** 98 * Check changes on specified hub 99 * @param hub_info_param pointer to usb_hub_info_t structure 100 * @return error code if there is problem when initializing communication with 101 * hub, EOK otherwise 102 */ 103 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param); 104 105 void usb_hub_removed_device(usb_hub_info_t *, uint16_t); 106 void usb_hub_over_current(usb_hub_info_t *, uint16_t); 94 107 95 108 int usb_hub_add_device(usb_device_t * usb_dev); 96 97 bool hub_port_changes_callback(usb_device_t *dev,98 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);99 109 100 110 #endif -
uspace/drv/usbhub/usbhub_private.h
rdc4c19e ra49e171 54 54 // 55 55 //************ 56 #define usb_new(type) (type*)malloc(sizeof(type)) 56 57 57 58 59 /** 60 * Create hub structure instance 61 * 62 * Set the address and port count information most importantly. 63 * 64 * @param device 65 * @param hc host controller phone 66 * @return 67 */ 58 68 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device); 59 69 … … 100 110 101 111 /** 102 * Clear feature on hub port.103 *104 * @param hc Host controller telephone105 * @param address Hub address106 * @param port_index Port107 * @param feature Feature selector108 * @return Operation result109 */110 static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,111 int port_index,112 usb_hub_class_feature_t feature) {113 114 usb_device_request_setup_packet_t clear_request = {115 .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,116 .request = USB_DEVREQ_SET_FEATURE,117 .length = 0,118 .index = port_index119 };120 clear_request.value = feature;121 return usb_pipe_control_write(pipe, &clear_request,122 sizeof(clear_request), NULL, 0);123 }124 125 126 /**127 * Clear feature on hub port.128 *129 * @param pipe pipe to hub control endpoint130 * @param feature Feature selector131 * @return Operation result132 */133 static inline int usb_hub_clear_feature(usb_pipe_t *pipe,134 usb_hub_class_feature_t feature) {135 136 usb_device_request_setup_packet_t clear_request = {137 .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,138 .request = USB_DEVREQ_CLEAR_FEATURE,139 .length = 0,140 .index = 0141 };142 clear_request.value = feature;143 return usb_pipe_control_write(pipe, &clear_request,144 sizeof(clear_request), NULL, 0);145 }146 147 /**148 * Clear feature on hub port.149 *150 * @param pipe pipe to hub control endpoint151 * @param feature Feature selector152 * @return Operation result153 */154 static inline int usb_hub_set_feature(usb_pipe_t *pipe,155 usb_hub_class_feature_t feature) {156 157 usb_device_request_setup_packet_t clear_request = {158 .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,159 .request = USB_DEVREQ_SET_FEATURE,160 .length = 0,161 .index = 0162 };163 clear_request.value = feature;164 return usb_pipe_control_write(pipe, &clear_request,165 sizeof(clear_request), NULL, 0);166 }167 168 /**169 112 * create uint8_t array with serialized descriptor 170 113 * -
uspace/drv/usbhub/utils.c
rdc4c19e ra49e171 60 60 size_t size = 7; 61 61 //variable size according to port count 62 size_t var_size = (descriptor->ports_count+7)/8;62 size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0); 63 63 size += 2 * var_size; 64 uint8_t * result = malloc(size);64 uint8_t * result = (uint8_t*) malloc(size); 65 65 //size 66 66 result[0] = size; … … 84 84 } 85 85 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor( 87 void * serialized_descriptor) { 88 uint8_t * sdescriptor = serialized_descriptor; 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) { 87 uint8_t * sdescriptor = (uint8_t*) serialized_descriptor; 89 88 90 89 if (sdescriptor[1] != USB_DESCTYPE_HUB) { 91 usb_log_warning("trying to deserialize wrong descriptor %x\n", 92 sdescriptor[1]); 90 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]); 93 91 return NULL; 94 92 } 95 93 96 usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t));94 usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t); 97 95 98 96 … … 102 100 result->pwr_on_2_good_time = sdescriptor[5]; 103 101 result->current_requirement = sdescriptor[6]; 104 size_t var_size = (result->ports_count+7) / 8; 102 size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) 103 ? 1 : 0); 105 104 result->devices_removable = (uint8_t*) malloc(var_size); 106 105 -
uspace/drv/usbmid/main.c
rdc4c19e ra49e171 55 55 int rc; 56 56 57 rc = usb_pipe_start_ long_transfer(&dev->ctrl_pipe);57 rc = usb_pipe_start_session(&dev->ctrl_pipe); 58 58 if (rc != EOK) { 59 usb_log_error("Failed to start transferon control pipe: %s.\n",59 usb_log_error("Failed to start session on control pipe: %s.\n", 60 60 str_error(rc)); 61 61 return rc; … … 64 64 bool accept = usbmid_explore_device(dev); 65 65 66 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 66 rc = usb_pipe_end_session(&dev->ctrl_pipe); 67 if (rc != EOK) { 68 usb_log_warning("Failed to end session on control pipe: %s.\n", 69 str_error(rc)); 70 } 67 71 68 72 if (!accept) { -
uspace/drv/vhc/connhost.c
rdc4c19e ra49e171 257 257 258 258 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 259 size_t max_packet_size, 259 260 void *data, size_t size, 260 261 usbhc_iface_transfer_out_callback_t callback, void *arg) … … 266 267 267 268 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 269 size_t max_packet_size, 268 270 void *data, size_t size, 269 271 usbhc_iface_transfer_in_callback_t callback, void *arg) … … 275 277 276 278 static int control_write(ddf_fun_t *fun, usb_target_t target, 279 size_t max_packet_size, 277 280 void *setup_packet, size_t setup_packet_size, 278 281 void *data, size_t data_size, … … 292 295 293 296 static int control_read(ddf_fun_t *fun, usb_target_t target, 297 size_t max_packet_size, 294 298 void *setup_packet, size_t setup_packet_size, 295 299 void *data, size_t data_size, … … 324 328 } 325 329 330 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t ignored) 331 { 332 usb_address_keeping_reserve_default(&addresses); 333 return EOK; 334 } 335 336 static int release_default_address(ddf_fun_t *fun) 337 { 338 usb_address_keeping_release_default(&addresses); 339 return EOK; 340 } 341 326 342 static int request_address(ddf_fun_t *fun, usb_speed_t ignored, 327 343 usb_address_t *address) … … 376 392 377 393 usbhc_iface_t vhc_iface = { 394 .reserve_default_address = reserve_default_address, 395 .release_default_address = release_default_address, 378 396 .request_address = request_address, 379 397 .bind_address = bind_address, -
uspace/lib/drv/generic/remote_usbhc.c
rdc4c19e ra49e171 50 50 static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 51 51 static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 52 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 52 54 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 53 55 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 59 61 /** Remote USB host controller interface operations. */ 60 62 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 63 remote_usbhc_reserve_default_address, 64 remote_usbhc_release_default_address, 65 61 66 remote_usbhc_request_address, 62 67 remote_usbhc_bind_address, … … 124 129 } 125 130 131 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface, 132 ipc_callid_t callid, ipc_call_t *call) 133 { 134 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 135 136 if (!usb_iface->reserve_default_address) { 137 async_answer_0(callid, ENOTSUP); 138 return; 139 } 140 141 usb_speed_t speed = DEV_IPC_GET_ARG1(*call); 142 143 int rc = usb_iface->reserve_default_address(fun, speed); 144 145 async_answer_0(callid, rc); 146 } 147 148 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface, 149 ipc_callid_t callid, ipc_call_t *call) 150 { 151 usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface; 152 153 if (!usb_iface->release_default_address) { 154 async_answer_0(callid, ENOTSUP); 155 return; 156 } 157 158 int rc = usb_iface->release_default_address(fun); 159 160 async_answer_0(callid, rc); 161 } 162 126 163 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 127 164 ipc_callid_t callid, ipc_call_t *call) … … 233 270 } 234 271 272 size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 235 273 usb_target_t target = { 236 274 .address = DEV_IPC_GET_ARG1(*call), … … 262 300 trans->size = len; 263 301 264 rc = transfer_func(fun, target, 302 rc = transfer_func(fun, target, max_packet_size, 265 303 buffer, len, 266 304 callback_out, trans); … … 288 326 } 289 327 328 size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 290 329 usb_target_t target = { 291 330 .address = DEV_IPC_GET_ARG1(*call), … … 309 348 trans->size = len; 310 349 311 int rc = transfer_func(fun, target, 350 int rc = transfer_func(fun, target, max_packet_size, 312 351 trans->buffer, len, 313 352 callback_in, trans); … … 375 414 }; 376 415 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call); 416 size_t max_packet_size = DEV_IPC_GET_ARG4(*call); 377 417 378 418 int rc; … … 410 450 trans->size = data_buffer_len; 411 451 412 rc = usb_iface->control_write(fun, target, 452 rc = usb_iface->control_write(fun, target, max_packet_size, 413 453 setup_packet, setup_packet_len, 414 454 data_buffer, data_buffer_len, … … 437 477 .endpoint = DEV_IPC_GET_ARG2(*call) 438 478 }; 479 size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 439 480 440 481 int rc; … … 474 515 } 475 516 476 rc = usb_iface->control_read(fun, target, 517 rc = usb_iface->control_read(fun, target, max_packet_size, 477 518 setup_packet, setup_packet_len, 478 519 trans->buffer, trans->size, … … 496 537 } 497 538 498 #define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \ 499 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 500 #define _INIT_FROM_LOW_DATA2(type, var, arg_no) \ 501 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16) 502 #define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \ 503 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16) 504 #define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \ 505 type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8) 506 #define _INIT_FROM_LOW_DATA3(type, var, arg_no) \ 507 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8) 508 509 _INIT_FROM_HIGH_DATA2(usb_address_t, address, 1); 510 _INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1); 511 512 _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2); 513 _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2); 514 _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2); 515 516 _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3); 517 _INIT_FROM_LOW_DATA2(unsigned int, interval, 3); 518 519 #undef _INIT_FROM_HIGH_DATA2 520 #undef _INIT_FROM_LOW_DATA2 521 #undef _INIT_FROM_HIGH_DATA3 522 #undef _INIT_FROM_MIDDLE_DATA3 523 #undef _INIT_FROM_LOW_DATA3 524 525 int rc = usb_iface->register_endpoint(fun, address, speed, endpoint, 539 #define INIT_FROM_HIGH_DATA(type, var, arg_no) \ 540 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256 541 #define INIT_FROM_LOW_DATA(type, var, arg_no) \ 542 type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256 543 544 INIT_FROM_HIGH_DATA(usb_address_t, address, 1); 545 INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1); 546 INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2); 547 INIT_FROM_LOW_DATA(usb_direction_t, direction, 2); 548 549 #undef INIT_FROM_HIGH_DATA 550 #undef INIT_FROM_LOW_DATA 551 552 size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call); 553 unsigned int interval = (unsigned int) DEV_IPC_GET_ARG4(*call); 554 555 int rc = usb_iface->register_endpoint(fun, address, endpoint, 526 556 transfer_type, direction, max_packet_size, interval); 527 557 -
uspace/lib/drv/include/usbhc_iface.h
rdc4c19e ra49e171 66 66 * - argument #1 is target address 67 67 * - argument #2 is target endpoint 68 * - argument #3 is max packet size of the endpoint 68 69 * - this call is immediately followed by IPC data read (async version) 69 70 * - the call is not answered until the device returns some data (or until … … 84 85 */ 85 86 typedef enum { 87 /** Reserve usage of default address. 88 * This call informs the host controller that the caller will be 89 * using default USB address. It is duty of the HC driver to ensure 90 * that only single entity will have it reserved. 91 * The address is returned via IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS. 92 * The caller can start using the address after receiving EOK 93 * answer. 94 */ 95 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, 96 97 /** Release usage of default address. 98 * @see IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS 99 */ 100 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS, 101 86 102 /** Asks for address assignment by host controller. 87 103 * Answer: … … 153 169 /** Register endpoint attributes at host controller. 154 170 * This is used to reserve portion of USB bandwidth. 155 * When speed is invalid, speed of the device is used.156 171 * Parameters: 157 * - USB address + endpoint number 158 * - packed as ADDR << 16 + EP 159 * - speed + transfer type + direction 160 * - packed as ( SPEED << 8 + TYPE ) << 8 + DIR 161 * - maximum packet size + interval (in milliseconds) 162 * - packed as MPS << 16 + INT 172 * - USB address + endpoint number (ADDR * 256 + EP) 173 * - transfer type + direction (TYPE * 256 + DIR) 174 * - maximum packet size 175 * - interval (in milliseconds) 163 176 * Answer: 164 177 * - EOK - reservation successful … … 189 202 190 203 /** Out transfer processing function prototype. */ 191 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, 204 typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t, size_t, 192 205 void *, size_t, 193 206 usbhc_iface_transfer_out_callback_t, void *); … … 197 210 198 211 /** In transfer processing function prototype. */ 199 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, 212 typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t, size_t, 200 213 void *, size_t, 201 214 usbhc_iface_transfer_in_callback_t, void *); … … 209 222 int (*release_address)(ddf_fun_t *, usb_address_t); 210 223 211 int (*register_endpoint)(ddf_fun_t *, 212 usb_address_t, usb_speed_t, usb_endpoint_t, 224 int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, 213 225 usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 214 226 int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t, … … 222 234 223 235 int (*control_write)(ddf_fun_t *, usb_target_t, 236 size_t, 224 237 void *, size_t, void *, size_t, 225 238 usbhc_iface_transfer_out_callback_t, void *); 226 239 227 240 int (*control_read)(ddf_fun_t *, usb_target_t, 241 size_t, 228 242 void *, size_t, void *, size_t, 229 243 usbhc_iface_transfer_in_callback_t, void *); -
uspace/lib/usb/Makefile
rdc4c19e ra49e171 43 43 src/hidparser.c \ 44 44 src/hub.c \ 45 src/pipepriv.c \46 45 src/pipes.c \ 47 46 src/pipesinit.c \ -
uspace/lib/usb/include/usb/classes/hub.h
rdc4c19e ra49e171 43 43 */ 44 44 typedef enum { 45 USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,46 USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,47 45 USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0, 48 46 USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1, … … 61 59 /* USB_HUB_FEATURE_ = , */ 62 60 } usb_hub_class_feature_t; 63 64 61 65 62 /** Header of standard hub descriptor without the "variadic" part. */ -
uspace/lib/usb/include/usb/devdrv.h
rdc4c19e ra49e171 169 169 usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *); 170 170 171 int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);172 int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,173 usb_endpoint_description_t **, uint8_t *, size_t, int, int,174 usb_endpoint_mapping_t **, size_t *);175 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);176 177 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);178 179 171 #endif 180 172 /** -
uspace/lib/usb/include/usb/host/batch.h
rdc4c19e ra49e171 92 92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 93 93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance); 95 96 static inline void usb_transfer_batch_finish_error( 97 usb_transfer_batch_t *instance, int error) 98 { 99 assert(instance); 100 instance->error = error; 101 usb_transfer_batch_finish(instance); 102 } 94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error); 103 95 104 96 #endif -
uspace/lib/usb/include/usb/host/device_keeper.h
rdc4c19e ra49e171 71 71 void usb_device_keeper_init(usb_device_keeper_t *instance); 72 72 73 void usb_device_keeper_add_ep( 74 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep); 75 73 76 void usb_device_keeper_reserve_default_address( 74 77 usb_device_keeper_t *instance, usb_speed_t speed); … … 93 96 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance, 94 97 usb_address_t address); 98 99 void usb_device_keeper_use_control(usb_device_keeper_t *instance, 100 usb_target_t target); 101 102 void usb_device_keeper_release_control(usb_device_keeper_t *instance, 103 usb_target_t target); 104 95 105 #endif 96 106 /** -
uspace/lib/usb/include/usb/host/endpoint.h
rdc4c19e ra49e171 39 39 #include <bool.h> 40 40 #include <adt/list.h> 41 #include <fibril_synch.h>42 43 41 #include <usb/usb.h> 44 42 … … 50 48 usb_speed_t speed; 51 49 size_t max_packet_size; 50 bool active; 52 51 unsigned toggle:1; 53 fibril_mutex_t guard; 54 fibril_condvar_t avail; 55 volatile bool active; 52 link_t same_device_eps; 56 53 } endpoint_t; 57 54 … … 62 59 void endpoint_destroy(endpoint_t *instance); 63 60 64 void endpoint_use(endpoint_t *instance);65 66 void endpoint_release(endpoint_t *instance);67 68 61 int endpoint_toggle_get(endpoint_t *instance); 69 62 70 63 void endpoint_toggle_set(endpoint_t *instance, int toggle); 71 64 72 void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target); 65 void endpoint_toggle_reset(link_t *ep); 66 67 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn); 68 73 69 #endif 74 70 /** -
uspace/lib/usb/include/usb/host/usb_endpoint_manager.h
rdc4c19e ra49e171 78 78 size_t *bw); 79 79 80 void usb_endpoint_manager_reset_if_need(81 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);82 80 #endif 83 81 /** -
uspace/lib/usb/include/usb/hub.h
rdc4c19e ra49e171 59 59 } usb_hc_attached_device_t; 60 60 61 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t); 62 int usb_hc_release_default_address(usb_hc_connection_t *); 63 61 64 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t); 62 65 int usb_hc_register_device(usb_hc_connection_t *, -
uspace/lib/usb/include/usb/pipes.h
rdc4c19e ra49e171 42 42 #include <ipc/devman.h> 43 43 #include <ddf/driver.h> 44 #include <fibril_synch.h>45 44 46 45 /** Abstraction of a physical connection to the device. … … 60 59 * This endpoint must be bound with existing usb_device_connection_t 61 60 * (i.e. the wire to send data over). 62 *63 * Locking order: if you want to lock both mutexes64 * (@c guard and @c hc_phone_mutex), lock @c guard first.65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex66 * only.67 61 */ 68 62 typedef struct { 69 /** Guard of the whole pipe. */70 fibril_mutex_t guard;71 72 63 /** The connection used for sending the data. */ 73 64 usb_device_connection_t *wire; … … 87 78 /** Phone to the host controller. 88 79 * Negative when no session is active. 89 * It is an error to access this member without @c hc_phone_mutex90 * being locked.91 * If call over the phone is to be made, it must be preceeded by92 * call to pipe_add_ref() [internal libusb function].93 80 */ 94 81 int hc_phone; 95 96 /** Guard for serialization of requests over the phone. */97 fibril_mutex_t hc_phone_mutex;98 99 /** Number of active transfers over the pipe. */100 int refcount;101 82 } usb_pipe_t; 102 83 … … 153 134 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 154 135 size_t, uint8_t *, size_t, usb_device_connection_t *); 155 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,156 unsigned int, usb_hc_connection_t *);157 136 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *); 158 137 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *); … … 161 140 int usb_pipe_end_session(usb_pipe_t *); 162 141 bool usb_pipe_is_session_started(usb_pipe_t *); 163 164 int usb_pipe_start_long_transfer(usb_pipe_t *);165 void usb_pipe_end_long_transfer(usb_pipe_t *);166 142 167 143 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usb/include/usb/usb.h
rdc4c19e ra49e171 77 77 USB_SPEED_FULL, 78 78 /** USB 2.0 high speed (480Mbits/s). */ 79 USB_SPEED_HIGH, 80 /** Psuedo-speed serving as a boundary. */ 81 USB_SPEED_MAX 79 USB_SPEED_HIGH 82 80 } usb_speed_t; 83 81 -
uspace/lib/usb/src/devdrv.c
rdc4c19e ra49e171 72 72 } 73 73 74 /** Log out of memory error on given device. 75 * 76 * @param dev Device causing the trouble. 77 */ 78 static void usb_log_oom(ddf_dev_t *dev) 79 { 80 usb_log_error("Out of memory when adding device `%s'.\n", 81 dev->name); 82 } 83 74 84 /** Count number of pipes the driver expects. 75 85 * … … 98 108 */ 99 109 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 100 usb_device_t *dev, int alternate_setting) 101 { 102 usb_endpoint_mapping_t *pipes; 103 size_t pipes_count; 104 105 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 110 usb_device_t *dev) 111 { 112 int rc; 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 116 return EOK; 117 } 118 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 120 if (dev->pipes == NULL) { 121 usb_log_oom(dev->ddf_dev); 122 return ENOMEM; 123 } 124 125 size_t i; 126 127 /* Initialize to NULL first for rollback purposes. */ 128 for (i = 0; i < pipe_count; i++) { 129 dev->pipes[i].pipe = NULL; 130 } 131 132 for (i = 0; i < pipe_count; i++) { 133 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 134 if (dev->pipes[i].pipe == NULL) { 135 usb_log_oom(dev->ddf_dev); 136 rc = ENOMEM; 137 goto rollback; 138 } 139 140 dev->pipes[i].description = endpoints[i]; 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 143 } 144 145 rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count, 106 146 dev->descriptors.configuration, dev->descriptors.configuration_size, 107 dev->interface_no, alternate_setting, 108 &pipes, &pipes_count); 109 147 &dev->wire); 148 if (rc != EOK) { 149 usb_log_error("Failed initializing USB endpoints: %s.\n", 150 str_error(rc)); 151 goto rollback; 152 } 153 154 /* Register the endpoints. */ 155 usb_hc_connection_t hc_conn; 156 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 110 157 if (rc != EOK) { 111 158 usb_log_error( 112 "Failed to create endpoint pipes for `%s': %s.\n", 113 dev->ddf_dev->name, str_error(rc)); 114 return rc; 115 } 116 117 dev->pipes = pipes; 118 dev->pipes_count = pipes_count; 159 "Failed initializing connection to host controller: %s.\n", 160 str_error(rc)); 161 goto rollback; 162 } 163 rc = usb_hc_connection_open(&hc_conn); 164 if (rc != EOK) { 165 usb_log_error("Failed to connect to host controller: %s.\n", 166 str_error(rc)); 167 goto rollback; 168 } 169 for (i = 0; i < pipe_count; i++) { 170 if (dev->pipes[i].present) { 171 rc = usb_pipe_register(dev->pipes[i].pipe, 172 dev->pipes[i].descriptor->poll_interval, 173 &hc_conn); 174 /* Ignore error when operation not supported by HC. */ 175 if ((rc != EOK) && (rc != ENOTSUP)) { 176 /* FIXME: what shall we do? */ 177 dev->pipes[i].present = false; 178 free(dev->pipes[i].pipe); 179 dev->pipes[i].pipe = NULL; 180 } 181 } 182 } 183 /* Ignoring errors here. */ 184 usb_hc_connection_close(&hc_conn); 185 186 dev->pipes_count = pipe_count; 119 187 120 188 return EOK; 189 190 rollback: 191 for (i = 0; i < pipe_count; i++) { 192 if (dev->pipes[i].pipe != NULL) { 193 free(dev->pipes[i].pipe); 194 } 195 } 196 free(dev->pipes); 197 198 return rc; 121 199 } 122 200 … … 161 239 162 240 /* 163 * We will do some querying of the device, it is worth to prepare 164 * the long transfer. 241 * For further actions, we need open session on default control pipe. 165 242 */ 166 rc = usb_pipe_start_ long_transfer(&dev->ctrl_pipe);167 if (rc != EOK) { 168 usb_log_error("Failed to start transfer: %s.\n",243 rc = usb_pipe_start_session(&dev->ctrl_pipe); 244 if (rc != EOK) { 245 usb_log_error("Failed to start an IPC session: %s.\n", 169 246 str_error(rc)); 170 247 return rc; 171 248 } 172 249 173 /* Retrieve the descriptors. */ 174 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 175 &dev->descriptors); 176 if (rc != EOK) { 177 usb_log_error("Failed to retrieve standard device " \ 178 "descriptors of %s: %s.\n", 250 /* Get the device descriptor. */ 251 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, 252 &dev->descriptors.device); 253 if (rc != EOK) { 254 usb_log_error("Failed to retrieve device descriptor: %s.\n", 255 str_error(rc)); 256 return rc; 257 } 258 259 /* Get the full configuration descriptor. */ 260 rc = usb_request_get_full_configuration_descriptor_alloc( 261 &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration, 262 &dev->descriptors.configuration_size); 263 if (rc != EOK) { 264 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n", 179 265 dev->ddf_dev->name, str_error(rc)); 180 266 return rc; 181 267 } 182 268 183 184 269 if (driver->endpoints != NULL) { 185 rc = initialize_other_pipes(driver->endpoints, dev, 0); 186 } 187 188 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 270 rc = initialize_other_pipes(driver->endpoints, dev); 271 } 272 273 /* No checking here. */ 274 usb_pipe_end_session(&dev->ctrl_pipe); 189 275 190 276 /* Rollback actions. */ … … 205 291 * @return Number of alternate interfaces for @p interface_no interface. 206 292 */ 207 s ize_t usb_interface_count_alternates(uint8_t *config_descr,208 size_t config_descr_size, uint8_t interface_no)293 static size_t count_alternate_interfaces(uint8_t *config_descr, 294 size_t config_descr_size, int interface_no) 209 295 { 210 296 assert(config_descr != NULL); 211 assert(config_descr_size > 0);212 213 297 usb_dp_parser_t dp_parser = { 214 298 .nesting = usb_dp_standard_descriptor_nesting … … 259 343 260 344 alternates->alternative_count 261 = usb_interface_count_alternates(dev->descriptors.configuration,345 = count_alternate_interfaces(dev->descriptors.configuration, 262 346 dev->descriptors.configuration_size, dev->interface_no); 263 347 … … 373 457 static int destroy_current_pipes(usb_device_t *dev) 374 458 { 375 int rc = usb_device_destroy_pipes(dev->ddf_dev, 376 dev->pipes, dev->pipes_count); 377 if (rc != EOK) { 378 return rc; 379 } 380 459 size_t i; 460 int rc; 461 462 /* TODO: this shall be done under some device mutex. */ 463 464 /* First check that no session is opened. */ 465 for (i = 0; i < dev->pipes_count; i++) { 466 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 467 return EBUSY; 468 } 469 } 470 471 /* Prepare connection to HC. */ 472 usb_hc_connection_t hc_conn; 473 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 474 if (rc != EOK) { 475 return rc; 476 } 477 rc = usb_hc_connection_open(&hc_conn); 478 if (rc != EOK) { 479 return rc; 480 } 481 482 /* Destroy the pipes. */ 483 for (i = 0; i < dev->pipes_count; i++) { 484 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 485 free(dev->pipes[i].pipe); 486 } 487 488 usb_hc_connection_close(&hc_conn); 489 490 free(dev->pipes); 381 491 dev->pipes = NULL; 382 492 dev->pipes_count = 0; … … 425 535 426 536 /* Create new pipes. */ 427 rc = initialize_other_pipes(endpoints, dev , (int) alternate_setting);537 rc = initialize_other_pipes(endpoints, dev); 428 538 429 539 return rc; 430 }431 432 /** Retrieve basic descriptors from the device.433 *434 * @param[in] ctrl_pipe Control pipe with opened session.435 * @param[out] descriptors Where to store the descriptors.436 * @return Error code.437 */438 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,439 usb_device_descriptors_t *descriptors)440 {441 assert(descriptors != NULL);442 assert(usb_pipe_is_session_started(ctrl_pipe));443 444 descriptors->configuration = NULL;445 446 int rc;447 448 /* Get the device descriptor. */449 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);450 if (rc != EOK) {451 return rc;452 }453 454 /* Get the full configuration descriptor. */455 rc = usb_request_get_full_configuration_descriptor_alloc(456 ctrl_pipe, 0, (void **) &descriptors->configuration,457 &descriptors->configuration_size);458 if (rc != EOK) {459 return rc;460 }461 462 return EOK;463 }464 465 /** Create pipes for a device.466 *467 * This is more or less a wrapper that does following actions:468 * - allocate and initialize pipes469 * - map endpoints to the pipes based on the descriptions470 * - registers endpoints with the host controller471 *472 * @param[in] dev Generic DDF device backing the USB one.473 * @param[in] wire Initialized backing connection to the host controller.474 * @param[in] endpoints Endpoints description, NULL terminated.475 * @param[in] config_descr Configuration descriptor of active configuration.476 * @param[in] config_descr_size Size of @p config_descr in bytes.477 * @param[in] interface_no Interface to map from.478 * @param[in] interface_setting Interface setting (default is usually 0).479 * @param[out] pipes_ptr Where to store array of created pipes480 * (not NULL terminated).481 * @param[out] pipes_count_ptr Where to store number of pipes482 * (set to if you wish to ignore the count).483 * @return Error code.484 */485 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,486 usb_endpoint_description_t **endpoints,487 uint8_t *config_descr, size_t config_descr_size,488 int interface_no, int interface_setting,489 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)490 {491 assert(dev != NULL);492 assert(wire != NULL);493 assert(endpoints != NULL);494 assert(config_descr != NULL);495 assert(config_descr_size > 0);496 assert(pipes_ptr != NULL);497 498 size_t i;499 int rc;500 501 size_t pipe_count = count_other_pipes(endpoints);502 if (pipe_count == 0) {503 *pipes_ptr = NULL;504 return EOK;505 }506 507 usb_endpoint_mapping_t *pipes508 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);509 if (pipes == NULL) {510 return ENOMEM;511 }512 513 /* Initialize to NULL to allow smooth rollback. */514 for (i = 0; i < pipe_count; i++) {515 pipes[i].pipe = NULL;516 }517 518 /* Now allocate and fully initialize. */519 for (i = 0; i < pipe_count; i++) {520 pipes[i].pipe = malloc(sizeof(usb_pipe_t));521 if (pipes[i].pipe == NULL) {522 rc = ENOMEM;523 goto rollback_free_only;524 }525 pipes[i].description = endpoints[i];526 pipes[i].interface_no = interface_no;527 pipes[i].interface_setting = interface_setting;528 }529 530 /* Find the mapping from configuration descriptor. */531 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,532 config_descr, config_descr_size, wire);533 if (rc != EOK) {534 goto rollback_free_only;535 }536 537 /* Register the endpoints with HC. */538 usb_hc_connection_t hc_conn;539 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);540 if (rc != EOK) {541 goto rollback_free_only;542 }543 544 rc = usb_hc_connection_open(&hc_conn);545 if (rc != EOK) {546 goto rollback_free_only;547 }548 549 for (i = 0; i < pipe_count; i++) {550 if (pipes[i].present) {551 rc = usb_pipe_register(pipes[i].pipe,552 pipes[i].descriptor->poll_interval, &hc_conn);553 if (rc != EOK) {554 goto rollback_unregister_endpoints;555 }556 }557 }558 559 usb_hc_connection_close(&hc_conn);560 561 *pipes_ptr = pipes;562 if (pipes_count_ptr != NULL) {563 *pipes_count_ptr = pipe_count;564 }565 566 return EOK;567 568 /*569 * Jump here if something went wrong after endpoints have570 * been registered.571 * This is also the target when the registration of572 * endpoints fails.573 */574 rollback_unregister_endpoints:575 for (i = 0; i < pipe_count; i++) {576 if (pipes[i].present) {577 usb_pipe_unregister(pipes[i].pipe, &hc_conn);578 }579 }580 581 usb_hc_connection_close(&hc_conn);582 583 /*584 * Jump here if something went wrong before some actual communication585 * with HC. Then the only thing that needs to be done is to free586 * allocated memory.587 */588 rollback_free_only:589 for (i = 0; i < pipe_count; i++) {590 if (pipes[i].pipe != NULL) {591 free(pipes[i].pipe);592 }593 }594 free(pipes);595 596 return rc;597 }598 599 /** Destroy pipes previously created by usb_device_create_pipes.600 *601 * @param[in] dev Generic DDF device backing the USB one.602 * @param[in] pipes Endpoint mapping to be destroyed.603 * @param[in] pipes_count Number of endpoints.604 */605 int usb_device_destroy_pipes(ddf_dev_t *dev,606 usb_endpoint_mapping_t *pipes, size_t pipes_count)607 {608 assert(dev != NULL);609 assert(((pipes != NULL) && (pipes_count > 0))610 || ((pipes == NULL) && (pipes_count == 0)));611 612 if (pipes_count == 0) {613 return EOK;614 }615 616 int rc;617 618 /* Prepare connection to HC to allow endpoint unregistering. */619 usb_hc_connection_t hc_conn;620 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);621 if (rc != EOK) {622 return rc;623 }624 rc = usb_hc_connection_open(&hc_conn);625 if (rc != EOK) {626 return rc;627 }628 629 /* Destroy the pipes. */630 size_t i;631 for (i = 0; i < pipes_count; i++) {632 usb_pipe_unregister(pipes[i].pipe, &hc_conn);633 free(pipes[i].pipe);634 }635 636 usb_hc_connection_close(&hc_conn);637 638 free(pipes);639 640 return EOK;641 540 } 642 541 -
uspace/lib/usb/src/devpoll.c
rdc4c19e ra49e171 77 77 int rc; 78 78 79 rc = usb_pipe_start_session(pipe); 80 if (rc != EOK) { 81 failed_attempts++; 82 continue; 83 } 84 79 85 size_t actual_size; 80 86 rc = usb_pipe_read(pipe, polling_data->buffer, 81 87 polling_data->request_size, &actual_size); 82 88 89 /* Quit the session regardless of errors. */ 90 usb_pipe_end_session(pipe); 83 91 84 92 // if (rc == ESTALL) { -
uspace/lib/usb/src/host/batch.c
rdc4c19e ra49e171 63 63 instance->transfer_type = transfer_type; 64 64 instance->speed = speed; 65 instance->direction = ep->direction;65 instance->direction = USB_DIRECTION_BOTH; 66 66 instance->callback_in = func_in; 67 67 instance->callback_out = func_out; … … 79 79 instance->error = EOK; 80 80 instance->ep = ep; 81 endpoint_use(instance->ep);82 81 } 83 82 /*----------------------------------------------------------------------------*/ … … 87 86 * 88 87 */ 89 void usb_transfer_batch_finish(usb_transfer_batch_t *instance )88 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error) 90 89 { 91 90 assert(instance); 92 assert(instance->ep); 93 endpoint_release(instance->ep); 91 instance->error = error; 94 92 instance->next_step(instance); 95 93 } -
uspace/lib/usb/src/host/device_keeper.c
rdc4c19e ra49e171 54 54 for (; i < USB_ADDRESS_COUNT; ++i) { 55 55 instance->devices[i].occupied = false; 56 instance->devices[i].control_used = 0; 56 57 instance->devices[i].handle = 0; 57 instance->devices[i].speed = USB_SPEED_MAX; 58 } 59 // TODO: is this hack enough? 60 // (it is needed to allow smooth registration at default address) 61 instance->devices[0].occupied = true; 58 list_initialize(&instance->devices[i].endpoints); 59 } 60 } 61 /*----------------------------------------------------------------------------*/ 62 void usb_device_keeper_add_ep( 63 usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep) 64 { 65 assert(instance); 66 fibril_mutex_lock(&instance->guard); 67 assert(instance->devices[address].occupied); 68 list_append(&ep->same_device_eps, &instance->devices[address].endpoints); 69 fibril_mutex_unlock(&instance->guard); 62 70 } 63 71 /*----------------------------------------------------------------------------*/ … … 94 102 } 95 103 /*----------------------------------------------------------------------------*/ 104 /** Check setup packet data for signs of toggle reset. 105 * 106 * @param[in] instance Device keeper structure to use. 107 * @param[in] target Device to receive setup packet. 108 * @param[in] data Setup packet data. 109 * 110 * Really ugly one. 111 */ 112 void usb_device_keeper_reset_if_need( 113 usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data) 114 { 115 assert(instance); 116 fibril_mutex_lock(&instance->guard); 117 if (target.endpoint > 15 || target.endpoint < 0 118 || target.address >= USB_ADDRESS_COUNT || target.address < 0 119 || !instance->devices[target.address].occupied) { 120 fibril_mutex_unlock(&instance->guard); 121 usb_log_error("Invalid data when checking for toggle reset.\n"); 122 return; 123 } 124 125 switch (data[1]) 126 { 127 case 0x01: /*clear feature*/ 128 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */ 129 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 130 link_t *current = 131 instance->devices[target.address].endpoints.next; 132 while (current != 133 &instance->devices[target.address].endpoints) 134 { 135 /* endpoint number is < 16, thus first byte is enough */ 136 endpoint_toggle_reset_filtered( 137 current, data[4]); 138 current = current->next; 139 } 140 } 141 break; 142 143 case 0x9: /* set configuration */ 144 case 0x11: /* set interface */ 145 /* target must be device */ 146 if ((data[0] & 0xf) == 0) { 147 link_t *current = 148 instance->devices[target.address].endpoints.next; 149 while (current != 150 &instance->devices[target.address].endpoints) 151 { 152 endpoint_toggle_reset(current); 153 current = current->next; 154 } 155 } 156 break; 157 } 158 fibril_mutex_unlock(&instance->guard); 159 } 96 160 /*----------------------------------------------------------------------------*/ 97 161 /** Get a free USB address … … 200 264 return instance->devices[address].speed; 201 265 } 266 /*----------------------------------------------------------------------------*/ 267 void usb_device_keeper_use_control( 268 usb_device_keeper_t *instance, usb_target_t target) 269 { 270 assert(instance); 271 const uint16_t ep = 1 << target.endpoint; 272 fibril_mutex_lock(&instance->guard); 273 while (instance->devices[target.address].control_used & ep) { 274 fibril_condvar_wait(&instance->change, &instance->guard); 275 } 276 instance->devices[target.address].control_used |= ep; 277 fibril_mutex_unlock(&instance->guard); 278 } 279 /*----------------------------------------------------------------------------*/ 280 void usb_device_keeper_release_control( 281 usb_device_keeper_t *instance, usb_target_t target) 282 { 283 assert(instance); 284 const uint16_t ep = 1 << target.endpoint; 285 fibril_mutex_lock(&instance->guard); 286 assert((instance->devices[target.address].control_used & ep) != 0); 287 instance->devices[target.address].control_used &= ~ep; 288 fibril_mutex_unlock(&instance->guard); 289 fibril_condvar_signal(&instance->change); 290 } 202 291 /** 203 292 * @} -
uspace/lib/usb/src/host/endpoint.c
rdc4c19e ra49e171 34 34 */ 35 35 36 #include <assert.h>37 36 #include <errno.h> 38 37 #include <usb/host/endpoint.h> … … 50 49 instance->max_packet_size = max_packet_size; 51 50 instance->toggle = 0; 52 instance->active = false; 53 fibril_mutex_initialize(&instance->guard); 54 fibril_condvar_initialize(&instance->avail); 51 link_initialize(&instance->same_device_eps); 55 52 return EOK; 56 53 } … … 59 56 { 60 57 assert(instance); 61 assert(!instance->active);58 list_remove(&instance->same_device_eps); 62 59 free(instance); 63 }64 /*----------------------------------------------------------------------------*/65 void endpoint_use(endpoint_t *instance)66 {67 assert(instance);68 fibril_mutex_lock(&instance->guard);69 while (instance->active)70 fibril_condvar_wait(&instance->avail, &instance->guard);71 instance->active = true;72 fibril_mutex_unlock(&instance->guard);73 }74 /*----------------------------------------------------------------------------*/75 void endpoint_release(endpoint_t *instance)76 {77 assert(instance);78 fibril_mutex_lock(&instance->guard);79 instance->active = false;80 fibril_mutex_unlock(&instance->guard);81 fibril_condvar_signal(&instance->avail);82 60 } 83 61 /*----------------------------------------------------------------------------*/ … … 95 73 } 96 74 /*----------------------------------------------------------------------------*/ 97 void endpoint_toggle_reset _filtered(endpoint_t *instance, usb_target_t target)75 void endpoint_toggle_reset(link_t *ep) 98 76 { 77 endpoint_t *instance = 78 list_get_instance(ep, endpoint_t, same_device_eps); 99 79 assert(instance); 100 if (instance->address == target.address && 101 (instance->endpoint == target.endpoint || target.endpoint == 0)) 80 instance->toggle = 0; 81 } 82 /*----------------------------------------------------------------------------*/ 83 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn) 84 { 85 endpoint_t *instance = 86 list_get_instance(ep, endpoint_t, same_device_eps); 87 assert(instance); 88 if (instance->endpoint == epn) 102 89 instance->toggle = 0; 103 90 } -
uspace/lib/usb/src/host/usb_endpoint_manager.c
rdc4c19e ra49e171 31 31 #include <errno.h> 32 32 33 #include <usb/debug.h>34 33 #include <usb/host/usb_endpoint_manager.h> 35 34 … … 81 80 endpoint_destroy(node->ep); 82 81 free(node); 83 }84 /*----------------------------------------------------------------------------*/85 static void node_toggle_reset_filtered(link_t *item, void *arg)86 {87 assert(item);88 node_t *node = hash_table_get_instance(item, node_t, link);89 usb_target_t *target = arg;90 endpoint_toggle_reset_filtered(node->ep, *target);91 82 } 92 83 /*----------------------------------------------------------------------------*/ … … 239 230 return node->ep; 240 231 } 241 /*----------------------------------------------------------------------------*/242 /** Check setup packet data for signs of toggle reset.243 *244 * @param[in] instance Device keeper structure to use.245 * @param[in] target Device to receive setup packet.246 * @param[in] data Setup packet data.247 *248 * Really ugly one.249 */250 void usb_endpoint_manager_reset_if_need(251 usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)252 {253 assert(instance);254 if (target.endpoint > 15 || target.endpoint < 0255 || target.address >= USB11_ADDRESS_MAX || target.address < 0) {256 usb_log_error("Invalid data when checking for toggle reset.\n");257 return;258 }259 260 switch (data[1])261 {262 case 0x01: /*clear feature*/263 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */264 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {265 /* endpoint number is < 16, thus first byte is enough */266 usb_target_t reset_target =267 { .address = target.address, data[4] };268 fibril_mutex_lock(&instance->guard);269 hash_table_apply(&instance->ep_table,270 node_toggle_reset_filtered, &reset_target);271 fibril_mutex_unlock(&instance->guard);272 }273 break;274 275 case 0x9: /* set configuration */276 case 0x11: /* set interface */277 /* target must be device */278 if ((data[0] & 0xf) == 0) {279 usb_target_t reset_target =280 { .address = target.address, 0 };281 fibril_mutex_lock(&instance->guard);282 hash_table_apply(&instance->ep_table,283 node_toggle_reset_filtered, &reset_target);284 fibril_mutex_unlock(&instance->guard);285 }286 break;287 }288 } -
uspace/lib/usb/src/hub.c
rdc4c19e ra49e171 40 40 #include <errno.h> 41 41 #include <assert.h> 42 #include <usb/debug.h>43 44 /** How much time to wait between attempts to register endpoint 0:0.45 * The value is based on typical value for port reset + some overhead.46 */47 #define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))48 42 49 43 /** Check that HC connection is alright. … … 59 53 } while (false) 60 54 55 56 /** Tell host controller to reserve default address. 57 * 58 * @param connection Opened connection to host controller. 59 * @param speed Speed of the device that will respond on the default address. 60 * @return Error code. 61 */ 62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection, 63 usb_speed_t speed) 64 { 65 CHECK_CONNECTION(connection); 66 67 return async_req_2_0(connection->hc_phone, 68 DEV_IFACE_ID(USBHC_DEV_IFACE), 69 IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed); 70 } 71 72 /** Tell host controller to release default address. 73 * 74 * @param connection Opened connection to host controller. 75 * @return Error code. 76 */ 77 int usb_hc_release_default_address(usb_hc_connection_t *connection) 78 { 79 CHECK_CONNECTION(connection); 80 81 return async_req_1_0(connection->hc_phone, 82 DEV_IFACE_ID(USBHC_DEV_IFACE), 83 IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS); 84 } 85 61 86 /** Ask host controller for free address assignment. 62 87 * … … 153 178 * error codes than those listed as return codes by this function itself). 154 179 * 155 * The @p connection representing connection with host controller does not156 * need to be started.157 * This function duplicates the connection to allow simultaneous calls of158 * this function (i.e. from different fibrils).159 *160 180 * @param[in] parent Parent device (i.e. the hub device). 161 * @param[in] connection Connection to host controller.181 * @param[in] connection Opened connection to host controller. 162 182 * @param[in] dev_speed New device speed. 163 183 * @param[in] enable_port Function for enabling signaling through the port the … … 186 206 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 187 207 { 188 assert(connection != NULL); 189 // FIXME: this is awful, we are accessing directly the structure. 190 usb_hc_connection_t hc_conn = { 191 .hc_handle = connection->hc_handle, 192 .hc_phone = -1 193 }; 208 CHECK_CONNECTION(connection); 209 210 /* 211 * Request new address. 212 */ 213 usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed); 214 if (dev_addr < 0) { 215 return EADDRNOTAVAIL; 216 } 194 217 195 218 int rc; 196 219 197 rc = usb_hc_connection_open(&hc_conn);198 if (rc != EOK) {199 return rc;200 }201 202 203 /*204 * Request new address.205 */ 206 usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);207 if (dev_addr < 0) {208 usb_hc_connection_close(&hc_conn);209 return EADDRNOTAVAIL;210 }211 212 /*213 * We will not register control pipe on default address. 214 * The registration might fail. That means that someone else already215 * registered that endpoint. We will simply wait and try again.216 * (Someone else already wants to add a new device.)220 /* 221 * Reserve the default address. 222 */ 223 rc = usb_hc_reserve_default_address(connection, dev_speed); 224 if (rc != EOK) { 225 rc = EBUSY; 226 goto leave_release_free_address; 227 } 228 229 /* 230 * Enable the port (i.e. allow signaling through this port). 231 */ 232 rc = enable_port(port_no, arg); 233 if (rc != EOK) { 234 goto leave_release_default_address; 235 } 236 237 /* 238 * Change the address from default to the free one. 239 * We need to create a new control pipe for that. 217 240 */ 218 241 usb_device_connection_t dev_conn; 219 242 rc = usb_device_connection_initialize_on_default_address(&dev_conn, 220 &hc_conn);243 connection); 221 244 if (rc != EOK) { 222 245 rc = ENOTCONN; 223 goto leave_release_ free_address;246 goto leave_release_default_address; 224 247 } 225 248 … … 229 252 if (rc != EOK) { 230 253 rc = ENOTCONN; 231 goto leave_release_free_address; 232 } 233 234 do { 235 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0, 236 &hc_conn); 237 if (rc != EOK) { 238 /* Do not overheat the CPU ;-). */ 239 async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC); 240 } 241 } while (rc != EOK); 242 243 /* 244 * Endpoint is registered. We can enable the port and change 245 * device address. 246 */ 247 rc = enable_port(port_no, arg); 248 if (rc != EOK) { 249 goto leave_release_default_address; 250 } 251 254 goto leave_release_default_address; 255 } 256 257 /* Before sending any traffic, we need to register this 258 * endpoint. 259 */ 260 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 261 if (rc != EOK) { 262 rc = EREFUSED; 263 goto leave_release_default_address; 264 } 252 265 rc = usb_pipe_probe_default_control(&ctrl_pipe); 253 266 if (rc != EOK) { 267 rc = ENOTCONN; 268 goto leave_release_default_address; 269 } 270 271 rc = usb_pipe_start_session(&ctrl_pipe); 272 if (rc != EOK) { 273 rc = ENOTCONN; 274 goto leave_unregister_endpoint; 275 } 276 277 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 278 if (rc != EOK) { 254 279 rc = ESTALL; 255 goto leave_release_default_address; 256 } 257 258 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 259 if (rc != EOK) { 260 rc = ESTALL; 261 goto leave_release_default_address; 262 } 263 264 /* 265 * Address changed. We can release the original endpoint, thus 266 * allowing other to access the default address. 267 */ 268 unregister_control_endpoint_on_default_address(&hc_conn); 269 270 /* 271 * Time to register the new endpoint. 272 */ 273 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 274 if (rc != EOK) { 275 goto leave_release_free_address; 276 } 280 goto leave_stop_session; 281 } 282 283 usb_pipe_end_session(&ctrl_pipe); 284 285 /* 286 * Register the control endpoint for the new device. 287 */ 288 rc = usb_pipe_register(&ctrl_pipe, 0, connection); 289 if (rc != EOK) { 290 rc = EREFUSED; 291 goto leave_unregister_endpoint; 292 } 293 294 /* 295 * Release the original endpoint. 296 */ 297 unregister_control_endpoint_on_default_address(connection); 298 299 /* 300 * Once the address is changed, we can return the default address. 301 */ 302 usb_hc_release_default_address(connection); 303 277 304 278 305 /* … … 289 316 } 290 317 318 319 291 320 /* 292 321 * And now inform the host controller about the handle. … … 296 325 .handle = child_handle 297 326 }; 298 rc = usb_hc_register_device( &hc_conn, &new_device);327 rc = usb_hc_register_device(connection, &new_device); 299 328 if (rc != EOK) { 300 329 rc = EDESTADDRREQ; … … 320 349 * Completely ignoring errors here. 321 350 */ 351 352 leave_stop_session: 353 usb_pipe_end_session(&ctrl_pipe); 354 355 leave_unregister_endpoint: 356 usb_pipe_unregister(&ctrl_pipe, connection); 357 322 358 leave_release_default_address: 323 usb_ pipe_unregister(&ctrl_pipe, &hc_conn);359 usb_hc_release_default_address(connection); 324 360 325 361 leave_release_free_address: 326 usb_hc_unregister_device(&hc_conn, dev_addr); 327 328 usb_hc_connection_close(&hc_conn); 362 usb_hc_unregister_device(connection, dev_addr); 329 363 330 364 return rc; -
uspace/lib/usb/src/pipes.c
rdc4c19e ra49e171 41 41 #include <errno.h> 42 42 #include <assert.h> 43 #include "pipepriv.h"44 43 45 44 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */ … … 242 241 * necessary. 243 242 * 244 * @deprecated245 * Obsoleted with introduction of usb_pipe_start_long_transfer246 *247 243 * @param pipe Endpoint pipe to start the session on. 248 244 * @return Error code. … … 250 246 int usb_pipe_start_session(usb_pipe_t *pipe) 251 247 { 252 usb_log_warning("usb_pipe_start_session() was deprecated.\n"); 248 assert(pipe); 249 250 if (usb_pipe_is_session_started(pipe)) { 251 return EBUSY; 252 } 253 254 int phone = devman_device_connect(pipe->wire->hc_handle, 0); 255 if (phone < 0) { 256 return phone; 257 } 258 259 pipe->hc_phone = phone; 260 253 261 return EOK; 254 262 } … … 257 265 /** Ends a session on the endpoint pipe. 258 266 * 259 * @deprecated260 * Obsoleted with introduction of usb_pipe_end_long_transfer261 *262 267 * @see usb_pipe_start_session 263 268 * … … 267 272 int usb_pipe_end_session(usb_pipe_t *pipe) 268 273 { 269 usb_log_warning("usb_pipe_end_session() was deprecated.\n"); 274 assert(pipe); 275 276 if (!usb_pipe_is_session_started(pipe)) { 277 return ENOENT; 278 } 279 280 int rc = async_hangup(pipe->hc_phone); 281 if (rc != EOK) { 282 return rc; 283 } 284 285 pipe->hc_phone = -1; 286 270 287 return EOK; 271 288 } … … 281 298 bool usb_pipe_is_session_started(usb_pipe_t *pipe) 282 299 { 283 pipe_acquire(pipe); 284 bool started = pipe->refcount > 0; 285 pipe_release(pipe); 286 return started; 287 } 288 289 /** Prepare pipe for a long transfer. 290 * 291 * By a long transfer is mean transfer consisting of several 292 * requests to the HC. 293 * Calling such function is optional and it has positive effect of 294 * improved performance because IPC session is initiated only once. 295 * 296 * @param pipe Pipe over which the transfer will happen. 297 * @return Error code. 298 */ 299 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 300 { 301 return pipe_add_ref(pipe); 302 } 303 304 /** Terminate a long transfer on a pipe. 305 * 306 * @see usb_pipe_start_long_transfer 307 * 308 * @param pipe Pipe where to end the long transfer. 309 */ 310 void usb_pipe_end_long_transfer(usb_pipe_t *pipe) 311 { 312 pipe_drop_ref(pipe); 300 return (pipe->hc_phone >= 0); 313 301 } 314 302 -
uspace/lib/usb/src/pipesinit.c
rdc4c19e ra49e171 356 356 assert(connection); 357 357 358 fibril_mutex_initialize(&pipe->guard);359 358 pipe->wire = connection; 360 359 pipe->hc_phone = -1; 361 fibril_mutex_initialize(&pipe->hc_phone_mutex);362 360 pipe->endpoint_no = endpoint_no; 363 361 pipe->transfer_type = transfer_type; 364 362 pipe->max_packet_size = max_packet_size; 365 363 pipe->direction = direction; 366 pipe->refcount = 0;367 364 368 365 return EOK; … … 416 413 int rc; 417 414 418 rc = usb_pipe_start_long_transfer(pipe); 415 TRY_LOOP(failed_attempts) { 416 rc = usb_pipe_start_session(pipe); 417 if (rc == EOK) { 418 break; 419 } 420 } 419 421 if (rc != EOK) { 420 422 return rc; … … 437 439 } 438 440 } 439 usb_pipe_end_ long_transfer(pipe);441 usb_pipe_end_session(pipe); 440 442 if (rc != EOK) { 441 443 return rc; … … 459 461 usb_hc_connection_t *hc_connection) 460 462 { 461 return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,462 interval, hc_connection);463 }464 465 /** Register endpoint with a speed at the host controller.466 *467 * You will rarely need to use this function because it is needed only468 * if the registered endpoint is of address 0 and there is no other way469 * to tell speed of the device at address 0.470 *471 * @param pipe Pipe to be registered.472 * @param speed Speed of the device473 * (invalid speed means use previously specified one).474 * @param interval Polling interval.475 * @param hc_connection Connection to the host controller (must be opened).476 * @return Error code.477 */478 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,479 unsigned int interval,480 usb_hc_connection_t *hc_connection)481 {482 463 assert(pipe); 483 464 assert(hc_connection); … … 487 468 } 488 469 489 #define _PACK2(high, low) (((high) << 16) + (low)) 490 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low)) 491 492 return async_req_4_0(hc_connection->hc_phone, 470 #define _PACK(high, low) ((high) * 256 + (low)) 471 472 return async_req_5_0(hc_connection->hc_phone, 493 473 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT, 494 _PACK2(pipe->wire->address, pipe->endpoint_no), 495 _PACK3(speed, pipe->transfer_type, pipe->direction), 496 _PACK2(pipe->max_packet_size, interval)); 497 498 #undef _PACK2 499 #undef _PACK3 474 _PACK(pipe->wire->address, pipe->endpoint_no), 475 _PACK(pipe->transfer_type, pipe->direction), 476 pipe->max_packet_size, interval); 477 478 #undef _PACK 500 479 } 501 480 -
uspace/lib/usb/src/pipesio.c
rdc4c19e ra49e171 49 49 #include <assert.h> 50 50 #include <usbhc_iface.h> 51 #include "pipepriv.h"52 51 53 52 /** Request an in transfer, no checking of input parameters. … … 79 78 } 80 79 81 /* Ensure serialization over the phone. */82 pipe_start_transaction(pipe);83 84 80 /* 85 81 * Make call identifying target USB device and type of transfer. 86 82 */ 87 aid_t opening_request = async_send_ 3(pipe->hc_phone,83 aid_t opening_request = async_send_4(pipe->hc_phone, 88 84 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 89 85 pipe->wire->address, pipe->endpoint_no, 86 pipe->max_packet_size, 90 87 NULL); 91 88 if (opening_request == 0) { 92 pipe_end_transaction(pipe);93 89 return ENOMEM; 94 90 } … … 100 96 aid_t data_request = async_data_read(pipe->hc_phone, buffer, size, 101 97 &data_request_call); 102 103 /*104 * Since now on, someone else might access the backing phone105 * without breaking the transfer IPC protocol.106 */107 pipe_end_transaction(pipe);108 98 109 99 if (data_request == 0) { … … 156 146 157 147 if (buffer == NULL) { 158 return EINVAL;148 return EINVAL; 159 149 } 160 150 … … 163 153 } 164 154 155 if (!usb_pipe_is_session_started(pipe)) { 156 return EBADF; 157 } 158 165 159 if (pipe->direction != USB_DIRECTION_IN) { 166 160 return EBADF; … … 171 165 } 172 166 167 size_t act_size = 0; 173 168 int rc; 174 rc = pipe_add_ref(pipe);175 if (rc != EOK) {176 return rc;177 }178 179 180 size_t act_size = 0;181 169 182 170 rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size); 183 184 pipe_drop_ref(pipe);185 186 171 if (rc != EOK) { 187 172 return rc; … … 225 210 } 226 211 227 /* Ensure serialization over the phone. */228 pipe_start_transaction(pipe);229 230 212 /* 231 213 * Make call identifying target USB device and type of transfer. 232 214 */ 233 aid_t opening_request = async_send_ 3(pipe->hc_phone,215 aid_t opening_request = async_send_4(pipe->hc_phone, 234 216 DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method, 235 217 pipe->wire->address, pipe->endpoint_no, 218 pipe->max_packet_size, 236 219 NULL); 237 220 if (opening_request == 0) { 238 pipe_end_transaction(pipe);239 221 return ENOMEM; 240 222 } … … 244 226 */ 245 227 int rc = async_data_write_start(pipe->hc_phone, buffer, size); 246 247 /*248 * Since now on, someone else might access the backing phone249 * without breaking the transfer IPC protocol.250 */251 pipe_end_transaction(pipe);252 253 228 if (rc != EOK) { 254 229 async_wait_for(opening_request, NULL); … … 285 260 } 286 261 262 if (!usb_pipe_is_session_started(pipe)) { 263 return EBADF; 264 } 265 287 266 if (pipe->direction != USB_DIRECTION_OUT) { 288 267 return EBADF; … … 293 272 } 294 273 295 int rc; 296 297 rc = pipe_add_ref(pipe); 298 if (rc != EOK) { 299 return rc; 300 } 301 302 rc = usb_pipe_write_no_check(pipe, buffer, size); 303 304 pipe_drop_ref(pipe); 274 int rc = usb_pipe_write_no_check(pipe, buffer, size); 305 275 306 276 return rc; … … 323 293 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size) 324 294 { 325 /* Ensure serialization over the phone. */326 pipe_start_transaction(pipe);327 328 295 /* 329 296 * Make call identifying target USB device and control transfer type. 330 297 */ 331 aid_t opening_request = async_send_ 3(pipe->hc_phone,298 aid_t opening_request = async_send_4(pipe->hc_phone, 332 299 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ, 333 300 pipe->wire->address, pipe->endpoint_no, 301 pipe->max_packet_size, 334 302 NULL); 335 303 if (opening_request == 0) { … … 343 311 setup_buffer, setup_buffer_size); 344 312 if (rc != EOK) { 345 pipe_end_transaction(pipe);346 313 async_wait_for(opening_request, NULL); 347 314 return rc; … … 355 322 data_buffer, data_buffer_size, 356 323 &data_request_call); 357 358 /*359 * Since now on, someone else might access the backing phone360 * without breaking the transfer IPC protocol.361 */362 pipe_end_transaction(pipe);363 364 365 324 if (data_request == 0) { 366 325 async_wait_for(opening_request, NULL); … … 420 379 } 421 380 381 if (!usb_pipe_is_session_started(pipe)) { 382 return EBADF; 383 } 384 422 385 if ((pipe->direction != USB_DIRECTION_BOTH) 423 386 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 425 388 } 426 389 427 int rc;428 429 rc = pipe_add_ref(pipe);430 if (rc != EOK) {431 return rc;432 }433 434 390 size_t act_size = 0; 435 rc = usb_pipe_control_read_no_check(pipe,391 int rc = usb_pipe_control_read_no_check(pipe, 436 392 setup_buffer, setup_buffer_size, 437 393 data_buffer, data_buffer_size, &act_size); 438 439 pipe_drop_ref(pipe);440 394 441 395 if (rc != EOK) { … … 464 418 void *data_buffer, size_t data_buffer_size) 465 419 { 466 /* Ensure serialization over the phone. */467 pipe_start_transaction(pipe);468 469 420 /* 470 421 * Make call identifying target USB device and control transfer type. 471 422 */ 472 aid_t opening_request = async_send_ 4(pipe->hc_phone,423 aid_t opening_request = async_send_5(pipe->hc_phone, 473 424 DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE, 474 425 pipe->wire->address, pipe->endpoint_no, 475 426 data_buffer_size, 427 pipe->max_packet_size, 476 428 NULL); 477 429 if (opening_request == 0) { 478 pipe_end_transaction(pipe);479 430 return ENOMEM; 480 431 } … … 486 437 setup_buffer, setup_buffer_size); 487 438 if (rc != EOK) { 488 pipe_end_transaction(pipe);489 439 async_wait_for(opening_request, NULL); 490 440 return rc; … … 497 447 rc = async_data_write_start(pipe->hc_phone, 498 448 data_buffer, data_buffer_size); 499 500 /* All data sent, pipe can be released. */501 pipe_end_transaction(pipe);502 503 449 if (rc != EOK) { 504 450 async_wait_for(opening_request, NULL); 505 451 return rc; 506 452 } 507 } else {508 /* No data to send, we can release the pipe for others. */509 pipe_end_transaction(pipe);510 453 } 511 454 … … 548 491 } 549 492 493 if (!usb_pipe_is_session_started(pipe)) { 494 return EBADF; 495 } 496 550 497 if ((pipe->direction != USB_DIRECTION_BOTH) 551 498 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { … … 553 500 } 554 501 555 int rc; 556 557 rc = pipe_add_ref(pipe); 558 if (rc != EOK) { 559 return rc; 560 } 561 562 rc = usb_pipe_control_write_no_check(pipe, 502 int rc = usb_pipe_control_write_no_check(pipe, 563 503 setup_buffer, setup_buffer_size, data_buffer, data_buffer_size); 564 565 pipe_drop_ref(pipe);566 504 567 505 return rc; -
uspace/lib/usb/src/recognise.c
rdc4c19e ra49e171 404 404 child->driver_data = dev_data; 405 405 406 rc = usb_pipe_start_session(&ctrl_pipe); 407 if (rc != EOK) { 408 goto failure; 409 } 410 406 411 rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids); 412 if (rc != EOK) { 413 goto failure; 414 } 415 416 rc = usb_pipe_end_session(&ctrl_pipe); 407 417 if (rc != EOK) { 408 418 goto failure;
Note:
See TracChangeset
for help on using the changeset viewer.
