source: mainline/uspace/drv/ohci/root_hub.c@ cee51fd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cee51fd was aee6c73, checked in by Matus Dekanek <smekideki@…>, 14 years ago

merge from development

  • Property mode set to 100644
File size: 24.5 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/** @addtogroup drvusbohci
29 * @{
30 */
31/** @file
32 * @brief OHCI driver
33 */
34#include <assert.h>
35#include <errno.h>
36#include <str_error.h>
37
38#include <usb/debug.h>
39
40#include "root_hub.h"
41#include "usb/classes/classes.h"
42#include <usb/request.h>
43#include <usb/classes/hub.h>
44
45static const usb_standard_device_descriptor_t ohci_rh_device_descriptor =
46{
47 .configuration_count = 1,
48 .descriptor_type = USB_DESCTYPE_DEVICE,
49 .device_class = USB_CLASS_HUB,
50 .device_protocol = 0,
51 .device_subclass = 0,
52 .device_version = 0,
53 .length = sizeof(usb_standard_device_descriptor_t),
54 /// \TODO this value is guessed
55 .max_packet_size = 8,
56 .vendor_id = 0x16db,
57 .product_id = 0x0001,
58 /// \TODO these values migt be different
59 .str_serial_number = 0,
60 .usb_spec_version = 0,
61};
62
63static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =
64{
65 /// \TODO some values are default or guessed
66 .attributes = 1<<7,
67 .configuration_number = 1,
68 .descriptor_type = USB_DESCTYPE_CONFIGURATION,
69 .interface_count = 1,
70 .length = sizeof(usb_standard_configuration_descriptor_t),
71 .max_power = 100,
72 .str_configuration = 0,
73};
74
75static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =
76{
77 .alternate_setting = 0,
78 .descriptor_type = USB_DESCTYPE_INTERFACE,
79 .endpoint_count = 1,
80 .interface_class = USB_CLASS_HUB,
81 /// \TODO is this correct?
82 .interface_number = 1,
83 .interface_protocol = 0,
84 .interface_subclass = 0,
85 .length = sizeof(usb_standard_interface_descriptor_t),
86 .str_interface = 0,
87};
88
89static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =
90{
91 .attributes = USB_TRANSFER_INTERRUPT,
92 .descriptor_type = USB_DESCTYPE_ENDPOINT,
93 .endpoint_address = 1 + (1<<7),
94 .length = sizeof(usb_standard_endpoint_descriptor_t),
95 .max_packet_size = 8,
96 .poll_interval = 255,
97};
98
99/** Root hub initialization
100 * @return Error code.
101 */
102int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs)
103{
104 assert(instance);
105 instance->address = -1;
106 instance->registers = regs;
107 instance->device = dev;
108
109
110 usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff);
111
112 //start generic usb hub driver
113
114 /* TODO: implement */
115 return EOK;
116}
117/*----------------------------------------------------------------------------*/
118
119/**
120 * create answer to port status_request
121 *
122 * Copy content of corresponding port status register to answer buffer.
123 *
124 * @param instance root hub instance
125 * @param port port number, counted from 1
126 * @param request structure containing both request and response information
127 * @return error code
128 */
129static int process_get_port_status_request(rh_t *instance, uint16_t port,
130 usb_transfer_batch_t * request){
131 if(port<1 || port>instance->port_count)
132 return EINVAL;
133 uint32_t * uint32_buffer = (uint32_t*)request->buffer;
134 request->transfered_size = 4;
135 uint32_buffer[0] = instance->registers->rh_port_status[port -1];
136 return EOK;
137}
138
139/**
140 * create answer to port status_request
141 *
142 * Copy content of hub status register to answer buffer.
143 *
144 * @param instance root hub instance
145 * @param request structure containing both request and response information
146 * @return error code
147 */
148static int process_get_hub_status_request(rh_t *instance,
149 usb_transfer_batch_t * request){
150 uint32_t * uint32_buffer = (uint32_t*)request->buffer;
151 //bits, 0,1,16,17
152 request->transfered_size = 4;
153 uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);
154 uint32_buffer[0] = mask & instance->registers->rh_status;
155 return EOK;
156
157}
158
159/**
160 * Create hub descriptor used in hub-driver <-> hub communication
161 *
162 * This means creating byt array from data in root hub registers. For more
163 * info see usb hub specification.
164 *
165 * @param instance root hub instance
166 * @param@out out_result pointer to resultant serialized descriptor
167 * @param@out out_size size of serialized descriptor
168 */
169static void usb_create_serialized_hub_descriptor(rh_t *instance,
170 uint8_t ** out_result,
171 size_t * out_size) {
172 //base size
173 size_t size = 7;
174 //variable size according to port count
175 size_t var_size = instance->port_count / 8 +
176 ((instance->port_count % 8 > 0) ? 1 : 0);
177 size += 2 * var_size;
178 uint8_t * result = (uint8_t*) malloc(size);
179 bzero(result,size);
180 //size
181 result[0] = size;
182 //descriptor type
183 result[1] = USB_DESCTYPE_HUB;
184 result[2] = instance->port_count;
185 uint32_t hub_desc_reg = instance->registers->rh_desc_a;
186 result[3] =
187 ((hub_desc_reg >> 8) %2) +
188 (((hub_desc_reg >> 9) %2) << 1) +
189 (((hub_desc_reg >> 10) %2) << 2) +
190 (((hub_desc_reg >> 11) %2) << 3) +
191 (((hub_desc_reg >> 12) %2) << 4);
192 result[4] = 0;
193 result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
194 result[6] = 50;
195
196 int port;
197 for (port = 1; port <= instance->port_count; ++port) {
198 result[7 + port/8] +=
199 ((instance->registers->rh_desc_b >> port)%2) << (port%8);
200 }
201 size_t i;
202 for (i = 0; i < var_size; ++i) {
203 result[7 + var_size + i] = 255;
204 }
205 (*out_result) = result;
206 (*out_size) = size;
207}
208
209
210/**
211 * create answer to status request
212 *
213 * This might be either hub status or port status request. If neither,
214 * ENOTSUP is returned.
215 * @param instance root hub instance
216 * @param request structure containing both request and response information
217 * @return error code
218 */
219static int process_get_status_request(rh_t *instance,
220 usb_transfer_batch_t * request)
221{
222 size_t buffer_size = request->buffer_size;
223 usb_device_request_setup_packet_t * request_packet =
224 (usb_device_request_setup_packet_t*)
225 request->setup_buffer;
226
227 usb_hub_bm_request_type_t request_type = request_packet->request_type;
228 if(buffer_size<4/*request_packet->length*/){///\TODO
229 usb_log_warning("requested more data than buffer size\n");
230 return EINVAL;
231 }
232
233 if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
234 return process_get_hub_status_request(instance, request);
235 if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
236 return process_get_port_status_request(instance, request_packet->index,
237 request);
238 return ENOTSUP;
239}
240
241/**
242 * create answer to status interrupt consisting of change bitmap
243 *
244 * Result contains bitmap where bit 0 indicates change on hub and
245 * bit i indicates change on i`th port (i>0). For more info see
246 * Hub and Port status bitmap specification in USB specification.
247 * @param instance root hub instance
248 * @param@out buffer pointer to created interrupt mas
249 * @param@out buffer_size size of created interrupt mask
250 */
251static void create_interrupt_mask(rh_t *instance, void ** buffer,
252 size_t * buffer_size){
253 int bit_count = instance->port_count + 1;
254 (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1;
255 (*buffer) = malloc(*buffer_size);
256 uint8_t * bitmap = (uint8_t*)(*buffer);
257 uint32_t mask = (1<<16) + (1<<17);
258 bzero(bitmap,(*buffer_size));
259 if(instance->registers->rh_status & mask){
260 bitmap[0] = 1;
261 }
262 int port;
263 mask = 0;
264 int i;
265 for(i=16;i<=20;++i)
266 mask += 1<<i;
267 for(port = 1; port<=instance->port_count;++port){
268 if(mask & instance->registers->rh_port_status[port-1]){
269 bitmap[(port+1)/8] += 1<<(port%8);
270 }
271 }
272}
273
274/**
275 * create standard device descriptor for a hub
276 * @return newly allocated descriptor
277 */
278static usb_standard_device_descriptor_t *
279 usb_ohci_rh_create_standard_device_descriptor(){
280 usb_standard_device_descriptor_t * descriptor =
281 (usb_standard_device_descriptor_t*)
282 malloc(sizeof(usb_standard_device_descriptor_t));
283 descriptor->configuration_count = 1;
284 descriptor->descriptor_type = USB_DESCTYPE_DEVICE;
285 descriptor->device_class = USB_CLASS_HUB;
286 descriptor->device_protocol = 0;
287 descriptor->device_subclass = 0;
288 descriptor->device_version = 0;
289 descriptor->length = sizeof(usb_standard_device_descriptor_t);
290 /// \TODO this value is guessed
291 descriptor->max_packet_size = 8;
292 descriptor->product_id = 0x0001;
293 /// \TODO these values migt be different
294 descriptor->str_serial_number = 0;
295 descriptor->str_serial_number = 0;
296 descriptor->usb_spec_version = 0;
297 descriptor->vendor_id = 0x16db;
298 return descriptor;
299}
300
301/**
302 * create standart configuration descriptor for the root hub instance
303 * @param instance root hub instance
304 * @return newly allocated descriptor
305 */
306static usb_standard_configuration_descriptor_t *
307usb_ohci_rh_create_standart_configuration_descriptor(rh_t *instance){
308 usb_standard_configuration_descriptor_t * descriptor =
309 (usb_standard_configuration_descriptor_t*)
310 malloc(sizeof(usb_standard_configuration_descriptor_t));
311 /// \TODO some values are default or guessed
312 descriptor->attributes = 1<<7;
313 descriptor->configuration_number = 1;
314 descriptor->descriptor_type = USB_DESCTYPE_CONFIGURATION;
315 descriptor->interface_count = 1;
316 descriptor->length = sizeof(usb_standard_configuration_descriptor_t);
317 descriptor->max_power = 100;
318 descriptor->str_configuration = 0;
319 /// \TODO should this include device descriptor?
320 size_t hub_descriptor_size = 7 +
321 2* (instance->port_count / 8 +
322 ((instance->port_count % 8 > 0) ? 1 : 0));
323 descriptor->total_length =
324 sizeof(usb_standard_configuration_descriptor_t)+
325 sizeof(usb_standard_endpoint_descriptor_t)+
326 sizeof(usb_standard_interface_descriptor_t)+
327 hub_descriptor_size;
328 return descriptor;
329}
330
331/**
332 * create standard interface descriptor for a root hub
333 * @return newly allocated descriptor
334 */
335static usb_standard_interface_descriptor_t *
336usb_ohci_rh_create_standard_interface_descriptor(){
337 usb_standard_interface_descriptor_t * descriptor =
338 (usb_standard_interface_descriptor_t*)
339 malloc(sizeof(usb_standard_interface_descriptor_t));
340 descriptor->alternate_setting = 0;
341 descriptor->descriptor_type = USB_DESCTYPE_INTERFACE;
342 descriptor->endpoint_count = 1;
343 descriptor->interface_class = USB_CLASS_HUB;
344 /// \TODO is this correct?
345 descriptor->interface_number = 1;
346 descriptor->interface_protocol = 0;
347 descriptor->interface_subclass = 0;
348 descriptor->length = sizeof(usb_standard_interface_descriptor_t);
349 descriptor->str_interface = 0;
350 return descriptor;
351}
352
353/**
354 * create standard endpoint descriptor for a root hub
355 * @return newly allocated descriptor
356 */
357static usb_standard_endpoint_descriptor_t *
358usb_ohci_rh_create_standard_endpoint_descriptor(){
359 usb_standard_endpoint_descriptor_t * descriptor =
360 (usb_standard_endpoint_descriptor_t*)
361 malloc(sizeof(usb_standard_endpoint_descriptor_t));
362 descriptor->attributes = USB_TRANSFER_INTERRUPT;
363 descriptor->descriptor_type = USB_DESCTYPE_ENDPOINT;
364 descriptor->endpoint_address = 1 + (1<<7);
365 descriptor->length = sizeof(usb_standard_endpoint_descriptor_t);
366 descriptor->max_packet_size = 8;
367 descriptor->poll_interval = 255;
368 return descriptor;
369}
370
371/**
372 * create answer to a descriptor request
373 *
374 * This might be a request for standard (configuration, device, endpoint or
375 * interface) or device specific (hub) descriptor.
376 * @param instance root hub instance
377 * @param request structure containing both request and response information
378 * @return error code
379 */
380static int process_get_descriptor_request(rh_t *instance,
381 usb_transfer_batch_t *request){
382 usb_device_request_setup_packet_t * setup_request =
383 (usb_device_request_setup_packet_t*)request->setup_buffer;
384 size_t size;
385 const void * result_descriptor = NULL;
386 const uint16_t setup_request_value = setup_request->value_high;
387 //(setup_request->value_low << 8);
388#if 0
389 bool del = false;
390 //this code was merged from development and has to be reviewed
391 switch (setup_request_value)
392 {
393 case USB_DESCTYPE_HUB: {
394 uint8_t * descriptor;
395 usb_create_serialized_hub_descriptor(
396 instance, &descriptor, &size);
397 result_descriptor = descriptor;
398 break;
399 }
400 case USB_DESCTYPE_DEVICE: {
401 usb_log_debug("USB_DESCTYPE_DEVICE\n");
402 result_descriptor = &ohci_rh_device_descriptor;
403 size = sizeof(ohci_rh_device_descriptor);
404 break;
405 }
406 case USB_DESCTYPE_CONFIGURATION: {
407 usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
408 usb_standard_configuration_descriptor_t * descriptor =
409 malloc(sizeof(usb_standard_configuration_descriptor_t));
410 memcpy(descriptor, &ohci_rh_conf_descriptor,
411 sizeof(usb_standard_configuration_descriptor_t));
412 /// \TODO should this include device descriptor?
413 const size_t hub_descriptor_size = 7 +
414 2* (instance->port_count / 8 +
415 ((instance->port_count % 8 > 0) ? 1 : 0));
416 descriptor->total_length =
417 sizeof(usb_standard_configuration_descriptor_t)+
418 sizeof(usb_standard_endpoint_descriptor_t)+
419 sizeof(usb_standard_interface_descriptor_t)+
420 hub_descriptor_size;
421 result_descriptor = descriptor;
422 size = sizeof(usb_standard_configuration_descriptor_t);
423 del = true;
424 break;
425 }
426 case USB_DESCTYPE_INTERFACE: {
427 usb_log_debug("USB_DESCTYPE_INTERFACE\n");
428 result_descriptor = &ohci_rh_iface_descriptor;
429 size = sizeof(ohci_rh_iface_descriptor);
430 break;
431 }
432 case USB_DESCTYPE_ENDPOINT: {
433 usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
434 result_descriptor = &ohci_rh_ep_descriptor;
435 size = sizeof(ohci_rh_ep_descriptor);
436 break;
437 }
438 default: {
439 usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
440 usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
441 setup_request->request_type,
442 setup_request->request,
443 setup_request_value,
444 setup_request->index,
445 setup_request->length
446 );
447 return EINVAL;
448 }
449 }
450#endif
451 if(setup_request_value == USB_DESCTYPE_HUB){
452 usb_log_debug("USB_DESCTYPE_HUB\n");
453 //create hub descriptor
454 uint8_t * descriptor;
455 usb_create_serialized_hub_descriptor(instance,
456 &descriptor, &size);
457 result_descriptor = descriptor;
458 }else if(setup_request_value == USB_DESCTYPE_DEVICE){
459 //create std device descriptor
460 usb_log_debug("USB_DESCTYPE_DEVICE\n");
461 result_descriptor =
462 usb_ohci_rh_create_standard_device_descriptor();
463 size = sizeof(usb_standard_device_descriptor_t);
464 }else if(setup_request_value == USB_DESCTYPE_CONFIGURATION){
465 usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");
466 result_descriptor =
467 usb_ohci_rh_create_standart_configuration_descriptor(instance);
468 size = sizeof(usb_standard_configuration_descriptor_t);
469
470 }else if(setup_request_value == USB_DESCTYPE_INTERFACE){
471 usb_log_debug("USB_DESCTYPE_INTERFACE\n");
472 result_descriptor =
473 usb_ohci_rh_create_standard_interface_descriptor();
474 size = sizeof(usb_standard_interface_descriptor_t);
475 }else if(setup_request_value == USB_DESCTYPE_ENDPOINT){
476 usb_log_debug("USB_DESCTYPE_ENDPOINT\n");
477 result_descriptor =
478 usb_ohci_rh_create_standard_endpoint_descriptor();
479 size = sizeof(usb_standard_endpoint_descriptor_t);
480 }else{
481 usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);
482 usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",
483 setup_request->request_type,
484 setup_request->request,
485 setup_request_value,
486 setup_request->index,
487 setup_request->length
488 );
489 return EINVAL;
490 }
491 if(request->buffer_size < size){
492 size = request->buffer_size;
493 }
494 request->transfered_size = size;
495 memcpy(request->buffer,result_descriptor,size);
496 if (result_descriptor)
497 free(result_descriptor);
498 return EOK;
499}
500
501/**
502 * answer to get configuration request
503 *
504 * Root hub works independently on the configuration.
505 * @param instance root hub instance
506 * @param request structure containing both request and response information
507 * @return error code
508 */
509static int process_get_configuration_request(rh_t *instance,
510 usb_transfer_batch_t *request){
511 //set and get configuration requests do not have any meaning, only dummy
512 //values are returned
513 if(request->buffer_size != 1)
514 return EINVAL;
515 request->buffer[0] = 1;
516 request->transfered_size = 1;
517 return EOK;
518}
519
520/**
521 * process feature-enabling/disabling request on hub
522 *
523 * @param instance root hub instance
524 * @param feature feature selector
525 * @param enable enable or disable specified feature
526 * @return error code
527 */
528static int process_hub_feature_set_request(rh_t *instance,
529 uint16_t feature, bool enable){
530 if(feature > USB_HUB_FEATURE_C_HUB_OVER_CURRENT)
531 return EINVAL;
532 instance->registers->rh_status =
533 enable ?
534 (instance->registers->rh_status | (1<<feature))
535 :
536 (instance->registers->rh_status & (~(1<<feature)));
537 /// \TODO any error?
538 return EOK;
539}
540
541/**
542 * process feature-enabling/disabling request on hub
543 *
544 * @param instance root hub instance
545 * @param feature feature selector
546 * @param port port number, counted from 1
547 * @param enable enable or disable the specified feature
548 * @return error code
549 */
550static int process_port_feature_set_request(rh_t *instance,
551 uint16_t feature, uint16_t port, bool enable){
552 if(feature > USB_HUB_FEATURE_C_PORT_RESET)
553 return EINVAL;
554 if(port<1 || port>instance->port_count)
555 return EINVAL;
556 instance->registers->rh_port_status[port - 1] =
557 enable ?
558 (instance->registers->rh_port_status[port - 1] | (1<<feature))
559 :
560 (instance->registers->rh_port_status[port - 1] & (~(1<<feature)));
561 /// \TODO any error?
562 return EOK;
563}
564
565/**
566 * register address to this device
567 *
568 * @param instance root hub instance
569 * @param address new address
570 * @return error code
571 */
572static int process_address_set_request(rh_t *instance,
573 uint16_t address){
574 instance->address = address;
575 return EOK;
576}
577
578/**
579 * process one of requests that requere output data
580 *
581 * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or
582 * USB_DEVREQ_GET_CONFIGURATION.
583 * @param instance root hub instance
584 * @param request structure containing both request and response information
585 * @return error code
586 */
587static int process_request_with_output(rh_t *instance,
588 usb_transfer_batch_t *request){
589 usb_device_request_setup_packet_t * setup_request =
590 (usb_device_request_setup_packet_t*)request->setup_buffer;
591 if(setup_request->request == USB_DEVREQ_GET_STATUS){
592 usb_log_debug("USB_DEVREQ_GET_STATUS\n");
593 return process_get_status_request(instance, request);
594 }
595 if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){
596 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
597 return process_get_descriptor_request(instance, request);
598 }
599 if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){
600 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
601 return process_get_configuration_request(instance, request);
602 }
603 return ENOTSUP;
604}
605
606/**
607 * process one of requests that carry input data
608 *
609 * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or
610 * USB_DEVREQ_SET_CONFIGURATION.
611 * @param instance root hub instance
612 * @param request structure containing both request and response information
613 * @return error code
614 */
615static int process_request_with_input(rh_t *instance,
616 usb_transfer_batch_t *request){
617 usb_device_request_setup_packet_t * setup_request =
618 (usb_device_request_setup_packet_t*)request->setup_buffer;
619 request->transfered_size = 0;
620 if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){
621 return ENOTSUP;
622 }
623 if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){
624 //set and get configuration requests do not have any meaning,
625 //only dummy values are returned
626 return EOK;
627 }
628 return ENOTSUP;
629}
630
631/**
632 * process one of requests that do not request nor carry additional data
633 *
634 * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
635 * USB_DEVREQ_SET_ADDRESS.
636 * @param instance root hub instance
637 * @param request structure containing both request and response information
638 * @return error code
639 */
640static int process_request_without_data(rh_t *instance,
641 usb_transfer_batch_t *request){
642 usb_device_request_setup_packet_t * setup_request =
643 (usb_device_request_setup_packet_t*)request->setup_buffer;
644 request->transfered_size = 0;
645 if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE
646 || setup_request->request == USB_DEVREQ_SET_FEATURE){
647 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){
648 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
649 return process_hub_feature_set_request(instance, setup_request->value,
650 setup_request->request == USB_DEVREQ_SET_FEATURE);
651 }
652 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){
653 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
654 return process_port_feature_set_request(instance, setup_request->value,
655 setup_request->index,
656 setup_request->request == USB_DEVREQ_SET_FEATURE);
657 }
658 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);
659 return EINVAL;
660 }
661 if(setup_request->request == USB_DEVREQ_SET_ADDRESS){
662 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
663 return process_address_set_request(instance, setup_request->value);
664 }
665 usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type);
666 return ENOTSUP;
667}
668
669/**
670 * process hub control request
671 *
672 * If needed, writes answer into the request structure.
673 * Request can be one of
674 * USB_DEVREQ_GET_STATUS,
675 * USB_DEVREQ_GET_DESCRIPTOR,
676 * USB_DEVREQ_GET_CONFIGURATION,
677 * USB_DEVREQ_CLEAR_FEATURE,
678 * USB_DEVREQ_SET_FEATURE,
679 * USB_DEVREQ_SET_ADDRESS,
680 * USB_DEVREQ_SET_DESCRIPTOR or
681 * USB_DEVREQ_SET_CONFIGURATION.
682 *
683 * @param instance root hub instance
684 * @param request structure containing both request and response information
685 * @return error code
686 */
687static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request){
688 int opResult;
689 if (request->setup_buffer) {
690 if(sizeof(usb_device_request_setup_packet_t)>request->setup_size){
691 usb_log_error("setup packet too small\n");
692 return EINVAL;
693 }
694 usb_log_info("CTRL packet: %s.\n",
695 usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8));
696 usb_device_request_setup_packet_t * setup_request =
697 (usb_device_request_setup_packet_t*)request->setup_buffer;
698 if(
699 setup_request->request == USB_DEVREQ_GET_STATUS
700 || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR
701 || setup_request->request == USB_DEVREQ_GET_CONFIGURATION
702 ){
703 usb_log_debug("processing request with output\n");
704 opResult = process_request_with_output(instance,request);
705 }else if(
706 setup_request->request == USB_DEVREQ_CLEAR_FEATURE
707 || setup_request->request == USB_DEVREQ_SET_FEATURE
708 || setup_request->request == USB_DEVREQ_SET_ADDRESS
709 ){
710 usb_log_debug("processing request without additional data\n");
711 opResult = process_request_without_data(instance,request);
712 }else if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR
713 || setup_request->request == USB_DEVREQ_SET_CONFIGURATION
714 ){
715 usb_log_debug("processing request with input\n");
716 opResult = process_request_with_input(instance,request);
717 }else{
718 usb_log_warning("received unsuported request: %d\n",
719 setup_request->request
720 );
721 opResult = ENOTSUP;
722 }
723 }else{
724 usb_log_error("root hub received empty transaction?");
725 opResult = EINVAL;
726 }
727 return opResult;
728}
729
730/**
731 * process root hub request
732 *
733 * @param instance root hub instance
734 * @param request structure containing both request and response information
735 * @return error code
736 */
737int rh_request(rh_t *instance, usb_transfer_batch_t *request)
738{
739 assert(instance);
740 assert(request);
741 int opResult;
742 if(request->transfer_type == USB_TRANSFER_CONTROL){
743 usb_log_info("Root hub got CONTROL packet\n");
744 opResult = process_ctrl_request(instance,request);
745 }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){
746 usb_log_info("Root hub got INTERRUPT packet\n");
747 void * buffer;
748 create_interrupt_mask(instance, &buffer,
749 &(request->transfered_size));
750 memcpy(request->transport_buffer,buffer, request->transfered_size);
751 opResult = EOK;
752 }else{
753 opResult = EINVAL;
754 }
755 usb_transfer_batch_finish(request, opResult);
756 return EOK;
757}
758/*----------------------------------------------------------------------------*/
759
760
761void rh_interrupt(rh_t *instance)
762{
763 usb_log_info("Whoa whoa wait, I`m not supposed to receive interrupts, am I?\n");
764 /* TODO: implement? */
765}
766/**
767 * @}
768 */
Note: See TracBrowser for help on using the repository browser.