Changes in / [e160bfe8:367db39a] in mainline
- Files:
-
- 6 added
- 37 deleted
- 62 edited
-
.bzrignore (modified) (2 diffs)
-
boot/Makefile.common (modified) (1 diff)
-
boot/arch/amd64/Makefile.inc (modified) (1 diff)
-
tools/ew.py (modified) (5 diffs)
-
uspace/Makefile (modified) (1 diff)
-
uspace/drv/bus/usb/ehci/Makefile (modified) (1 diff)
-
uspace/drv/bus/usb/ehci/ehci_batch.c (modified) (21 diffs)
-
uspace/drv/bus/usb/ehci/ehci_batch.h (modified) (3 diffs)
-
uspace/drv/bus/usb/ehci/ehci_bus.c (deleted)
-
uspace/drv/bus/usb/ehci/ehci_bus.h (deleted)
-
uspace/drv/bus/usb/ehci/ehci_endpoint.c (added)
-
uspace/drv/bus/usb/ehci/ehci_endpoint.h (added)
-
uspace/drv/bus/usb/ehci/ehci_rh.c (modified) (3 diffs)
-
uspace/drv/bus/usb/ehci/endpoint_list.h (modified) (1 diff)
-
uspace/drv/bus/usb/ehci/hc.c (modified) (12 diffs)
-
uspace/drv/bus/usb/ehci/hc.h (modified) (2 diffs)
-
uspace/drv/bus/usb/ehci/hw_struct/queue_head.c (modified) (3 diffs)
-
uspace/drv/bus/usb/ehci/main.c (modified) (4 diffs)
-
uspace/drv/bus/usb/ehci/res.c (modified) (4 diffs)
-
uspace/drv/bus/usb/ehci/res.h (modified) (1 diff)
-
uspace/drv/bus/usb/ohci/Makefile (modified) (1 diff)
-
uspace/drv/bus/usb/ohci/endpoint_list.h (modified) (1 diff)
-
uspace/drv/bus/usb/ohci/hc.c (modified) (10 diffs)
-
uspace/drv/bus/usb/ohci/hc.h (modified) (5 diffs)
-
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c (modified) (1 diff)
-
uspace/drv/bus/usb/ohci/main.c (modified) (4 diffs)
-
uspace/drv/bus/usb/ohci/ohci_batch.c (modified) (17 diffs)
-
uspace/drv/bus/usb/ohci/ohci_batch.h (modified) (3 diffs)
-
uspace/drv/bus/usb/ohci/ohci_bus.c (deleted)
-
uspace/drv/bus/usb/ohci/ohci_bus.h (deleted)
-
uspace/drv/bus/usb/ohci/ohci_endpoint.c (added)
-
uspace/drv/bus/usb/ohci/ohci_endpoint.h (added)
-
uspace/drv/bus/usb/ohci/ohci_rh.c (modified) (3 diffs)
-
uspace/drv/bus/usb/uhci/hc.c (modified) (9 diffs)
-
uspace/drv/bus/usb/uhci/hc.h (modified) (3 diffs)
-
uspace/drv/bus/usb/uhci/main.c (modified) (5 diffs)
-
uspace/drv/bus/usb/uhci/transfer_list.c (modified) (1 diff)
-
uspace/drv/bus/usb/uhci/uhci_batch.c (modified) (17 diffs)
-
uspace/drv/bus/usb/uhci/uhci_batch.h (modified) (6 diffs)
-
uspace/drv/bus/usb/uhci/uhci_rh.c (modified) (3 diffs)
-
uspace/drv/bus/usb/usbhid/main.c (modified) (1 diff)
-
uspace/drv/bus/usb/usbhub/status.h (modified) (1 diff)
-
uspace/drv/bus/usb/usbmast/main.c (modified) (1 diff)
-
uspace/drv/bus/usb/vhc/main.c (modified) (3 diffs)
-
uspace/drv/bus/usb/vhc/transfer.c (modified) (14 diffs)
-
uspace/drv/bus/usb/vhc/vhcd.h (modified) (2 diffs)
-
uspace/drv/bus/usb/xhci/Makefile (deleted)
-
uspace/drv/bus/usb/xhci/bus.c (deleted)
-
uspace/drv/bus/usb/xhci/bus.h (deleted)
-
uspace/drv/bus/usb/xhci/commands.c (deleted)
-
uspace/drv/bus/usb/xhci/commands.h (deleted)
-
uspace/drv/bus/usb/xhci/debug.c (deleted)
-
uspace/drv/bus/usb/xhci/debug.h (deleted)
-
uspace/drv/bus/usb/xhci/endpoint.c (deleted)
-
uspace/drv/bus/usb/xhci/endpoint.h (deleted)
-
uspace/drv/bus/usb/xhci/hc.c (deleted)
-
uspace/drv/bus/usb/xhci/hc.h (deleted)
-
uspace/drv/bus/usb/xhci/hw_struct/README (deleted)
-
uspace/drv/bus/usb/xhci/hw_struct/common.h (deleted)
-
uspace/drv/bus/usb/xhci/hw_struct/context.h (deleted)
-
uspace/drv/bus/usb/xhci/hw_struct/regs.h (deleted)
-
uspace/drv/bus/usb/xhci/hw_struct/trb.h (deleted)
-
uspace/drv/bus/usb/xhci/main.c (deleted)
-
uspace/drv/bus/usb/xhci/rh.c (deleted)
-
uspace/drv/bus/usb/xhci/rh.h (deleted)
-
uspace/drv/bus/usb/xhci/scratchpad.c (deleted)
-
uspace/drv/bus/usb/xhci/scratchpad.h (deleted)
-
uspace/drv/bus/usb/xhci/test/reg-ops.c (deleted)
-
uspace/drv/bus/usb/xhci/transfers.c (deleted)
-
uspace/drv/bus/usb/xhci/transfers.h (deleted)
-
uspace/drv/bus/usb/xhci/trb_ring.c (deleted)
-
uspace/drv/bus/usb/xhci/trb_ring.h (deleted)
-
uspace/drv/bus/usb/xhci/xhci.ma (deleted)
-
uspace/lib/c/include/bitops.h (modified) (1 diff)
-
uspace/lib/c/include/byteorder.h (modified) (1 diff)
-
uspace/lib/drv/generic/remote_usb.c (modified) (4 diffs)
-
uspace/lib/drv/include/usb_iface.h (modified) (2 diffs)
-
uspace/lib/pcm/src/format.c (modified) (1 diff)
-
uspace/lib/usb/include/usb/descriptor.h (modified) (3 diffs)
-
uspace/lib/usb/include/usb/request.h (modified) (1 diff)
-
uspace/lib/usb/include/usb/usb.h (modified) (4 diffs)
-
uspace/lib/usb/src/usb.c (modified) (4 diffs)
-
uspace/lib/usbdev/include/usb/dev/pipes.h (modified) (1 diff)
-
uspace/lib/usbdev/src/devdrv.c (modified) (10 diffs)
-
uspace/lib/usbdev/src/devpoll.c (modified) (4 diffs)
-
uspace/lib/usbdev/src/pipes.c (modified) (11 diffs)
-
uspace/lib/usbdev/src/pipesinit.c (modified) (3 diffs)
-
uspace/lib/usbdev/src/request.c (modified) (2 diffs)
-
uspace/lib/usbhost/Makefile (modified) (1 diff)
-
uspace/lib/usbhost/include/usb/host/bandwidth.h (deleted)
-
uspace/lib/usbhost/include/usb/host/bus.h (deleted)
-
uspace/lib/usbhost/include/usb/host/ddf_helpers.h (modified) (3 diffs)
-
uspace/lib/usbhost/include/usb/host/endpoint.h (modified) (4 diffs)
-
uspace/lib/usbhost/include/usb/host/hcd.h (modified) (6 diffs)
-
uspace/lib/usbhost/include/usb/host/usb2_bus.h (deleted)
-
uspace/lib/usbhost/include/usb/host/usb_bus.h (added)
-
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h (modified) (4 diffs)
-
uspace/lib/usbhost/src/bandwidth.c (deleted)
-
uspace/lib/usbhost/src/bus.c (deleted)
-
uspace/lib/usbhost/src/ddf_helpers.c (modified) (31 diffs)
-
uspace/lib/usbhost/src/endpoint.c (modified) (2 diffs)
-
uspace/lib/usbhost/src/hcd.c (modified) (13 diffs)
-
uspace/lib/usbhost/src/usb2_bus.c (deleted)
-
uspace/lib/usbhost/src/usb_bus.c (added)
-
uspace/lib/usbhost/src/usb_transfer_batch.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
re160bfe8 r367db39a 234 234 uspace/dist/drv/virt/ 235 235 uspace/dist/drv/xtkbd/ 236 uspace/dist/drv/xhci/237 236 uspace/dist/inc/_link.ld 238 237 uspace/dist/inc/c/ … … 289 288 uspace/drv/bus/usb/usbmid/usbmid 290 289 uspace/drv/bus/usb/vhc/vhc 291 uspace/drv/bus/usb/xhci/xhci292 uspace/drv/bus/usb/xhci/test-xhci293 290 uspace/drv/char/atkbd/atkbd 294 291 uspace/drv/char/i8042/i8042 -
boot/Makefile.common
re160bfe8 r367db39a 235 235 $(USPACE_PATH)/lib/posix/test-libposix \ 236 236 $(USPACE_PATH)/lib/uri/test-liburi \ 237 $(USPACE_PATH)/drv/bus/usb/xhci/test-xhci \238 237 $(USPACE_PATH)/app/bdsh/test-bdsh \ 239 238 $(USPACE_PATH)/srv/net/tcp/test-tcp -
boot/arch/amd64/Makefile.inc
re160bfe8 r367db39a 54 54 bus/usb/usbmast \ 55 55 bus/usb/usbmid \ 56 bus/usb/vhc \ 57 bus/usb/xhci 56 bus/usb/vhc 58 57 59 58 RD_DRV_CFG += \ -
tools/ew.py
re160bfe8 r367db39a 160 160 return ' -usb' 161 161 162 def qemu_xhci_options():163 if is_override('noxhci'):164 return ''165 return ' -device nec-usb-xhci,id=xhci'166 167 162 def qemu_audio_options(): 168 163 if is_override('nosnd'): … … 185 180 if (not 'usb' in cfg.keys()) or cfg['usb']: 186 181 cmdline += qemu_usb_options() 187 if (not 'xhci' in cfg.keys()) or cfg['xhci']:188 cmdline += qemu_xhci_options()189 182 if (not 'audio' in cfg.keys()) or cfg['audio']: 190 183 cmdline += qemu_audio_options() … … 293 286 def usage(): 294 287 print("%s - emulator wrapper for running HelenOS\n" % os.path.basename(sys.argv[0])) 295 print("%s [-d] [-h] [-net e1k|rtl8139|ne2k] [-nohdd] [-nokvm] [-nonet] [-nosnd] [-nousb] [-noxhci]\n" %288 print("%s [-d] [-h] [-net e1k|rtl8139|ne2k] [-nohdd] [-nokvm] [-nonet] [-nosnd] [-nousb]\n" % 296 289 os.path.basename(sys.argv[0])) 297 290 print("-d\tDry run: do not run the emulation, just print the command line.") … … 302 295 print("-nosnd\tDisable sound, if applicable.") 303 296 print("-nousb\tDisable USB support, if applicable.") 304 print("-noxhci\tDisable XHCI support, if applicable.")305 297 306 298 def fail(platform, machine): … … 344 336 elif sys.argv[i] == '-nousb': 345 337 overrides['nousb'] = True 346 elif sys.argv[i] == '-noxhci':347 overrides['noxhci'] = True348 338 else: 349 339 usage() -
uspace/Makefile
re160bfe8 r367db39a 156 156 drv/bus/usb/usbmid \ 157 157 drv/bus/usb/vhc \ 158 drv/bus/usb/xhci \159 158 drv/char/i8042 \ 160 159 drv/char/ns8250 \ -
uspace/drv/bus/usb/ehci/Makefile
re160bfe8 r367db39a 46 46 SOURCES = \ 47 47 ehci_batch.c \ 48 ehci_ bus.c \48 ehci_endpoint.c \ 49 49 ehci_rh.c \ 50 50 endpoint_list.c \ -
uspace/drv/bus/usb/ehci/ehci_batch.c
re160bfe8 r367db39a 45 45 46 46 #include "ehci_batch.h" 47 #include "ehci_ bus.h"47 #include "ehci_endpoint.h" 48 48 49 49 /* The buffer pointer list in the qTD is long enough to support a maximum … … 53 53 #define EHCI_TD_MAX_TRANSFER (16 * 1024) 54 54 55 static void (*const batch_setup[])(ehci_transfer_batch_t* );55 static void (*const batch_setup[])(ehci_transfer_batch_t*, usb_direction_t); 56 56 57 57 /** Safely destructs ehci_transfer_batch_t structure … … 59 59 * @param[in] ehci_batch Instance to destroy. 60 60 */ 61 void ehci_transfer_batch_destroy(ehci_transfer_batch_t *ehci_batch) 62 { 63 assert(ehci_batch); 61 static void ehci_transfer_batch_dispose(ehci_transfer_batch_t *ehci_batch) 62 { 63 if (!ehci_batch) 64 return; 64 65 if (ehci_batch->tds) { 65 66 for (size_t i = 0; i < ehci_batch->td_count; ++i) { … … 68 69 free(ehci_batch->tds); 69 70 } 71 usb_transfer_batch_destroy(ehci_batch->usb_batch); 70 72 free32(ehci_batch->device_buffer); 71 73 free(ehci_batch); … … 73 75 } 74 76 77 /** Finishes usb_transfer_batch and destroys the structure. 78 * 79 * @param[in] uhci_batch Instance to finish and destroy. 80 */ 81 void ehci_transfer_batch_finish_dispose(ehci_transfer_batch_t *ehci_batch) 82 { 83 assert(ehci_batch); 84 assert(ehci_batch->usb_batch); 85 usb_transfer_batch_finish(ehci_batch->usb_batch, 86 ehci_batch->device_buffer + ehci_batch->usb_batch->setup_size); 87 ehci_transfer_batch_dispose(ehci_batch); 88 } 89 75 90 /** Allocate memory and initialize internal data structure. 76 91 * … … 79 94 * NULL otherwise. 80 95 * 81 */82 ehci_transfer_batch_t * ehci_transfer_batch_create(endpoint_t *ep)83 {84 assert(ep);85 86 ehci_transfer_batch_t *ehci_batch = calloc(1, sizeof(ehci_transfer_batch_t));87 if (!ehci_batch) {88 usb_log_error("Failed to allocate EHCI batch data.");89 return NULL;90 }91 92 usb_transfer_batch_init(&ehci_batch->base, ep);93 link_initialize(&ehci_batch->link);94 95 return ehci_batch;96 }97 98 /** Prepares a batch to be sent.99 *100 96 * Determines the number of needed transfer descriptors (TDs). 101 97 * Prepares a transport buffer (that is accessible by the hardware). 102 98 * Initializes parameters needed for the transfer and callback. 103 99 */ 104 int ehci_transfer_batch_prepare(ehci_transfer_batch_t *ehci_batch) 105 { 106 assert(ehci_batch); 107 108 const size_t setup_size = (ehci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL) 109 ? USB_SETUP_PACKET_SIZE 110 : 0; 111 112 const size_t size = ehci_batch->base.buffer_size; 113 114 /* Mix setup stage and data together, we have enough space */ 115 if (size + setup_size > 0) { 116 /* Use one buffer for setup and data stage */ 117 ehci_batch->device_buffer = malloc32(size + setup_size); 118 if (!ehci_batch->device_buffer) { 119 usb_log_error("Batch %p: Failed to allocate device " 120 "buffer", ehci_batch); 121 return ENOMEM; 122 } 123 /* Copy setup data */ 124 memcpy(ehci_batch->device_buffer, ehci_batch->base.setup.buffer, 125 setup_size); 126 /* Copy generic data */ 127 if (ehci_batch->base.dir != USB_DIRECTION_IN) 128 memcpy(ehci_batch->device_buffer + setup_size, 129 ehci_batch->base.buffer, ehci_batch->base.buffer_size); 130 } 131 132 /* Add TD left over by the previous transfer */ 133 ehci_batch->qh = ehci_endpoint_get(ehci_batch->base.ep)->qh; 134 135 /* Determine number of TDs needed */ 136 ehci_batch->td_count = (size + EHCI_TD_MAX_TRANSFER - 1) 137 / EHCI_TD_MAX_TRANSFER; 100 ehci_transfer_batch_t * ehci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 101 { 102 assert(usb_batch); 103 104 ehci_transfer_batch_t *ehci_batch = 105 calloc(1, sizeof(ehci_transfer_batch_t)); 106 if (!ehci_batch) { 107 usb_log_error("Batch %p: Failed to allocate EHCI batch data.", 108 usb_batch); 109 goto dispose; 110 } 111 link_initialize(&ehci_batch->link); 112 ehci_batch->td_count = 113 (usb_batch->buffer_size + EHCI_TD_MAX_TRANSFER - 1) 114 / EHCI_TD_MAX_TRANSFER; 138 115 139 116 /* Control transfer need Setup and Status stage */ 140 if ( ehci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL) {117 if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 141 118 ehci_batch->td_count += 2; 142 119 } … … 145 122 if (!ehci_batch->tds) { 146 123 usb_log_error("Batch %p: Failed to allocate EHCI transfer " 147 "descriptors.", ehci_batch); 148 return ENOMEM; 149 } 124 "descriptors.", usb_batch); 125 goto dispose; 126 } 127 128 /* Add TD left over by the previous transfer */ 129 ehci_batch->qh = ehci_endpoint_get(usb_batch->ep)->qh; 150 130 151 131 for (unsigned i = 0; i < ehci_batch->td_count; ++i) { … … 153 133 if (!ehci_batch->tds[i]) { 154 134 usb_log_error("Batch %p: Failed to allocate TD %d.", 155 ehci_batch, i);156 return ENOMEM;135 usb_batch, i); 136 goto dispose; 157 137 } 158 138 memset(ehci_batch->tds[i], 0, sizeof(td_t)); 159 139 } 160 140 161 assert(batch_setup[ehci_batch->base.ep->transfer_type]); 162 batch_setup[ehci_batch->base.ep->transfer_type](ehci_batch); 141 142 /* Mix setup stage and data together, we have enough space */ 143 if (usb_batch->setup_size + usb_batch->buffer_size > 0) { 144 /* Use one buffer for setup and data stage */ 145 ehci_batch->device_buffer = 146 malloc32(usb_batch->setup_size + usb_batch->buffer_size); 147 if (!ehci_batch->device_buffer) { 148 usb_log_error("Batch %p: Failed to allocate device " 149 "buffer", usb_batch); 150 goto dispose; 151 } 152 /* Copy setup data */ 153 memcpy(ehci_batch->device_buffer, usb_batch->setup_buffer, 154 usb_batch->setup_size); 155 /* Copy generic data */ 156 if (usb_batch->ep->direction != USB_DIRECTION_IN) 157 memcpy( 158 ehci_batch->device_buffer + usb_batch->setup_size, 159 usb_batch->buffer, usb_batch->buffer_size); 160 } 161 ehci_batch->usb_batch = usb_batch; 162 163 const usb_direction_t dir = usb_transfer_batch_direction(usb_batch); 164 assert(batch_setup[usb_batch->ep->transfer_type]); 165 batch_setup[usb_batch->ep->transfer_type](ehci_batch, dir); 163 166 164 167 usb_log_debug("Batch %p %s " USB_TRANSFER_BATCH_FMT " initialized.\n", 165 ehci_batch, usb_str_direction(ehci_batch->base.dir), 166 USB_TRANSFER_BATCH_ARGS(ehci_batch->base)); 167 168 return EOK; 168 usb_batch, usb_str_direction(dir), 169 USB_TRANSFER_BATCH_ARGS(*usb_batch)); 170 171 return ehci_batch; 172 dispose: 173 ehci_transfer_batch_dispose(ehci_batch); 174 return NULL; 169 175 } 170 176 … … 178 184 * completes with the last TD. 179 185 */ 180 bool ehci_transfer_batch_ check_completed(ehci_transfer_batch_t *ehci_batch)186 bool ehci_transfer_batch_is_complete(const ehci_transfer_batch_t *ehci_batch) 181 187 { 182 188 assert(ehci_batch); 189 assert(ehci_batch->usb_batch); 183 190 184 191 usb_log_debug("Batch %p: checking %zu td(s) for completion.\n", 185 ehci_batch , ehci_batch->td_count);192 ehci_batch->usb_batch, ehci_batch->td_count); 186 193 187 194 usb_log_debug2("Batch %p: QH: %08x:%08x:%08x:%08x:%08x:%08x.\n", 188 ehci_batch ,195 ehci_batch->usb_batch, 189 196 ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap, 190 197 ehci_batch->qh->status, ehci_batch->qh->current, … … 199 206 200 207 /* Assume all data got through */ 201 ehci_batch->base.transfered_size = ehci_batch->base.buffer_size; 208 ehci_batch->usb_batch->transfered_size = 209 ehci_batch->usb_batch->buffer_size; 202 210 203 211 /* Check all TDs */ … … 205 213 assert(ehci_batch->tds[i] != NULL); 206 214 usb_log_debug("Batch %p: TD %zu: %08x:%08x:%08x.", 207 ehci_batch , i,215 ehci_batch->usb_batch, i, 208 216 ehci_batch->tds[i]->status, ehci_batch->tds[i]->next, 209 217 ehci_batch->tds[i]->alternate); 210 218 211 ehci_batch-> base.error = td_error(ehci_batch->tds[i]);212 if (ehci_batch-> base.error == EOK) {219 ehci_batch->usb_batch->error = td_error(ehci_batch->tds[i]); 220 if (ehci_batch->usb_batch->error == EOK) { 213 221 /* If the TD got all its data through, it will report 214 222 * 0 bytes remain, the sole exception is INPUT with … … 223 231 * we leave the very last(unused) TD behind. 224 232 */ 225 ehci_batch-> base.transfered_size233 ehci_batch->usb_batch->transfered_size 226 234 -= td_remain_size(ehci_batch->tds[i]); 227 235 } else { 228 236 usb_log_debug("Batch %p found error TD(%zu):%08x (%d).", 229 ehci_batch , i,237 ehci_batch->usb_batch, i, 230 238 ehci_batch->tds[i]->status, 231 ehci_batch-> base.error);239 ehci_batch->usb_batch->error); 232 240 /* Clear possible ED HALT */ 233 241 qh_clear_halt(ehci_batch->qh); … … 236 244 } 237 245 238 assert(ehci_batch->base.transfered_size <= ehci_batch->base.buffer_size); 239 240 if (ehci_batch->base.dir == USB_DIRECTION_IN) 241 memcpy(ehci_batch->base.buffer, ehci_batch->device_buffer, ehci_batch->base.transfered_size); 242 246 assert(ehci_batch->usb_batch->transfered_size <= 247 ehci_batch->usb_batch->buffer_size); 243 248 /* Clear TD pointers */ 244 249 ehci_batch->qh->next = LINK_POINTER_TERM; 245 250 ehci_batch->qh->current = LINK_POINTER_TERM; 246 usb_log_debug("Batch %p complete: %s", ehci_batch ,247 str_error(ehci_batch-> base.error));251 usb_log_debug("Batch %p complete: %s", ehci_batch->usb_batch, 252 str_error(ehci_batch->usb_batch->error)); 248 253 249 254 return true; … … 263 268 * 264 269 * @param[in] ehci_batch Batch structure to use. 270 * @param[in] dir Communication direction 265 271 * 266 272 * Setup stage with toggle 0 and direction BOTH(SETUP_PID) 267 * Data stage with alternating toggle and direction 268 * Status stage with toggle 1 and direction 269 */ 270 static void batch_control(ehci_transfer_batch_t *ehci_batch )273 * Data stage with alternating toggle and direction supplied by parameter. 274 * Status stage with toggle 1 and direction supplied by parameter. 275 */ 276 static void batch_control(ehci_transfer_batch_t *ehci_batch, usb_direction_t dir) 271 277 { 272 278 assert(ehci_batch); 273 274 usb_direction_t dir = ehci_batch->base.dir; 279 assert(ehci_batch->usb_batch); 275 280 assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT); 276 281 277 282 usb_log_debug2("Batch %p: Control QH(%"PRIxn"): " 278 "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch ,283 "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch->usb_batch, 279 284 addr_to_phys(ehci_batch->qh), 280 285 ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap, … … 293 298 /* Setup stage */ 294 299 td_init(ehci_batch->tds[0], ehci_batch->tds[1], USB_DIRECTION_BOTH, 295 buffer, USB_SETUP_PACKET_SIZE, toggle, false);300 buffer, ehci_batch->usb_batch->setup_size, toggle, false); 296 301 usb_log_debug2("Batch %p: Created CONTROL SETUP TD(%"PRIxn"): " 297 "%08x:%08x:%08x", ehci_batch ,302 "%08x:%08x:%08x", ehci_batch->usb_batch, 298 303 addr_to_phys(ehci_batch->tds[0]), 299 304 ehci_batch->tds[0]->status, ehci_batch->tds[0]->next, 300 305 ehci_batch->tds[0]->alternate); 301 buffer += USB_SETUP_PACKET_SIZE;306 buffer += ehci_batch->usb_batch->setup_size; 302 307 303 308 /* Data stage */ 304 309 size_t td_current = 1; 305 size_t remain_size = ehci_batch-> base.buffer_size;310 size_t remain_size = ehci_batch->usb_batch->buffer_size; 306 311 while (remain_size > 0) { 307 312 const size_t transfer_size = … … 313 318 transfer_size, toggle, false); 314 319 usb_log_debug2("Batch %p: Created CONTROL DATA TD(%"PRIxn"): " 315 "%08x:%08x:%08x", ehci_batch ,320 "%08x:%08x:%08x", ehci_batch->usb_batch, 316 321 addr_to_phys(ehci_batch->tds[td_current]), 317 322 ehci_batch->tds[td_current]->status, … … 329 334 td_init(ehci_batch->tds[td_current], NULL, status_dir, NULL, 0, 1, true); 330 335 usb_log_debug2("Batch %p: Created CONTROL STATUS TD(%"PRIxn"): " 331 "%08x:%08x:%08x", ehci_batch ,336 "%08x:%08x:%08x", ehci_batch->usb_batch, 332 337 addr_to_phys(ehci_batch->tds[td_current]), 333 338 ehci_batch->tds[td_current]->status, … … 344 349 * EHCI hw in ED. 345 350 */ 346 static void batch_data(ehci_transfer_batch_t *ehci_batch )351 static void batch_data(ehci_transfer_batch_t *ehci_batch, usb_direction_t dir) 347 352 { 348 353 assert(ehci_batch); 354 assert(ehci_batch->usb_batch); 355 assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT); 349 356 350 357 usb_log_debug2("Batch %p: Data QH(%"PRIxn"): " 351 "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch ,358 "%08x:%08x:%08x:%08x:%08x:%08x", ehci_batch->usb_batch, 352 359 addr_to_phys(ehci_batch->qh), 353 360 ehci_batch->qh->ep_char, ehci_batch->qh->ep_cap, … … 356 363 357 364 size_t td_current = 0; 358 size_t remain_size = ehci_batch-> base.buffer_size;365 size_t remain_size = ehci_batch->usb_batch->buffer_size; 359 366 char *buffer = ehci_batch->device_buffer; 360 367 while (remain_size > 0) { … … 366 373 ehci_batch->tds[td_current], 367 374 last ? NULL : ehci_batch->tds[td_current + 1], 368 ehci_batch->base.dir, buffer, transfer_size, -1, last);375 dir, buffer, transfer_size, -1, last); 369 376 370 377 usb_log_debug2("Batch %p: DATA TD(%"PRIxn": %08x:%08x:%08x", 371 ehci_batch ,378 ehci_batch->usb_batch, 372 379 addr_to_phys(ehci_batch->tds[td_current]), 373 380 ehci_batch->tds[td_current]->status, … … 383 390 384 391 /** Transfer setup table. */ 385 static void (*const batch_setup[])(ehci_transfer_batch_t* ) =392 static void (*const batch_setup[])(ehci_transfer_batch_t*, usb_direction_t) = 386 393 { 387 394 [USB_TRANSFER_CONTROL] = batch_control, -
uspace/drv/bus/usb/ehci/ehci_batch.h
re160bfe8 r367db39a 45 45 /** EHCI specific data required for USB transfer */ 46 46 typedef struct ehci_transfer_batch { 47 usb_transfer_batch_t base;48 47 /** Link */ 49 48 link_t link; … … 60 59 } ehci_transfer_batch_t; 61 60 62 ehci_transfer_batch_t * ehci_transfer_batch_ create(endpoint_t *ep);63 int ehci_transfer_batch_prepare(ehci_transfer_batch_t *batch);61 ehci_transfer_batch_t * ehci_transfer_batch_get(usb_transfer_batch_t *batch); 62 bool ehci_transfer_batch_is_complete(const ehci_transfer_batch_t *batch); 64 63 void ehci_transfer_batch_commit(const ehci_transfer_batch_t *batch); 65 bool ehci_transfer_batch_check_completed(ehci_transfer_batch_t *batch); 66 void ehci_transfer_batch_destroy(ehci_transfer_batch_t *batch); 64 void ehci_transfer_batch_finish_dispose(ehci_transfer_batch_t *batch); 67 65 68 66 static inline ehci_transfer_batch_t *ehci_transfer_batch_from_link(link_t *l) … … 71 69 return list_get_instance(l, ehci_transfer_batch_t, link); 72 70 } 73 74 static inline ehci_transfer_batch_t * ehci_transfer_batch_get(usb_transfer_batch_t *usb_batch)75 {76 assert(usb_batch);77 78 return (ehci_transfer_batch_t *) usb_batch;79 }80 81 71 #endif 82 72 /** -
uspace/drv/bus/usb/ehci/ehci_rh.c
re160bfe8 r367db39a 144 144 assert(instance); 145 145 assert(batch); 146 const usb_target_t target = batch->ep->target; 146 const usb_target_t target = {{ 147 .address = batch->ep->address, 148 .endpoint = batch->ep->endpoint, 149 }}; 147 150 batch->error = virthub_base_request(&instance->base, target, 148 batch->dir, (void*) batch->setup.buffer,151 usb_transfer_batch_direction(batch), (void*)batch->setup_buffer, 149 152 batch->buffer, batch->buffer_size, &batch->transfered_size); 150 153 if (batch->error == ENAK) { … … 157 160 instance->unfinished_interrupt_transfer = batch; 158 161 } else { 162 usb_transfer_batch_finish(batch, NULL); 163 usb_transfer_batch_destroy(batch); 159 164 usb_log_debug("RH(%p): BATCH(%p) virtual request complete: %s", 160 165 instance, batch, str_error(batch->error)); 161 usb_transfer_batch_finish(batch);162 166 } 163 167 return EOK; … … 179 183 instance, batch); 180 184 if (batch) { 181 const usb_target_t target = batch->ep->target; 185 const usb_target_t target = {{ 186 .address = batch->ep->address, 187 .endpoint = batch->ep->endpoint, 188 }}; 182 189 batch->error = virthub_base_request(&instance->base, target, 183 batch->dir, (void*) batch->setup.buffer, 190 usb_transfer_batch_direction(batch), 191 (void*)batch->setup_buffer, 184 192 batch->buffer, batch->buffer_size, &batch->transfered_size); 185 usb_transfer_batch_finish(batch); 193 usb_transfer_batch_finish(batch, NULL); 194 usb_transfer_batch_destroy(batch); 186 195 } 187 196 return EOK; -
uspace/drv/bus/usb/ehci/endpoint_list.h
re160bfe8 r367db39a 40 40 #include <usb/host/utils/malloc32.h> 41 41 42 #include "ehci_ bus.h"42 #include "ehci_endpoint.h" 43 43 #include "hw_struct/queue_head.h" 44 44 -
uspace/drv/bus/usb/ehci/hc.c
re160bfe8 r367db39a 89 89 }; 90 90 91 static void hc_start(hc_t *instance); 91 92 static int hc_init_memory(hc_t *instance); 92 93 … … 97 98 * @return Error code. 98 99 */ 99 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd,const hw_res_list_parsed_t *hw_res)100 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res) 100 101 { 101 102 assert(code); 102 103 assert(hw_res); 103 104 hc_t *instance = hcd_get_driver_data(hcd);105 104 106 105 if (hw_res->irqs.count != 1 || hw_res->mem_ranges.count != 1) … … 129 128 130 129 memcpy(code->cmds, ehci_irq_commands, sizeof(ehci_irq_commands)); 130 ehci_caps_regs_t *caps = NULL; 131 132 int ret = pio_enable_range(®s, (void**)&caps); 133 if (ret != EOK) { 134 free(code->ranges); 135 free(code->cmds); 136 return ret; 137 } 131 138 132 139 ehci_regs_t *registers = 133 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(instance->caps->caplength));140 (ehci_regs_t *)(RNGABSPTR(regs) + EHCI_RD8(caps->caplength)); 134 141 code->cmds[0].addr = (void *) ®isters->usbsts; 135 142 code->cmds[3].addr = (void *) ®isters->usbsts; … … 149 156 * @return Error code 150 157 */ 151 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res )158 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts) 152 159 { 153 160 assert(instance); … … 165 172 return ret; 166 173 } 167 168 174 usb_log_info("HC(%p): Device registers at %"PRIx64" (%zuB) accessible.", 169 175 instance, hw_res->mem_ranges.ranges[0].address.absolute, … … 189 195 ehci_rh_init( 190 196 &instance->rh, instance->caps, instance->registers, "ehci rh"); 191 192 ehci_bus_init(&instance->bus, instance); 197 usb_log_debug("HC(%p): Starting HW.", instance); 198 hc_start(instance); 199 193 200 return EOK; 194 201 } … … 215 222 ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep); 216 223 usb_log_debug("HC(%p) enqueue EP(%d:%d:%s:%s)\n", instance, 217 ep-> target.address, ep->target.endpoint,224 ep->address, ep->endpoint, 218 225 usb_str_transfer_type_short(ep->transfer_type), 219 226 usb_str_direction(ep->direction)); … … 239 246 ehci_endpoint_t *ehci_ep = ehci_endpoint_get(ep); 240 247 usb_log_debug("HC(%p) dequeue EP(%d:%d:%s:%s)\n", instance, 241 ep-> target.address, ep->target.endpoint,248 ep->address, ep->endpoint, 242 249 usb_str_transfer_type_short(ep->transfer_type), 243 250 usb_str_direction(ep->direction)); … … 291 298 292 299 /* Check for root hub communication */ 293 if (batch->ep-> target.address == ehci_rh_get_address(&instance->rh)) {300 if (batch->ep->address == ehci_rh_get_address(&instance->rh)) { 294 301 usb_log_debug("HC(%p): Scheduling BATCH(%p) for RH(%p)", 295 302 instance, batch, &instance->rh); 296 303 return ehci_rh_schedule(&instance->rh, batch); 297 304 } 298 299 305 ehci_transfer_batch_t *ehci_batch = ehci_transfer_batch_get(batch); 300 301 const int err = ehci_transfer_batch_prepare(ehci_batch); 302 if (err) 303 return err; 306 if (!ehci_batch) 307 return ENOMEM; 304 308 305 309 fibril_mutex_lock(&instance->guard); … … 346 350 ehci_transfer_batch_from_link(current); 347 351 348 if (ehci_transfer_batch_ check_completed(batch)) {352 if (ehci_transfer_batch_is_complete(batch)) { 349 353 list_remove(current); 350 usb_transfer_batch_finish(&batch->base);354 ehci_transfer_batch_finish_dispose(batch); 351 355 } 352 356 } … … 364 368 * @param[in] instance EHCI hc driver structure. 365 369 */ 366 int hc_start(hc_t *instance, bool interrupts) 367 { 368 assert(instance); 369 usb_log_debug("HC(%p): Starting HW.", instance); 370 370 void hc_start(hc_t *instance) 371 { 372 assert(instance); 371 373 /* Turn off the HC if it's running, Reseting a running device is 372 374 * undefined */ … … 433 435 EHCI_WR(instance->registers->usbsts, EHCI_RD(instance->registers->usbsts)); 434 436 EHCI_WR(instance->registers->usbintr, EHCI_USED_INTERRUPTS); 435 436 return EOK;437 437 } 438 438 -
uspace/drv/bus/usb/ehci/hc.h
re160bfe8 r367db39a 80 80 /** USB hub emulation structure */ 81 81 ehci_rh_t rh; 82 83 /** USB bookkeeping */84 ehci_bus_t bus;85 82 } hc_t; 86 83 87 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res); 88 int hc_start(hc_t *instance, bool interrupts); 84 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts); 89 85 void hc_fini(hc_t *instance); 90 86 … … 92 88 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep); 93 89 94 int ehci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd,const hw_res_list_parsed_t *hw_res);90 int ehci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res); 95 91 96 92 void ehci_hc_interrupt(hcd_t *hcd, uint32_t status); -
uspace/drv/bus/usb/ehci/hw_struct/queue_head.c
re160bfe8 r367db39a 37 37 #include <mem.h> 38 38 #include <macros.h> 39 #include <usb/host/bus.h>40 39 41 40 #include "mem_access.h" … … 66 65 assert(ep->speed < ARRAY_SIZE(speed)); 67 66 EHCI_MEM32_WR(instance->ep_char, 68 QH_EP_CHAR_ADDR_SET(ep-> target.address) |69 QH_EP_CHAR_EP_SET(ep-> target.endpoint) |67 QH_EP_CHAR_ADDR_SET(ep->address) | 68 QH_EP_CHAR_EP_SET(ep->endpoint) | 70 69 speed[ep->speed] | 71 70 QH_EP_CHAR_MAX_LENGTH_SET(ep->max_packet_size) … … 82 81 if (ep->speed != USB_SPEED_HIGH) { 83 82 ep_cap |= 84 QH_EP_CAP_TT_PORT_SET(ep-> device->tt.port) |85 QH_EP_CAP_TT_ADDR_SET(ep-> device->tt.address);83 QH_EP_CAP_TT_PORT_SET(ep->tt.port) | 84 QH_EP_CAP_TT_ADDR_SET(ep->tt.address); 86 85 } 87 86 if (ep->transfer_type == USB_TRANSFER_INTERRUPT) { -
uspace/drv/bus/usb/ehci/main.c
re160bfe8 r367db39a 48 48 #include "res.h" 49 49 #include "hc.h" 50 #include "ehci_endpoint.h" 50 51 51 52 #define NAME "ehci" 52 53 53 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 54 static int ehci_driver_claim(hcd_t *, ddf_dev_t *); 55 static int ehci_driver_start(hcd_t *, bool); 54 static int ehci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 56 55 static void ehci_driver_fini(hcd_t *); 57 56 58 57 static const ddf_hc_driver_t ehci_hc_driver = { 58 .claim = disable_legacy, 59 .hc_speed = USB_SPEED_HIGH, 60 .irq_code_gen = ehci_hc_gen_irq_code, 61 .init = ehci_driver_init, 62 .fini = ehci_driver_fini, 59 63 .name = "EHCI-PCI", 60 .init = ehci_driver_init,61 .irq_code_gen = ehci_hc_gen_irq_code,62 .claim = ehci_driver_claim,63 .start = ehci_driver_start,64 .setup_root_hub = hcd_setup_virtual_root_hub,65 .fini = ehci_driver_fini,66 64 .ops = { 67 65 .schedule = ehci_hc_schedule, 66 .ep_add_hook = ehci_endpoint_init, 67 .ep_remove_hook = ehci_endpoint_fini, 68 68 .irq_hook = ehci_hc_interrupt, 69 69 .status_hook = ehci_hc_status, … … 72 72 73 73 74 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device) 74 static int ehci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, 75 bool irq) 75 76 { 76 77 assert(hcd); … … 81 82 return ENOMEM; 82 83 83 const int ret = hc_init(instance, res );84 const int ret = hc_init(instance, res, irq); 84 85 if (ret == EOK) { 85 hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops , &instance->bus.base.base);86 hcd_set_implementation(hcd, instance, &ehci_hc_driver.ops); 86 87 } else { 87 88 free(instance); 88 89 } 89 90 return ret; 90 }91 92 static int ehci_driver_claim(hcd_t *hcd, ddf_dev_t *dev)93 {94 hc_t *instance = hcd_get_driver_data(hcd);95 assert(instance);96 97 return disable_legacy(instance, dev);98 }99 100 static int ehci_driver_start(hcd_t *hcd, bool irq) {101 hc_t *instance = hcd_get_driver_data(hcd);102 assert(instance);103 104 return hc_start(instance, irq);105 91 } 106 92 … … 113 99 114 100 free(hc); 115 hcd_set_implementation(hcd, NULL, NULL , NULL);101 hcd_set_implementation(hcd, NULL, NULL); 116 102 } 117 103 -
uspace/drv/bus/usb/ehci/res.c
re160bfe8 r367db39a 172 172 } 173 173 174 int disable_legacy( hc_t *hc,ddf_dev_t *device)174 int disable_legacy(ddf_dev_t *device) 175 175 { 176 176 assert(device); … … 182 182 usb_log_debug("Disabling EHCI legacy support.\n"); 183 183 184 185 const uint32_t hcc_params = EHCI_RD(hc->caps->hccparams); 184 hw_res_list_parsed_t res; 185 hw_res_list_parsed_init(&res); 186 int ret = hw_res_get_list_parsed(parent_sess, &res, 0); 187 if (ret != EOK) { 188 usb_log_error("Failed to get resource list: %s\n", 189 str_error(ret)); 190 goto clean; 191 } 192 193 if (res.mem_ranges.count < 1) { 194 usb_log_error("Incorrect mem range count: %zu", 195 res.mem_ranges.count); 196 ret = EINVAL; 197 goto clean; 198 } 199 200 /* Map EHCI registers */ 201 void *regs = NULL; 202 ret = pio_enable_range(&res.mem_ranges.ranges[0], ®s); 203 if (ret != EOK) { 204 usb_log_error("Failed to map registers %p: %s.\n", 205 RNGABSPTR(res.mem_ranges.ranges[0]), str_error(ret)); 206 goto clean; 207 } 208 209 usb_log_debug("Registers mapped at: %p.\n", regs); 210 211 ehci_caps_regs_t *ehci_caps = regs; 212 213 const uint32_t hcc_params = EHCI_RD(ehci_caps->hccparams); 186 214 usb_log_debug2("Value of hcc params register: %x.\n", hcc_params); 187 215 … … 192 220 usb_log_debug2("Value of EECP: %x.\n", eecp); 193 221 194 intret = disable_extended_caps(parent_sess, eecp);222 ret = disable_extended_caps(parent_sess, eecp); 195 223 if (ret != EOK) { 196 224 usb_log_error("Failed to disable extended capabilities: %s.\n", … … 199 227 } 200 228 clean: 201 async_hangup(parent_sess); 229 //TODO unmap registers 230 hw_res_list_parsed_clean(&res); 202 231 return ret; 203 232 } -
uspace/drv/bus/usb/ehci/res.h
re160bfe8 r367db39a 39 39 #include <device/hw_res_parsed.h> 40 40 41 #include "hc.h" 42 43 extern int disable_legacy(hc_t *, ddf_dev_t *); 41 extern int disable_legacy(ddf_dev_t *); 44 42 45 43 #endif -
uspace/drv/bus/usb/ohci/Makefile
re160bfe8 r367db39a 49 49 main.c \ 50 50 ohci_batch.c \ 51 ohci_ bus.c \51 ohci_endpoint.c \ 52 52 ohci_rh.c \ 53 53 hw_struct/endpoint_descriptor.c \ -
uspace/drv/bus/usb/ohci/endpoint_list.h
re160bfe8 r367db39a 41 41 #include <usb/host/utils/malloc32.h> 42 42 43 #include "ohci_ bus.h"43 #include "ohci_endpoint.h" 44 44 #include "hw_struct/endpoint_descriptor.h" 45 45 -
uspace/drv/bus/usb/ohci/hc.c
re160bfe8 r367db39a 47 47 #include <usb/usb.h> 48 48 49 #include "ohci_ bus.h"49 #include "ohci_endpoint.h" 50 50 #include "ohci_batch.h" 51 51 … … 89 89 }; 90 90 91 static void hc_gain_control(hc_t *instance); 92 static void hc_start(hc_t *instance); 91 93 static int hc_init_transfer_lists(hc_t *instance); 92 94 static int hc_init_memory(hc_t *instance); … … 101 103 * @return Error code. 102 104 */ 103 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd,const hw_res_list_parsed_t *hw_res)105 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res) 104 106 { 105 107 assert(code); … … 149 151 * @return Error code 150 152 */ 151 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res )153 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts) 152 154 { 153 155 assert(instance); … … 170 172 list_initialize(&instance->pending_batches); 171 173 fibril_mutex_initialize(&instance->guard); 174 instance->hw_interrupts = interrupts; 172 175 173 176 ret = hc_init_memory(instance); … … 178 181 return ret; 179 182 } 183 184 hc_gain_control(instance); 185 186 ohci_rh_init(&instance->rh, instance->registers, "ohci rh"); 187 hc_start(instance); 180 188 181 189 return EOK; … … 287 295 288 296 /* Check for root hub communication */ 289 if (batch->ep-> target.address == ohci_rh_get_address(&instance->rh)) {297 if (batch->ep->address == ohci_rh_get_address(&instance->rh)) { 290 298 usb_log_debug("OHCI root hub request.\n"); 291 299 return ohci_rh_schedule(&instance->rh, batch); … … 294 302 if (!ohci_batch) 295 303 return ENOMEM; 296 297 const int err = ohci_transfer_batch_prepare(ohci_batch);298 if (err)299 return err;300 304 301 305 fibril_mutex_lock(&instance->guard); … … 350 354 ohci_transfer_batch_from_link(current); 351 355 352 if (ohci_transfer_batch_ check_completed(batch)) {356 if (ohci_transfer_batch_is_complete(batch)) { 353 357 list_remove(current); 354 usb_transfer_batch_finish(&batch->base);358 ohci_transfer_batch_finish_dispose(batch); 355 359 } 356 360 … … 439 443 void hc_start(hc_t *instance) 440 444 { 441 ohci_rh_init(&instance->rh, instance->registers, "ohci rh");442 443 445 /* OHCI guide page 42 */ 444 446 assert(instance); -
uspace/drv/bus/usb/ohci/hc.h
re160bfe8 r367db39a 52 52 #include "ohci_regs.h" 53 53 #include "ohci_rh.h" 54 #include "ohci_bus.h"55 54 #include "endpoint_list.h" 56 55 #include "hw_struct/hcca.h" … … 60 59 /** Memory mapped I/O registers area */ 61 60 ohci_regs_t *registers; 62 63 61 /** Host controller communication area structure */ 64 62 hcca_t *hcca; … … 66 64 /** Transfer schedules */ 67 65 endpoint_list_t lists[4]; 68 69 66 /** List of active transfers */ 70 67 list_t pending_batches; … … 81 78 /** USB hub emulation structure */ 82 79 ohci_rh_t rh; 83 84 /** USB bookkeeping */85 ohci_bus_t bus;86 80 } hc_t; 87 81 88 extern int hc_init(hc_t *, const hw_res_list_parsed_t *); 89 extern void hc_gain_control(hc_t *instance); 90 extern void hc_start(hc_t *instance); 82 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool); 91 83 extern void hc_fini(hc_t *); 92 84 … … 94 86 extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *); 95 87 96 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd,const hw_res_list_parsed_t *hw_res);88 int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res); 97 89 98 90 extern void ohci_hc_interrupt(hcd_t *, uint32_t); -
uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
re160bfe8 r367db39a 79 79 /* Status: address, endpoint nr, direction mask and max packet size. */ 80 80 OHCI_MEM32_WR(instance->status, 81 ((ep-> target.address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)82 | ((ep-> target.endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)81 ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT) 82 | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT) 83 83 | ((dir[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT) 84 84 | ((ep->max_packet_size & ED_STATUS_MPS_MASK) -
uspace/drv/bus/usb/ohci/main.c
re160bfe8 r367db39a 45 45 46 46 #include "hc.h" 47 #include "ohci_bus.h"48 47 49 48 #define NAME "ohci" 50 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 51 static int ohci_driver_start(hcd_t *, bool); 52 static int ohci_driver_claim(hcd_t *, ddf_dev_t *); 49 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 53 50 static void ohci_driver_fini(hcd_t *); 54 51 55 52 static const ddf_hc_driver_t ohci_hc_driver = { 53 .hc_speed = USB_SPEED_FULL, 56 54 .irq_code_gen = ohci_hc_gen_irq_code, 57 55 .init = ohci_driver_init, 58 .claim = ohci_driver_claim,59 .start = ohci_driver_start,60 .setup_root_hub = hcd_setup_virtual_root_hub,61 56 .fini = ohci_driver_fini, 62 57 .name = "OHCI", 63 58 .ops = { 64 59 .schedule = ohci_hc_schedule, 60 .ep_add_hook = ohci_endpoint_init, 61 .ep_remove_hook = ohci_endpoint_fini, 65 62 .irq_hook = ohci_hc_interrupt, 66 63 .status_hook = ohci_hc_status, … … 69 66 70 67 71 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)68 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq) 72 69 { 73 int err;74 75 70 assert(hcd); 76 71 assert(hcd_get_driver_data(hcd) == NULL); … … 80 75 return ENOMEM; 81 76 82 if ((err = hc_init(instance, res)) != EOK) 83 goto err; 84 85 if ((err = ohci_bus_init(&instance->bus, instance))) 86 goto err; 87 88 hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops, &instance->bus.base.base); 89 90 return EOK; 91 92 err: 93 free(instance); 94 return err; 95 } 96 97 static int ohci_driver_claim(hcd_t *hcd, ddf_dev_t *dev) 98 { 99 hc_t *hc = hcd_get_driver_data(hcd); 100 assert(hc); 101 102 hc_gain_control(hc); 103 104 return EOK; 105 } 106 107 static int ohci_driver_start(hcd_t *hcd, bool interrupts) 108 { 109 hc_t *hc = hcd_get_driver_data(hcd); 110 assert(hc); 111 112 hc->hw_interrupts = interrupts; 113 hc_start(hc); 114 return EOK; 77 const int ret = hc_init(instance, res, irq); 78 if (ret == EOK) { 79 hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops); 80 } else { 81 free(instance); 82 } 83 return ret; 115 84 } 116 85 … … 122 91 hc_fini(hc); 123 92 124 hcd_set_implementation(hcd, NULL, NULL , NULL);93 hcd_set_implementation(hcd, NULL, NULL); 125 94 free(hc); 126 95 } -
uspace/drv/bus/usb/ohci/ohci_batch.c
re160bfe8 r367db39a 45 45 46 46 #include "ohci_batch.h" 47 #include "ohci_ bus.h"48 49 static void (*const batch_setup[])(ohci_transfer_batch_t* );47 #include "ohci_endpoint.h" 48 49 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t); 50 50 51 51 /** Safely destructs ohci_transfer_batch_t structure … … 53 53 * @param[in] ohci_batch Instance to destroy. 54 54 */ 55 void ohci_transfer_batch_destroy(ohci_transfer_batch_t *ohci_batch) 56 { 57 assert(ohci_batch); 55 static void ohci_transfer_batch_dispose(ohci_transfer_batch_t *ohci_batch) 56 { 57 if (!ohci_batch) 58 return; 58 59 if (ohci_batch->tds) { 59 60 const ohci_endpoint_t *ohci_ep = … … 66 67 free(ohci_batch->tds); 67 68 } 69 usb_transfer_batch_destroy(ohci_batch->usb_batch); 68 70 free32(ohci_batch->device_buffer); 69 71 free(ohci_batch); 72 } 73 74 /** Finishes usb_transfer_batch and destroys the structure. 75 * 76 * @param[in] uhci_batch Instance to finish and destroy. 77 */ 78 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch) 79 { 80 assert(ohci_batch); 81 assert(ohci_batch->usb_batch); 82 usb_transfer_batch_finish(ohci_batch->usb_batch, 83 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size); 84 ohci_transfer_batch_dispose(ohci_batch); 70 85 } 71 86 … … 75 90 * @return Valid pointer if all structures were successfully created, 76 91 * NULL otherwise. 77 */ 78 ohci_transfer_batch_t * ohci_transfer_batch_create(endpoint_t *ep) 79 { 80 assert(ep); 92 * 93 * Determines the number of needed transfer descriptors (TDs). 94 * Prepares a transport buffer (that is accessible by the hardware). 95 * Initializes parameters needed for the transfer and callback. 96 */ 97 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 98 { 99 assert(usb_batch); 81 100 82 101 ohci_transfer_batch_t *ohci_batch = … … 84 103 if (!ohci_batch) { 85 104 usb_log_error("Failed to allocate OHCI batch data."); 86 return NULL; 87 } 88 89 usb_transfer_batch_init(&ohci_batch->base, ep); 105 goto dispose; 106 } 90 107 link_initialize(&ohci_batch->link); 91 92 return ohci_batch; 93 } 94 95 /** Prepares a batch to be sent. 96 * 97 * Determines the number of needed transfer descriptors (TDs). 98 * Prepares a transport buffer (that is accessible by the hardware). 99 * Initializes parameters needed for the transfer and callback. 100 */ 101 int ohci_transfer_batch_prepare(ohci_transfer_batch_t *ohci_batch) 102 { 103 assert(ohci_batch); 104 105 const size_t setup_size = (ohci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL) 106 ? USB_SETUP_PACKET_SIZE 107 : 0; 108 109 usb_transfer_batch_t *usb_batch = &ohci_batch->base; 110 111 ohci_batch->td_count = (usb_batch->buffer_size + OHCI_TD_MAX_TRANSFER - 1) 108 ohci_batch->td_count = 109 (usb_batch->buffer_size + OHCI_TD_MAX_TRANSFER - 1) 112 110 / OHCI_TD_MAX_TRANSFER; 113 111 /* Control transfer need Setup and Status stage */ … … 120 118 if (!ohci_batch->tds) { 121 119 usb_log_error("Failed to allocate OHCI transfer descriptors."); 122 return ENOMEM;120 goto dispose; 123 121 } 124 122 … … 131 129 if (!ohci_batch->tds[i]) { 132 130 usb_log_error("Failed to allocate TD %d.", i); 133 return ENOMEM;131 goto dispose; 134 132 } 135 133 } 134 136 135 137 136 /* NOTE: OHCI is capable of handling buffer that crosses page boundaries … … 139 138 * than two pages (the first page is computed using start pointer, the 140 139 * other using the end pointer) */ 141 if ( setup_size + usb_batch->buffer_size > 0) {140 if (usb_batch->setup_size + usb_batch->buffer_size > 0) { 142 141 /* Use one buffer for setup and data stage */ 143 142 ohci_batch->device_buffer = 144 malloc32( setup_size + usb_batch->buffer_size);143 malloc32(usb_batch->setup_size + usb_batch->buffer_size); 145 144 if (!ohci_batch->device_buffer) { 146 145 usb_log_error("Failed to allocate device buffer"); 147 return ENOMEM;146 goto dispose; 148 147 } 149 148 /* Copy setup data */ 150 memcpy(ohci_batch->device_buffer, usb_batch->setup.buffer, setup_size); 149 memcpy(ohci_batch->device_buffer, usb_batch->setup_buffer, 150 usb_batch->setup_size); 151 151 /* Copy generic data */ 152 152 if (usb_batch->ep->direction != USB_DIRECTION_IN) 153 153 memcpy( 154 ohci_batch->device_buffer + setup_size,154 ohci_batch->device_buffer + usb_batch->setup_size, 155 155 usb_batch->buffer, usb_batch->buffer_size); 156 156 } 157 157 ohci_batch->usb_batch = usb_batch; 158 159 const usb_direction_t dir = usb_transfer_batch_direction(usb_batch); 158 160 assert(batch_setup[usb_batch->ep->transfer_type]); 159 batch_setup[usb_batch->ep->transfer_type](ohci_batch); 160 161 return EOK; 161 batch_setup[usb_batch->ep->transfer_type](ohci_batch, dir); 162 163 return ohci_batch; 164 dispose: 165 ohci_transfer_batch_dispose(ohci_batch); 166 return NULL; 162 167 } 163 168 … … 171 176 * completes with the last TD. 172 177 */ 173 bool ohci_transfer_batch_ check_completed(ohci_transfer_batch_t *ohci_batch)178 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch) 174 179 { 175 180 assert(ohci_batch); 181 assert(ohci_batch->usb_batch); 176 182 177 183 usb_log_debug("Batch %p checking %zu td(s) for completion.\n", … … 188 194 189 195 /* Assume all data got through */ 190 ohci_batch->base.transfered_size = ohci_batch->base.buffer_size; 196 ohci_batch->usb_batch->transfered_size = 197 ohci_batch->usb_batch->buffer_size; 191 198 192 199 /* Assume we will leave the last(unused) TD behind */ … … 200 207 ohci_batch->tds[i]->next, ohci_batch->tds[i]->be); 201 208 202 ohci_batch-> base.error = td_error(ohci_batch->tds[i]);203 if (ohci_batch-> base.error == EOK) {209 ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]); 210 if (ohci_batch->usb_batch->error == EOK) { 204 211 /* If the TD got all its data through, it will report 205 212 * 0 bytes remain, the sole exception is INPUT with … … 214 221 * we leave the very last(unused) TD behind. 215 222 */ 216 ohci_batch-> base.transfered_size223 ohci_batch->usb_batch->transfered_size 217 224 -= td_remain_size(ohci_batch->tds[i]); 218 225 } else { … … 245 252 } 246 253 } 247 assert(ohci_batch->base.transfered_size <= 248 ohci_batch->base.buffer_size); 249 250 if (ohci_batch->base.dir == USB_DIRECTION_IN) 251 memcpy(ohci_batch->base.buffer, ohci_batch->device_buffer, ohci_batch->base.transfered_size); 254 assert(ohci_batch->usb_batch->transfered_size <= 255 ohci_batch->usb_batch->buffer_size); 252 256 253 257 /* Store the remaining TD */ 254 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch-> base.ep);258 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 255 259 assert(ohci_ep); 256 260 ohci_ep->td = ohci_batch->tds[leave_td]; … … 282 286 * Status stage with toggle 1 and direction supplied by parameter. 283 287 */ 284 static void batch_control(ohci_transfer_batch_t *ohci_batch )288 static void batch_control(ohci_transfer_batch_t *ohci_batch, usb_direction_t dir) 285 289 { 286 290 assert(ohci_batch); 287 288 usb_direction_t dir = ohci_batch->base.dir; 291 assert(ohci_batch->usb_batch); 289 292 assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT); 290 291 293 usb_log_debug("Using ED(%p): %08x:%08x:%08x:%08x.\n", ohci_batch->ed, 292 294 ohci_batch->ed->status, ohci_batch->ed->td_tail, … … 305 307 td_init( 306 308 ohci_batch->tds[0], ohci_batch->tds[1], USB_DIRECTION_BOTH, 307 buffer, USB_SETUP_PACKET_SIZE, toggle);309 buffer, ohci_batch->usb_batch->setup_size, toggle); 308 310 usb_log_debug("Created CONTROL SETUP TD: %08x:%08x:%08x:%08x.\n", 309 311 ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp, 310 312 ohci_batch->tds[0]->next, ohci_batch->tds[0]->be); 311 buffer += USB_SETUP_PACKET_SIZE;313 buffer += ohci_batch->usb_batch->setup_size; 312 314 313 315 /* Data stage */ … … 359 361 * OHCI hw in ED. 360 362 */ 361 static void batch_data(ohci_transfer_batch_t *ohci_batch )363 static void batch_data(ohci_transfer_batch_t *ohci_batch, usb_direction_t dir) 362 364 { 363 365 assert(ohci_batch); 364 365 usb_direction_t dir = ohci_batch->base.dir; 366 assert(ohci_batch->usb_batch); 366 367 assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT); 367 368 usb_log_debug("Using ED(%p): %08x:%08x:%08x:%08x.\n", ohci_batch->ed, … … 400 401 401 402 /** Transfer setup table. */ 402 static void (*const batch_setup[])(ohci_transfer_batch_t* ) =403 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) = 403 404 { 404 405 [USB_TRANSFER_CONTROL] = batch_control, -
uspace/drv/bus/usb/ohci/ohci_batch.h
re160bfe8 r367db39a 45 45 /** OHCI specific data required for USB transfer */ 46 46 typedef struct ohci_transfer_batch { 47 usb_transfer_batch_t base;48 49 47 /** Link */ 50 48 link_t link; … … 61 59 } ohci_transfer_batch_t; 62 60 63 ohci_transfer_batch_t * ohci_transfer_batch_ create(endpoint_t *batch);64 int ohci_transfer_batch_prepare(ohci_transfer_batch_t *ohci_batch);61 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 62 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch); 65 63 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch); 66 bool ohci_transfer_batch_check_completed(ohci_transfer_batch_t *batch); 67 void ohci_transfer_batch_destroy(ohci_transfer_batch_t *ohci_batch); 64 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 68 65 69 66 static inline ohci_transfer_batch_t *ohci_transfer_batch_from_link(link_t *l) … … 72 69 return list_get_instance(l, ohci_transfer_batch_t, link); 73 70 } 74 75 static inline ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch)76 {77 assert(usb_batch);78 79 return (ohci_transfer_batch_t *) usb_batch;80 }81 82 71 #endif 83 72 /** -
uspace/drv/bus/usb/ohci/ohci_rh.c
re160bfe8 r367db39a 178 178 assert(instance); 179 179 assert(batch); 180 const usb_target_t target = batch->ep->target; 180 const usb_target_t target = {{ 181 .address = batch->ep->address, 182 .endpoint = batch->ep->endpoint, 183 }}; 181 184 batch->error = virthub_base_request(&instance->base, target, 182 batch->dir, &batch->setup.packet,185 usb_transfer_batch_direction(batch), (void*)batch->setup_buffer, 183 186 batch->buffer, batch->buffer_size, &batch->transfered_size); 184 187 if (batch->error == ENAK) { … … 189 192 instance->unfinished_interrupt_transfer = batch; 190 193 } else { 191 usb_transfer_batch_finish(batch); 194 usb_transfer_batch_finish(batch, NULL); 195 usb_transfer_batch_destroy(batch); 192 196 } 193 197 return EOK; … … 207 211 instance->unfinished_interrupt_transfer = NULL; 208 212 if (batch) { 209 const usb_target_t target = batch->ep->target; 213 const usb_target_t target = {{ 214 .address = batch->ep->address, 215 .endpoint = batch->ep->endpoint, 216 }}; 210 217 batch->error = virthub_base_request(&instance->base, target, 211 batch->dir, &batch->setup.packet, 218 usb_transfer_batch_direction(batch), 219 (void*)batch->setup_buffer, 212 220 batch->buffer, batch->buffer_size, &batch->transfered_size); 213 usb_transfer_batch_finish(batch); 221 usb_transfer_batch_finish(batch, NULL); 222 usb_transfer_batch_destroy(batch); 214 223 } 215 224 return EOK; -
uspace/drv/bus/usb/uhci/hc.c
re160bfe8 r367db39a 50 50 #include <usb/usb.h> 51 51 #include <usb/host/utils/malloc32.h> 52 #include <usb/host/bandwidth.h>53 52 54 53 #include "uhci_batch.h" … … 107 106 * @return Error code. 108 107 */ 109 int uhci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd,const hw_res_list_parsed_t *hw_res)108 int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res) 110 109 { 111 110 assert(code); … … 177 176 uhci_transfer_batch_t *batch = 178 177 uhci_transfer_batch_from_link(current); 179 u sb_transfer_batch_finish(&batch->base);178 uhci_transfer_batch_finish_dispose(batch); 180 179 } 181 180 } … … 215 214 * interrupt fibrils. 216 215 */ 217 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res )216 int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts) 218 217 { 219 218 assert(instance); … … 223 222 return EINVAL; 224 223 224 instance->hw_interrupts = interrupts; 225 225 instance->hw_failures = 0; 226 226 … … 246 246 } 247 247 248 return EOK;249 }250 251 void hc_start(hc_t *instance)252 {253 248 hc_init_hw(instance); 254 249 (void)hc_debug_checker; 255 250 256 251 uhci_rh_init(&instance->rh, instance->registers->ports, "uhci"); 252 253 return EOK; 257 254 } 258 255 … … 309 306 } 310 307 311 static usb_transfer_batch_t *create_transfer_batch(bus_t *bus, endpoint_t *ep)312 {313 uhci_transfer_batch_t *batch = uhci_transfer_batch_create(ep);314 return &batch->base;315 }316 317 static void destroy_transfer_batch(usb_transfer_batch_t *batch)318 {319 uhci_transfer_batch_destroy(uhci_transfer_batch_get(batch));320 }321 322 308 /** Initialize UHCI hc memory structures. 323 309 * … … 332 318 int hc_init_mem_structures(hc_t *instance) 333 319 { 334 int err; 335 assert(instance); 336 337 if ((err = usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11))) 338 return err; 339 340 instance->bus.base.ops.create_batch = create_transfer_batch; 341 instance->bus.base.ops.destroy_batch = destroy_transfer_batch; 320 assert(instance); 342 321 343 322 /* Init USB frame list page */ … … 461 440 assert(batch); 462 441 463 if (batch->ep-> target.address == uhci_rh_get_address(&instance->rh))442 if (batch->ep->address == uhci_rh_get_address(&instance->rh)) 464 443 return uhci_rh_schedule(&instance->rh, batch); 465 444 466 uhci_transfer_batch_t *uhci_batch = (uhci_transfer_batch_t *) batch;445 uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch); 467 446 if (!uhci_batch) { 468 447 usb_log_error("Failed to create UHCI transfer structures.\n"); 469 448 return ENOMEM; 470 449 } 471 472 const int err = uhci_transfer_batch_prepare(uhci_batch);473 if (err)474 return err;475 450 476 451 transfer_list_t *list = -
uspace/drv/bus/usb/uhci/hc.h
re160bfe8 r367db39a 43 43 #include <ddi.h> 44 44 #include <usb/host/hcd.h> 45 #include <usb/host/usb2_bus.h>46 45 #include <usb/host/usb_transfer_batch.h> 47 46 … … 101 100 typedef struct hc { 102 101 uhci_rh_t rh; 103 usb2_bus_t bus;104 102 /** Addresses of I/O registers */ 105 103 uhci_regs_t *registers; … … 126 124 } hc_t; 127 125 128 extern int hc_init(hc_t *, const hw_res_list_parsed_t *); 129 extern void hc_start(hc_t *); 126 extern int hc_init(hc_t *, const hw_res_list_parsed_t *, bool); 130 127 extern void hc_fini(hc_t *); 131 128 132 extern int uhci_hc_gen_irq_code(irq_code_t *, hcd_t *,const hw_res_list_parsed_t *);129 extern int uhci_hc_gen_irq_code(irq_code_t *, const hw_res_list_parsed_t *); 133 130 134 131 extern void uhci_hc_interrupt(hcd_t *, uint32_t); -
uspace/drv/bus/usb/uhci/main.c
re160bfe8 r367db39a 49 49 #define NAME "uhci" 50 50 51 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 52 static int uhci_driver_start(hcd_t *, bool); 51 static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *, bool); 53 52 static void uhci_driver_fini(hcd_t *); 54 static int disable_legacy( hcd_t *,ddf_dev_t *);53 static int disable_legacy(ddf_dev_t *); 55 54 56 55 static const ddf_hc_driver_t uhci_hc_driver = { 57 56 .claim = disable_legacy, 57 .hc_speed = USB_SPEED_FULL, 58 58 .irq_code_gen = uhci_hc_gen_irq_code, 59 59 .init = uhci_driver_init, 60 .start = uhci_driver_start,61 .setup_root_hub = hcd_setup_virtual_root_hub,62 60 .fini = uhci_driver_fini, 63 61 .name = "UHCI", … … 69 67 }; 70 68 71 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device)69 static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, bool irq) 72 70 { 73 int err;74 75 71 assert(hcd); 76 72 assert(hcd_get_driver_data(hcd) == NULL); … … 80 76 return ENOMEM; 81 77 82 if ((err = hc_init(instance, res)) != EOK) 83 goto err; 84 85 hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops, &instance->bus.base); 86 87 return EOK; 88 89 err: 90 free(instance); 91 return err; 92 } 93 94 static int uhci_driver_start(hcd_t *hcd, bool interrupts) 95 { 96 assert(hcd); 97 hc_t *hc = hcd_get_driver_data(hcd); 98 99 hc->hw_interrupts = interrupts; 100 hc_start(hc); 101 return EOK; 78 const int ret = hc_init(instance, res, irq); 79 if (ret == EOK) { 80 hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops); 81 } else { 82 free(instance); 83 } 84 return ret; 102 85 } 103 86 … … 109 92 hc_fini(hc); 110 93 111 hcd_set_implementation(hcd, NULL, NULL , NULL);94 hcd_set_implementation(hcd, NULL, NULL); 112 95 free(hc); 113 96 } … … 118 101 * @return Error code. 119 102 */ 120 static int disable_legacy( hcd_t *hcd,ddf_dev_t *device)103 static int disable_legacy(ddf_dev_t *device) 121 104 { 122 105 assert(device); -
uspace/drv/bus/usb/uhci/transfer_list.c
re160bfe8 r367db39a 167 167 uhci_transfer_batch_from_link(current); 168 168 169 if (uhci_transfer_batch_ check_completed(batch)) {169 if (uhci_transfer_batch_is_complete(batch)) { 170 170 /* Save for processing */ 171 171 transfer_list_remove_batch(instance, batch); -
uspace/drv/bus/usb/uhci/uhci_batch.c
re160bfe8 r367db39a 50 50 #define DEFAULT_ERROR_COUNT 3 51 51 52 /** Safely destructs uhci_transfer_batch_t structure. 53 * 54 * @param[in] uhci_batch Instance to destroy. 55 */ 56 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch) 57 { 58 if (uhci_batch) { 59 usb_transfer_batch_destroy(uhci_batch->usb_batch); 60 free32(uhci_batch->device_buffer); 61 free(uhci_batch); 62 } 63 } 64 65 /** Finishes usb_transfer_batch and destroys the structure. 66 * 67 * @param[in] uhci_batch Instance to finish and destroy. 68 */ 69 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch) 70 { 71 assert(uhci_batch); 72 assert(uhci_batch->usb_batch); 73 assert(!link_in_use(&uhci_batch->link)); 74 usb_transfer_batch_finish(uhci_batch->usb_batch, 75 uhci_transfer_batch_data_buffer(uhci_batch)); 76 uhci_transfer_batch_dispose(uhci_batch); 77 } 78 52 79 /** Transfer batch setup table. */ 53 static void (*const batch_setup[])(uhci_transfer_batch_t*); 54 55 /** Destroys uhci_transfer_batch_t structure. 56 * 57 * @param[in] uhci_batch Instance to destroy. 58 */ 59 void uhci_transfer_batch_destroy(uhci_transfer_batch_t *uhci_batch) 60 { 61 assert(uhci_batch); 62 free32(uhci_batch->device_buffer); 63 free(uhci_batch); 64 } 80 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t); 65 81 66 82 /** Allocate memory and initialize internal data structure. … … 69 85 * @return Valid pointer if all structures were successfully created, 70 86 * NULL otherwise. 71 */72 uhci_transfer_batch_t * uhci_transfer_batch_create(endpoint_t *ep)73 {74 uhci_transfer_batch_t *uhci_batch =75 calloc(1, sizeof(uhci_transfer_batch_t));76 if (!uhci_batch) {77 usb_log_error("Failed to allocate UHCI batch.\n");78 return NULL;79 }80 81 usb_transfer_batch_init(&uhci_batch->base, ep);82 83 link_initialize(&uhci_batch->link);84 return uhci_batch;85 }86 87 /* Prepares batch for commiting.88 87 * 89 88 * Determines the number of needed transfer descriptors (TDs). … … 91 90 * Initializes parameters needed for the transfer and callback. 92 91 */ 93 int uhci_transfer_batch_prepare(uhci_transfer_batch_t *uhci_batch)92 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 94 93 { 95 94 static_assert((sizeof(td_t) % 16) == 0); 96 97 usb_transfer_batch_t *usb_batch = &uhci_batch->base; 98 99 uhci_batch->td_count = (usb_batch->buffer_size + usb_batch->ep->max_packet_size - 1) 100 / usb_batch->ep->max_packet_size; 101 95 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \ 96 if (ptr == NULL) { \ 97 usb_log_error(message); \ 98 uhci_transfer_batch_dispose(uhci_batch); \ 99 return NULL; \ 100 } else (void)0 101 102 uhci_transfer_batch_t *uhci_batch = 103 calloc(1, sizeof(uhci_transfer_batch_t)); 104 CHECK_NULL_DISPOSE_RETURN(uhci_batch, 105 "Failed to allocate UHCI batch.\n"); 106 link_initialize(&uhci_batch->link); 107 uhci_batch->td_count = 108 (usb_batch->buffer_size + usb_batch->ep->max_packet_size - 1) 109 / usb_batch->ep->max_packet_size; 102 110 if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 103 111 uhci_batch->td_count += 2; 104 112 } 105 113 106 const size_t setup_size = (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)107 ? USB_SETUP_PACKET_SIZE108 : 0;109 110 114 const size_t total_size = (sizeof(td_t) * uhci_batch->td_count) 111 + sizeof(qh_t) + setup_size + usb_batch->buffer_size;115 + sizeof(qh_t) + usb_batch->setup_size + usb_batch->buffer_size; 112 116 uhci_batch->device_buffer = malloc32(total_size); 113 if (!uhci_batch->device_buffer) { 114 usb_log_error("Failed to allocate UHCI buffer.\n"); 115 return ENOMEM; 116 } 117 CHECK_NULL_DISPOSE_RETURN(uhci_batch->device_buffer, 118 "Failed to allocate UHCI buffer.\n"); 117 119 memset(uhci_batch->device_buffer, 0, total_size); 118 120 … … 128 130 + sizeof(qh_t); 129 131 /* Copy SETUP packet data to the device buffer */ 130 memcpy(dest, usb_batch->setup .buffer,setup_size);131 dest += setup_size;132 memcpy(dest, usb_batch->setup_buffer, usb_batch->setup_size); 133 dest += usb_batch->setup_size; 132 134 /* Copy generic data unless they are provided by the device */ 133 135 if (usb_batch->ep->direction != USB_DIRECTION_IN) { 134 136 memcpy(dest, usb_batch->buffer, usb_batch->buffer_size); 135 137 } 138 uhci_batch->usb_batch = usb_batch; 136 139 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT 137 140 " memory structures ready.\n", usb_batch, 138 141 USB_TRANSFER_BATCH_ARGS(*usb_batch)); 139 142 143 const usb_direction_t dir = usb_transfer_batch_direction(usb_batch); 144 140 145 assert(batch_setup[usb_batch->ep->transfer_type]); 141 batch_setup[usb_batch->ep->transfer_type](uhci_batch );142 143 return EOK;146 batch_setup[usb_batch->ep->transfer_type](uhci_batch, dir); 147 148 return uhci_batch; 144 149 } 145 150 … … 153 158 * is reached. 154 159 */ 155 bool uhci_transfer_batch_ check_completed(uhci_transfer_batch_t *uhci_batch)160 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch) 156 161 { 157 162 assert(uhci_batch); 163 assert(uhci_batch->usb_batch); 158 164 159 165 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT … … 162 168 USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch), 163 169 uhci_batch->td_count); 164 uhci_batch-> base.transfered_size = 0;170 uhci_batch->usb_batch->transfered_size = 0; 165 171 166 172 for (size_t i = 0;i < uhci_batch->td_count; ++i) { … … 169 175 } 170 176 171 uhci_batch-> base.error = td_status(&uhci_batch->tds[i]);172 if (uhci_batch-> base.error != EOK) {173 assert(uhci_batch-> base.ep != NULL);177 uhci_batch->usb_batch->error = td_status(&uhci_batch->tds[i]); 178 if (uhci_batch->usb_batch->error != EOK) { 179 assert(uhci_batch->usb_batch->ep != NULL); 174 180 175 181 usb_log_debug("Batch %p found error TD(%zu->%p):%" … … 178 184 td_print_status(&uhci_batch->tds[i]); 179 185 180 endpoint_toggle_set(uhci_batch-> base.ep,186 endpoint_toggle_set(uhci_batch->usb_batch->ep, 181 187 td_toggle(&uhci_batch->tds[i])); 182 188 if (i > 0) … … 185 191 } 186 192 187 uhci_batch-> base.transfered_size193 uhci_batch->usb_batch->transfered_size 188 194 += td_act_size(&uhci_batch->tds[i]); 189 195 if (td_is_short(&uhci_batch->tds[i])) … … 191 197 } 192 198 substract_ret: 193 if (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL)194 uhci_batch->base.transfered_size -= USB_SETUP_PACKET_SIZE;199 uhci_batch->usb_batch->transfered_size 200 -= uhci_batch->usb_batch->setup_size; 195 201 return true; 196 202 } … … 210 216 * The last transfer is marked with IOC flag. 211 217 */ 212 static void batch_data(uhci_transfer_batch_t *uhci_batch )218 static void batch_data(uhci_transfer_batch_t *uhci_batch, usb_direction_t dir) 213 219 { 214 220 assert(uhci_batch); 215 216 usb_direction_t dir = uhci_batch->base.dir;221 assert(uhci_batch->usb_batch); 222 assert(uhci_batch->usb_batch->ep); 217 223 assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN); 218 224 … … 220 226 const usb_packet_id pid = direction_pids[dir]; 221 227 const bool low_speed = 222 uhci_batch->base.ep->speed == USB_SPEED_LOW; 223 const size_t mps = uhci_batch->base.ep->max_packet_size; 224 const usb_target_t target = uhci_batch->base.ep->target; 225 226 int toggle = endpoint_toggle_get(uhci_batch->base.ep); 228 uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW; 229 const size_t mps = uhci_batch->usb_batch->ep->max_packet_size; 230 const usb_target_t target = {{ 231 uhci_batch->usb_batch->ep->address, 232 uhci_batch->usb_batch->ep->endpoint }}; 233 234 int toggle = endpoint_toggle_get(uhci_batch->usb_batch->ep); 227 235 assert(toggle == 0 || toggle == 1); 228 236 229 237 size_t td = 0; 230 size_t remain_size = uhci_batch-> base.buffer_size;238 size_t remain_size = uhci_batch->usb_batch->buffer_size; 231 239 char *buffer = uhci_transfer_batch_data_buffer(uhci_batch); 232 240 … … 248 256 } 249 257 td_set_ioc(&uhci_batch->tds[td - 1]); 250 endpoint_toggle_set(uhci_batch-> base.ep, toggle);258 endpoint_toggle_set(uhci_batch->usb_batch->ep, toggle); 251 259 usb_log_debug2( 252 260 "Batch %p %s %s " USB_TRANSFER_BATCH_FMT " initialized.\n", \ 253 261 uhci_batch->usb_batch, 254 usb_str_transfer_type(uhci_batch-> base.ep->transfer_type),255 usb_str_direction(uhci_batch-> base.ep->direction),262 usb_str_transfer_type(uhci_batch->usb_batch->ep->transfer_type), 263 usb_str_direction(uhci_batch->usb_batch->ep->direction), 256 264 USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch)); 257 265 } … … 268 276 * The last transfer is marked with IOC. 269 277 */ 270 static void batch_control(uhci_transfer_batch_t *uhci_batch )278 static void batch_control(uhci_transfer_batch_t *uhci_batch, usb_direction_t dir) 271 279 { 272 280 assert(uhci_batch); 273 274 usb_direction_t dir = uhci_batch->base.dir;281 assert(uhci_batch->usb_batch); 282 assert(uhci_batch->usb_batch->ep); 275 283 assert(dir == USB_DIRECTION_OUT || dir == USB_DIRECTION_IN); 276 284 assert(uhci_batch->td_count >= 2); … … 283 291 const usb_packet_id status_stage_pid = status_stage_pids[dir]; 284 292 const bool low_speed = 285 uhci_batch->base.ep->speed == USB_SPEED_LOW; 286 const size_t mps = uhci_batch->base.ep->max_packet_size; 287 const usb_target_t target = uhci_batch->base.ep->target; 293 uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW; 294 const size_t mps = uhci_batch->usb_batch->ep->max_packet_size; 295 const usb_target_t target = {{ 296 uhci_batch->usb_batch->ep->address, 297 uhci_batch->usb_batch->ep->endpoint }}; 288 298 289 299 /* setup stage */ 290 300 td_init( 291 301 &uhci_batch->tds[0], DEFAULT_ERROR_COUNT, 292 USB_SETUP_PACKET_SIZE, 0, false,302 uhci_batch->usb_batch->setup_size, 0, false, 293 303 low_speed, target, USB_PID_SETUP, 294 304 uhci_transfer_batch_setup_buffer(uhci_batch), &uhci_batch->tds[1]); … … 297 307 size_t td = 1; 298 308 unsigned toggle = 1; 299 size_t remain_size = uhci_batch-> base.buffer_size;309 size_t remain_size = uhci_batch->usb_batch->buffer_size; 300 310 char *buffer = uhci_transfer_batch_data_buffer(uhci_batch); 301 311 … … 327 337 } 328 338 329 static void (*const batch_setup[])(uhci_transfer_batch_t* ) =339 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t) = 330 340 { 331 341 [USB_TRANSFER_CONTROL] = batch_control, -
uspace/drv/bus/usb/uhci/uhci_batch.h
re160bfe8 r367db39a 43 43 #include <stddef.h> 44 44 #include <usb/host/usb_transfer_batch.h> 45 #include <usb/host/endpoint.h>46 45 47 46 #include "hw_struct/queue_head.h" … … 50 49 /** UHCI specific data required for USB transfer */ 51 50 typedef struct uhci_transfer_batch { 52 usb_transfer_batch_t base;53 54 51 /** Queue head 55 52 * This QH is used to maintain UHCI schedule structure and the element … … 69 66 } uhci_transfer_batch_t; 70 67 71 uhci_transfer_batch_t * uhci_transfer_batch_create(endpoint_t *ep); 72 int uhci_transfer_batch_prepare(uhci_transfer_batch_t *uhci_batch); 73 bool uhci_transfer_batch_check_completed(uhci_transfer_batch_t *uhci_batch); 74 void uhci_transfer_batch_destroy(uhci_transfer_batch_t *uhci_batch); 68 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch); 69 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch); 70 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch); 75 71 76 72 /** Get offset to setup buffer accessible to the HC hw. … … 97 93 assert(uhci_batch->usb_batch); 98 94 return uhci_transfer_batch_setup_buffer(uhci_batch) + 99 (uhci_batch->base.ep->transfer_type == USB_TRANSFER_CONTROL ? USB_SETUP_PACKET_SIZE : 0);95 uhci_batch->usb_batch->setup_size; 100 96 } 101 97 … … 111 107 uhci_batch->usb_batch->error = EINTR; 112 108 uhci_batch->usb_batch->transfered_size = 0; 113 u sb_transfer_batch_finish(&uhci_batch->base);109 uhci_transfer_batch_finish_dispose(uhci_batch); 114 110 } 115 111 … … 124 120 } 125 121 126 static inline uhci_transfer_batch_t *uhci_transfer_batch_get(usb_transfer_batch_t *b)127 {128 assert(b);129 return (uhci_transfer_batch_t *) b;130 }131 132 122 #endif 133 123 -
uspace/drv/bus/usb/uhci/uhci_rh.c
re160bfe8 r367db39a 39 39 #include <usb/classes/hub.h> 40 40 #include <usb/request.h> 41 #include <usb/host/endpoint.h>42 41 #include <usb/usb.h> 43 42 … … 104 103 assert(batch); 105 104 106 const usb_target_t target = batch->ep->target; 105 const usb_target_t target = {{ 106 .address = batch->ep->address, 107 .endpoint = batch->ep->endpoint 108 }}; 107 109 do { 108 110 batch->error = virthub_base_request(&instance->base, target, 109 batch->dir, (void*) batch->setup.buffer,111 usb_transfer_batch_direction(batch), (void*)batch->setup_buffer, 110 112 batch->buffer, batch->buffer_size, &batch->transfered_size); 111 113 if (batch->error == ENAK) … … 114 116 //ENAK is technically an error condition 115 117 } while (batch->error == ENAK); 116 usb_transfer_batch_finish(batch); 118 usb_transfer_batch_finish(batch, NULL); 119 usb_transfer_batch_destroy(batch); 117 120 return EOK; 118 121 } -
uspace/drv/bus/usb/usbhid/main.c
re160bfe8 r367db39a 95 95 usb_hid_polling_callback, 96 96 /* How much data to request. */ 97 hid_dev->poll_pipe_mapping->pipe. desc.max_packet_size,97 hid_dev->poll_pipe_mapping->pipe.max_packet_size, 98 98 /* Delay */ 99 99 -1, -
uspace/drv/bus/usb/usbhub/status.h
re160bfe8 r367db39a 110 110 if ((status & USB_HUB_PORT_STATUS_HIGH_SPEED) != 0) 111 111 return USB_SPEED_HIGH; 112 /* TODO: add super speed */113 112 return USB_SPEED_FULL; 114 113 } -
uspace/drv/bus/usb/usbmast/main.c
re160bfe8 r367db39a 172 172 usb_device_get_name(dev)); 173 173 usb_log_debug("Bulk in endpoint: %d [%zuB].\n", 174 epm_in->pipe. desc.endpoint_no, epm_in->pipe.desc.max_packet_size);174 epm_in->pipe.endpoint_no, epm_in->pipe.max_packet_size); 175 175 usb_log_debug("Bulk out endpoint: %d [%zuB].\n", 176 epm_out->pipe. desc.endpoint_no, epm_out->pipe.desc.max_packet_size);176 epm_out->pipe.endpoint_no, epm_out->pipe.max_packet_size); 177 177 178 178 usb_log_debug("Get LUN count...\n"); -
uspace/drv/bus/usb/vhc/main.c
re160bfe8 r367db39a 89 89 90 90 /* Initialize generic structures */ 91 ret = hcd_ddf_setup_hc(dev); 91 ret = hcd_ddf_setup_hc(dev, USB_SPEED_FULL, 92 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 92 93 if (ret != EOK) { 93 94 usb_log_error("Failed to init HCD structures: %s.\n", … … 97 98 } 98 99 99 hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops , &data->bus.base);100 hcd_set_implementation(dev_to_hcd(dev), data, &vhc_hc_ops); 100 101 101 102 /* Add virtual hub device */ … … 111 112 * needs to be ready at this time. 112 113 */ 113 ret = hcd_ setup_virtual_root_hub(dev_to_hcd(dev),dev);114 ret = hcd_ddf_setup_root_hub(dev); 114 115 if (ret != EOK) { 115 116 usb_log_error("Failed to init VHC root hub: %s\n", -
uspace/drv/bus/usb/vhc/transfer.c
re160bfe8 r367db39a 31 31 #include <usb/debug.h> 32 32 #include <usbvirt/device.h> 33 #include <usb/host/bandwidth.h>34 33 #include <usbvirt/ipc.h> 35 34 #include "vhcd.h" … … 38 37 static bool is_set_address_transfer(vhc_transfer_t *transfer) 39 38 { 40 if (transfer->batch->ep-> target.endpoint != 0) {39 if (transfer->batch->ep->endpoint != 0) { 41 40 return false; 42 41 } … … 44 43 return false; 45 44 } 46 if ( transfer->batch->dir!= USB_DIRECTION_OUT) {47 return false; 48 } 49 const usb_device_request_setup_packet_t *setup 50 = &transfer->batch->setup.packet;45 if (usb_transfer_batch_direction(transfer->batch) != USB_DIRECTION_OUT) { 46 return false; 47 } 48 const usb_device_request_setup_packet_t *setup = 49 (void*)transfer->batch->setup_buffer; 51 50 if (setup->request_type != 0) { 52 51 return false; … … 63 62 { 64 63 int rc; 65 66 const usb_direction_t dir = batch->dir;64 65 const usb_direction_t dir = usb_transfer_batch_direction(batch); 67 66 68 67 if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 69 68 if (dir == USB_DIRECTION_IN) { 70 69 rc = usbvirt_control_read(dev, 71 batch->setup .buffer, USB_SETUP_PACKET_SIZE,70 batch->setup_buffer, batch->setup_size, 72 71 batch->buffer, batch->buffer_size, 73 72 actual_data_size); … … 75 74 assert(dir == USB_DIRECTION_OUT); 76 75 rc = usbvirt_control_write(dev, 77 batch->setup .buffer, USB_SETUP_PACKET_SIZE,76 batch->setup_buffer, batch->setup_size, 78 77 batch->buffer, batch->buffer_size); 79 78 } … … 81 80 if (dir == USB_DIRECTION_IN) { 82 81 rc = usbvirt_data_in(dev, batch->ep->transfer_type, 83 batch->ep-> target.endpoint,82 batch->ep->endpoint, 84 83 batch->buffer, batch->buffer_size, 85 84 actual_data_size); … … 87 86 assert(dir == USB_DIRECTION_OUT); 88 87 rc = usbvirt_data_out(dev, batch->ep->transfer_type, 89 batch->ep-> target.endpoint,88 batch->ep->endpoint, 90 89 batch->buffer, batch->buffer_size); 91 90 } … … 100 99 int rc; 101 100 102 const usb_direction_t dir = batch->dir;101 const usb_direction_t dir = usb_transfer_batch_direction(batch); 103 102 104 103 if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 105 104 if (dir == USB_DIRECTION_IN) { 106 105 rc = usbvirt_ipc_send_control_read(sess, 107 batch->setup .buffer, USB_SETUP_PACKET_SIZE,106 batch->setup_buffer, batch->setup_size, 108 107 batch->buffer, batch->buffer_size, 109 108 actual_data_size); … … 111 110 assert(dir == USB_DIRECTION_OUT); 112 111 rc = usbvirt_ipc_send_control_write(sess, 113 batch->setup .buffer, USB_SETUP_PACKET_SIZE,112 batch->setup_buffer, batch->setup_size, 114 113 batch->buffer, batch->buffer_size); 115 114 } 116 115 } else { 117 116 if (dir == USB_DIRECTION_IN) { 118 rc = usbvirt_ipc_send_data_in(sess, batch->ep-> target.endpoint,117 rc = usbvirt_ipc_send_data_in(sess, batch->ep->endpoint, 119 118 batch->ep->transfer_type, 120 119 batch->buffer, batch->buffer_size, … … 122 121 } else { 123 122 assert(dir == USB_DIRECTION_OUT); 124 rc = usbvirt_ipc_send_data_out(sess, batch->ep-> target.endpoint,123 rc = usbvirt_ipc_send_data_out(sess, batch->ep->endpoint, 125 124 batch->ep->transfer_type, 126 125 batch->buffer, batch->buffer_size); … … 149 148 assert(transfer); 150 149 assert(transfer->batch); 151 transfer->batch->error = outcome;152 transfer->batch->transfered_size = data_transfer_size;153 usb_transfer_batch_ finish(transfer->batch);150 usb_transfer_batch_finish_error(transfer->batch, NULL, 151 data_transfer_size, outcome); 152 usb_transfer_batch_destroy(transfer->batch); 154 153 free(transfer); 155 154 } … … 160 159 list_initialize(&instance->devices); 161 160 fibril_mutex_initialize(&instance->guard); 162 usb2_bus_init(&instance->bus, BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11);163 161 instance->magic = 0xDEADBEEF; 164 162 return virthub_init(&instance->hub, "root hub"); … … 184 182 list_foreach(vhc->devices, link, vhc_virtdev_t, dev) { 185 183 fibril_mutex_lock(&dev->guard); 186 if (dev->address == transfer->batch->ep-> target.address) {184 if (dev->address == transfer->batch->ep->address) { 187 185 if (!targets) { 188 186 list_append(&transfer->link, &dev->transfer_queue); … … 236 234 if (is_set_address_transfer(transfer)) { 237 235 usb_device_request_setup_packet_t *setup = 238 (void*) transfer->batch->setup .buffer;236 (void*) transfer->batch->setup_buffer; 239 237 dev->address = setup->value; 240 238 usb_log_debug2("Address changed to %d\n", -
uspace/drv/bus/usb/vhc/vhcd.h
re160bfe8 r367db39a 42 42 43 43 #include <usb/host/hcd.h> 44 #include <usb/host/usb2_bus.h>45 44 46 45 #define NAME "vhc" … … 61 60 fibril_mutex_t guard; 62 61 usbvirt_device_t hub; 63 usb2_bus_t bus;64 62 } vhc_data_t; 65 63 -
uspace/lib/c/include/bitops.h
re160bfe8 r367db39a 54 54 #define BIT_RANGE_EXTRACT(type, hi, lo, value) \ 55 55 (((value) >> (lo)) & BIT_RRANGE(type, (hi) - (lo) + 1)) 56 57 /** Insert @a value between bits @a hi .. @a lo. */58 #define BIT_RANGE_INSERT(type, hi, lo, value) \59 (((value) & BIT_RRANGE(type, (hi) - (lo) + 1)) << (lo))60 56 61 57 /** Return position of first non-zero bit from left (i.e. [log_2(arg)]). -
uspace/lib/c/include/byteorder.h
re160bfe8 r367db39a 85 85 #define ntohl(n) uint32_t_be2host((n)) 86 86 87 #define uint8_t_be2host(n) (n)88 #define uint8_t_le2host(n) (n)89 #define host2uint8_t_be(n) (n)90 #define host2uint8_t_le(n) (n)91 92 87 static inline uint64_t uint64_t_byteorder_swap(uint64_t n) 93 88 { -
uspace/lib/drv/generic/remote_usb.c
re160bfe8 r367db39a 175 175 } pack8_t; 176 176 177 int usb_register_endpoint(async_exch_t *exch, 178 usb_endpoint_desc_t *endpoint_desc) 179 { 180 if (!exch) 181 return EBADMEM; 182 183 aid_t opening_request = async_send_1(exch, 184 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_REGISTER_ENDPOINT, NULL); 185 186 if (opening_request == 0) { 187 return ENOMEM; 188 } 189 190 const int ret = async_data_write_start(exch, (void *) endpoint_desc, 191 sizeof(usb_endpoint_desc_t)); 192 193 if (ret != EOK) { 194 async_forget(opening_request); 195 return ret; 196 } 197 198 /* Wait for the answer. */ 199 sysarg_t opening_request_rc; 200 async_wait_for(opening_request, &opening_request_rc); 201 202 return (int) opening_request_rc; 203 } 204 205 int usb_unregister_endpoint(async_exch_t *exch, 206 usb_endpoint_desc_t *endpoint_desc) 207 { 208 if (!exch) 209 return EBADMEM; 210 211 aid_t opening_request = async_send_1(exch, 212 DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_UNREGISTER_ENDPOINT, NULL); 213 214 if (opening_request == 0) { 215 return ENOMEM; 216 } 217 218 const int ret = async_data_write_start(exch, endpoint_desc, 219 sizeof(usb_endpoint_desc_t)); 220 if (ret != EOK) { 221 async_forget(opening_request); 222 return ret; 223 } 224 225 /* Wait for the answer. */ 226 sysarg_t opening_request_rc; 227 async_wait_for(opening_request, &opening_request_rc); 228 229 return (int) opening_request_rc; 177 int usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint, 178 usb_transfer_type_t type, usb_direction_t direction, 179 size_t mps, unsigned packets, unsigned interval) 180 { 181 if (!exch) 182 return EBADMEM; 183 pack8_t pack; 184 pack.arr[0] = type; 185 pack.arr[1] = direction; 186 pack.arr[2] = interval; 187 pack.arr[3] = packets; 188 189 return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 190 IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps); 191 192 } 193 194 int usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint, 195 usb_direction_t direction) 196 { 197 if (!exch) 198 return EBADMEM; 199 return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE), 200 IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction); 230 201 } 231 202 … … 346 317 }; 347 318 348 typedef struct {349 ipc_callid_t caller;350 ipc_callid_t data_caller;351 void *buffer;352 } async_transaction_t;353 354 319 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface, 355 320 ipc_callid_t callid, ipc_call_t *call) … … 452 417 ipc_callid_t callid, ipc_call_t *call) 453 418 { 454 assert(fun); 455 assert(iface); 456 assert(call); 457 458 const usb_iface_t *usb_iface = iface; 419 usb_iface_t *usb_iface = (usb_iface_t *) iface; 459 420 460 421 if (!usb_iface->register_endpoint) { … … 463 424 } 464 425 465 void *buffer = NULL; 466 size_t size = 0; 467 int rc = async_data_write_accept(&buffer, false, 468 sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size); 469 470 if (rc != EOK) { 471 free(buffer); 472 async_answer_0(callid, rc); 473 return; 474 } 475 476 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer; 477 rc = usb_iface->register_endpoint(fun, endpoint_desc); 478 479 free(buffer); 426 const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call); 427 const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)}; 428 const size_t max_packet_size = DEV_IPC_GET_ARG3(*call); 429 430 const usb_transfer_type_t transfer_type = pack.arr[0]; 431 const usb_direction_t direction = pack.arr[1]; 432 unsigned packets = pack.arr[2]; 433 unsigned interval = pack.arr[3]; 434 435 const int ret = usb_iface->register_endpoint(fun, endpoint, 436 transfer_type, direction, max_packet_size, packets, interval); 437 438 async_answer_0(callid, ret); 439 } 440 441 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface, 442 ipc_callid_t callid, ipc_call_t *call) 443 { 444 usb_iface_t *usb_iface = (usb_iface_t *) iface; 445 446 if (!usb_iface->unregister_endpoint) { 447 async_answer_0(callid, ENOTSUP); 448 return; 449 } 450 451 usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call); 452 usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call); 453 454 int rc = usb_iface->unregister_endpoint(fun, endpoint, direction); 455 480 456 async_answer_0(callid, rc); 481 457 } 482 458 483 static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface, 484 ipc_callid_t callid, ipc_call_t *call) 485 { 486 assert(fun); 487 assert(iface); 488 assert(call); 489 490 const usb_iface_t *usb_iface = iface; 491 492 if (!usb_iface->unregister_endpoint) { 493 async_answer_0(callid, ENOTSUP); 494 return; 495 } 496 497 void *buffer = NULL; 498 size_t size = 0; 499 int rc = async_data_write_accept(&buffer, false, 500 sizeof(usb_endpoint_desc_t), sizeof(usb_endpoint_desc_t), 0, &size); 501 502 if (rc != EOK) { 503 free(buffer); 504 async_answer_0(callid, rc); 505 return; 506 } 507 508 usb_endpoint_desc_t *endpoint_desc = (usb_endpoint_desc_t *) buffer; 509 usb_iface->unregister_endpoint(fun, endpoint_desc); 510 511 free(buffer); 512 async_answer_0(callid, rc); 513 } 459 typedef struct { 460 ipc_callid_t caller; 461 ipc_callid_t data_caller; 462 void *buffer; 463 } async_transaction_t; 514 464 515 465 static void async_transaction_destroy(async_transaction_t *trans) -
uspace/lib/drv/include/usb_iface.h
re160bfe8 r367db39a 57 57 extern int usb_device_remove(async_exch_t *, unsigned port); 58 58 59 extern int usb_register_endpoint(async_exch_t *, usb_endpoint_desc_t *); 60 extern int usb_unregister_endpoint(async_exch_t *, usb_endpoint_desc_t *); 59 extern int usb_register_endpoint(async_exch_t *, usb_endpoint_t, 60 usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned); 61 extern int usb_unregister_endpoint(async_exch_t *, usb_endpoint_t, 62 usb_direction_t); 61 63 extern int usb_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t, 62 64 size_t *); … … 81 83 int (*device_remove)(ddf_fun_t *, unsigned); 82 84 83 int (*register_endpoint)(ddf_fun_t *, usb_endpoint_desc_t *); 84 int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_desc_t *); 85 int (*register_endpoint)(ddf_fun_t *, usb_endpoint_t, 86 usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned); 87 int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_t, 88 usb_direction_t); 85 89 86 90 int (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t, -
uspace/lib/pcm/src/format.c
re160bfe8 r367db39a 41 41 42 42 #include "format.h" 43 44 #define uint8_t_le2host(x) (x) 45 #define host2uint8_t_le(x) (x) 46 #define uint8_t_be2host(x) (x) 47 #define host2uint8_t_be(x) (x) 43 48 44 49 #define int8_t_le2host(x) (x) -
uspace/lib/usb/include/usb/descriptor.h
re160bfe8 r367db39a 49 49 USB_DESCTYPE_OTHER_SPEED_CONFIGURATION = 7, 50 50 USB_DESCTYPE_INTERFACE_POWER = 8, 51 /* USB 3.0 types */52 USB_DESCTYPE_OTG = 9,53 USB_DESCTYPE_DEBUG = 0xa,54 USB_DESCTYPE_IFACE_ASSOC = 0xb,55 USB_DESCTYPE_BOS = 0xf,56 USB_DESCTYPE_DEVICE_CAP = 0x10,57 51 /* Class specific */ 58 52 USB_DESCTYPE_HID = 0x21, … … 60 54 USB_DESCTYPE_HID_PHYSICAL = 0x23, 61 55 USB_DESCTYPE_HUB = 0x29, 62 USB_DESCTYPE_SSPEED_EP_COMPANION = 0x3063 56 /* USB_DESCTYPE_ = */ 64 57 } usb_descriptor_type_t; … … 224 217 } __attribute__ ((packed)) usb_standard_endpoint_descriptor_t; 225 218 226 /** Superspeed USB endpoint companion descriptor.227 * See USB 3 specification, section 9.6.7.228 */229 typedef struct {230 /** Size of this descriptor in bytes */231 uint8_t length;232 /** Descriptor type (USB_DESCTYPE_SSPEED_EP_COMPANION). */233 uint8_t descriptor_type;234 /** The maximum number of packets the endpoint can send235 * or receive as part of a burst. Valid values are from 0 to 15.236 * The endpoint can only burst max_burst + 1 packets at a time.237 */238 uint8_t max_burst;239 /** Valid only for bulk and isochronous endpoints.240 * For bulk endpoints, this field contains the amount of streams241 * supported by the endpoint.242 * For isochronous endpoints, this field contains either maximum243 * number of packets supported within a service interval, or244 * whether an isochronous endpoint companion descriptor follows.245 */246 uint8_t attributes;247 /** The total number of bytes this endpoint will transfer248 * every service interval (SI).249 * This field is only valid for periodic endpoints.250 */251 uint16_t bytes_per_interval;252 } __attribute__ ((packed)) usb_superspeed_endpoint_companion_descriptor_t;253 254 219 /** Part of standard USB HID descriptor specifying one class descriptor. 255 220 * -
uspace/lib/usb/include/usb/request.h
re160bfe8 r367db39a 109 109 int assert[(sizeof(usb_device_request_setup_packet_t) == 8) ? 1: -1]; 110 110 111 /** How much toggles needs to be reset */ 112 typedef enum { 113 RESET_NONE, 114 RESET_EP, 115 RESET_ALL 116 } toggle_reset_mode_t; 117 118 toggle_reset_mode_t usb_request_get_toggle_reset_mode( 111 int usb_request_needs_toggle_reset( 119 112 const usb_device_request_setup_packet_t *request); 120 121 #define GET_DEVICE_DESC(size) \122 { \123 .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \124 | (USB_REQUEST_TYPE_STANDARD << 5) \125 | USB_REQUEST_RECIPIENT_DEVICE, \126 .request = USB_DEVREQ_GET_DESCRIPTOR, \127 .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \128 .index = uint16_host2usb(0), \129 .length = uint16_host2usb(size), \130 };131 132 #define SET_ADDRESS(address) \133 { \134 .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \135 | (USB_REQUEST_TYPE_STANDARD << 5) \136 | USB_REQUEST_RECIPIENT_DEVICE, \137 .request = USB_DEVREQ_SET_ADDRESS, \138 .value = uint16_host2usb(address), \139 .index = uint16_host2usb(0), \140 .length = uint16_host2usb(0), \141 };142 143 #define CTRL_PIPE_MIN_PACKET_SIZE 8144 113 145 114 #endif -
uspace/lib/usb/include/usb/usb.h
re160bfe8 r367db39a 81 81 /** USB 2.0 high speed (480Mbits/s). */ 82 82 USB_SPEED_HIGH, 83 /** USB 3.0 super speed (5Gbits/s). */84 USB_SPEED_SUPER,85 83 /** Psuedo-speed serving as a boundary. */ 86 84 USB_SPEED_MAX … … 115 113 typedef int16_t usb_address_t; 116 114 117 typedef struct {118 usb_address_t address;119 unsigned port;120 } usb_tt_address_t;121 122 115 /** Default USB address. */ 123 116 #define USB_ADDRESS_DEFAULT 0 … … 164 157 165 158 166 /** USB complete address type. 159 /** USB complete address type. 167 160 * Pair address + endpoint is identification of transaction recipient. 168 161 */ … … 174 167 uint32_t packed; 175 168 } usb_target_t; 176 177 /** Description of usb endpoint.178 */179 typedef struct {180 /** Endpoint number. */181 usb_endpoint_t endpoint_no;182 183 /** Endpoint transfer type. */184 usb_transfer_type_t transfer_type;185 186 /** Endpoint direction. */187 usb_direction_t direction;188 189 /** Maximum packet size for the endpoint. */190 size_t max_packet_size;191 192 /** Number of packets per frame/uframe.193 * Only valid for HS INT and ISO transfers. All others should set to 1*/194 unsigned packets;195 196 struct {197 unsigned polling_interval;198 } usb2;199 } usb_endpoint_desc_t;200 169 201 170 /** Check USB target for allowed values (address and endpoint). -
uspace/lib/usb/src/usb.c
re160bfe8 r367db39a 44 44 [USB_SPEED_FULL] = "full", 45 45 [USB_SPEED_HIGH] = "high", 46 [USB_SPEED_SUPER] = "super",47 46 }; 48 47 … … 128 127 * 129 128 */ 130 toggle_reset_mode_t usb_request_get_toggle_reset_mode(129 int usb_request_needs_toggle_reset( 131 130 const usb_device_request_setup_packet_t *request) 132 131 { … … 139 138 if ((request->request_type == 0x2) && 140 139 (request->value == USB_FEATURE_ENDPOINT_HALT)) 141 return RESET_EP;140 return uint16_usb2host(request->index); 142 141 break; 143 142 case USB_DEVREQ_SET_CONFIGURATION: … … 149 148 * interface of an already setup device. */ 150 149 if (!(request->request_type & SETUP_REQUEST_TYPE_DEVICE_TO_HOST)) 151 return RESET_ALL;150 return 0; 152 151 break; 153 152 default: 154 153 break; 155 154 } 156 157 return RESET_NONE; 155 return -1; 158 156 } 159 157 -
uspace/lib/usbdev/include/usb/dev/pipes.h
re160bfe8 r367db39a 50 50 */ 51 51 typedef struct { 52 /** Endpoint description */ 53 usb_endpoint_desc_t desc; 52 /** Endpoint number. */ 53 usb_endpoint_t endpoint_no; 54 55 /** Endpoint transfer type. */ 56 usb_transfer_type_t transfer_type; 57 58 /** Endpoint direction. */ 59 usb_direction_t direction; 60 61 /** Maximum packet size for the endpoint. */ 62 size_t max_packet_size; 63 64 /** Number of packets per frame/uframe. 65 * Only valid for HS INT and ISO transfers. All others should set to 1*/ 66 unsigned packets; 67 54 68 /** Whether to automatically reset halt on the endpoint. 55 69 * Valid only for control endpoint zero. 56 70 */ 57 71 bool auto_reset_halt; 72 58 73 /** The connection used for sending the data. */ 59 74 usb_dev_session_t *bus_session; -
uspace/lib/usbdev/src/devdrv.c
re160bfe8 r367db39a 56 56 /** Connection to device on USB bus */ 57 57 usb_dev_session_t *bus_session; 58 58 59 59 /** devman handle */ 60 60 devman_handle_t handle; 61 61 62 62 /** The default control pipe. */ 63 63 usb_pipe_t ctrl_pipe; 64 64 65 65 /** Other endpoint pipes. 66 66 * … … 69 69 */ 70 70 usb_endpoint_mapping_t *pipes; 71 71 72 72 /** Number of other endpoint pipes. */ 73 73 size_t pipes_count; 74 74 75 75 /** Current interface. 76 76 * … … 79 79 */ 80 80 int interface_no; 81 81 82 82 /** Alternative interfaces. */ 83 83 usb_alternate_interfaces_t alternate_interfaces; 84 84 85 85 /** Some useful descriptors for USB device. */ 86 86 usb_device_descriptors_t descriptors; 87 87 88 88 /** Generic DDF device backing this one. DO NOT TOUCH! */ 89 89 ddf_dev_t *ddf_dev; 90 90 91 91 /** Custom driver data. 92 92 * … … 146 146 return rc; 147 147 } 148 148 149 149 /* Change current alternative */ 150 150 usb_dev->alternate_interfaces.current = alternate_setting; … … 296 296 assert(usb_dev); 297 297 assert(usb_dev->pipes || usb_dev->pipes_count == 0); 298 298 299 299 /* Destroy the pipes. */ 300 300 for (size_t i = 0; i < usb_dev->pipes_count; ++i) { … … 304 304 usb_pipe_unregister(&usb_dev->pipes[i].pipe); 305 305 } 306 306 307 307 free(usb_dev->pipes); 308 308 usb_dev->pipes = NULL; … … 332 332 assert(usb_dev); 333 333 for (unsigned i = 0; i < usb_dev->pipes_count; ++i) { 334 if (usb_dev->pipes[i].pipe. desc.endpoint_no == ep)334 if (usb_dev->pipes[i].pipe.endpoint_no == ep) 335 335 return &usb_dev->pipes[i]; 336 336 } … … 462 462 assert(handle); 463 463 assert(iface_no); 464 464 465 465 async_exch_t *exch = async_exchange_begin(sess); 466 466 if (!exch) 467 467 return EPARTY; 468 468 469 469 int ret = usb_get_my_device_handle(exch, handle); 470 470 if (ret == EOK) { … … 475 475 } 476 476 } 477 477 478 478 async_exchange_end(exch); 479 479 return ret; … … 502 502 return ENOMEM; 503 503 } 504 504 505 505 return usb_device_init(usb_dev, ddf_dev, desc, err, h, iface_no); 506 506 } -
uspace/lib/usbdev/src/devpoll.c
re160bfe8 r367db39a 96 96 (int) mapping->interface->interface_subclass, 97 97 (int) mapping->interface->interface_protocol, 98 data->request_size, pipe-> desc.max_packet_size);98 data->request_size, pipe->max_packet_size); 99 99 } 100 100 … … 128 128 usb_request_clear_endpoint_halt( 129 129 usb_device_get_default_pipe(data->dev), 130 pipe-> desc.endpoint_no);130 pipe->endpoint_no); 131 131 } 132 132 … … 156 156 157 157 /* Take a rest before next request. */ 158 158 159 159 // FIXME TODO: This is broken, the time is in ms not us. 160 160 // but first we need to fix drivers to actually stop using this, … … 216 216 if (request_size == 0) 217 217 return EINVAL; 218 219 if (!epm || (epm->pipe. desc.transfer_type != USB_TRANSFER_INTERRUPT) ||220 (epm->pipe.d esc.direction != USB_DIRECTION_IN))218 219 if (!epm || (epm->pipe.transfer_type != USB_TRANSFER_INTERRUPT) || 220 (epm->pipe.direction != USB_DIRECTION_IN)) 221 221 return EINVAL; 222 222 223 223 224 224 polling_data_t *polling_data = malloc(sizeof(polling_data_t)); -
uspace/lib/usbdev/src/pipes.c
re160bfe8 r367db39a 51 51 assert(pipe != NULL); 52 52 53 if (!pipe->auto_reset_halt || (pipe-> desc.endpoint_no != 0)) {53 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) { 54 54 return; 55 55 } … … 88 88 } 89 89 90 if ((pipe->d esc.direction != USB_DIRECTION_BOTH)91 || (pipe-> desc.transfer_type != USB_TRANSFER_CONTROL)) {90 if ((pipe->direction != USB_DIRECTION_BOTH) 91 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 92 92 return EBADF; 93 93 } … … 98 98 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 99 99 size_t act_size = 0; 100 const int rc = usb_read(exch, pipe-> desc.endpoint_no, setup_packet, buffer,100 const int rc = usb_read(exch, pipe->endpoint_no, setup_packet, buffer, 101 101 buffer_size, &act_size); 102 102 async_exchange_end(exch); … … 142 142 } 143 143 144 if ((pipe->d esc.direction != USB_DIRECTION_BOTH)145 || (pipe-> desc.transfer_type != USB_TRANSFER_CONTROL)) {144 if ((pipe->direction != USB_DIRECTION_BOTH) 145 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 146 146 return EBADF; 147 147 } … … 152 152 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 153 153 const int rc = usb_write(exch, 154 pipe-> desc.endpoint_no, setup_packet, buffer, buffer_size);154 pipe->endpoint_no, setup_packet, buffer, buffer_size); 155 155 async_exchange_end(exch); 156 156 … … 183 183 } 184 184 185 if (pipe->d esc.direction != USB_DIRECTION_IN) {186 return EBADF; 187 } 188 189 if (pipe-> desc.transfer_type == USB_TRANSFER_CONTROL) {185 if (pipe->direction != USB_DIRECTION_IN) { 186 return EBADF; 187 } 188 189 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 190 190 return EBADF; 191 191 } 192 192 193 193 /* Isochronous transfer are not supported (yet) */ 194 if (pipe-> desc.transfer_type != USB_TRANSFER_INTERRUPT &&195 pipe-> desc.transfer_type != USB_TRANSFER_BULK)194 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 195 pipe->transfer_type != USB_TRANSFER_BULK) 196 196 return ENOTSUP; 197 197 … … 199 199 size_t act_size = 0; 200 200 const int rc = 201 usb_read(exch, pipe-> desc.endpoint_no, 0, buffer, size, &act_size);201 usb_read(exch, pipe->endpoint_no, 0, buffer, size, &act_size); 202 202 async_exchange_end(exch); 203 203 … … 224 224 } 225 225 226 if (pipe->d esc.direction != USB_DIRECTION_OUT) {227 return EBADF; 228 } 229 230 if (pipe-> desc.transfer_type == USB_TRANSFER_CONTROL) {226 if (pipe->direction != USB_DIRECTION_OUT) { 227 return EBADF; 228 } 229 230 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 231 231 return EBADF; 232 232 } 233 233 234 234 /* Isochronous transfer are not supported (yet) */ 235 if (pipe-> desc.transfer_type != USB_TRANSFER_INTERRUPT &&236 pipe-> desc.transfer_type != USB_TRANSFER_BULK)235 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 236 pipe->transfer_type != USB_TRANSFER_BULK) 237 237 return ENOTSUP; 238 238 239 239 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 240 const int rc = usb_write(exch, pipe-> desc.endpoint_no, 0, buffer, size);240 const int rc = usb_write(exch, pipe->endpoint_no, 0, buffer, size); 241 241 async_exchange_end(exch); 242 242 return rc; … … 258 258 assert(pipe); 259 259 260 pipe-> desc.endpoint_no = endpoint_no;261 pipe-> desc.transfer_type = transfer_type;262 pipe-> desc.packets = packets;263 pipe-> desc.max_packet_size = max_packet_size;264 pipe->d esc.direction = direction;260 pipe->endpoint_no = endpoint_no; 261 pipe->transfer_type = transfer_type; 262 pipe->packets = packets; 263 pipe->max_packet_size = max_packet_size; 264 pipe->direction = direction; 265 265 pipe->auto_reset_halt = false; 266 266 pipe->bus_session = bus_session; … … 297 297 assert(pipe); 298 298 assert(pipe->bus_session); 299 300 pipe->desc.usb2.polling_interval = interval;301 299 async_exch_t *exch = async_exchange_begin(pipe->bus_session); 302 300 if (!exch) 303 301 return ENOMEM; 304 305 const int ret = usb_register_endpoint(exch, &pipe->desc);306 302 const int ret = usb_register_endpoint(exch, pipe->endpoint_no, 303 pipe->transfer_type, pipe->direction, pipe->max_packet_size, 304 pipe->packets, interval); 307 305 async_exchange_end(exch); 308 306 return ret; … … 321 319 if (!exch) 322 320 return ENOMEM; 323 324 const int ret = usb_unregister_endpoint(exch, &pipe->desc); 325 321 const int ret = usb_unregister_endpoint(exch, pipe->endpoint_no, 322 pipe->direction); 326 323 async_exchange_end(exch); 327 324 return ret; -
uspace/lib/usbdev/src/pipesinit.c
re160bfe8 r367db39a 288 288 if (config_descriptor == NULL) 289 289 return EBADMEM; 290 290 291 291 if (config_descriptor_size < 292 292 sizeof(usb_standard_configuration_descriptor_t)) { … … 343 343 static_assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE); 344 344 345 if ((pipe->d esc.direction != USB_DIRECTION_BOTH) ||346 (pipe-> desc.transfer_type != USB_TRANSFER_CONTROL) ||347 (pipe-> desc.endpoint_no != 0)) {345 if ((pipe->direction != USB_DIRECTION_BOTH) || 346 (pipe->transfer_type != USB_TRANSFER_CONTROL) || 347 (pipe->endpoint_no != 0)) { 348 348 return EINVAL; 349 349 } … … 369 369 } 370 370 371 pipe-> desc.max_packet_size371 pipe->max_packet_size 372 372 = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET]; 373 373 -
uspace/lib/usbdev/src/request.c
re160bfe8 r367db39a 844 844 } 845 845 return usb_request_clear_endpoint_halt(ctrl_pipe, 846 target_pipe-> desc.endpoint_no);846 target_pipe->endpoint_no); 847 847 } 848 848 … … 858 858 { 859 859 uint16_t status_tmp; 860 uint16_t pipe_index = (uint16_t) pipe-> desc.endpoint_no;860 uint16_t pipe_index = (uint16_t) pipe->endpoint_no; 861 861 int rc = usb_request_get_status(ctrl_pipe, 862 862 USB_REQUEST_RECIPIENT_ENDPOINT, uint16_host2usb(pipe_index), -
uspace/lib/usbhost/Makefile
re160bfe8 r367db39a 39 39 src/endpoint.c \ 40 40 src/hcd.c \ 41 src/bus.c \ 42 src/usb2_bus.c \ 43 src/bandwidth.c \ 41 src/usb_bus.c \ 44 42 src/usb_transfer_batch.c 45 43 -
uspace/lib/usbhost/include/usb/host/ddf_helpers.h
re160bfe8 r367db39a 38 38 39 39 #include <usb/host/hcd.h> 40 #include <usb/host/ bus.h>40 #include <usb/host/usb_bus.h> 41 41 #include <usb/usb.h> 42 42 … … 45 45 #include <device/hw_res_parsed.h> 46 46 47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *); 48 typedef int (*irq_code_gen_t)(irq_code_t *, hcd_t *, const hw_res_list_parsed_t *); 49 typedef int (*claim_t)(hcd_t *, ddf_dev_t *); 50 typedef int (*driver_start_t)(hcd_t *, bool irq); 51 typedef int (*setup_root_hub_t)(hcd_t *, ddf_dev_t *); 47 typedef int (*driver_init_t)(hcd_t *, const hw_res_list_parsed_t *, bool); 48 typedef void (*driver_fini_t)(hcd_t *); 49 typedef int (*claim_t)(ddf_dev_t *); 50 typedef int (*irq_code_gen_t)(irq_code_t *, const hw_res_list_parsed_t *); 52 51 53 typedef void (*driver_stop_t)(hcd_t *);54 typedef void (*driver_fini_t)(hcd_t *);55 56 /**57 * All callbacks are optional.58 */59 52 typedef struct { 60 53 hcd_ops_t ops; 54 claim_t claim; 55 usb_speed_t hc_speed; 56 driver_init_t init; 57 driver_fini_t fini; 58 interrupt_handler_t *irq_handler; 59 irq_code_gen_t irq_code_gen; 61 60 const char *name; 62 63 interrupt_handler_t *irq_handler; /**< Handler of IRQ. Do have generic implementation. */64 65 /* Initialization sequence: */66 driver_init_t init; /**< Initialize internal structures, memory */67 claim_t claim; /**< Claim device from BIOS */68 irq_code_gen_t irq_code_gen; /**< Generate IRQ handling code */69 driver_start_t start; /**< Start the HC */70 setup_root_hub_t setup_root_hub; /**< Setup the root hub */71 72 /* Destruction sequence: */73 driver_stop_t stop; /**< Stop the HC (counterpart of start) */74 driver_fini_t fini; /**< Destroy internal structures (counterpart of init) */75 61 } ddf_hc_driver_t; 76 62 77 63 int hcd_ddf_add_hc(ddf_dev_t *device, const ddf_hc_driver_t *driver); 78 64 79 int hcd_ddf_setup_hc(ddf_dev_t *device); 65 int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed, 66 size_t bw, bw_count_func_t bw_count); 80 67 void hcd_ddf_clean_hc(ddf_dev_t *device); 81 82 int hcd_setup_virtual_root_hub(hcd_t *, ddf_dev_t *); 83 84 device_t *hcd_ddf_device_create(ddf_dev_t *, size_t); 85 void hcd_ddf_device_destroy(device_t *); 86 int hcd_ddf_device_explore(hcd_t *, device_t *); 68 int hcd_ddf_setup_root_hub(ddf_dev_t *device); 87 69 88 70 hcd_t *dev_to_hcd(ddf_dev_t *dev); … … 93 75 const hw_res_list_parsed_t *hw_res, 94 76 interrupt_handler_t handler, 95 i rq_code_gen_t gen_irq_code);77 int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *)); 96 78 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev); 97 79 -
uspace/lib/usbhost/include/usb/host/endpoint.h
re160bfe8 r367db39a 32 32 /** @file 33 33 * 34 * Endpoint structure is tightly coupled to the bus. The bus controls the35 * life-cycle of endpoint. In order to keep endpoints lightweight, operations36 * on endpoints are part of the bus structure.37 *38 34 */ 39 35 #ifndef LIBUSBHOST_HOST_ENDPOINT_H … … 46 42 #include <atomic.h> 47 43 48 typedef struct bus bus_t;49 typedef struct device device_t;50 typedef struct usb_transfer_batch usb_transfer_batch_t;51 52 44 /** Host controller side endpoint structure. */ 53 45 typedef struct endpoint { 54 /** Managing bus */55 bus_t *bus;56 46 /** Reference count. */ 57 atomic_t refcnt; 47 atomic_t refcnt; 58 48 /** Part of linked list. */ 59 49 link_t link; 60 /** USB device */61 device_t *device;62 50 /** USB address. */ 63 usb_target_t target; 51 usb_address_t address; 52 /** USB endpoint number. */ 53 usb_endpoint_t endpoint; 64 54 /** Communication direction. */ 65 55 usb_direction_t direction; … … 72 62 /** Additional opportunities per uframe */ 73 63 unsigned packets; 74 /** Reservedbandwidth. */64 /** Necessary bandwidth. */ 75 65 size_t bandwidth; 76 66 /** Value of the toggle bit. */ 77 67 unsigned toggle:1; 78 68 /** True if there is a batch using this scheduled for this endpoint. */ 79 bool active;69 volatile bool active; 80 70 /** Protects resources and active status changes. */ 81 71 fibril_mutex_t guard; 82 72 /** Signals change of active status. */ 83 73 fibril_condvar_t avail; 84 85 /* This structure is meant to be extended by overriding. */ 74 /** High speed TT data */ 75 struct { 76 usb_address_t address; 77 unsigned port; 78 } tt; 79 /** Optional device specific data. */ 80 struct { 81 /** Device specific data. */ 82 void *data; 83 /** Callback to get the value of toggle bit. */ 84 int (*toggle_get)(void *); 85 /** Callback to set the value of toggle bit. */ 86 void (*toggle_set)(void *, int); 87 } hc_data; 86 88 } endpoint_t; 87 89 88 extern void endpoint_init(endpoint_t *, bus_t *); 90 extern endpoint_t *endpoint_create(usb_address_t, usb_endpoint_t, 91 usb_direction_t, usb_transfer_type_t, usb_speed_t, size_t, unsigned int, 92 size_t, usb_address_t, unsigned int); 93 extern void endpoint_destroy(endpoint_t *); 89 94 90 95 extern void endpoint_add_ref(endpoint_t *); 91 96 extern void endpoint_del_ref(endpoint_t *); 97 98 extern void endpoint_set_hc_data(endpoint_t *, void *, int (*)(void *), 99 void (*)(void *, int)); 100 extern void endpoint_clear_hc_data(endpoint_t *); 92 101 93 102 extern void endpoint_use(endpoint_t *); … … 95 104 96 105 extern int endpoint_toggle_get(endpoint_t *); 97 extern void endpoint_toggle_set(endpoint_t *, unsigned);106 extern void endpoint_toggle_set(endpoint_t *, int); 98 107 99 108 /** list_get_instance wrapper. -
uspace/lib/usbhost/include/usb/host/hcd.h
re160bfe8 r367db39a 38 38 39 39 #include <usb/host/endpoint.h> 40 #include <usb/host/ bus.h>40 #include <usb/host/usb_bus.h> 41 41 #include <usb/host/usb_transfer_batch.h> 42 42 #include <usb/usb.h> … … 50 50 51 51 typedef int (*schedule_hook_t)(hcd_t *, usb_transfer_batch_t *); 52 typedef int (*ep_add_hook_t)(hcd_t *, endpoint_t *); 53 typedef void (*ep_remove_hook_t)(hcd_t *, endpoint_t *); 52 54 typedef void (*interrupt_hook_t)(hcd_t *, uint32_t); 53 55 typedef int (*status_hook_t)(hcd_t *, uint32_t *); 54 typedef int (*address_device_hook_t)(hcd_t *, usb_speed_t, usb_tt_address_t, usb_address_t *);55 56 56 57 typedef struct { 57 58 /** Transfer scheduling, implement in device driver. */ 58 59 schedule_hook_t schedule; 60 /** Hook called upon registering new endpoint. */ 61 ep_add_hook_t ep_add_hook; 62 /** Hook called upon removing of an endpoint. */ 63 ep_remove_hook_t ep_remove_hook; 59 64 /** Hook to be called on device interrupt, passes ARG1 */ 60 65 interrupt_hook_t irq_hook; 61 66 /** Periodic polling hook */ 62 67 status_hook_t status_hook; 63 /** Hook to setup device address */64 address_device_hook_t address_device;65 68 } hcd_ops_t; 66 69 … … 68 71 struct hcd { 69 72 /** Endpoint manager. */ 70 bus_t *bus;73 usb_bus_t bus; 71 74 72 75 /** Interrupt replacement fibril */ … … 75 78 /** Driver implementation */ 76 79 hcd_ops_t ops; 77 78 80 /** Device specific driver data. */ 79 81 void * driver_data; 80 82 }; 81 83 82 extern void hcd_init(hcd_t * );84 extern void hcd_init(hcd_t *, usb_speed_t, size_t, bw_count_func_t); 83 85 84 86 static inline void hcd_set_implementation(hcd_t *hcd, void *data, 85 const hcd_ops_t *ops , bus_t *bus)87 const hcd_ops_t *ops) 86 88 { 87 89 assert(hcd); … … 89 91 hcd->driver_data = data; 90 92 hcd->ops = *ops; 91 hcd->bus = bus;92 93 } else { 93 94 memset(&hcd->ops, 0, sizeof(hcd->ops)); … … 103 104 extern usb_address_t hcd_request_address(hcd_t *, usb_speed_t); 104 105 106 extern int hcd_release_address(hcd_t *, usb_address_t); 107 108 extern int hcd_reserve_default_address(hcd_t *, usb_speed_t); 109 110 static inline int hcd_release_default_address(hcd_t *hcd) 111 { 112 return hcd_release_address(hcd, USB_ADDRESS_DEFAULT); 113 } 114 105 115 extern int hcd_add_ep(hcd_t *, usb_target_t, usb_direction_t, 106 usb_transfer_type_t, size_t, unsigned int, size_t, usb_tt_address_t); 116 usb_transfer_type_t, size_t, unsigned int, size_t, usb_address_t, 117 unsigned int); 107 118 108 119 extern int hcd_remove_ep(hcd_t *, usb_target_t, usb_direction_t); -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
re160bfe8 r367db39a 37 37 #define LIBUSBHOST_HOST_USB_TRANSFER_BATCH_H 38 38 39 #include <usb/host/endpoint.h> 39 40 #include <usb/usb.h> 40 #include <usb/request.h>41 41 42 #include <assert.h> 42 43 #include <stddef.h> 43 44 #include <stdint.h> … … 46 47 #define USB_SETUP_PACKET_SIZE 8 47 48 48 typedef struct endpoint endpoint_t;49 typedef struct bus bus_t;50 typedef struct usb_transfer_batch usb_transfer_batch_t;51 52 /** Callback to be called on transfer. */53 typedef int (*usb_transfer_batch_callback_t)(usb_transfer_batch_t *);54 55 49 /** Structure stores additional data needed for communication with EP */ 56 50 typedef struct usb_transfer_batch { 57 51 /** Endpoint used for communication */ 58 52 endpoint_t *ep; 59 /** Size reported to be sent */ 60 size_t expected_size; 61 62 /** Direction of the transfer */ 63 usb_direction_t dir; 64 65 /** Function called on completion */ 66 usb_transfer_batch_callback_t on_complete; 67 /** Arbitrary data for the handler */ 68 void *on_complete_data; 69 70 /** Place to store SETUP data needed by control transfers */ 71 union { 72 char buffer [USB_SETUP_PACKET_SIZE]; 73 usb_device_request_setup_packet_t packet; 74 uint64_t packed; 75 } setup; 76 77 /** Resetting the Toggle */ 78 toggle_reset_mode_t toggle_reset_mode; 79 53 /** Function called on completion (IN version) */ 54 usbhc_iface_transfer_in_callback_t callback_in; 55 /** Function called on completion (OUT version) */ 56 usbhc_iface_transfer_out_callback_t callback_out; 57 /** Argument to pass to the completion function */ 58 void *arg; 80 59 /** Place for data to send/receive */ 81 60 char *buffer; 82 61 /** Size of memory pointed to by buffer member */ 83 62 size_t buffer_size; 63 /** Place to store SETUP data needed by control transfers */ 64 char setup_buffer[USB_SETUP_PACKET_SIZE]; 65 /** Used portion of setup_buffer member 66 * 67 * SETUP buffer must be 8 bytes for control transfers and is left 68 * unused for all other transfers. Thus, this field is either 0 or 8. 69 */ 70 size_t setup_size; 84 71 85 /** Actually used portion of the buffer */ 72 /** Actually used portion of the buffer 73 * This member is never accessed by functions provided in this header, 74 * with the exception of usb_transfer_batch_finish. For external use. 75 */ 86 76 size_t transfered_size; 87 /** Indicates success/failure of the communication */ 77 /** Indicates success/failure of the communication 78 * This member is never accessed by functions provided in this header, 79 * with the exception of usb_transfer_batch_finish. For external use. 80 */ 88 81 int error; 89 82 } usb_transfer_batch_t; … … 96 89 */ 97 90 #define USB_TRANSFER_BATCH_ARGS(batch) \ 98 (batch).ep-> target.address, (batch).ep->target.endpoint, \91 (batch).ep->address, (batch).ep->endpoint, \ 99 92 usb_str_speed((batch).ep->speed), \ 100 93 usb_str_transfer_type_short((batch).ep->transfer_type), \ … … 102 95 (batch).buffer_size, (batch).ep->max_packet_size 103 96 104 void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);105 void usb_transfer_batch_finish(usb_transfer_batch_t *);106 97 107 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *); 108 void usb_transfer_batch_destroy(usb_transfer_batch_t *); 98 usb_transfer_batch_t * usb_transfer_batch_create( 99 endpoint_t *ep, 100 char *buffer, 101 size_t buffer_size, 102 uint64_t setup_buffer, 103 usbhc_iface_transfer_in_callback_t func_in, 104 usbhc_iface_transfer_out_callback_t func_out, 105 void *arg 106 ); 107 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); 109 108 110 /** Provided to ease the transition. Wraps old-style handlers into a new one. 109 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance, 110 const void* data, size_t size, int error); 111 112 /** Finish batch using stored error value and transferred size. 113 * 114 * @param[in] instance Batch structure to use. 115 * @param[in] data Data to copy to the output buffer. 111 116 */ 112 extern void usb_transfer_batch_set_old_handlers(usb_transfer_batch_t *, 113 usbhc_iface_transfer_in_callback_t, 114 usbhc_iface_transfer_out_callback_t, void *); 117 static inline void usb_transfer_batch_finish( 118 const usb_transfer_batch_t *instance, const void* data) 119 { 120 assert(instance); 121 usb_transfer_batch_finish_error( 122 instance, data, instance->transfered_size, instance->error); 123 } 124 125 /** Determine batch direction based on the callbacks present 126 * @param[in] instance Batch structure to use, non-null. 127 * @return USB_DIRECTION_IN, or USB_DIRECTION_OUT. 128 */ 129 static inline usb_direction_t usb_transfer_batch_direction( 130 const usb_transfer_batch_t *instance) 131 { 132 assert(instance); 133 if (instance->callback_in) { 134 assert(instance->callback_out == NULL); 135 assert(instance->ep == NULL 136 || instance->ep->transfer_type == USB_TRANSFER_CONTROL 137 || instance->ep->direction == USB_DIRECTION_IN); 138 return USB_DIRECTION_IN; 139 } 140 if (instance->callback_out) { 141 assert(instance->callback_in == NULL); 142 assert(instance->ep == NULL 143 || instance->ep->transfer_type == USB_TRANSFER_CONTROL 144 || instance->ep->direction == USB_DIRECTION_OUT); 145 return USB_DIRECTION_OUT; 146 } 147 assert(false); 148 } 115 149 116 150 #endif -
uspace/lib/usbhost/src/ddf_helpers.c
re160bfe8 r367db39a 35 35 36 36 #include <usb/classes/classes.h> 37 #include <usb/host/bus.h>38 37 #include <usb/debug.h> 39 38 #include <usb/descriptor.h> … … 50 49 #include <fibril_synch.h> 51 50 #include <macros.h> 51 #include <stdio.h> 52 52 #include <stdlib.h> 53 53 #include <str_error.h> … … 56 56 #include "ddf_helpers.h" 57 57 58 #define CTRL_PIPE_MIN_PACKET_SIZE 8 59 60 typedef struct usb_dev { 61 link_t link; 62 list_t devices; 63 fibril_mutex_t guard; 64 ddf_fun_t *fun; 65 usb_address_t address; 66 usb_speed_t speed; 67 usb_address_t tt_address; 68 unsigned port; 69 } usb_dev_t; 70 58 71 typedef struct hc_dev { 59 72 ddf_fun_t *ctl_fun; 60 73 hcd_t hcd; 74 usb_dev_t *root_hub; 61 75 } hc_dev_t; 62 76 … … 77 91 78 92 79 static int hcd_ddf_new_device( hcd_t *hcd, ddf_dev_t *hc, device_t *hub_dev, unsigned port);80 static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, unsigned port);93 static int hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port); 94 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port); 81 95 82 96 … … 85 99 /** Register endpoint interface function. 86 100 * @param fun DDF function. 87 * @param endpoint_desc Endpoint description. 101 * @param address USB address of the device. 102 * @param endpoint USB endpoint number to be registered. 103 * @param transfer_type Endpoint's transfer type. 104 * @param direction USB communication direction the endpoint is capable of. 105 * @param max_packet_size Maximu size of packets the endpoint accepts. 106 * @param interval Preferred timeout between communication. 88 107 * @return Error code. 89 108 */ 90 109 static int register_endpoint( 91 ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc) 110 ddf_fun_t *fun, usb_endpoint_t endpoint, 111 usb_transfer_type_t transfer_type, usb_direction_t direction, 112 size_t max_packet_size, unsigned packets, unsigned interval) 92 113 { 93 114 assert(fun); 94 115 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 95 device_t *dev = ddf_fun_data_get(fun);116 usb_dev_t *dev = ddf_fun_data_get(fun); 96 117 assert(hcd); 97 assert(hcd->bus);98 118 assert(dev); 99 100 const size_t size = endpoint_desc->max_packet_size; 119 const size_t size = max_packet_size; 120 const usb_target_t target = 121 {{.address = dev->address, .endpoint = endpoint}}; 101 122 102 123 usb_log_debug("Register endpoint %d:%d %s-%s %zuB %ums.\n", 103 dev->address, endpoint_desc->endpoint_no, 104 usb_str_transfer_type(endpoint_desc->transfer_type), 105 usb_str_direction(endpoint_desc->direction), 106 endpoint_desc->max_packet_size, endpoint_desc->usb2.polling_interval); 107 108 return bus_add_ep(hcd->bus, dev, endpoint_desc->endpoint_no, 109 endpoint_desc->direction, endpoint_desc->transfer_type, 110 endpoint_desc->max_packet_size, endpoint_desc->packets, 111 size); 112 } 113 114 /** Unregister endpoint interface function. 115 * @param fun DDF function. 116 * @param endpoint_desc Endpoint description. 117 * @return Error code. 118 */ 124 dev->address, endpoint, usb_str_transfer_type(transfer_type), 125 usb_str_direction(direction), max_packet_size, interval); 126 127 return hcd_add_ep(hcd, target, direction, transfer_type, 128 max_packet_size, packets, size, dev->tt_address, dev->port); 129 } 130 131 /** Unregister endpoint interface function. 132 * @param fun DDF function. 133 * @param address USB address of the endpoint. 134 * @param endpoint USB endpoint number. 135 * @param direction Communication direction of the enpdoint to unregister. 136 * @return Error code. 137 */ 119 138 static int unregister_endpoint( 120 ddf_fun_t *fun, usb_endpoint_desc_t *endpoint_desc)139 ddf_fun_t *fun, usb_endpoint_t endpoint, usb_direction_t direction) 121 140 { 122 141 assert(fun); 123 142 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 124 device_t *dev = ddf_fun_data_get(fun);143 usb_dev_t *dev = ddf_fun_data_get(fun); 125 144 assert(hcd); 126 assert(hcd->bus);127 145 assert(dev); 128 129 const usb_target_t target = {{ 130 .address = dev->address, 131 .endpoint = endpoint_desc->endpoint_no 132 }}; 133 146 const usb_target_t target = 147 {{.address = dev->address, .endpoint = endpoint}}; 134 148 usb_log_debug("Unregister endpoint %d:%d %s.\n", 135 dev->address, endpoint_desc->endpoint_no, 136 usb_str_direction(endpoint_desc->direction)); 137 return bus_remove_ep(hcd->bus, target, endpoint_desc->direction); 149 dev->address, endpoint, usb_str_direction(direction)); 150 return hcd_remove_ep(hcd, target, direction); 138 151 } 139 152 … … 142 155 assert(fun); 143 156 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 144 device_t *dev = ddf_fun_data_get(fun);157 usb_dev_t *dev = ddf_fun_data_get(fun); 145 158 assert(hcd); 146 assert(hcd->bus);147 159 assert(dev); 148 160 149 161 usb_log_debug("Device %d requested default address at %s speed\n", 150 162 dev->address, usb_str_speed(speed)); 151 return bus_reserve_default_address(hcd->bus, speed);163 return hcd_reserve_default_address(hcd, speed); 152 164 } 153 165 … … 156 168 assert(fun); 157 169 hcd_t *hcd = dev_to_hcd(ddf_fun_get_dev(fun)); 158 device_t *dev = ddf_fun_data_get(fun);170 usb_dev_t *dev = ddf_fun_data_get(fun); 159 171 assert(hcd); 160 assert(hcd->bus);161 172 assert(dev); 162 173 163 174 usb_log_debug("Device %d released default address\n", dev->address); 164 return bus_release_default_address(hcd->bus);175 return hcd_release_default_address(hcd); 165 176 } 166 177 167 178 static int device_enumerate(ddf_fun_t *fun, unsigned port) 168 {169 assert(fun);170 ddf_dev_t *hc = ddf_fun_get_dev(fun);171 assert(hc);172 hcd_t *hcd = dev_to_hcd(hc);173 assert(hcd);174 device_t *hub = ddf_fun_data_get(fun);175 assert(hub);176 177 usb_log_debug("Hub %d reported a new USB device on port: %u\n",178 hub->address, port);179 return hcd_ddf_new_device(hcd, hc, hub, port);180 }181 182 static int device_remove(ddf_fun_t *fun, unsigned port)183 179 { 184 180 assert(fun); 185 181 ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun); 186 device_t *dev = ddf_fun_data_get(fun); 182 usb_dev_t *dev = ddf_fun_data_get(fun); 183 assert(ddf_dev); 184 assert(dev); 185 usb_log_debug("Hub %d reported a new USB device on port: %u\n", 186 dev->address, port); 187 return hcd_ddf_new_device(ddf_dev, dev, port); 188 } 189 190 static int device_remove(ddf_fun_t *fun, unsigned port) 191 { 192 assert(fun); 193 ddf_dev_t *ddf_dev = ddf_fun_get_dev(fun); 194 usb_dev_t *dev = ddf_fun_data_get(fun); 187 195 assert(ddf_dev); 188 196 assert(dev); … … 221 229 { 222 230 assert(fun); 223 device_t *dev = ddf_fun_data_get(fun);224 assert( dev);231 usb_dev_t *usb_dev = ddf_fun_data_get(fun); 232 assert(usb_dev); 225 233 const usb_target_t target = {{ 226 .address =dev->address,234 .address = usb_dev->address, 227 235 .endpoint = endpoint, 228 236 }}; … … 247 255 { 248 256 assert(fun); 249 device_t *dev = ddf_fun_data_get(fun);250 assert( dev);257 usb_dev_t *usb_dev = ddf_fun_data_get(fun); 258 assert(usb_dev); 251 259 const usb_target_t target = {{ 252 .address =dev->address,260 .address = usb_dev->address, 253 261 .endpoint = endpoint, 254 262 }}; … … 282 290 283 291 /* DDF HELPERS */ 292 293 #define GET_DEVICE_DESC(size) \ 294 { \ 295 .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST \ 296 | (USB_REQUEST_TYPE_STANDARD << 5) \ 297 | USB_REQUEST_RECIPIENT_DEVICE, \ 298 .request = USB_DEVREQ_GET_DESCRIPTOR, \ 299 .value = uint16_host2usb(USB_DESCTYPE_DEVICE << 8), \ 300 .index = uint16_host2usb(0), \ 301 .length = uint16_host2usb(size), \ 302 }; 303 304 #define SET_ADDRESS(address) \ 305 { \ 306 .request_type = SETUP_REQUEST_TYPE_HOST_TO_DEVICE \ 307 | (USB_REQUEST_TYPE_STANDARD << 5) \ 308 | USB_REQUEST_RECIPIENT_DEVICE, \ 309 .request = USB_DEVREQ_SET_ADDRESS, \ 310 .value = uint16_host2usb(address), \ 311 .index = uint16_host2usb(0), \ 312 .length = uint16_host2usb(0), \ 313 }; 314 315 static int hcd_ddf_add_device(ddf_dev_t *parent, usb_dev_t *hub_dev, 316 unsigned port, usb_address_t address, usb_speed_t speed, const char *name, 317 const match_id_list_t *mids) 318 { 319 assert(parent); 320 321 char default_name[10] = { 0 }; /* usbxyz-ss */ 322 if (!name) { 323 snprintf(default_name, sizeof(default_name) - 1, 324 "usb%u-%cs", address, usb_str_speed(speed)[0]); 325 name = default_name; 326 } 327 328 ddf_fun_t *fun = ddf_fun_create(parent, fun_inner, name); 329 if (!fun) 330 return ENOMEM; 331 usb_dev_t *info = ddf_fun_data_alloc(fun, sizeof(usb_dev_t)); 332 if (!info) { 333 ddf_fun_destroy(fun); 334 return ENOMEM; 335 } 336 info->address = address; 337 info->speed = speed; 338 info->fun = fun; 339 info->port = port; 340 info->tt_address = hub_dev ? hub_dev->tt_address : -1; 341 link_initialize(&info->link); 342 list_initialize(&info->devices); 343 fibril_mutex_initialize(&info->guard); 344 345 if (hub_dev && hub_dev->speed == USB_SPEED_HIGH && usb_speed_is_11(speed)) 346 info->tt_address = hub_dev->address; 347 348 ddf_fun_set_ops(fun, &usb_ops); 349 list_foreach(mids->ids, link, const match_id_t, mid) { 350 ddf_fun_add_match_id(fun, mid->id, mid->score); 351 } 352 353 int ret = ddf_fun_bind(fun); 354 if (ret != EOK) { 355 ddf_fun_destroy(fun); 356 return ret; 357 } 358 359 if (hub_dev) { 360 fibril_mutex_lock(&hub_dev->guard); 361 list_append(&info->link, &hub_dev->devices); 362 fibril_mutex_unlock(&hub_dev->guard); 363 } else { 364 hc_dev_t *hc_dev = dev_to_hc_dev(parent); 365 assert(hc_dev->root_hub == NULL); 366 hc_dev->root_hub = info; 367 } 368 return EOK; 369 } 284 370 285 371 #define ADD_MATCHID_OR_RETURN(list, sc, str, ...) \ … … 308 394 assert(l); 309 395 assert(d); 310 396 311 397 if (d->vendor_id != 0) { 312 398 /* First, with release number. */ … … 315 401 d->vendor_id, d->product_id, (d->device_version >> 8), 316 402 (d->device_version & 0xff)); 317 403 318 404 /* Next, without release number. */ 319 405 ADD_MATCHID_OR_RETURN(l, 90, "usb&vendor=%#04x&product=%#04x", … … 329 415 330 416 return EOK; 331 } 332 333 static int hcd_ddf_remove_device(ddf_dev_t *device, device_t *hub, 417 418 } 419 420 static int hcd_ddf_remove_device(ddf_dev_t *device, usb_dev_t *hub, 334 421 unsigned port) 335 422 { … … 338 425 hcd_t *hcd = dev_to_hcd(device); 339 426 assert(hcd); 340 assert(hcd->bus);341 427 342 428 hc_dev_t *hc_dev = dev_to_hc_dev(device); … … 345 431 fibril_mutex_lock(&hub->guard); 346 432 347 device_t *victim = NULL;348 349 list_foreach(hub->devices, link, device_t, it) {433 usb_dev_t *victim = NULL; 434 435 list_foreach(hub->devices, link, usb_dev_t, it) { 350 436 if (it->port == port) { 351 437 victim = it; … … 354 440 } 355 441 if (victim) { 356 assert(victim->fun);357 442 assert(victim->port == port); 358 assert(victim->hub == hub);359 443 list_remove(&victim->link); 360 444 fibril_mutex_unlock(&hub->guard); … … 362 446 if (ret == EOK) { 363 447 usb_address_t address = victim->address; 364 bus_remove_device(hcd->bus, hcd, victim);365 448 ddf_fun_destroy(victim->fun); 366 bus_release_address(hcd->bus, address);449 hcd_release_address(hcd, address); 367 450 } else { 368 451 usb_log_warning("Failed to unbind device `%s': %s\n", … … 375 458 } 376 459 377 device_t *hcd_ddf_device_create(ddf_dev_t *hc, size_t device_size) 378 { 379 /* Create DDF function for the new device */ 380 ddf_fun_t *fun = ddf_fun_create(hc, fun_inner, NULL); 381 if (!fun) 382 return NULL; 383 384 ddf_fun_set_ops(fun, &usb_ops); 385 386 /* Create USB device node for the new device */ 387 device_t *dev = ddf_fun_data_alloc(fun, device_size); 388 if (!dev) { 389 ddf_fun_destroy(fun); 390 return NULL; 391 } 392 393 device_init(dev); 394 dev->fun = fun; 395 return dev; 396 } 397 398 void hcd_ddf_device_destroy(device_t *dev) 399 { 400 assert(dev); 401 assert(dev->fun); 402 ddf_fun_destroy(dev->fun); 403 } 404 405 int hcd_ddf_device_explore(hcd_t *hcd, device_t *device) 406 { 407 int err; 408 match_id_list_t mids; 460 static int hcd_ddf_new_device(ddf_dev_t *device, usb_dev_t *hub, unsigned port) 461 { 462 assert(device); 463 464 hcd_t *hcd = dev_to_hcd(device); 465 assert(hcd); 466 467 usb_speed_t speed = USB_SPEED_MAX; 468 469 /* This checks whether the default address is reserved and gets speed */ 470 int ret = usb_bus_get_speed(&hcd->bus, USB_ADDRESS_DEFAULT, &speed); 471 if (ret != EOK) { 472 usb_log_error("Failed to verify speed: %s.", str_error(ret)); 473 return ret; 474 } 475 476 usb_log_debug("Found new %s speed USB device.", usb_str_speed(speed)); 477 478 static const usb_target_t default_target = {{ 479 .address = USB_ADDRESS_DEFAULT, 480 .endpoint = 0, 481 }}; 482 483 const usb_address_t address = hcd_request_address(hcd, speed); 484 if (address < 0) { 485 usb_log_error("Failed to reserve new address: %s.", 486 str_error(address)); 487 return address; 488 } 489 490 usb_log_debug("Reserved new address: %d\n", address); 491 492 const usb_target_t target = {{ 493 .address = address, 494 .endpoint = 0, 495 }}; 496 497 const usb_address_t tt_address = hub ? hub->tt_address : -1; 498 499 /* Add default pipe on default address */ 500 usb_log_debug("Device(%d): Adding default target(0:0)\n", address); 501 ret = hcd_add_ep(hcd, 502 default_target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, 503 CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1, 504 tt_address, port); 505 if (ret != EOK) { 506 usb_log_error("Device(%d): Failed to add default target: %s.", 507 address, str_error(ret)); 508 hcd_release_address(hcd, address); 509 return ret; 510 } 511 512 /* Get max packet size for default pipe */ 409 513 usb_standard_device_descriptor_t desc = { 0 }; 410 411 init_match_ids(&mids); 412 413 usb_target_t control_ep = {{ 414 .address = device->address, 415 .endpoint = 0 416 }}; 514 const usb_device_request_setup_packet_t get_device_desc_8 = 515 GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE); 516 517 // TODO CALLBACKS 518 usb_log_debug("Device(%d): Requesting first 8B of device descriptor.", 519 address); 520 ssize_t got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN, 521 &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8, 522 "read first 8 bytes of dev descriptor"); 523 524 if (got != CTRL_PIPE_MIN_PACKET_SIZE) { 525 ret = got < 0 ? got : EOVERFLOW; 526 usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.", 527 address, str_error(ret)); 528 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH); 529 hcd_release_address(hcd, address); 530 return ret; 531 } 532 533 /* Register EP on the new address */ 534 usb_log_debug("Device(%d): Registering control EP.", address); 535 ret = hcd_add_ep(hcd, target, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, 536 ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)), 537 ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)), 538 ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)), 539 tt_address, port); 540 if (ret != EOK) { 541 usb_log_error("Device(%d): Failed to register EP0: %s", 542 address, str_error(ret)); 543 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH); 544 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 545 hcd_release_address(hcd, address); 546 return ret; 547 } 548 549 /* Set new address */ 550 const usb_device_request_setup_packet_t set_address = 551 SET_ADDRESS(target.address); 552 553 usb_log_debug("Device(%d): Setting USB address.", address); 554 got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT, 555 NULL, 0, *(uint64_t *)&set_address, "set address"); 556 557 usb_log_debug("Device(%d): Removing default (0:0) EP.", address); 558 hcd_remove_ep(hcd, default_target, USB_DIRECTION_BOTH); 559 560 if (got != 0) { 561 usb_log_error("Device(%d): Failed to set new address: %s.", 562 address, str_error(got)); 563 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 564 hcd_release_address(hcd, address); 565 return got; 566 } 417 567 418 568 /* Get std device descriptor */ … … 421 571 422 572 usb_log_debug("Device(%d): Requesting full device descriptor.", 423 device->address);424 ssize_t got = hcd_send_batch_sync(hcd, control_ep, USB_DIRECTION_IN,573 address); 574 got = hcd_send_batch_sync(hcd, target, USB_DIRECTION_IN, 425 575 &desc, sizeof(desc), *(uint64_t *)&get_device_desc, 426 576 "read device descriptor"); 427 if (got < 0) { 428 err = got < 0 ? got : EOVERFLOW; 577 if (ret != EOK) { 429 578 usb_log_error("Device(%d): Failed to set get dev descriptor: %s", 430 device->address, str_error(err)); 431 goto out; 579 address, str_error(ret)); 580 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 581 hcd_release_address(hcd, target.address); 582 return ret; 432 583 } 433 584 434 585 /* Create match ids from the device descriptor */ 435 usb_log_debug("Device(%d): Creating match IDs.", device->address); 436 if ((err = create_match_ids(&mids, &desc))) { 437 usb_log_error("Device(%d): Failed to create match ids: %s", device->address, str_error(err)); 438 goto out; 439 } 440 441 list_foreach(mids.ids, link, const match_id_t, mid) { 442 ddf_fun_add_match_id(device->fun, mid->id, mid->score); 443 } 444 445 out: 586 match_id_list_t mids; 587 init_match_ids(&mids); 588 589 usb_log_debug("Device(%d): Creating match IDs.", address); 590 ret = create_match_ids(&mids, &desc); 591 if (ret != EOK) { 592 usb_log_error("Device(%d): Failed to create match ids: %s", 593 address, str_error(ret)); 594 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 595 hcd_release_address(hcd, target.address); 596 return ret; 597 } 598 599 /* Register device */ 600 usb_log_debug("Device(%d): Registering DDF device.", address); 601 ret = hcd_ddf_add_device(device, hub, port, address, speed, NULL, &mids); 446 602 clean_match_ids(&mids); 447 return err; 448 } 449 450 static int hcd_ddf_new_device(hcd_t *hcd, ddf_dev_t *hc, device_t *hub, unsigned port) 451 { 452 int err; 453 assert(hcd); 454 assert(hcd->bus); 455 assert(hub); 456 assert(hc); 457 458 device_t *dev = hcd_ddf_device_create(hc, hcd->bus->device_size); 459 if (!dev) { 460 usb_log_error("Failed to create USB device function."); 461 return ENOMEM; 462 } 463 464 dev->hub = hub; 465 dev->port = port; 466 467 if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) { 468 usb_log_error("Failed to initialize USB dev memory structures."); 469 return err; 470 } 471 472 /* If the driver didn't name the dev when enumerating, 473 * do it in some generic way. 474 */ 475 if (!ddf_fun_get_name(dev->fun)) { 476 device_set_default_name(dev); 477 } 478 479 if ((err = ddf_fun_bind(dev->fun))) { 480 usb_log_error("Device(%d): Failed to register: %s.", dev->address, str_error(err)); 481 goto err_usb_dev; 482 } 483 484 fibril_mutex_lock(&hub->guard); 485 list_append(&dev->link, &hub->devices); 486 fibril_mutex_unlock(&hub->guard); 487 488 return EOK; 489 490 err_usb_dev: 491 hcd_ddf_device_destroy(dev); 492 return err; 603 if (ret != EOK) { 604 usb_log_error("Device(%d): Failed to register: %s.", 605 address, str_error(ret)); 606 hcd_remove_ep(hcd, target, USB_DIRECTION_BOTH); 607 hcd_release_address(hcd, target.address); 608 } 609 610 return ret; 493 611 } 494 612 … … 498 616 * @return Error code 499 617 */ 500 int hcd_setup_virtual_root_hub(hcd_t *hcd, ddf_dev_t *hc) 501 { 502 int err; 503 504 assert(hc); 618 int hcd_ddf_setup_root_hub(ddf_dev_t *device) 619 { 620 assert(device); 621 hcd_t *hcd = dev_to_hcd(device); 505 622 assert(hcd); 506 assert(hcd->bus); 507 508 if ((err = bus_reserve_default_address(hcd->bus, USB_SPEED_MAX))) { 509 usb_log_error("Failed to reserve default address for roothub setup: %s", str_error(err)); 510 return err; 511 } 512 513 device_t *dev = hcd_ddf_device_create(hc, USB_SPEED_MAX); 514 if (!dev) { 515 usb_log_error("Failed to create function for the root hub."); 516 goto err_default_address; 517 } 518 519 ddf_fun_set_name(dev->fun, "roothub"); 520 521 dev->tt = (usb_tt_address_t) { 522 .address = -1, 523 .port = 0, 524 }; 525 526 /* Assign an address to the device */ 527 if ((err = bus_enumerate_device(hcd->bus, hcd, dev))) { 528 usb_log_error("Failed to enumerate roothub device: %s", str_error(err)); 529 goto err_usb_dev; 530 } 531 532 if ((err = ddf_fun_bind(dev->fun))) { 533 usb_log_error("Failed to register roothub: %s.", str_error(err)); 534 goto err_usb_dev; 535 } 536 537 bus_release_default_address(hcd->bus); 538 return EOK; 539 540 err_usb_dev: 541 hcd_ddf_device_destroy(dev); 542 err_default_address: 543 bus_release_default_address(hcd->bus); 544 return err; 623 624 hcd_reserve_default_address(hcd, hcd->bus.max_speed); 625 const int ret = hcd_ddf_new_device(device, NULL, 0); 626 hcd_release_default_address(hcd); 627 return ret; 545 628 } 546 629 … … 555 638 * This function does all the ddf work for hc driver. 556 639 */ 557 int hcd_ddf_setup_hc(ddf_dev_t *device) 640 int hcd_ddf_setup_hc(ddf_dev_t *device, usb_speed_t max_speed, 641 size_t bw, bw_count_func_t bw_count) 558 642 { 559 643 assert(device); … … 564 648 return ENOMEM; 565 649 } 566 hcd_init(&instance->hcd); 650 instance->root_hub = NULL; 651 hcd_init(&instance->hcd, max_speed, bw, bw_count); 567 652 568 653 int ret = ENOMEM; … … 663 748 const hw_res_list_parsed_t *hw_res, 664 749 interrupt_handler_t handler, 665 irq_code_gen_t gen_irq_code) 666 { 750 int (*gen_irq_code)(irq_code_t *, const hw_res_list_parsed_t *hw_res)) 751 { 752 667 753 assert(device); 668 669 hcd_t *hcd = dev_to_hcd(device);670 671 754 if (!handler || !gen_irq_code) 672 755 return ENOTSUP; … … 674 757 irq_code_t irq_code = {0}; 675 758 676 const int irq = gen_irq_code(&irq_code, h cd, hw_res);759 const int irq = gen_irq_code(&irq_code, hw_res); 677 760 if (irq < 0) { 678 761 usb_log_error("Failed to generate IRQ code: %s.\n", … … 694 777 int ret = hcd_ddf_enable_interrupt(device, irq); 695 778 if (ret != EOK) { 696 usb_log_error("Failed to enable interrupts: %s.\n",779 usb_log_error("Failed to register interrupt handler: %s.\n", 697 780 str_error(ret)); 698 781 unregister_interrupt_handler(device, irq_cap); … … 761 844 { 762 845 assert(driver); 846 static const struct { size_t bw; bw_count_func_t bw_count; }bw[] = { 847 [USB_SPEED_FULL] = { .bw = BANDWIDTH_AVAILABLE_USB11, 848 .bw_count = bandwidth_count_usb11 }, 849 [USB_SPEED_HIGH] = { .bw = BANDWIDTH_AVAILABLE_USB11, 850 .bw_count = bandwidth_count_usb11 }, 851 }; 763 852 764 853 int ret = EOK; 854 const usb_speed_t speed = driver->hc_speed; 855 if (speed >= ARRAY_SIZE(bw) || bw[speed].bw == 0) { 856 usb_log_error("Driver `%s' reported unsupported speed: %s", 857 driver->name, usb_str_speed(speed)); 858 return ENOTSUP; 859 } 765 860 766 861 hw_res_list_parsed_t hw_res; … … 773 868 } 774 869 775 ret = hcd_ddf_setup_hc(device );870 ret = hcd_ddf_setup_hc(device, speed, bw[speed].bw, bw[speed].bw_count); 776 871 if (ret != EOK) { 777 872 usb_log_error("Failed to setup generic HCD.\n"); 778 goto err_hw_res; 779 } 780 781 hcd_t *hcd = dev_to_hcd(device); 782 783 if (driver->init) 784 ret = driver->init(hcd, &hw_res, device); 785 if (ret != EOK) { 786 usb_log_error("Failed to init HCD.\n"); 787 goto err_hcd; 788 } 789 790 /* Setup interrupts */ 873 hw_res_list_parsed_clean(&hw_res); 874 return ret; 875 } 876 791 877 interrupt_handler_t *irq_handler = 792 878 driver->irq_handler ? driver->irq_handler : ddf_hcd_gen_irq_handler; … … 798 884 } 799 885 800 /* Claim the device from BIOS */801 886 if (driver->claim) 802 ret = driver->claim(hcd, device); 803 if (ret != EOK) { 804 usb_log_error("Failed to claim `%s' for driver `%s': %s", 805 ddf_dev_get_name(device), driver->name, str_error(ret)); 806 goto err_irq; 807 } 808 809 /* Start hw driver */ 810 if (driver->start) 811 ret = driver->start(hcd, irqs_enabled); 812 if (ret != EOK) { 813 usb_log_error("Failed to start HCD: %s.\n", str_error(ret)); 814 goto err_irq; 887 ret = driver->claim(device); 888 if (ret != EOK) { 889 usb_log_error("Failed to claim `%s' for driver `%s'", 890 ddf_dev_get_name(device), driver->name); 891 return ret; 892 } 893 894 895 /* Init hw driver */ 896 hcd_t *hcd = dev_to_hcd(device); 897 ret = driver->init(hcd, &hw_res, irqs_enabled); 898 hw_res_list_parsed_clean(&hw_res); 899 if (ret != EOK) { 900 usb_log_error("Failed to init HCD: %s.\n", str_error(ret)); 901 goto irq_unregister; 815 902 } 816 903 … … 821 908 usb_log_error("Failed to create polling fibril\n"); 822 909 ret = ENOMEM; 823 goto err_started;910 goto irq_unregister; 824 911 } 825 912 fibril_add_ready(hcd->polling_fibril); … … 832 919 * needs to be ready at this time. 833 920 */ 834 if (driver->setup_root_hub) 835 ret = driver->setup_root_hub(hcd, device); 921 ret = hcd_ddf_setup_root_hub(device); 836 922 if (ret != EOK) { 837 923 usb_log_error("Failed to setup HC root hub: %s.\n", 838 924 str_error(ret)); 839 goto err_polling; 925 driver->fini(dev_to_hcd(device)); 926 irq_unregister: 927 /* Unregistering non-existent should be ok */ 928 unregister_interrupt_handler(device, irq_cap); 929 hcd_ddf_clean_hc(device); 930 return ret; 840 931 } 841 932 … … 843 934 driver->name, ddf_dev_get_name(device)); 844 935 return EOK; 845 846 err_polling: 847 // TODO: Stop the polling fibril (refactor the interrupt_polling func) 848 // 849 err_started: 850 if (driver->stop) 851 driver->stop(hcd); 852 err_irq: 853 unregister_interrupt_handler(device, irq_cap); 854 if (driver->fini) 855 driver->fini(hcd); 856 err_hcd: 857 hcd_ddf_clean_hc(device); 858 err_hw_res: 859 hw_res_list_parsed_clean(&hw_res); 860 return ret; 861 } 862 936 } 863 937 /** 864 938 * @} -
uspace/lib/usbhost/src/endpoint.c
re160bfe8 r367db39a 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2017 Ondrej Hlavaty <aearsis@eideo.cz>4 3 * All rights reserved. 5 4 * … … 36 35 37 36 #include <usb/host/endpoint.h> 38 #include <usb/host/bus.h>39 37 40 38 #include <assert.h> 39 #include <stdlib.h> 41 40 #include <atomic.h> 42 #include <mem.h>43 #include <stdlib.h>44 41 45 /** Initialize provided endpoint structure. 42 /** Allocate ad initialize endpoint_t structure. 43 * @param address USB address. 44 * @param endpoint USB endpoint number. 45 * @param direction Communication direction. 46 * @param type USB transfer type. 47 * @param speed Communication speed. 48 * @param max_packet_size Maximum size of data packets. 49 * @param bw Required bandwidth. 50 * @return Pointer to initialized endpoint_t structure, NULL on failure. 46 51 */ 47 void endpoint_init(endpoint_t *ep, bus_t *bus) 52 endpoint_t * endpoint_create(usb_address_t address, usb_endpoint_t endpoint, 53 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 54 size_t max_packet_size, unsigned packets, size_t bw, 55 usb_address_t tt_address, unsigned tt_p) 48 56 { 49 memset(ep, 0, sizeof(endpoint_t)); 50 51 ep->bus = bus; 52 atomic_set(&ep->refcnt, 0); 53 link_initialize(&ep->link); 54 fibril_mutex_initialize(&ep->guard); 55 fibril_condvar_initialize(&ep->avail); 57 endpoint_t *instance = malloc(sizeof(endpoint_t)); 58 if (instance) { 59 atomic_set(&instance->refcnt, 0); 60 instance->address = address; 61 instance->endpoint = endpoint; 62 instance->direction = direction; 63 instance->transfer_type = type; 64 instance->speed = speed; 65 instance->max_packet_size = max_packet_size; 66 instance->packets = packets; 67 instance->bandwidth = bw; 68 instance->toggle = 0; 69 instance->active = false; 70 instance->tt.address = tt_address; 71 instance->tt.port = tt_p; 72 instance->hc_data.data = NULL; 73 instance->hc_data.toggle_get = NULL; 74 instance->hc_data.toggle_set = NULL; 75 link_initialize(&instance->link); 76 fibril_mutex_initialize(&instance->guard); 77 fibril_condvar_initialize(&instance->avail); 78 } 79 return instance; 56 80 } 57 81 58 void endpoint_add_ref(endpoint_t *ep) 82 /** Properly dispose of endpoint_t structure. 83 * @param instance endpoint_t structure. 84 */ 85 void endpoint_destroy(endpoint_t *instance) 59 86 { 60 atomic_inc(&ep->refcnt); 87 assert(instance); 88 assert(!instance->active); 89 assert(instance->hc_data.data == NULL); 90 free(instance); 61 91 } 62 92 63 void endpoint_ del_ref(endpoint_t *ep)93 void endpoint_add_ref(endpoint_t *instance) 64 94 { 65 if (atomic_predec(&ep->refcnt) == 0) { 66 if (ep->bus->ops.destroy_endpoint) { 67 ep->bus->ops.destroy_endpoint(ep); 68 } 69 else { 70 assert(!ep->active); 95 atomic_inc(&instance->refcnt); 96 } 71 97 72 /* Assume mostly the eps will be allocated by malloc. */ 73 free(ep); 74 } 75 } 98 void endpoint_del_ref(endpoint_t *instance) 99 { 100 if (atomic_predec(&instance->refcnt) == 0) 101 endpoint_destroy(instance); 102 } 103 104 /** Set device specific data and hooks. 105 * @param instance endpoint_t structure. 106 * @param data device specific data. 107 * @param toggle_get Hook to call when retrieving value of toggle bit. 108 * @param toggle_set Hook to call when setting the value of toggle bit. 109 */ 110 void endpoint_set_hc_data(endpoint_t *instance, 111 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 112 { 113 assert(instance); 114 fibril_mutex_lock(&instance->guard); 115 instance->hc_data.data = data; 116 instance->hc_data.toggle_get = toggle_get; 117 instance->hc_data.toggle_set = toggle_set; 118 fibril_mutex_unlock(&instance->guard); 119 } 120 121 /** Clear device specific data and hooks. 122 * @param instance endpoint_t structure. 123 * @note This function does not free memory pointed to by data pointer. 124 */ 125 void endpoint_clear_hc_data(endpoint_t *instance) 126 { 127 assert(instance); 128 endpoint_set_hc_data(instance, NULL, NULL, NULL); 76 129 } 77 130 78 131 /** Mark the endpoint as active and block access for further fibrils. 79 * @param ependpoint_t structure.132 * @param instance endpoint_t structure. 80 133 */ 81 void endpoint_use(endpoint_t * ep)134 void endpoint_use(endpoint_t *instance) 82 135 { 83 assert( ep);136 assert(instance); 84 137 /* Add reference for active endpoint. */ 85 endpoint_add_ref( ep);86 fibril_mutex_lock(& ep->guard);87 while ( ep->active)88 fibril_condvar_wait(& ep->avail, &ep->guard);89 ep->active = true;90 fibril_mutex_unlock(& ep->guard);138 endpoint_add_ref(instance); 139 fibril_mutex_lock(&instance->guard); 140 while (instance->active) 141 fibril_condvar_wait(&instance->avail, &instance->guard); 142 instance->active = true; 143 fibril_mutex_unlock(&instance->guard); 91 144 } 92 145 93 146 /** Mark the endpoint as inactive and allow access for further fibrils. 94 * @param ependpoint_t structure.147 * @param instance endpoint_t structure. 95 148 */ 96 void endpoint_release(endpoint_t * ep)149 void endpoint_release(endpoint_t *instance) 97 150 { 98 assert( ep);99 fibril_mutex_lock(& ep->guard);100 ep->active = false;101 fibril_mutex_unlock(& ep->guard);102 fibril_condvar_signal(& ep->avail);151 assert(instance); 152 fibril_mutex_lock(&instance->guard); 153 instance->active = false; 154 fibril_mutex_unlock(&instance->guard); 155 fibril_condvar_signal(&instance->avail); 103 156 /* Drop reference for active endpoint. */ 104 endpoint_del_ref( ep);157 endpoint_del_ref(instance); 105 158 } 106 159 107 /** Get the value of toggle bit. Either uses the toggle_get op, or just returns108 * the value of the toggle.109 * @ param ep endpoint_t structure.160 /** Get the value of toggle bit. 161 * @param instance endpoint_t structure. 162 * @note Will use provided hook. 110 163 */ 111 int endpoint_toggle_get(endpoint_t * ep)164 int endpoint_toggle_get(endpoint_t *instance) 112 165 { 113 assert(ep); 114 fibril_mutex_lock(&ep->guard); 115 const int ret = ep->bus->ops.endpoint_get_toggle 116 ? ep->bus->ops.endpoint_get_toggle(ep) 117 : ep->toggle; 118 fibril_mutex_unlock(&ep->guard); 166 assert(instance); 167 fibril_mutex_lock(&instance->guard); 168 if (instance->hc_data.toggle_get) 169 instance->toggle = 170 instance->hc_data.toggle_get(instance->hc_data.data); 171 const int ret = instance->toggle; 172 fibril_mutex_unlock(&instance->guard); 119 173 return ret; 120 174 } 121 175 122 /** Set the value of toggle bit. Either uses the toggle_set op, or just sets123 * the toggle inside.124 * @ param ep endpoint_t structure.176 /** Set the value of toggle bit. 177 * @param instance endpoint_t structure. 178 * @note Will use provided hook. 125 179 */ 126 void endpoint_toggle_set(endpoint_t * ep, unsignedtoggle)180 void endpoint_toggle_set(endpoint_t *instance, int toggle) 127 181 { 128 assert( ep);182 assert(instance); 129 183 assert(toggle == 0 || toggle == 1); 130 fibril_mutex_lock(&ep->guard); 131 if (ep->bus->ops.endpoint_set_toggle) { 132 ep->bus->ops.endpoint_set_toggle(ep, toggle); 133 } 134 else { 135 ep->toggle = toggle; 136 } 137 fibril_mutex_unlock(&ep->guard); 184 fibril_mutex_lock(&instance->guard); 185 instance->toggle = toggle; 186 if (instance->hc_data.toggle_set) 187 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 188 fibril_mutex_unlock(&instance->guard); 138 189 } 139 140 190 141 191 /** -
uspace/lib/usbhost/src/hcd.c
re160bfe8 r367db39a 41 41 #include <errno.h> 42 42 #include <usb_iface.h> 43 #include <str_error.h>44 43 45 44 #include "hcd.h" 45 46 /** Calls ep_add_hook upon endpoint registration. 47 * @param ep Endpoint to be registered. 48 * @param arg hcd_t in disguise. 49 * @return Error code. 50 */ 51 static int register_helper(endpoint_t *ep, void *arg) 52 { 53 hcd_t *hcd = arg; 54 assert(ep); 55 assert(hcd); 56 if (hcd->ops.ep_add_hook) 57 return hcd->ops.ep_add_hook(hcd, ep); 58 return EOK; 59 } 60 61 /** Calls ep_remove_hook upon endpoint removal. 62 * @param ep Endpoint to be unregistered. 63 * @param arg hcd_t in disguise. 64 */ 65 static void unregister_helper(endpoint_t *ep, void *arg) 66 { 67 hcd_t *hcd = arg; 68 assert(ep); 69 assert(hcd); 70 if (hcd->ops.ep_remove_hook) 71 hcd->ops.ep_remove_hook(hcd, ep); 72 } 73 74 /** Calls ep_remove_hook upon endpoint removal. Prints warning. 75 * * @param ep Endpoint to be unregistered. 76 * * @param arg hcd_t in disguise. 77 * */ 78 static void unregister_helper_warn(endpoint_t *ep, void *arg) 79 { 80 assert(ep); 81 usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n", 82 ep->address, ep->endpoint, usb_str_direction(ep->direction)); 83 unregister_helper(ep, arg); 84 } 46 85 47 86 … … 54 93 * @param bw_count Bandwidth compute function, passed to endpoint manager. 55 94 */ 56 void hcd_init(hcd_t *hcd) { 57 assert(hcd); 58 59 hcd_set_implementation(hcd, NULL, NULL, NULL); 95 void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth, 96 bw_count_func_t bw_count) 97 { 98 assert(hcd); 99 usb_bus_init(&hcd->bus, bandwidth, bw_count, max_speed); 100 101 hcd_set_implementation(hcd, NULL, NULL); 60 102 } 61 103 … … 64 106 assert(hcd); 65 107 usb_address_t address = 0; 66 const int ret = bus_request_address(hcd->bus, &address, false, speed); 108 const int ret = usb_bus_request_address( 109 &hcd->bus, &address, false, speed); 67 110 if (ret != EOK) 68 111 return ret; … … 70 113 } 71 114 115 int hcd_release_address(hcd_t *hcd, usb_address_t address) 116 { 117 assert(hcd); 118 return usb_bus_remove_address(&hcd->bus, address, 119 unregister_helper_warn, hcd); 120 } 121 122 int hcd_reserve_default_address(hcd_t *hcd, usb_speed_t speed) 123 { 124 assert(hcd); 125 usb_address_t address = 0; 126 return usb_bus_request_address(&hcd->bus, &address, true, speed); 127 } 128 129 int hcd_add_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir, 130 usb_transfer_type_t type, size_t max_packet_size, unsigned packets, 131 size_t size, usb_address_t tt_address, unsigned tt_port) 132 { 133 assert(hcd); 134 return usb_bus_add_ep(&hcd->bus, target.address, 135 target.endpoint, dir, type, max_packet_size, packets, size, 136 register_helper, hcd, tt_address, tt_port); 137 } 138 139 int hcd_remove_ep(hcd_t *hcd, usb_target_t target, usb_direction_t dir) 140 { 141 assert(hcd); 142 return usb_bus_remove_ep(&hcd->bus, target.address, 143 target.endpoint, dir, unregister_helper, hcd); 144 } 145 146 147 typedef struct { 148 void *original_data; 149 usbhc_iface_transfer_out_callback_t original_callback; 150 usb_target_t target; 151 hcd_t *hcd; 152 } toggle_t; 153 154 static void toggle_reset_callback(int retval, void *arg) 155 { 156 assert(arg); 157 toggle_t *toggle = arg; 158 if (retval == EOK) { 159 usb_log_debug2("Reseting toggle on %d:%d.\n", 160 toggle->target.address, toggle->target.endpoint); 161 usb_bus_reset_toggle(&toggle->hcd->bus, 162 toggle->target, toggle->target.endpoint == 0); 163 } 164 165 toggle->original_callback(retval, toggle->original_data); 166 } 167 72 168 /** Prepare generic usb_transfer_batch and schedule it. 73 169 * @param hcd Host controller driver. 170 * @param fun DDF fun 74 171 * @param target address and endpoint number. 75 172 * @param setup_data Data to use in setup stage (Control communication type) … … 80 177 * @return Error code. 81 178 */ 82 int hcd_send_batch(hcd_t *hcd, usb_target_t target, usb_direction_t direction, 83 void *data, size_t size, uint64_t setup_data, 84 usbhc_iface_transfer_in_callback_t in, usbhc_iface_transfer_out_callback_t out, 85 void *arg, const char *name) 86 { 87 assert(hcd); 88 89 endpoint_t *ep = bus_find_endpoint(hcd->bus, target, direction); 179 int hcd_send_batch( 180 hcd_t *hcd, usb_target_t target, usb_direction_t direction, 181 void *data, size_t size, uint64_t setup_data, 182 usbhc_iface_transfer_in_callback_t in, 183 usbhc_iface_transfer_out_callback_t out, void *arg, const char* name) 184 { 185 assert(hcd); 186 187 endpoint_t *ep = usb_bus_find_ep(&hcd->bus, 188 target.address, target.endpoint, direction); 90 189 if (ep == NULL) { 91 190 usb_log_error("Endpoint(%d:%d) not registered for %s.\n", … … 97 196 name, target.address, target.endpoint, size, ep->max_packet_size); 98 197 99 const size_t bw = bus_count_bw(ep, size); 198 const size_t bw = bandwidth_count_usb11( 199 ep->speed, ep->transfer_type, size, ep->max_packet_size); 100 200 /* Check if we have enough bandwidth reserved */ 101 201 if (ep->bandwidth < bw) { 102 202 usb_log_error("Endpoint(%d:%d) %s needs %zu bw " 103 203 "but only %zu is reserved.\n", 104 ep-> target.address, ep->target.endpoint, name, bw, ep->bandwidth);204 ep->address, ep->endpoint, name, bw, ep->bandwidth); 105 205 return ENOSPC; 106 206 } … … 110 210 } 111 211 112 usb_transfer_batch_t *batch = usb_transfer_batch_create(ep); 212 /* Check for commands that reset toggle bit */ 213 if (ep->transfer_type == USB_TRANSFER_CONTROL) { 214 const int reset_toggle = usb_request_needs_toggle_reset( 215 (usb_device_request_setup_packet_t *) &setup_data); 216 if (reset_toggle >= 0) { 217 assert(out); 218 toggle_t *toggle = malloc(sizeof(toggle_t)); 219 if (!toggle) 220 return ENOMEM; 221 toggle->target.address = target.address; 222 toggle->target.endpoint = reset_toggle; 223 toggle->original_callback = out; 224 toggle->original_data = arg; 225 toggle->hcd = hcd; 226 227 arg = toggle; 228 out = toggle_reset_callback; 229 } 230 } 231 232 usb_transfer_batch_t *batch = usb_transfer_batch_create( 233 ep, data, size, setup_data, in, out, arg); 113 234 if (!batch) { 114 235 usb_log_error("Failed to create transfer batch.\n"); … … 116 237 } 117 238 118 batch->buffer = data;119 batch->buffer_size = size;120 batch->setup.packed = setup_data;121 batch->dir = direction;122 123 /* Check for commands that reset toggle bit */124 if (ep->transfer_type == USB_TRANSFER_CONTROL)125 batch->toggle_reset_mode126 = usb_request_get_toggle_reset_mode(&batch->setup.packet);127 128 usb_transfer_batch_set_old_handlers(batch, in, out, arg);129 130 239 const int ret = hcd->ops.schedule(hcd, batch); 131 if (ret != EOK) { 132 usb_log_warning("Batch %p failed to schedule: %s", batch, str_error(ret)); 240 if (ret != EOK) 133 241 usb_transfer_batch_destroy(batch); 134 }135 242 136 243 /* Drop our own reference to ep. */ … … 141 248 142 249 typedef struct { 143 fibril_mutex_t done_mtx; 144 fibril_condvar_t done_cv; 145 unsigned done; 250 volatile unsigned done; 146 251 int ret; 147 252 size_t size; … … 153 258 assert(d); 154 259 d->ret = ret; 260 d->done = 1; 155 261 d->size = size; 156 fibril_mutex_lock(&d->done_mtx);157 d->done = 1;158 fibril_condvar_broadcast(&d->done_cv);159 fibril_mutex_unlock(&d->done_mtx);160 262 } 161 263 … … 165 267 assert(data); 166 268 d->ret = ret; 167 fibril_mutex_lock(&d->done_mtx);168 269 d->done = 1; 169 fibril_condvar_broadcast(&d->done_cv);170 fibril_mutex_unlock(&d->done_mtx);171 270 } 172 271 … … 178 277 assert(hcd); 179 278 sync_data_t sd = { .done = 0, .ret = EBUSY, .size = size }; 180 fibril_mutex_initialize(&sd.done_mtx);181 fibril_condvar_initialize(&sd.done_cv);182 279 183 280 const int ret = hcd_send_batch(hcd, target, dir, data, size, setup_data, … … 187 284 return ret; 188 285 189 fibril_mutex_lock(&sd.done_mtx); 190 while (!sd.done) 191 fibril_condvar_wait(&sd.done_cv, &sd.done_mtx); 192 fibril_mutex_unlock(&sd.done_mtx); 286 while (!sd.done) { 287 async_usleep(1000); 288 } 193 289 194 290 if (sd.ret == EOK) -
uspace/lib/usbhost/src/usb_transfer_batch.c
re160bfe8 r367db39a 34 34 35 35 #include <usb/host/usb_transfer_batch.h> 36 #include <usb/host/endpoint.h>37 #include <usb/host/bus.h>38 36 #include <usb/debug.h> 39 37 40 38 #include <assert.h> 41 39 #include <errno.h> 42 #include <str_error.h> 40 #include <macros.h> 41 #include <mem.h> 42 #include <stdlib.h> 43 #include <usbhc_iface.h> 43 44 45 /** Allocate and initialize usb_transfer_batch structure. 46 * @param ep endpoint used by the transfer batch. 47 * @param buffer data to send/recieve. 48 * @param buffer_size Size of data buffer. 49 * @param setup_buffer Data to send in SETUP stage of control transfer. 50 * @param func_in callback on IN transfer completion. 51 * @param func_out callback on OUT transfer completion. 52 * @param fun DDF function (passed to callback function). 53 * @param arg Argument to pass to the callback function. 54 * @param private_data driver specific per batch data. 55 * @param private_data_dtor Function to properly destroy private_data. 56 * @return Pointer to valid usb_transfer_batch_t structure, NULL on failure. 57 */ 58 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep, char *buffer, 59 size_t buffer_size, 60 uint64_t setup_buffer, 61 usbhc_iface_transfer_in_callback_t func_in, 62 usbhc_iface_transfer_out_callback_t func_out, 63 void *arg) 64 { 65 if (func_in == NULL && func_out == NULL) 66 return NULL; 67 if (func_in != NULL && func_out != NULL) 68 return NULL; 44 69 45 /** Create a batch on given endpoint. 46 */ 47 usb_transfer_batch_t *usb_transfer_batch_create(endpoint_t *ep) 48 { 49 assert(ep); 50 assert(ep->bus); 51 52 usb_transfer_batch_t *batch; 53 if (ep->bus->ops.create_batch) 54 batch = ep->bus->ops.create_batch(ep->bus, ep); 55 else 56 batch = malloc(sizeof(usb_transfer_batch_t)); 57 58 return batch; 70 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 71 if (instance) { 72 instance->ep = ep; 73 instance->callback_in = func_in; 74 instance->callback_out = func_out; 75 instance->arg = arg; 76 instance->buffer = buffer; 77 instance->buffer_size = buffer_size; 78 instance->setup_size = 0; 79 instance->transfered_size = 0; 80 instance->error = EOK; 81 if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) { 82 memcpy(instance->setup_buffer, &setup_buffer, 83 USB_SETUP_PACKET_SIZE); 84 instance->setup_size = USB_SETUP_PACKET_SIZE; 85 } 86 if (instance->ep) 87 endpoint_use(instance->ep); 88 } 89 return instance; 59 90 } 60 91 61 /** Initialize given batch structure. 92 /** Correctly dispose all used data structures. 93 * 94 * @param[in] instance Batch structure to use. 62 95 */ 63 void usb_transfer_batch_ init(usb_transfer_batch_t *batch, endpoint_t *ep)96 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance) 64 97 { 65 endpoint_use(ep); 66 67 memset(batch, 0, sizeof(*batch)); 68 batch->ep = ep; 98 if (!instance) 99 return; 100 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n", 101 instance, USB_TRANSFER_BATCH_ARGS(*instance)); 102 if (instance->ep) { 103 endpoint_release(instance->ep); 104 } 105 free(instance); 69 106 } 70 107 71 /** Call the handler of the batch.108 /** Prepare data and call the right callback. 72 109 * 73 * @param[in] batch Batch structure to use. 110 * @param[in] instance Batch structure to use. 111 * @param[in] data Data to copy to the output buffer. 112 * @param[in] size Size of @p data. 113 * @param[in] error Error value to use. 74 114 */ 75 static int batch_complete(usb_transfer_batch_t *batch) 115 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance, 116 const void *data, size_t size, int error) 76 117 { 77 assert(batch); 118 assert(instance); 119 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " finishing.\n", 120 instance, USB_TRANSFER_BATCH_ARGS(*instance)); 78 121 79 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed.\n", 80 batch, USB_TRANSFER_BATCH_ARGS(*batch)); 81 82 if (batch->error == EOK && batch->toggle_reset_mode != RESET_NONE) { 83 usb_log_debug2("Reseting %s due to transaction of %d:%d.\n", 84 batch->toggle_reset_mode == RESET_ALL ? "all EPs toggle" : "EP toggle", 85 batch->ep->target.address, batch->ep->target.endpoint); 86 bus_reset_toggle(batch->ep->bus, 87 batch->ep->target, batch->toggle_reset_mode == RESET_ALL); 122 /* NOTE: Only one of these pointers should be set. */ 123 if (instance->callback_out) { 124 instance->callback_out(error, instance->arg); 88 125 } 89 126 90 return batch->on_complete 91 ? batch->on_complete(batch) 92 : EOK; 93 } 94 95 /** Destroy the batch. 96 * 97 * @param[in] batch Batch structure to use. 98 */ 99 void usb_transfer_batch_destroy(usb_transfer_batch_t *batch) 100 { 101 assert(batch); 102 assert(batch->ep); 103 assert(batch->ep->bus); 104 105 bus_t *bus = batch->ep->bus; 106 if (bus->ops.destroy_batch) { 107 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " destroying.\n", 108 batch, USB_TRANSFER_BATCH_ARGS(*batch)); 109 bus->ops.destroy_batch(batch); 127 if (instance->callback_in) { 128 /* We care about the data and there are some to copy */ 129 const size_t safe_size = min(size, instance->buffer_size); 130 if (data) { 131 memcpy(instance->buffer, data, safe_size); 132 } 133 instance->callback_in(error, safe_size, instance->arg); 110 134 } 111 else {112 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",113 batch, USB_TRANSFER_BATCH_ARGS(*batch));114 free(batch);115 }116 117 endpoint_release(batch->ep);118 }119 120 /** Finish a transfer batch: call handler, destroy batch, release endpoint.121 *122 * Call only after the batch have been scheduled && completed!123 *124 * @param[in] batch Batch structure to use.125 */126 void usb_transfer_batch_finish(usb_transfer_batch_t *batch)127 {128 const int err = batch_complete(batch);129 if (err)130 usb_log_warning("batch %p failed to complete: %s", batch, str_error(err));131 132 usb_transfer_batch_destroy(batch);133 }134 135 136 struct old_handler_wrapper_data {137 usbhc_iface_transfer_in_callback_t in_callback;138 usbhc_iface_transfer_out_callback_t out_callback;139 void *arg;140 };141 142 static int old_handler_wrapper(usb_transfer_batch_t *batch)143 {144 struct old_handler_wrapper_data *data = batch->on_complete_data;145 146 assert(data);147 148 if (data->out_callback)149 data->out_callback(batch->error, data->arg);150 151 if (data->in_callback)152 data->in_callback(batch->error, batch->transfered_size, data->arg);153 154 free(data);155 return EOK;156 }157 158 void usb_transfer_batch_set_old_handlers(usb_transfer_batch_t *batch,159 usbhc_iface_transfer_in_callback_t in_callback,160 usbhc_iface_transfer_out_callback_t out_callback,161 void *arg)162 {163 struct old_handler_wrapper_data *data = malloc(sizeof(*data));164 165 assert((!in_callback) != (!out_callback));166 167 data->in_callback = in_callback;168 data->out_callback = out_callback;169 data->arg = arg;170 171 batch->on_complete = old_handler_wrapper;172 batch->on_complete_data = data;173 135 } 174 136 /**
Note:
See TracChangeset
for help on using the changeset viewer.
