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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ccbcd895 was ccbcd895, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

Fix: do not EVER touch batch.buffer

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