Changeset dc4c19e in mainline
- Timestamp:
- 2011-04-10T12:18:09Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 60c0573
- Parents:
- a49e171 (diff), 82e8861 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace
- Files:
-
- 6 added
- 54 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/usbinfo/dev.c
ra49e171 rdc4c19e 50 50 51 51 int rc; 52 bool transfer_started = false; 52 53 53 54 rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr); … … 76 77 } 77 78 78 rc = usb_pipe_start_ session(&dev->ctrl_pipe);79 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 79 80 if (rc != EOK) { 80 81 fprintf(stderr, 81 NAME ": failed to start sessionon control pipe: %s.\n",82 NAME ": failed to start transfer on control pipe: %s.\n", 82 83 str_error(rc)); 83 84 goto leave; 84 85 } 86 transfer_started = true; 85 87 86 88 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, … … 107 109 108 110 leave: 109 if ( usb_pipe_is_session_started(&dev->ctrl_pipe)) {110 usb_pipe_end_ session(&dev->ctrl_pipe);111 if (transfer_started) { 112 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 111 113 } 112 114 … … 118 120 void destroy_device(usbinfo_device_t *dev) 119 121 { 120 usb_pipe_end_ session(&dev->ctrl_pipe);122 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 121 123 free(dev); 122 124 } -
uspace/doc/doxygroups.h
ra49e171 rdc4c19e 269 269 270 270 /** 271 * @defgroup drvusbohci OHCI driver 272 * @ingroup usb 273 * @brief Driver for OHCI host controller. 274 */ 275 276 /** 271 277 * @defgroup drvusbehci EHCI driver 272 278 * @ingroup usb … … 275 281 276 282 /** 277 * @defgroup drvusbfallback USB fallback driver .283 * @defgroup drvusbfallback USB fallback driver 278 284 * @ingroup usb 279 285 * @brief Fallback driver for any USB device. -
uspace/drv/ehci-hcd/hc_iface.c
ra49e171 rdc4c19e 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). 125 126 * @param[in] endpoint Endpoint number. 126 127 * @param[in] transfer_type USB transfer type. … … 131 132 */ 132 133 static int register_endpoint(ddf_fun_t *fun, 133 usb_address_t address, usb_ endpoint_t endpoint,134 usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint, 134 135 usb_transfer_type_t transfer_type, usb_direction_t direction, 135 136 size_t max_packet_size, unsigned int interval) … … 165 166 * @param[in] fun Device function the action was invoked on. 166 167 * @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 size_t max_packet_size,void *data, size_t size,176 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.194 193 * @param[in] data Buffer where to store the data (in USB endianess, 195 194 * allocated and deallocated by the caller). … … 200 199 */ 201 200 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 202 size_t max_packet_size,void *data, size_t size,201 void *data, size_t size, 203 202 usbhc_iface_transfer_in_callback_t callback, void *arg) 204 203 { … … 217 216 * @param[in] fun Device function the action was invoked on. 218 217 * @param[in] target Target pipe (address and endpoint number) specification. 219 * @param[in] max_packet_size Max packet size for the transfer.220 218 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 221 219 * by the caller). … … 226 224 */ 227 225 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 228 size_t max_packet_size,void *data, size_t size,226 void *data, size_t size, 229 227 usbhc_iface_transfer_out_callback_t callback, void *arg) 230 228 { … … 243 241 * @param[in] fun Device function the action was invoked on. 244 242 * @param[in] target Target pipe (address and endpoint number) specification. 245 * @param[in] max_packet_size Max packet size for the transfer.246 243 * @param[in] data Buffer where to store the data (in USB endianess, 247 244 * allocated and deallocated by the caller). … … 252 249 */ 253 250 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 254 size_t max_packet_size,void *data, size_t size,251 void *data, size_t size, 255 252 usbhc_iface_transfer_in_callback_t callback, void *arg) 256 253 { … … 269 266 * @param[in] fun Device function the action was invoked on. 270 267 * @param[in] target Target pipe (address and endpoint number) specification. 271 * @param[in] max_packet_size Max packet size for the transfer.272 268 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 273 269 * and deallocated by the caller). … … 281 277 */ 282 278 static int control_write(ddf_fun_t *fun, usb_target_t target, 283 size_t max_packet_size,284 279 void *setup_packet, size_t setup_packet_size, 285 280 void *data_buffer, size_t data_buffer_size, … … 300 295 * @param[in] fun Device function the action was invoked on. 301 296 * @param[in] target Target pipe (address and endpoint number) specification. 302 * @param[in] max_packet_size Max packet size for the transfer.303 297 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 304 298 * and deallocated by the caller). … … 312 306 */ 313 307 static int control_read(ddf_fun_t *fun, usb_target_t target, 314 size_t max_packet_size,315 308 void *setup_packet, size_t setup_packet_size, 316 309 void *data_buffer, size_t data_buffer_size, -
uspace/drv/ohci/Makefile
ra49e171 rdc4c19e 33 33 34 34 SOURCES = \ 35 batch.c \ 36 hc.c \ 35 37 iface.c \ 36 batch.c \37 38 main.c \ 38 hc.c \39 39 ohci.c \ 40 pci.c \ 40 41 root_hub.c \ 41 pci.c 42 transfer_list.c \ 43 hw_struct/endpoint_descriptor.c \ 44 hw_struct/transfer_descriptor.c 45 42 46 43 47 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/ohci/batch.c
ra49e171 rdc4c19e 40 40 #include "batch.h" 41 41 #include "utils/malloc32.h" 42 42 #include "hw_struct/endpoint_descriptor.h" 43 #include "hw_struct/transfer_descriptor.h" 44 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); 43 53 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance); 44 54 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance); 45 55 46 56 #define DEFAULT_ERROR_COUNT 3 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, 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, 57 59 usbhc_iface_transfer_in_callback_t func_in, 58 usbhc_iface_transfer_out_callback_t func_out, 59 void *arg, 60 usb_device_keeper_t *manager 61 ) 60 usbhc_iface_transfer_out_callback_t func_out, void *arg) 62 61 { 63 62 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \ … … 73 72 CHECK_NULL_DISPOSE_RETURN(instance, 74 73 "Failed to allocate batch instance.\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); 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"); 78 100 79 101 if (buffer_size > 0) { … … 90 112 } 91 113 92 93 114 return instance; 94 115 } … … 97 118 { 98 119 assert(instance); 120 ohci_batch_t *data = instance->private_data; 121 assert(data); 122 free32(data->ed); 123 free32(data->tds); 124 free32(instance->setup_buffer); 99 125 free32(instance->transport_buffer); 100 free 32(instance->setup_buffer);126 free(data); 101 127 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; 102 153 } 103 154 /*----------------------------------------------------------------------------*/ … … 109 160 instance->buffer_size); 110 161 instance->next_step = batch_call_out_and_dispose; 111 /* TODO: implement */162 batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN); 112 163 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 113 164 } … … 117 168 assert(instance); 118 169 instance->next_step = batch_call_in_and_dispose; 119 /* TODO: implement */170 batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT); 120 171 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 121 172 } … … 124 175 { 125 176 assert(instance); 126 instance->direction = USB_DIRECTION_IN;177 assert(instance->direction == USB_DIRECTION_IN); 127 178 instance->next_step = batch_call_in_and_dispose; 128 179 /* TODO: implement */ … … 133 184 { 134 185 assert(instance); 135 instance->direction = USB_DIRECTION_OUT;186 assert(instance->direction == USB_DIRECTION_OUT); 136 187 /* We are data out, we are supposed to provide data */ 137 188 memcpy(instance->transport_buffer, instance->buffer, … … 160 211 } 161 212 /*----------------------------------------------------------------------------*/ 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 /*----------------------------------------------------------------------------*/ 162 270 /** Helper function calls callback and correctly disposes of batch structure. 163 271 * -
uspace/drv/ohci/batch.h
ra49e171 rdc4c19e 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup drvusb ohci28 /** @addtogroup drvusbuhcihc 29 29 * @{ 30 30 */ 31 31 /** @file 32 * @brief OHCI driver USB transaction structure32 * @brief UHCI driver USB transaction structure 33 33 */ 34 #ifndef DRV_OHCI_BATCH_H 35 #define DRV_OHCI_BATCH_H 36 34 #ifndef DRV_UHCI_BATCH_H 35 #define DRV_UHCI_BATCH_H 37 36 38 37 #include <usbhc_iface.h> 39 38 #include <usb/usb.h> 40 39 #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 43 45 usb_transfer_batch_t * batch_get( 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, 46 ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size, 47 char *setup_buffer, size_t setup_size, 53 48 usbhc_iface_transfer_in_callback_t func_in, 54 49 usbhc_iface_transfer_out_callback_t func_out, 55 void *arg, 56 usb_device_keeper_t *manager 57 ); 50 void *arg); 58 51 59 52 void batch_dispose(usb_transfer_batch_t *instance); 53 54 bool batch_is_complete(usb_transfer_batch_t *instance); 60 55 61 56 void batch_control_write(usb_transfer_batch_t *instance); … … 70 65 71 66 void batch_bulk_out(usb_transfer_batch_t *instance); 67 68 ed_t * batch_ed(usb_transfer_batch_t *instance); 72 69 #endif 73 70 /** -
uspace/drv/ohci/hc.c
ra49e171 rdc4c19e 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); 49 51 /*----------------------------------------------------------------------------*/ 50 52 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun) … … 59 61 &instance->manager, hub_address, hub_fun->handle); 60 62 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 61 71 char *match_str = NULL; 62 intret = asprintf(&match_str, "usb&class=hub");63 ret = (match_str == NULL) ? ret : EOK;72 ret = asprintf(&match_str, "usb&class=hub"); 73 // ret = (match_str == NULL) ? ret : EOK; 64 74 if (ret < 0) { 65 usb_log_error("Failed to create root hub match-id string.\n"); 75 usb_log_error( 76 "Failed(%d) to create root hub match-id string.\n", ret); 66 77 return ret; 67 78 } … … 97 108 ret, str_error(ret)); 98 109 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 99 118 if (!interrupts) { 100 119 instance->interrupt_emulator = … … 103 122 } 104 123 105 hc_gain_control(instance);106 107 rh_init(&instance->rh, dev, instance->registers);108 109 hc_init_hw(instance);110 111 /* TODO: implement */112 124 return EOK; 113 125 } … … 117 129 assert(instance); 118 130 assert(batch); 131 132 /* check for root hub communication */ 119 133 if (batch->target.address == instance->rh.address) { 120 134 return rh_request(&instance->rh, batch); 121 135 } 122 /* TODO: implement */ 123 return ENOTSUP; 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; 124 157 } 125 158 /*----------------------------------------------------------------------------*/ … … 127 160 { 128 161 assert(instance); 129 if ( status == 0)162 if ((status & ~IS_SF) == 0) /* ignore sof status */ 130 163 return; 131 164 if (status & IS_RHSC) … … 134 167 usb_log_info("OHCI interrupt: %x.\n", status); 135 168 136 /* TODO: Check for further interrupt causes */ 137 /* TODO: implement */ 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 } 138 183 } 139 184 /*----------------------------------------------------------------------------*/ … … 154 199 { 155 200 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 156 208 /* Interrupt routing enabled => smm driver is active */ 157 209 if (instance->registers->control & C_IR) { 158 usb_log_ info("Found SMM driver requestingownership change.\n");210 usb_log_debug("SMM driver: request ownership change.\n"); 159 211 instance->registers->command_status |= CS_OCR; 160 212 while (instance->registers->control & C_IR) { 161 213 async_usleep(1000); 162 214 } 163 usb_log_info(" Ownership taken from SMM driver.\n");215 usb_log_info("SMM driver: Ownership taken.\n"); 164 216 return; 165 217 } … … 169 221 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 170 222 if (hc_status != C_HCFS_RESET) { 171 usb_log_ info("Found BIOS driver.\n");223 usb_log_debug("BIOS driver found.\n"); 172 224 if (hc_status == C_HCFS_OPERATIONAL) { 173 usb_log_info(" HC operational(BIOS).\n");225 usb_log_info("BIOS driver: HC operational.\n"); 174 226 return; 175 227 } … … 177 229 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT); 178 230 async_usleep(20000); 231 usb_log_info("BIOS driver: HC resumed.\n"); 179 232 return; 180 233 } … … 182 235 /* HC is in reset (hw startup) => no other driver 183 236 * maintain reset for at least the time specified in USB spec (50 ms)*/ 237 usb_log_info("HC found in reset.\n"); 184 238 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 193 239 } 194 240 /*----------------------------------------------------------------------------*/ 195 241 void hc_init_hw(hc_t *instance) 196 242 { 197 assert(instance); 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 */ 198 248 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; 199 254 instance->registers->command_status = CS_HCR; 200 async_usleep(10); 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 */ 201 262 instance->registers->fm_interval = fm_interval; 202 263 assert((instance->registers->command_status & CS_HCR) == 0); 264 203 265 /* hc is now in suspend state */ 204 /* TODO: init HCCA block */ 205 /* TODO: init queues */ 206 /* TODO: enable queues */ 207 /* TODO: enable interrupts */ 208 /* TODO: set periodic start to 90% */ 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); 209 288 210 289 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT); 211 usb_log_info("OHCI HC up and running.\n"); 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; 212 370 } 213 371 /** -
uspace/drv/ohci/hc.h
ra49e171 rdc4c19e 48 48 #include "ohci_regs.h" 49 49 #include "root_hub.h" 50 #include "transfer_list.h" 50 51 #include "hw_struct/hcca.h" 51 52 … … 54 55 usb_address_t rh_address; 55 56 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 56 67 ddf_fun_t *ddf_instance; 57 68 usb_device_keeper_t manager; -
uspace/drv/ohci/hw_struct/completion_codes.h
ra49e171 rdc4c19e 35 35 #define DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H 36 36 37 #include <errno.h> 38 37 39 #define CC_NOERROR (0x0) 38 40 #define CC_CRC (0x1) … … 50 52 #define CC_NOACCESS2 (0xf) 51 53 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 52 88 #endif 53 89 /** -
uspace/drv/ohci/hw_struct/endpoint_descriptor.h
ra49e171 rdc4c19e 35 35 #define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H 36 36 37 #include <assert.h> 37 38 #include <stdint.h> 39 40 #include <usb/host/endpoint.h> 41 42 #include "utils/malloc32.h" 43 #include "transfer_descriptor.h" 38 44 39 45 #include "completion_codes.h" … … 44 50 #define ED_STATUS_FA_SHIFT (0) 45 51 #define ED_STATUS_EN_MASK (0xf) /* USB endpoint address */ 46 #define ED_STATUS_EN_SHIFT ( 6)52 #define ED_STATUS_EN_SHIFT (7) 47 53 #define ED_STATUS_D_MASK (0x3) /* direction */ 48 #define ED_STATUS_D_SHIFT (1 0)54 #define ED_STATUS_D_SHIFT (11) 49 55 #define ED_STATUS_D_IN (0x1) 50 56 #define ED_STATUS_D_OUT (0x2) 57 #define ED_STATUS_D_TRANSFER (0x3) 51 58 52 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag */59 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */ 53 60 #define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */ 54 61 #define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/ … … 71 78 #define ED_NEXT_PTR_SHIFT (0) 72 79 } __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 73 99 #endif 74 100 /** -
uspace/drv/ohci/hw_struct/transfer_descriptor.h
ra49e171 rdc4c19e 35 35 #define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H 36 36 37 #include <bool.h> 37 38 #include <stdint.h> 39 #include "utils/malloc32.h" 38 40 39 41 #include "completion_codes.h" 42 43 /* OHCI TDs can handle up to 8KB buffers */ 44 #define OHCI_TD_MAX_TRANSFER (8 * 1024) 40 45 41 46 typedef struct td { … … 52 57 #define TD_STATUS_T_MASK (0x3) /* data toggle 1x = use ED toggle carry */ 53 58 #define TD_STATUS_T_SHIFT (24) 59 #define TD_STATUS_T_0 (0x2) 60 #define TD_STATUS_T_1 (0x3) 54 61 #define TD_STATUS_EC_MASK (0x3) /* error count */ 55 62 #define TD_STATUS_EC_SHIFT (26) … … 64 71 volatile uint32_t be; /* buffer end, address of the last byte */ 65 72 } __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 } 66 104 #endif 67 105 /** -
uspace/drv/ohci/iface.c
ra49e171 rdc4c19e 1 1 /* 2 * Copyright (c) 2011 Vojtech Horky 2 * Copyright (c) 2011 Vojtech Horky, Jan Vesely 3 3 * All rights reserved. 4 4 * … … 30 30 */ 31 31 /** @file 32 * USB-HC interface implementation.32 * @brief OHCI driver 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> 38 39 39 40 #include "iface.h" 40 41 #include "hc.h" 41 42 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 { 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); 57 52 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); 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; 62 81 return EOK; 63 82 } 64 83 /*----------------------------------------------------------------------------*/ 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. 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. 85 89 * @return Error code. 86 90 */ … … 101 105 } 102 106 /*----------------------------------------------------------------------------*/ 103 /** Bind USB address with device devman handle.104 * 105 * @param[in] fun D evice function the action was invoked on.106 * @param[in] address USB address of the device.107 * @param[in] handle Devman handle of the device .107 /** Bind address interface function 108 * 109 * @param[in] fun DDF function that was called. 110 * @param[in] address Address of the device 111 * @param[in] handle Devman handle of the device driver. 108 112 * @return Error code. 109 113 */ 110 114 static int bind_address( 111 115 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle) 112 116 { 113 117 assert(fun); … … 119 123 } 120 124 /*----------------------------------------------------------------------------*/ 121 /** Release previously requested address.122 * 123 * @param[in] fun D evice function the action was invoked on.125 /** Release address interface function 126 * 127 * @param[in] fun DDF function that was called. 124 128 * @param[in] address USB address to be released. 125 129 * @return Error code. … … 139 143 * @param[in] fun Device function the action was invoked on. 140 144 * @param[in] address USB address of the device. 145 * @param[in] ep_speed Endpoint speed (invalid means to use device one). 141 146 * @param[in] endpoint Endpoint number. 142 147 * @param[in] transfer_type USB transfer type. … … 146 151 * @return Error code. 147 152 */ 148 static int register_endpoint( 149 ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,153 static int register_endpoint(ddf_fun_t *fun, 154 usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint, 150 155 usb_transfer_type_t transfer_type, usb_direction_t direction, 151 156 size_t max_packet_size, unsigned int interval) 152 157 { 153 assert(fun);154 158 hc_t *hc = fun_to_hc(fun); 155 159 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); 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 } 160 165 const size_t size = max_packet_size; 166 int ret; 167 161 168 usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n", 162 169 address, endpoint, usb_str_transfer_type(transfer_type), 163 170 usb_str_speed(speed), direction, size, max_packet_size, interval); 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 */ 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 /*----------------------------------------------------------------------------*/ 176 189 static int unregister_endpoint( 177 190 ddf_fun_t *fun, usb_address_t address, 178 191 usb_endpoint_t endpoint, usb_direction_t direction) 179 192 { 180 assert(fun);181 193 hc_t *hc = fun_to_hc(fun); 182 194 assert(hc); … … 196 208 * @param[in] fun Device function the action was invoked on. 197 209 * @param[in] target Target pipe (address and endpoint number) specification. 198 * @param[in] max_packet_size Max packet size for the transfer.199 210 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 200 211 * by the caller). … … 205 216 */ 206 217 static int interrupt_out( 207 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,218 ddf_fun_t *fun, usb_target_t target, void *data, 208 219 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 209 220 { 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; 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; 224 227 batch_interrupt_out(batch); 225 const intret = hc_schedule(hc, batch);228 ret = hc_schedule(hc, batch); 226 229 if (ret != EOK) { 227 230 batch_dispose(batch); … … 239 242 * @param[in] fun Device function the action was invoked on. 240 243 * @param[in] target Target pipe (address and endpoint number) specification. 241 * @param[in] max_packet_size Max packet size for the transfer.242 244 * @param[in] data Buffer where to store the data (in USB endianess, 243 245 * allocated and deallocated by the caller). … … 248 250 */ 249 251 static int interrupt_in( 250 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,252 ddf_fun_t *fun, usb_target_t target, void *data, 251 253 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 252 254 { 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; 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; 266 261 batch_interrupt_in(batch); 267 const intret = hc_schedule(hc, batch);262 ret = hc_schedule(hc, batch); 268 263 if (ret != EOK) { 269 264 batch_dispose(batch); … … 281 276 * @param[in] fun Device function the action was invoked on. 282 277 * @param[in] target Target pipe (address and endpoint number) specification. 283 * @param[in] max_packet_size Max packet size for the transfer.284 278 * @param[in] data Data to be sent (in USB endianess, allocated and deallocated 285 279 * by the caller). … … 290 284 */ 291 285 static int bulk_out( 292 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,286 ddf_fun_t *fun, usb_target_t target, void *data, 293 287 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 294 288 { 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; 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; 309 295 batch_bulk_out(batch); 310 const intret = hc_schedule(hc, batch);296 ret = hc_schedule(hc, batch); 311 297 if (ret != EOK) { 312 298 batch_dispose(batch); … … 324 310 * @param[in] fun Device function the action was invoked on. 325 311 * @param[in] target Target pipe (address and endpoint number) specification. 326 * @param[in] max_packet_size Max packet size for the transfer.327 312 * @param[in] data Buffer where to store the data (in USB endianess, 328 313 * allocated and deallocated by the caller). … … 333 318 */ 334 319 static int bulk_in( 335 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,320 ddf_fun_t *fun, usb_target_t target, void *data, 336 321 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 337 322 { 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; 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; 351 329 batch_bulk_in(batch); 352 const intret = hc_schedule(hc, batch);330 ret = hc_schedule(hc, batch); 353 331 if (ret != EOK) { 354 332 batch_dispose(batch); … … 366 344 * @param[in] fun Device function the action was invoked on. 367 345 * @param[in] target Target pipe (address and endpoint number) specification. 368 * @param[in] max_packet_size Max packet size for the transfer.369 346 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 370 347 * and deallocated by the caller). … … 378 355 */ 379 356 static int control_write( 380 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,357 ddf_fun_t *fun, usb_target_t target, 381 358 void *setup_data, size_t setup_size, void *data, size_t size, 382 359 usbhc_iface_transfer_out_callback_t callback, void *arg) 383 360 { 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); 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); 402 369 batch_control_write(batch); 403 const intret = hc_schedule(hc, batch);370 ret = hc_schedule(hc, batch); 404 371 if (ret != EOK) { 405 372 batch_dispose(batch); … … 417 384 * @param[in] fun Device function the action was invoked on. 418 385 * @param[in] target Target pipe (address and endpoint number) specification. 419 * @param[in] max_packet_size Max packet size for the transfer.420 386 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 421 387 * and deallocated by the caller). … … 429 395 */ 430 396 static int control_read( 431 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,397 ddf_fun_t *fun, usb_target_t target, 432 398 void *setup_data, size_t setup_size, void *data, size_t size, 433 399 usbhc_iface_transfer_in_callback_t callback, void *arg) 434 400 { 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; 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; 449 408 batch_control_read(batch); 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. */ 409 ret = hc_schedule(hc, batch); 410 if (ret != EOK) { 411 batch_dispose(batch); 412 } 413 return ret; 414 } 415 /*----------------------------------------------------------------------------*/ 458 416 usbhc_iface_t hc_iface = { 459 .reserve_default_address = reserve_default_address,460 .release_default_address = release_default_address,461 417 .request_address = request_address, 462 418 .bind_address = bind_address, … … 475 431 .control_read = control_read, 476 432 }; 477 478 433 /** 479 434 * @} -
uspace/drv/ohci/ohci_regs.h
ra49e171 rdc4c19e 41 41 const volatile uint32_t revision; 42 42 volatile uint32_t control; 43 #define C_CSBR_MASK (0x3) 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) 44 48 #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 50 #define C_HCFS_MASK (0x3) 51 #define C_HCFS_ SHIFT (6)52 #define C_HCFS_RESET (0x0)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 */ 54 55 #define C_HCFS_MASK (0x3) /* Host controller functional state */ 56 #define C_HCFS_RESET (0x0) 53 57 #define C_HCFS_OPERATIONAL (0x1) 54 #define C_HCFS_RESUME (0x2) 55 #define C_HCFS_SUSPEND (0x3) 56 57 #define C_IR (1 << 8) 58 #define C_RWC (1 << 9) 59 #define C_RWE (1 << 10) 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 */ 60 65 61 66 volatile uint32_t command_status; 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) 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 */ 67 72 #define CS_SOC_SHIFT (16) 68 73 69 74 volatile uint32_t interrupt_status; 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) 78 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 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 */ 83 84 /** Interupt enable/disable, reads give the same value, writing causes 85 * enable/disable */ 86 volatile uint32_t interrupt_enable; 90 87 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) */ 91 99 volatile uint32_t hcca; 92 volatile uint32_t period_corrent; 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 */ 93 106 volatile uint32_t control_head; 107 108 /** Currently executed control endpoint */ 94 109 volatile uint32_t control_current; 110 111 /** The first bulk endpoint */ 95 112 volatile uint32_t bulk_head; 113 114 /** Currently executed bulk endpoint */ 96 115 volatile uint32_t bulk_current; 97 volatile uint32_t done_head; 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 */ 98 121 volatile uint32_t fm_interval; 99 volatile uint32_t fm_remaining; 100 volatile uint32_t fm_number; 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 */ 101 139 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 */ 102 143 volatile uint32_t ls_threshold; 144 #define LST_LST_MASK (0x7fff) 145 146 /** The first root hub control register */ 103 147 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 */ 104 159 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 */ 105 171 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 ports 175 * 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 HC 180 * 1-connect status change wakes HC 181 * write: 1-set DRWE, 0-no effect */ 182 #define RHS_SET_DRWE RHS_DRWE_FLAG 183 #define RHS_LPSC_FLAG (1 << 16)/* read: 0, 184 * write: 0-no effect 185 * 1-turn on port power for ports 186 * 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 */ 106 193 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_FLAG 197 #define RHPS_PES_FLAG (1 << 1) /* r: port enable status 198 * w: 1-set port enable, 0-nothing */ 199 #define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG 200 #define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status 201 * w: 1-set port suspend, 0-nothing */ 202 #define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG 203 #define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port 204 * w: 1-clear port suspend (start resume 205 * if suspened) 206 * 0-nothing */ 207 #define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG 208 #define RHPS_PRS_FLAG (1 << 4) /* r: port reset status 209 * w: 1-set port reset, 0-nothing */ 210 #define RHPS_SET_PORT_RESET RHPS_PRS_FLAG 211 #define RHPS_PPS_FLAG (1 << 8) /* r: port power status 212 * w: 1-set port power, 0-nothing */ 213 #define RHPS_SET_PORT_POWER RHPS_PPS_FLAG 214 #define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached 215 * w: 1-clear port power, 0-nothing */ 216 #define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG 217 #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 0x1f0000 107 223 } __attribute__((packed)) ohci_regs_t; 108 224 #endif -
uspace/drv/ohci/root_hub.c
ra49e171 rdc4c19e 47 47 * standart device descriptor for ohci root hub 48 48 */ 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, 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, 65 64 }; 66 65 … … 69 68 * for ohci root hubs 70 69 */ 71 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = 72 { 70 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = { 73 71 /// \TODO some values are default or guessed 74 .attributes = 1 <<7,72 .attributes = 1 << 7, 75 73 .configuration_number = 1, 76 74 .descriptor_type = USB_DESCTYPE_CONFIGURATION, 77 75 .interface_count = 1, 78 .length = sizeof (usb_standard_configuration_descriptor_t),76 .length = sizeof (usb_standard_configuration_descriptor_t), 79 77 .max_power = 100, 80 78 .str_configuration = 0, … … 84 82 * standart ohci root hub interface descriptor 85 83 */ 86 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = 87 { 84 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = { 88 85 .alternate_setting = 0, 89 86 .descriptor_type = USB_DESCTYPE_INTERFACE, … … 94 91 .interface_protocol = 0, 95 92 .interface_subclass = 0, 96 .length = sizeof (usb_standard_interface_descriptor_t),93 .length = sizeof (usb_standard_interface_descriptor_t), 97 94 .str_interface = 0, 98 95 }; … … 101 98 * standart ohci root hub endpoint descriptor 102 99 */ 103 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = 104 { 100 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = { 105 101 .attributes = USB_TRANSFER_INTERRUPT, 106 102 .descriptor_type = USB_DESCTYPE_ENDPOINT, 107 .endpoint_address = 1 + (1 <<7),108 .length = sizeof (usb_standard_endpoint_descriptor_t),103 .endpoint_address = 1 + (1 << 7), 104 .length = sizeof (usb_standard_endpoint_descriptor_t), 109 105 .max_packet_size = 8, 110 106 .poll_interval = 255, … … 112 108 113 109 static const uint32_t hub_clear_feature_valid_mask = 114 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) +115 110 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER) | 111 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 116 112 117 113 static const uint32_t hub_clear_feature_by_writing_one_mask = … … 119 115 120 116 static const uint32_t hub_set_feature_valid_mask = 121 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 122 123 117 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) | 118 (1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER); 119 120 124 121 static const uint32_t hub_set_feature_direct_mask = 125 122 (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT); 126 123 127 124 static const uint32_t port_set_feature_valid_mask = 128 (1 << USB_HUB_FEATURE_PORT_ENABLE) +129 (1 << USB_HUB_FEATURE_PORT_SUSPEND) + 130 (1 << USB_HUB_FEATURE_PORT_RESET) + 131 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); 132 129 133 130 static const uint32_t port_clear_feature_valid_mask = 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 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 /*----------------------------------------------------------------------------*/ 147 266 148 267 /** … … 157 276 */ 158 277 static void usb_create_serialized_hub_descriptor(rh_t *instance, 159 160 278 uint8_t ** out_result, 279 size_t * out_size) { 161 280 //base size 162 281 size_t size = 7; 163 282 //variable size according to port count 164 283 size_t var_size = instance->port_count / 8 + 165 284 ((instance->port_count % 8 > 0) ? 1 : 0); 166 285 size += 2 * var_size; 167 286 uint8_t * result = (uint8_t*) malloc(size); 168 bzero(result, size);287 bzero(result, size); 169 288 //size 170 289 result[0] = size; … … 174 293 uint32_t hub_desc_reg = instance->registers->rh_desc_a; 175 294 result[3] = 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);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); 181 300 result[4] = 0; 182 301 result[5] = /*descriptor->pwr_on_2_good_time*/ 50; … … 185 304 int port; 186 305 for (port = 1; port <= instance->port_count; ++port) { 187 result[7 + port/8] += 188 ((instance->registers->rh_desc_b >> port)%2) << (port%8); 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); 189 310 } 190 311 size_t i; … … 195 316 (*out_size) = size; 196 317 } 197 318 /*----------------------------------------------------------------------------*/ 198 319 199 320 /** initialize hub descriptors … … 203 324 * @instance root hub instance 204 325 */ 205 static void rh_init_descriptors(rh_t *instance) {326 static void rh_init_descriptors(rh_t *instance) { 206 327 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 207 sizeof (ohci_rh_device_descriptor)208 );328 sizeof (ohci_rh_device_descriptor) 329 ); 209 330 usb_standard_configuration_descriptor_t descriptor; 210 memcpy(&descriptor, &ohci_rh_conf_descriptor,211 sizeof(ohci_rh_conf_descriptor));331 memcpy(&descriptor, &ohci_rh_conf_descriptor, 332 sizeof (ohci_rh_conf_descriptor)); 212 333 uint8_t * hub_descriptor; 213 334 size_t hub_desc_size; 214 335 usb_create_serialized_hub_descriptor(instance, &hub_descriptor, 215 336 &hub_desc_size); 216 337 217 338 descriptor.total_length = 218 sizeof(usb_standard_configuration_descriptor_t)+219 sizeof(usb_standard_endpoint_descriptor_t)+220 sizeof(usb_standard_interface_descriptor_t)+221 222 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 223 344 uint8_t * full_config_descriptor = 224 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 235 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 236 357 instance->descriptors.configuration = full_config_descriptor; 237 358 instance->descriptors.configuration_size = descriptor.total_length; 238 359 } 239 240 /** Root hub initialization241 * @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 mode252 253 254 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);255 256 //start generic usb hub driver257 258 /* TODO: implement */259 return EOK;260 }261 360 /*----------------------------------------------------------------------------*/ 262 361 … … 272 371 */ 273 372 static int process_get_port_status_request(rh_t *instance, uint16_t port, 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;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; 278 377 request->transfered_size = 4; 279 uint32_buffer[0] = instance->registers->rh_port_status[port -1]; 280 return EOK; 281 } 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 /*----------------------------------------------------------------------------*/ 282 390 283 391 /** … … 291 399 */ 292 400 static int process_get_hub_status_request(rh_t *instance, 293 usb_transfer_batch_t * request){ 294 uint32_t * uint32_buffer = (uint32_t*)request->transport_buffer; 401 usb_transfer_batch_t * request) { 402 uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer; 403 request->transfered_size = 4; 295 404 //bits, 0,1,16,17 296 request->transfered_size = 4; 297 uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17); 405 uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17); 298 406 uint32_buffer[0] = mask & instance->registers->rh_status; 299 407 return EOK; 300 301 } 302 303 408 } 409 /*----------------------------------------------------------------------------*/ 304 410 305 411 /** … … 313 419 */ 314 420 static int process_get_status_request(rh_t *instance, 315 usb_transfer_batch_t * request) 316 { 421 usb_transfer_batch_t * request) { 317 422 size_t buffer_size = request->buffer_size; 318 423 usb_device_request_setup_packet_t * request_packet = 319 320 424 (usb_device_request_setup_packet_t*) 425 request->setup_buffer; 321 426 322 427 usb_hub_bm_request_type_t request_type = request_packet->request_type; 323 if (buffer_size<4/*request_packet->length*/){///\TODO428 if (buffer_size < 4/*request_packet->length*/) {///\TODO 324 429 usb_log_warning("requested more data than buffer size\n"); 325 430 return EINVAL; 326 431 } 327 432 328 if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)433 if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) 329 434 return process_get_hub_status_request(instance, 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); 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); 333 439 return ENOTSUP; 334 440 } 441 /*----------------------------------------------------------------------------*/ 335 442 336 443 /** … … 339 446 * Result contains bitmap where bit 0 indicates change on hub and 340 447 * bit i indicates change on i`th port (i>0). For more info see 341 * Hub and Port status bitmap specification in USB specification. 448 * Hub and Port status bitmap specification in USB specification 449 * (chapter 11.13.4) 342 450 * @param instance root hub instance 343 451 * @param@out buffer pointer to created interrupt mas … … 345 453 */ 346 454 static void create_interrupt_mask(rh_t *instance, void ** buffer, 347 size_t * buffer_size){455 size_t * buffer_size) { 348 456 int bit_count = instance->port_count + 1; 349 (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1; 457 (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1); 458 350 459 (*buffer) = malloc(*buffer_size); 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){ 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) { 355 465 bitmap[0] = 1; 356 466 } 357 467 int port; 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 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 369 477 /** 370 478 * create answer to a descriptor request … … 377 485 */ 378 486 static int process_get_descriptor_request(rh_t *instance, 379 usb_transfer_batch_t *request){487 usb_transfer_batch_t *request) { 380 488 usb_device_request_setup_packet_t * setup_request = 381 (usb_device_request_setup_packet_t*)request->setup_buffer;489 (usb_device_request_setup_packet_t*) request->setup_buffer; 382 490 size_t size; 383 491 const void * result_descriptor = NULL; 384 492 const uint16_t setup_request_value = setup_request->value_high; 385 493 //(setup_request->value_low << 8); 386 494 bool del = false; 387 switch (setup_request_value) 388 {389 case USB_DESCTYPE_HUB:{495 switch (setup_request_value) { 496 case USB_DESCTYPE_HUB: 497 { 390 498 uint8_t * descriptor; 391 499 usb_create_serialized_hub_descriptor( 392 500 instance, &descriptor, &size); 393 501 result_descriptor = descriptor; 394 if (result_descriptor) del = true;502 if (result_descriptor) del = true; 395 503 break; 396 504 } 397 case USB_DESCTYPE_DEVICE: { 505 case USB_DESCTYPE_DEVICE: 506 { 398 507 usb_log_debug("USB_DESCTYPE_DEVICE\n"); 399 508 result_descriptor = &ohci_rh_device_descriptor; 400 size = sizeof (ohci_rh_device_descriptor);509 size = sizeof (ohci_rh_device_descriptor); 401 510 break; 402 511 } 403 case USB_DESCTYPE_CONFIGURATION: { 512 case USB_DESCTYPE_CONFIGURATION: 513 { 404 514 usb_log_debug("USB_DESCTYPE_CONFIGURATION\n"); 405 515 result_descriptor = instance->descriptors.configuration; … … 407 517 break; 408 518 } 409 case USB_DESCTYPE_INTERFACE: { 519 case USB_DESCTYPE_INTERFACE: 520 { 410 521 usb_log_debug("USB_DESCTYPE_INTERFACE\n"); 411 522 result_descriptor = &ohci_rh_iface_descriptor; 412 size = sizeof (ohci_rh_iface_descriptor);523 size = sizeof (ohci_rh_iface_descriptor); 413 524 break; 414 525 } 415 case USB_DESCTYPE_ENDPOINT: { 526 case USB_DESCTYPE_ENDPOINT: 527 { 416 528 usb_log_debug("USB_DESCTYPE_ENDPOINT\n"); 417 529 result_descriptor = &ohci_rh_ep_descriptor; 418 size = sizeof (ohci_rh_ep_descriptor);530 size = sizeof (ohci_rh_ep_descriptor); 419 531 break; 420 532 } 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 ); 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 ); 430 545 return EINVAL; 431 546 } 432 547 } 433 if (request->buffer_size < size){548 if (request->buffer_size < size) { 434 549 size = request->buffer_size; 435 550 } 436 551 request->transfered_size = 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)); 552 memcpy(request->transport_buffer, result_descriptor, size); 440 553 if (del) 441 554 free(result_descriptor); 442 555 return EOK; 443 556 } 557 /*----------------------------------------------------------------------------*/ 444 558 445 559 /** … … 451 565 * @return error code 452 566 */ 453 static int process_get_configuration_request(rh_t *instance, 454 usb_transfer_batch_t *request){567 static int process_get_configuration_request(rh_t *instance, 568 usb_transfer_batch_t *request) { 455 569 //set and get configuration requests do not have any meaning, only dummy 456 570 //values are returned 457 if (request->buffer_size != 1)571 if (request->buffer_size != 1) 458 572 return EINVAL; 459 573 request->transport_buffer[0] = 1; … … 461 575 return EOK; 462 576 } 577 /*----------------------------------------------------------------------------*/ 463 578 464 579 /** 465 580 * process feature-enabling request on hub 466 * 581 * 467 582 * @param instance root hub instance 468 583 * @param feature feature selector … … 470 585 */ 471 586 static int process_hub_feature_set_request(rh_t *instance, 472 uint16_t feature){ 473 if(! ((1<<feature) & hub_set_feature_valid_mask)) 474 return EINVAL; 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; 475 592 instance->registers->rh_status = 476 (instance->registers->rh_status | (1<<feature)) 477 & (~ hub_clear_feature_by_writing_one_mask); 478 return EOK; 479 } 593 (instance->registers->rh_status | (1 << feature)) 594 & (~hub_clear_feature_by_writing_one_mask); 595 return EOK; 596 } 597 /*----------------------------------------------------------------------------*/ 480 598 481 599 /** … … 487 605 */ 488 606 static int process_hub_feature_clear_request(rh_t *instance, 489 uint16_t feature){490 if (! ((1<<feature) & hub_clear_feature_valid_mask))607 uint16_t feature) { 608 if (!((1 << feature) & hub_clear_feature_valid_mask)) 491 609 return EINVAL; 492 610 //is the feature cleared directly? 493 if ((1 <<feature) & hub_set_feature_direct_mask){611 if ((1 << feature) & hub_set_feature_direct_mask) { 494 612 instance->registers->rh_status = 495 (instance->registers->rh_status & (~(1 <<feature)))496 & (~ 497 } else{//the feature is cleared by writing '1'613 (instance->registers->rh_status & (~(1 << feature))) 614 & (~hub_clear_feature_by_writing_one_mask); 615 } else {//the feature is cleared by writing '1' 498 616 instance->registers->rh_status = 499 (instance->registers->rh_status 500 & (~ hub_clear_feature_by_writing_one_mask)) 501 | (1<<feature); 502 } 503 return EOK; 504 } 505 506 617 (instance->registers->rh_status 618 & (~hub_clear_feature_by_writing_one_mask)) 619 | (1 << feature); 620 } 621 return EOK; 622 } 623 /*----------------------------------------------------------------------------*/ 507 624 508 625 /** 509 626 * process feature-enabling request on hub 510 * 627 * 511 628 * @param instance root hub instance 512 629 * @param feature feature selector … … 516 633 */ 517 634 static int process_port_feature_set_request(rh_t *instance, 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)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) 522 639 return EINVAL; 523 640 instance->registers->rh_port_status[port - 1] = 524 (instance->registers->rh_port_status[port - 1] | (1<<feature))525 641 (instance->registers->rh_port_status[port - 1] | (1 << feature)) 642 & (~port_clear_feature_valid_mask); 526 643 /// \TODO any error? 527 644 return EOK; 528 645 } 646 /*----------------------------------------------------------------------------*/ 529 647 530 648 /** … … 538 656 */ 539 657 static int process_port_feature_clear_request(rh_t *instance, 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)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) 546 664 feature = USB_HUB_FEATURE_PORT_LOW_SPEED; 547 if (feature == USB_HUB_FEATURE_PORT_SUSPEND)665 if (feature == USB_HUB_FEATURE_PORT_SUSPEND) 548 666 feature = USB_HUB_FEATURE_PORT_OVER_CURRENT; 549 667 instance->registers->rh_port_status[port - 1] = 550 (instance->registers->rh_port_status[port - 1]551 552 | (1<<feature);668 (instance->registers->rh_port_status[port - 1] 669 & (~port_clear_feature_valid_mask)) 670 | (1 << feature); 553 671 /// \TODO any error? 554 672 return EOK; 555 673 } 556 674 /*----------------------------------------------------------------------------*/ 557 675 558 676 /** 559 677 * register address to this device 560 * 678 * 561 679 * @param instance root hub instance 562 680 * @param address new address … … 564 682 */ 565 683 static int process_address_set_request(rh_t *instance, 566 uint16_t address){684 uint16_t address) { 567 685 instance->address = address; 568 686 return EOK; 569 687 } 688 /*----------------------------------------------------------------------------*/ 570 689 571 690 /** … … 579 698 */ 580 699 static int process_request_with_output(rh_t *instance, 581 usb_transfer_batch_t *request){700 usb_transfer_batch_t *request) { 582 701 usb_device_request_setup_packet_t * setup_request = 583 (usb_device_request_setup_packet_t*)request->setup_buffer;584 if (setup_request->request == USB_DEVREQ_GET_STATUS){702 (usb_device_request_setup_packet_t*) request->setup_buffer; 703 if (setup_request->request == USB_DEVREQ_GET_STATUS) { 585 704 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 586 705 return process_get_status_request(instance, request); 587 706 } 588 if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){707 if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) { 589 708 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 590 709 return process_get_descriptor_request(instance, request); 591 710 } 592 if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION){711 if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) { 593 712 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 594 713 return process_get_configuration_request(instance, request); … … 596 715 return ENOTSUP; 597 716 } 717 /*----------------------------------------------------------------------------*/ 598 718 599 719 /** … … 607 727 */ 608 728 static int process_request_with_input(rh_t *instance, 609 usb_transfer_batch_t *request){729 usb_transfer_batch_t *request) { 610 730 usb_device_request_setup_packet_t * setup_request = 611 (usb_device_request_setup_packet_t*)request->setup_buffer;731 (usb_device_request_setup_packet_t*) request->setup_buffer; 612 732 request->transfered_size = 0; 613 if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){733 if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) { 614 734 return ENOTSUP; 615 735 } 616 if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION){736 if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) { 617 737 //set and get configuration requests do not have any meaning, 618 738 //only dummy values are returned … … 621 741 return ENOTSUP; 622 742 } 743 /*----------------------------------------------------------------------------*/ 623 744 624 745 /** … … 632 753 */ 633 754 static int process_request_without_data(rh_t *instance, 634 usb_transfer_batch_t *request){755 usb_transfer_batch_t *request) { 635 756 usb_device_request_setup_packet_t * setup_request = 636 (usb_device_request_setup_packet_t*)request->setup_buffer;757 (usb_device_request_setup_packet_t*) request->setup_buffer; 637 758 request->transfered_size = 0; 638 if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE){639 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){759 if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) { 760 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) { 640 761 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 641 762 return process_hub_feature_clear_request(instance, 642 643 } 644 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){763 setup_request->value); 764 } 765 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) { 645 766 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 646 767 return process_port_feature_clear_request(instance, 647 648 768 setup_request->value, 769 setup_request->index); 649 770 } 650 771 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n", 651 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){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) { 656 777 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 657 778 return process_hub_feature_set_request(instance, 658 659 } 660 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){779 setup_request->value); 780 } 781 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) { 661 782 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 662 783 return process_port_feature_set_request(instance, 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){ 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) { 670 792 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 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); 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); 674 798 return ENOTSUP; 675 799 } 800 /*----------------------------------------------------------------------------*/ 676 801 677 802 /** … … 693 818 * @return error code 694 819 */ 695 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request){ 820 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) { 821 if (!request->setup_buffer) { 822 usb_log_error("root hub received empty transaction?"); 823 return EINVAL; 824 } 696 825 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 705 (usb_device_request_setup_packet_t*)request->setup_buffer;706 if(707 setup_request->request == USB_DEVREQ_GET_STATUS708 || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR709 || setup_request->request == USB_DEVREQ_GET_CONFIGURATION710 ){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: 711 840 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 ); 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 ); 729 864 opResult = ENOTSUP; 730 }731 }else{732 usb_log_error("root hub received empty transaction?");733 opResult = EINVAL;734 865 } 735 866 return opResult; … … 737 868 738 869 /** 739 * process root hub request740 *741 * @param instance root hub instance742 * @param request structure containing both request and response information743 * @return error code744 */745 int rh_request(rh_t *instance, usb_transfer_batch_t *request)746 {747 assert(instance);748 assert(request);749 int opResult;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 }774 /**775 870 * @} 776 871 */ -
uspace/drv/ohci/utils/malloc32.h
ra49e171 rdc4c19e 37 37 #include <assert.h> 38 38 #include <malloc.h> 39 #include <errno.h> 39 40 #include <mem.h> 40 41 #include <as.h> -
uspace/drv/uhci-hcd/batch.c
ra49e171 rdc4c19e 80 80 * transaction and callback. 81 81 */ 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, 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, 86 84 usbhc_iface_transfer_in_callback_t func_in, 87 usbhc_iface_transfer_out_callback_t func_out, void *arg , endpoint_t *ep88 ) 89 { 85 usbhc_iface_transfer_out_callback_t func_out, void *arg) 86 { 87 assert(ep); 90 88 assert(func_in == NULL || func_out == NULL); 91 89 assert(func_in != NULL || func_out != NULL); … … 103 101 CHECK_NULL_DISPOSE_RETURN(instance, 104 102 "Failed to allocate batch instance.\n"); 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); 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); 109 108 110 109 111 110 uhci_batch_t *data = malloc(sizeof(uhci_batch_t)); 112 CHECK_NULL_DISPOSE_RETURN(instance, 113 "Failed to allocate batch instance.\n"); 111 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 114 112 bzero(data, sizeof(uhci_batch_t)); 115 113 instance->private_data = data; 116 114 117 data->transfers = (buffer_size + max_packet_size - 1) / max_packet_size; 118 if (transfer_type == USB_TRANSFER_CONTROL) { 115 data->transfers = 116 (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size; 117 if (ep->transfer_type == USB_TRANSFER_CONTROL) { 119 118 data->transfers += 2; 120 119 } … … 178 177 instance, i, data->tds[i].status); 179 178 td_print_status(&data->tds[i]); 180 if (instance->ep != NULL) 181 endpoint_toggle_set(instance->ep, 182 td_toggle(&data->tds[i])); 179 assert(instance->ep != NULL); 180 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
ra49e171 rdc4c19e 44 44 45 45 usb_transfer_batch_t * batch_get( 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, 46 ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size, 47 char *setup_buffer, size_t setup_size, 55 48 usbhc_iface_transfer_in_callback_t func_in, 56 49 usbhc_iface_transfer_out_callback_t func_out, 57 void *arg, 58 endpoint_t *ep 59 ); 50 void *arg); 60 51 61 52 void batch_dispose(usb_transfer_batch_t *instance); -
uspace/drv/uhci-hcd/hc.c
ra49e171 rdc4c19e 240 240 usb_log_debug("Initialized device manager.\n"); 241 241 242 ret = 243 usb_endpoint_manager_init(&instance->ep_manager, 244 BANDWIDTH_AVAILABLE_USB11); 242 ret = usb_endpoint_manager_init(&instance->ep_manager, 243 BANDWIDTH_AVAILABLE_USB11); 245 244 assert(ret == EOK); 246 245 … … 332 331 instance->transfers[batch->speed][batch->transfer_type]; 333 332 assert(list); 334 if (batch->transfer_type == USB_TRANSFER_CONTROL) {335 usb_device_keeper_use_control(336 &instance->manager, batch->target);337 }338 333 transfer_list_add_batch(list, batch); 339 334 … … 373 368 usb_transfer_batch_t *batch = 374 369 list_get_instance(item, usb_transfer_batch_t, link); 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); 370 usb_transfer_batch_finish(batch); 398 371 } 399 372 } -
uspace/drv/uhci-hcd/iface.c
ra49e171 rdc4c19e 41 41 #include "hc.h" 42 42 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 { 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); 51 52 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) 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) 60 80 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 #endif76 }77 /*----------------------------------------------------------------------------*/78 /** Release default address interface function79 *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);92 81 return EOK; 93 82 } … … 151 140 /*----------------------------------------------------------------------------*/ 152 141 static int register_endpoint( 153 ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint, 142 ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed, 143 usb_endpoint_t endpoint, 154 144 usb_transfer_type_t transfer_type, usb_direction_t direction, 155 145 size_t max_packet_size, unsigned int interval) … … 157 147 hc_t *hc = fun_to_hc(fun); 158 148 assert(hc); 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; 149 const size_t size = max_packet_size; 165 150 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 } 155 usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n", 156 address, endpoint, usb_str_transfer_type(transfer_type), 157 usb_str_speed(speed), direction, size, max_packet_size, interval); 158 166 159 167 160 endpoint_t *ep = malloc(sizeof(endpoint_t)); … … 175 168 } 176 169 177 usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",178 address, endpoint, usb_str_transfer_type(transfer_type),179 usb_str_speed(speed), direction, size, max_packet_size, interval);180 181 170 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size); 182 171 if (ret != EOK) { 183 172 endpoint_destroy(ep); 184 } else {185 usb_device_keeper_add_ep(&hc->manager, address, ep);186 173 } 187 174 return ret; … … 204 191 * @param[in] fun DDF function that was called. 205 192 * @param[in] target USB device to write to. 206 * @param[in] max_packet_size maximum size of data packet the device accepts207 193 * @param[in] data Source of data. 208 194 * @param[in] size Size of data source. … … 212 198 */ 213 199 static int interrupt_out( 214 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,200 ddf_fun_t *fun, usb_target_t target, void *data, 215 201 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 216 202 { 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; 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; 251 209 batch_interrupt_out(batch); 252 const intret = hc_schedule(hc, batch);210 ret = hc_schedule(hc, batch); 253 211 if (ret != EOK) { 254 212 batch_dispose(batch); … … 261 219 * @param[in] fun DDF function that was called. 262 220 * @param[in] target USB device to write to. 263 * @param[in] max_packet_size maximum size of data packet the device accepts264 221 * @param[out] data Data destination. 265 222 * @param[in] size Size of data source. … … 269 226 */ 270 227 static int interrupt_in( 271 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,228 ddf_fun_t *fun, usb_target_t target, void *data, 272 229 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 273 230 { 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; 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; 309 237 batch_interrupt_in(batch); 310 const intret = hc_schedule(hc, batch);238 ret = hc_schedule(hc, batch); 311 239 if (ret != EOK) { 312 240 batch_dispose(batch); … … 319 247 * @param[in] fun DDF function that was called. 320 248 * @param[in] target USB device to write to. 321 * @param[in] max_packet_size maximum size of data packet the device accepts322 249 * @param[in] data Source of data. 323 250 * @param[in] size Size of data source. … … 327 254 */ 328 255 static int bulk_out( 329 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,256 ddf_fun_t *fun, usb_target_t target, void *data, 330 257 size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg) 331 258 { 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; 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; 356 265 batch_bulk_out(batch); 357 const intret = hc_schedule(hc, batch);266 ret = hc_schedule(hc, batch); 358 267 if (ret != EOK) { 359 268 batch_dispose(batch); … … 366 275 * @param[in] fun DDF function that was called. 367 276 * @param[in] target USB device to write to. 368 * @param[in] max_packet_size maximum size of data packet the device accepts369 277 * @param[out] data Data destination. 370 278 * @param[in] size Size of data source. … … 374 282 */ 375 283 static int bulk_in( 376 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,void *data,284 ddf_fun_t *fun, usb_target_t target, void *data, 377 285 size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg) 378 286 { 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; 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; 402 293 batch_bulk_in(batch); 403 const intret = hc_schedule(hc, batch);294 ret = hc_schedule(hc, batch); 404 295 if (ret != EOK) { 405 296 batch_dispose(batch); … … 412 303 * @param[in] fun DDF function that was called. 413 304 * @param[in] target USB device to write to. 414 * @param[in] max_packet_size maximum size of data packet the device accepts.415 305 * @param[in] setup_data Data to send with SETUP transfer. 416 306 * @param[in] setup_size Size of data to send with SETUP transfer (always 8B). … … 422 312 */ 423 313 static int control_write( 424 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,314 ddf_fun_t *fun, usb_target_t target, 425 315 void *setup_data, size_t setup_size, void *data, size_t size, 426 316 usbhc_iface_transfer_out_callback_t callback, void *arg) 427 317 { 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); 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); 451 326 batch_control_write(batch); 452 const intret = hc_schedule(hc, batch);327 ret = hc_schedule(hc, batch); 453 328 if (ret != EOK) { 454 329 batch_dispose(batch); … … 461 336 * @param[in] fun DDF function that was called. 462 337 * @param[in] target USB device to write to. 463 * @param[in] max_packet_size maximum size of data packet the device accepts.464 338 * @param[in] setup_data Data to send with SETUP packet. 465 339 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B). … … 471 345 */ 472 346 static int control_read( 473 ddf_fun_t *fun, usb_target_t target, size_t max_packet_size,347 ddf_fun_t *fun, usb_target_t target, 474 348 void *setup_data, size_t setup_size, void *data, size_t size, 475 349 usbhc_iface_transfer_in_callback_t callback, void *arg) 476 350 { 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; 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; 496 358 batch_control_read(batch); 497 const intret = hc_schedule(hc, batch);359 ret = hc_schedule(hc, batch); 498 360 if (ret != EOK) { 499 361 batch_dispose(batch); … … 503 365 /*----------------------------------------------------------------------------*/ 504 366 usbhc_iface_t hc_iface = { 505 .reserve_default_address = reserve_default_address,506 .release_default_address = release_default_address,507 367 .request_address = request_address, 508 368 .bind_address = bind_address, -
uspace/drv/uhci-hcd/transfer_list.c
ra49e171 rdc4c19e 132 132 } 133 133 /*----------------------------------------------------------------------------*/ 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. 134 /** Create list for finished batches. 135 * 136 * @param[in] instance List to use. 137 * @param[in] done list to fill 142 138 */ 143 139 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done) … … 161 157 } 162 158 fibril_mutex_unlock(&instance->guard); 163 164 159 } 165 160 /*----------------------------------------------------------------------------*/ … … 176 171 list_get_instance(current, usb_transfer_batch_t, link); 177 172 transfer_list_remove_batch(instance, batch); 178 usb_transfer_batch_finish (batch, EIO);173 usb_transfer_batch_finish_error(batch, EIO); 179 174 } 180 175 fibril_mutex_unlock(&instance->guard); -
uspace/drv/uhci-rhd/root_hub.h
ra49e171 rdc4c19e 40 40 41 41 #define UHCI_ROOT_HUB_PORT_COUNT 2 42 #define ROOT_HUB_WAIT_USEC 5000000 /* 5seconds */42 #define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */ 43 43 44 44 typedef struct root_hub { -
uspace/drv/usbhub/Makefile
ra49e171 rdc4c19e 34 34 SOURCES = \ 35 35 main.c \ 36 ports.c \37 36 utils.c \ 38 usbhub.c 37 usbhub.c \ 38 ports.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/usbhub/port_status.h
ra49e171 rdc4c19e 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 in 55 * "Universal Serial Bus Specification Revision 1.1" 56 * 57 */ 58 typedef uint32_t usb_hub_status_t; 59 60 /** 51 61 * set values in request to be it a port status request 52 62 * @param request … … 54 64 */ 55 65 static inline void usb_hub_set_port_status_request( 56 usb_device_request_setup_packet_t * request, uint16_t port57 ){66 usb_device_request_setup_packet_t * request, uint16_t port 67 ) { 58 68 request->index = port; 59 69 request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS; … … 63 73 } 64 74 75 /** 76 * set values in request to be it a port status request 77 * @param request 78 * @param port 79 */ 80 static inline void usb_hub_set_hub_status_request( 81 usb_device_request_setup_packet_t * request 82 ) { 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 } 65 89 66 90 /** … … 70 94 */ 71 95 static inline usb_device_request_setup_packet_t * 72 usb_hub_create_port_status_request(uint16_t port) {96 usb_hub_create_port_status_request(uint16_t port) { 73 97 usb_device_request_setup_packet_t * result = 74 usb_new(usb_device_request_setup_packet_t);75 usb_hub_set_port_status_request(result, port);98 malloc(sizeof(usb_device_request_setup_packet_t)); 99 usb_hub_set_port_status_request(result, port); 76 100 return result; 77 101 } 78 102 79 80 103 /** 81 104 * set the device request to be a port feature enable request … … 85 108 */ 86 109 static inline void usb_hub_set_enable_port_feature_request( 87 usb_device_request_setup_packet_t * request, uint16_t port,88 89 ){110 usb_device_request_setup_packet_t * request, uint16_t port, 111 uint16_t feature_selector 112 ) { 90 113 request->index = port; 91 114 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 102 125 */ 103 126 static inline void usb_hub_set_disable_port_feature_request( 104 usb_device_request_setup_packet_t * request, uint16_t port,105 106 ){127 usb_device_request_setup_packet_t * request, uint16_t port, 128 uint16_t feature_selector 129 ) { 107 130 request->index = port; 108 131 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 118 141 */ 119 142 static inline void usb_hub_set_enable_port_request( 120 usb_device_request_setup_packet_t * request, uint16_t port121 ){143 usb_device_request_setup_packet_t * request, uint16_t port 144 ) { 122 145 request->index = port; 123 146 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 133 156 */ 134 157 static inline usb_device_request_setup_packet_t * 135 usb_hub_create_enable_port_request(uint16_t port) {158 usb_hub_create_enable_port_request(uint16_t port) { 136 159 usb_device_request_setup_packet_t * result = 137 usb_new(usb_device_request_setup_packet_t);138 usb_hub_set_enable_port_request(result, port);160 malloc(sizeof(usb_device_request_setup_packet_t)); 161 usb_hub_set_enable_port_request(result, port); 139 162 return result; 140 163 } … … 146 169 */ 147 170 static inline void usb_hub_set_disable_port_request( 148 usb_device_request_setup_packet_t * request, uint16_t port149 ){171 usb_device_request_setup_packet_t * request, uint16_t port 172 ) { 150 173 request->index = port; 151 174 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 161 184 */ 162 185 static inline usb_device_request_setup_packet_t * 163 usb_hub_create_disable_port_request(uint16_t port) {186 usb_hub_create_disable_port_request(uint16_t port) { 164 187 usb_device_request_setup_packet_t * result = 165 usb_new(usb_device_request_setup_packet_t);166 usb_hub_set_disable_port_request(result, port);188 malloc(sizeof(usb_device_request_setup_packet_t)); 189 usb_hub_set_disable_port_request(result, port); 167 190 return result; 168 191 } … … 174 197 */ 175 198 static inline void usb_hub_set_reset_port_request( 176 usb_device_request_setup_packet_t * request, uint16_t port177 ){199 usb_device_request_setup_packet_t * request, uint16_t port 200 ) { 178 201 request->index = port; 179 202 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 189 212 */ 190 213 static inline usb_device_request_setup_packet_t * 191 usb_hub_create_reset_port_request(uint16_t port) {214 usb_hub_create_reset_port_request(uint16_t port) { 192 215 usb_device_request_setup_packet_t * result = 193 usb_new(usb_device_request_setup_packet_t);194 usb_hub_set_reset_port_request(result, port);216 malloc(sizeof(usb_device_request_setup_packet_t)); 217 usb_hub_set_reset_port_request(result, port); 195 218 return result; 196 219 } … … 202 225 */ 203 226 static inline void usb_hub_set_power_port_request( 204 usb_device_request_setup_packet_t * request, uint16_t port205 ){227 usb_device_request_setup_packet_t * request, uint16_t port 228 ) { 206 229 request->index = port; 207 230 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 217 240 */ 218 241 static inline void usb_hub_unset_power_port_request( 219 usb_device_request_setup_packet_t * request, uint16_t port220 ){242 usb_device_request_setup_packet_t * request, uint16_t port 243 ) { 221 244 request->index = port; 222 245 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 226 249 } 227 250 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); 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); 251 321 } 252 322 253 323 //port 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); 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); 260 343 } 261 344 262 345 //port 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); 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); 269 364 } 270 365 271 366 //over currect 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); 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); 278 385 } 279 386 280 387 //port reset 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); 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); 287 406 } 288 407 289 408 //powered 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 } 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 297 430 298 431 //low speed device attached 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)) 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)) 318 481 return USB_SPEED_LOW; 319 if (usb_port_high_speed(status))482 if (usb_port_high_speed(status)) 320 483 return USB_SPEED_HIGH; 321 484 return USB_SPEED_FULL; 322 485 } 323 486 324 487 #if 0 325 488 //connect 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); 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); 332 506 } 333 507 334 508 //port enable 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); 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); 341 527 } 342 528 343 529 //suspend 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); 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); 350 548 } 351 549 352 550 //over current 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); 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); 359 569 } 360 570 361 571 //reset change 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 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 370 680 371 681 -
uspace/drv/usbhub/ports.c
ra49e171 rdc4c19e 33 33 * Hub ports functions. 34 34 */ 35 #include "port_status.h" 36 #include < inttypes.h>35 36 #include <bool.h> 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <usb/request.h> 39 #include <inttypes.h> 40 #include <fibril_synch.h> 41 40 42 #include <usb/debug.h> 43 44 #include "ports.h" 45 #include "usbhub.h" 46 #include "usbhub_private.h" 47 #include "port_status.h" 48 49 50 /** Information for fibril for device discovery. */ 51 struct add_device_phase1 { 52 usb_hub_info_t *hub; 53 size_t port; 54 usb_speed_t speed; 55 }; 56 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 port 78 * 79 * Accepts connection, over current and port reset change. 80 * @param hub hub representation 81 * @param port port number, starting from 1 82 */ 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 change 87 //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 change 99 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 current 118 if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) { 119 //check if it was not auto-resolved 120 usb_log_debug("overcurrent change on port\n"); 121 usb_hub_port_over_current(hub, port, status); 122 } 123 //port reset 124 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 removed 148 * 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 device 151 * from it`s device tree. 152 * @param hub hub representation 153 * @param port port number, starting from 1 154 */ 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 in 164 * devide manager 165 */ 166 167 //close address 168 //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 removal 171 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 the 189 * 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 change 203 * 204 * After this change port should be enabled, unless some problem occured. 205 * This functions triggers second phase of enabling new device. 206 * @param hub 207 * @param port 208 * @param status 209 */ 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 representation 234 * @param port port number, starting from 1 235 */ 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 } 41 255 42 256 /** Retrieve port status. … … 73 287 } 74 288 75 /** Information for fibril for device discovery. */76 struct add_device_phase1 {77 usb_hub_info_t *hub;78 size_t port;79 usb_speed_t speed;80 };81 82 289 /** Callback for enabling a specific port. 83 290 * … … 91 298 static int enable_port_callback(int port_no, void *arg) 92 299 { 93 usb_hub_info_t *hub = (usb_hub_info_t *)arg;300 usb_hub_info_t *hub = arg; 94 301 int rc; 95 302 usb_device_request_setup_packet_t request; … … 122 329 } 123 330 124 return EOK; 331 if (my_port->reset_okay) { 332 return EOK; 333 } else { 334 return ESTALL; 335 } 125 336 } 126 337 … … 156 367 data->hub->ports[data->port].attached_device.address = new_address; 157 368 158 usb_log_info("Detected new device on `%s' (port %zu), " \369 usb_log_info("Detected new device on `%s' (port %zu), " 159 370 "address %d (handle %" PRIun ").\n", 160 371 data->hub->usb_device->ddf_dev->name, data->port, … … 166 377 return EOK; 167 378 } 379 168 380 169 381 /** Start device adding when connection change is detected. … … 176 388 * @return Error code. 177 389 */ 178 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port,390 static int create_add_device_fibril(usb_hub_info_t *hub, size_t port, 179 391 usb_speed_t speed) 180 392 { … … 213 425 } 214 426 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 329 427 /** 330 428 * @} -
uspace/drv/usbhub/ports.h
ra49e171 rdc4c19e 36 36 #define DRV_USBHUB_PORTS_H 37 37 38 #include <ipc/devman.h> 39 #include <usb/usb.h> 40 #include <ddf/driver.h> 41 #include <fibril_synch.h> 42 38 #include <usb/devdrv.h> 43 39 #include <usb/hub.h> 44 40 45 #include <usb/pipes.h> 46 #include <usb/devdrv.h> 41 typedef struct usb_hub_info_t usb_hub_info_t; 47 42 48 43 /** Information about single port on a hub. */ … … 56 51 */ 57 52 bool reset_completed; 53 /** Whether to announce the port reset as successful. */ 54 bool reset_okay; 58 55 59 56 /** Information about attached device. */ … … 72 69 } 73 70 74 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *); 71 72 void usb_hub_process_interrupt(usb_hub_info_t * hub, 73 uint16_t port); 74 75 75 76 76 -
uspace/drv/usbhub/usbhub.c
ra49e171 rdc4c19e 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h> 39 40 40 41 #include <usb_iface.h> … … 53 54 #include "usb/classes/classes.h" 54 55 55 static int usb_hub_trigger_connecting_non_removable_devices( 56 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 57 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 58 75 59 76 //********************************************* 60 77 // 61 78 // hub driver code, initialization 79 // 80 //********************************************* 81 82 /** 83 * Initialize hub device driver fibril 84 * 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 information 88 * @return error code 89 */ 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 connection 94 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 configuration 108 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_devs 116 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 functions 62 185 // 63 186 //********************************************* … … 71 194 */ 72 195 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) { 73 usb_hub_info_t * result = usb_new(usb_hub_info_t);74 if (!result) return NULL;196 usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t)); 197 if (!result) return NULL; 75 198 result->usb_device = usb_dev; 76 199 result->status_change_pipe = usb_dev->pipes[0].pipe; … … 90 213 * @return error code 91 214 */ 92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {215 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) { 93 216 // get hub descriptor 94 217 usb_log_debug("creating serialized descriptor\n"); 95 218 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE); 96 219 usb_hub_descriptor_t * descriptor; 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 */ 220 int opResult; 221 107 222 size_t received_size; 108 int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe,109 110 USB_DESCTYPE_HUB,111 0, 0, serialized_descriptor,112 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 113 114 if (opResult != EOK) {115 usb_log_error("failed when receiving hub descriptor,badcode = %d\n",116 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); 227 228 if (opResult != EOK) { 229 usb_log_error("failed when receiving hub descriptor, " 230 "badcode = %d\n", 231 opResult); 117 232 free(serialized_descriptor); 118 233 return opResult; … … 120 235 usb_log_debug2("deserializing descriptor\n"); 121 236 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor); 122 if (descriptor==NULL){237 if (descriptor == NULL) { 123 238 usb_log_warning("could not deserialize descriptor \n"); 124 239 return opResult; 125 240 } 126 usb_log_debug("setting port count to %d\n", descriptor->ports_count);241 usb_log_debug("setting port count to %d\n", descriptor->ports_count); 127 242 hub_info->port_count = descriptor->ports_count; 128 hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1)); 243 /// \TODO this is not semantically correct 244 hub_info->ports = malloc( 245 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 129 246 size_t port; 130 247 for (port = 0; port < hub_info->port_count + 1; port++) { 131 248 usb_hub_port_init(&hub_info->ports[port]); 132 249 } 133 //handle non-removable devices134 usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);135 250 usb_log_debug2("freeing data\n"); 136 251 free(serialized_descriptor); … … 139 254 return EOK; 140 255 } 256 141 257 /** 142 258 * Set configuration of hub … … 147 263 * @return error code 148 264 */ 149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {265 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) { 150 266 //device descriptor 151 267 usb_standard_device_descriptor_t *std_descriptor … … 153 269 usb_log_debug("hub has %d configurations\n", 154 270 std_descriptor->configuration_count); 155 if (std_descriptor->configuration_count<1){271 if (std_descriptor->configuration_count < 1) { 156 272 usb_log_error("there are no configurations available\n"); 157 273 return EINVAL; … … 173 289 } 174 290 usb_log_debug("\tused configuration %d\n", 175 291 config_descriptor->configuration_number); 176 292 177 293 return EOK; … … 179 295 180 296 /** 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 186 * @return error code 187 */ 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 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 303 * @return error code 304 */ 305 static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){ 233 306 /* 234 307 * The processing will require opened control pipe and connection … … 239 312 * auto destruction, this could work better. 240 313 */ 241 rc = usb_pipe_start_session(&usb_dev->ctrl_pipe);314 int rc = usb_pipe_start_session(hub_info->control_pipe); 242 315 if (rc != EOK) { 243 316 usb_log_error("Failed to start session on control pipe: %s.\n", 244 317 str_error(rc)); 245 goto leave;318 return rc; 246 319 } 247 320 rc = usb_hc_connection_open(&hub_info->connection); 248 321 if (rc != EOK) { 249 usb_pipe_end_session( &usb_dev->ctrl_pipe);322 usb_pipe_end_session(hub_info->control_pipe); 250 323 usb_log_error("Failed to open connection to HC: %s.\n", 251 324 str_error(rc)); 252 goto leave;325 return rc; 253 326 } 254 327 255 328 rc = usb_device_auto_poll(hub_info->usb_device, 0, 256 hub_port_changes_callback, ((hub_info->port_count +1) / 8) + 1,329 hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1, 257 330 NULL, hub_info); 258 331 if (rc != EOK) { … … 266 339 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 267 340 return EOK; 268 269 leave: 270 free(hub_info); 271 272 return rc; 273 } 274 275 276 //********************************************* 277 // 278 // hub driver code, main loop and port handling 279 // 280 //********************************************* 281 282 /** 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 289 * @return error code 290 */ 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; 341 } 342 343 //********************************************* 344 // 345 // change handling functions 346 // 347 //********************************************* 348 349 350 /** 351 * process hub over current change 352 * 353 * This means either to power off the hub or power it on. 354 * @param hub_info hub instance 355 * @param status hub status bitmask 356 * @return error code 357 */ 358 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 359 usb_hub_status_t status) { 296 360 int opResult; 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 ); 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); 312 405 if (opResult != EOK) { 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"); 406 usb_log_error("cannot power on port %d; %d\n", 407 port, opResult); 345 408 } 346 409 } 347 410 } 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){ 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; 452 424 int opResult; 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 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 } 461 456 462 457 /** -
uspace/drv/usbhub/usbhub.h
ra49e171 rdc4c19e 37 37 38 38 #include <ipc/devman.h> 39 #include <usb/usb.h>40 39 #include <ddf/driver.h> 41 40 42 #define NAME "usbhub"43 44 41 #include <usb/hub.h> 42 #include <usb/classes/hub.h> 45 43 46 44 #include <usb/pipes.h> 47 45 #include <usb/devdrv.h> 46 47 #include <fibril_synch.h> 48 49 #define NAME "usbhub" 48 50 49 51 #include "ports.h" … … 52 54 53 55 /** Information about attached hub. */ 54 typedef struct{56 struct usb_hub_info_t{ 55 57 /** Number of ports. */ 56 58 size_t port_count; 57 59 58 /** Ports.*/60 /** attached device handles, for each port one */ 59 61 usb_hub_port_t *ports; 60 62 61 63 /** connection to hcd */ 62 64 usb_hc_connection_t connection; … … 87 89 /** generic usb device data*/ 88 90 usb_device_t * usb_device; 89 } usb_hub_info_t;91 }; 90 92 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); 93 //int usb_hub_control_loop(void * hub_info_param); 107 94 108 95 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); 109 99 110 100 #endif -
uspace/drv/usbhub/usbhub_private.h
ra49e171 rdc4c19e 54 54 // 55 55 //************ 56 #define usb_new(type) (type*)malloc(sizeof(type))57 56 58 57 59 /**60 * Create hub structure instance61 *62 * Set the address and port count information most importantly.63 *64 * @param device65 * @param hc host controller phone66 * @return67 */68 58 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device); 69 59 … … 110 100 111 101 /** 102 * Clear feature on hub port. 103 * 104 * @param hc Host controller telephone 105 * @param address Hub address 106 * @param port_index Port 107 * @param feature Feature selector 108 * @return Operation result 109 */ 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_index 119 }; 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 endpoint 130 * @param feature Feature selector 131 * @return Operation result 132 */ 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 = 0 141 }; 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 endpoint 151 * @param feature Feature selector 152 * @return Operation result 153 */ 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 = 0 162 }; 163 clear_request.value = feature; 164 return usb_pipe_control_write(pipe, &clear_request, 165 sizeof(clear_request), NULL, 0); 166 } 167 168 /** 112 169 * create uint8_t array with serialized descriptor 113 170 * -
uspace/drv/usbhub/utils.c
ra49e171 rdc4c19e 60 60 size_t size = 7; 61 61 //variable size according to port count 62 size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);62 size_t var_size = (descriptor->ports_count+7)/8; 63 63 size += 2 * var_size; 64 uint8_t * result = (uint8_t*)malloc(size);64 uint8_t * result = malloc(size); 65 65 //size 66 66 result[0] = size; … … 84 84 } 85 85 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) { 87 uint8_t * sdescriptor = (uint8_t*) serialized_descriptor; 86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor( 87 void * serialized_descriptor) { 88 uint8_t * sdescriptor = serialized_descriptor; 88 89 89 90 if (sdescriptor[1] != USB_DESCTYPE_HUB) { 90 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]); 91 usb_log_warning("trying to deserialize wrong descriptor %x\n", 92 sdescriptor[1]); 91 93 return NULL; 92 94 } 93 95 94 usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t);96 usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t)); 95 97 96 98 … … 100 102 result->pwr_on_2_good_time = sdescriptor[5]; 101 103 result->current_requirement = sdescriptor[6]; 102 size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0) 103 ? 1 : 0); 104 size_t var_size = (result->ports_count+7) / 8; 104 105 result->devices_removable = (uint8_t*) malloc(var_size); 105 106 -
uspace/drv/usbmid/main.c
ra49e171 rdc4c19e 55 55 int rc; 56 56 57 rc = usb_pipe_start_ session(&dev->ctrl_pipe);57 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 58 58 if (rc != EOK) { 59 usb_log_error("Failed to start sessionon control pipe: %s.\n",59 usb_log_error("Failed to start transfer 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 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 } 66 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 71 67 72 68 if (!accept) { -
uspace/drv/vhc/connhost.c
ra49e171 rdc4c19e 257 257 258 258 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 259 size_t max_packet_size,260 259 void *data, size_t size, 261 260 usbhc_iface_transfer_out_callback_t callback, void *arg) … … 267 266 268 267 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 269 size_t max_packet_size,270 268 void *data, size_t size, 271 269 usbhc_iface_transfer_in_callback_t callback, void *arg) … … 277 275 278 276 static int control_write(ddf_fun_t *fun, usb_target_t target, 279 size_t max_packet_size,280 277 void *setup_packet, size_t setup_packet_size, 281 278 void *data, size_t data_size, … … 295 292 296 293 static int control_read(ddf_fun_t *fun, usb_target_t target, 297 size_t max_packet_size,298 294 void *setup_packet, size_t setup_packet_size, 299 295 void *data, size_t data_size, … … 328 324 } 329 325 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 342 326 static int request_address(ddf_fun_t *fun, usb_speed_t ignored, 343 327 usb_address_t *address) … … 392 376 393 377 usbhc_iface_t vhc_iface = { 394 .reserve_default_address = reserve_default_address,395 .release_default_address = release_default_address,396 378 .request_address = request_address, 397 379 .bind_address = bind_address, -
uspace/lib/drv/generic/remote_usbhc.c
ra49e171 rdc4c19e 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 *);54 52 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 55 53 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); … … 61 59 /** Remote USB host controller interface operations. */ 62 60 static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = { 63 remote_usbhc_reserve_default_address,64 remote_usbhc_release_default_address,65 66 61 remote_usbhc_request_address, 67 62 remote_usbhc_bind_address, … … 129 124 } 130 125 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 163 126 void remote_usbhc_request_address(ddf_fun_t *fun, void *iface, 164 127 ipc_callid_t callid, ipc_call_t *call) … … 270 233 } 271 234 272 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);273 235 usb_target_t target = { 274 236 .address = DEV_IPC_GET_ARG1(*call), … … 300 262 trans->size = len; 301 263 302 rc = transfer_func(fun, target, max_packet_size,264 rc = transfer_func(fun, target, 303 265 buffer, len, 304 266 callback_out, trans); … … 326 288 } 327 289 328 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);329 290 usb_target_t target = { 330 291 .address = DEV_IPC_GET_ARG1(*call), … … 348 309 trans->size = len; 349 310 350 int rc = transfer_func(fun, target, max_packet_size,311 int rc = transfer_func(fun, target, 351 312 trans->buffer, len, 352 313 callback_in, trans); … … 414 375 }; 415 376 size_t data_buffer_len = DEV_IPC_GET_ARG3(*call); 416 size_t max_packet_size = DEV_IPC_GET_ARG4(*call);417 377 418 378 int rc; … … 450 410 trans->size = data_buffer_len; 451 411 452 rc = usb_iface->control_write(fun, target, max_packet_size,412 rc = usb_iface->control_write(fun, target, 453 413 setup_packet, setup_packet_len, 454 414 data_buffer, data_buffer_len, … … 477 437 .endpoint = DEV_IPC_GET_ARG2(*call) 478 438 }; 479 size_t max_packet_size = DEV_IPC_GET_ARG3(*call);480 439 481 440 int rc; … … 515 474 } 516 475 517 rc = usb_iface->control_read(fun, target, max_packet_size,476 rc = usb_iface->control_read(fun, target, 518 477 setup_packet, setup_packet_len, 519 478 trans->buffer, trans->size, … … 537 496 } 538 497 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, 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, 556 526 transfer_type, direction, max_packet_size, interval); 557 527 -
uspace/lib/drv/include/usbhc_iface.h
ra49e171 rdc4c19e 66 66 * - argument #1 is target address 67 67 * - argument #2 is target endpoint 68 * - argument #3 is max packet size of the endpoint69 68 * - this call is immediately followed by IPC data read (async version) 70 69 * - the call is not answered until the device returns some data (or until … … 85 84 */ 86 85 typedef enum { 87 /** Reserve usage of default address.88 * This call informs the host controller that the caller will be89 * using default USB address. It is duty of