Changeset 7feeb84 in mainline for uspace/lib/usbvirt
- Timestamp:
- 2010-12-13T14:25:49Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 76daaf9f
- Parents:
- 8f8ae1fd
- Location:
- uspace/lib/usbvirt
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usbvirt/include/usbvirt/device.h
r8f8ae1fd r7feeb84 40 40 #include <usb/devreq.h> 41 41 42 typedef enum { 43 USBVIRT_REQUEST_TYPE_STANDARD = 0, 44 USBVIRT_REQUEST_TYPE_CLASS = 1 45 } usbvirt_request_type_t; 46 47 typedef enum { 48 USBVIRT_REQUEST_RECIPIENT_DEVICE = 0, 49 USBVIRT_REQUEST_RECIPIENT_INTERFACE = 1, 50 USBVIRT_REQUEST_RECIPIENT_ENDPOINT = 2, 51 USBVIRT_REQUEST_RECIPIENT_OTHER = 3 52 } usbvirt_request_recipient_t; 53 42 54 typedef struct usbvirt_device usbvirt_device_t; 43 55 struct usbvirt_control_transfer; … … 47 59 uint8_t *data); 48 60 61 typedef int (*usbvirt_control_request_callback_t)(usbvirt_device_t *dev, 62 usb_device_request_setup_packet_t *request, 63 uint8_t *data); 64 65 typedef struct { 66 uint8_t request_type; 67 uint8_t request; 68 usbvirt_control_request_callback_t callback; 69 } usbvirt_control_transfer_handler_t; 70 71 #define USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, type, recipient) \ 72 ((((direction) == USB_DIRECTION_IN) ? 1 : 0) << 7) \ 73 | (((type) & 3) << 5) \ 74 | (((recipient) & 31)) 75 76 #define USBVIRT_CONTROL_TRANSFER_HANDLER_LAST { 0, 0, NULL } 77 49 78 /** Device operations. */ 50 79 typedef struct { 51 /** Callbacks for standard device requests. 52 * The callbacks are indexed by usb_stddevreq_t enum. 53 */ 54 usbvirt_on_device_request_t on_standard_request[USB_DEVREQ_LAST_STD]; 55 /** Callback for class-specific USB request. */ 56 usbvirt_on_device_request_t on_class_device_request; 57 80 /** Callbacks for transfers over control pipe zero. */ 81 usbvirt_control_transfer_handler_t *control_transfer_handlers; 82 58 83 int (*on_control_transfer)(usbvirt_device_t *dev, 59 84 usb_endpoint_t endpoint, struct usbvirt_control_transfer *transfer); -
uspace/lib/usbvirt/src/ctrlpipe.c
r8f8ae1fd r7feeb84 37 37 #include "private.h" 38 38 39 #define REQUEST_TYPE_STANDARD 0 40 #define REQUEST_TYPE_CLASS 1 39 /** Compares handler type with request packet type. 40 * 41 * @param handler Handler. 42 * @param request_packet Request packet. 43 * @return Whether handler can serve this packet. 44 */ 45 static bool is_suitable_handler(usbvirt_control_transfer_handler_t *handler, 46 usb_device_request_setup_packet_t *request_packet) 47 { 48 return ( 49 (handler->request_type == request_packet->request_type) 50 && (handler->request == request_packet->request)); 41 51 42 #define GET_MIDBITS_MASK(size, shift) \ 43 (((1 << size) - 1) << shift) 44 #define GET_MIDBITS(value, size, shift) \ 45 ((value & GET_MIDBITS_MASK(size, shift)) >> shift) 52 } 53 54 /** Find suitable transfer handler for given request packet. 55 * 56 * @param handlers Array of available handlers. 57 * @param request_packet Request SETUP packet. 58 * @return Handler or NULL. 59 */ 60 static usbvirt_control_transfer_handler_t *find_handler( 61 usbvirt_control_transfer_handler_t *handlers, 62 usb_device_request_setup_packet_t *request_packet) 63 { 64 if (handlers == NULL) { 65 return NULL; 66 } 67 68 while (handlers->callback != NULL) { 69 if (is_suitable_handler(handlers, request_packet)) { 70 return handlers; 71 } 72 handlers++; 73 } 74 75 return NULL; 76 } 46 77 47 78 48 static const char *str_request_type(int type)49 {50 switch (type) {51 case REQUEST_TYPE_STANDARD:52 return "standard";53 case REQUEST_TYPE_CLASS:54 return "class";55 default:56 return "unknown";57 }58 }59 60 /** Tell request type.61 * By type is meant either standard, class, vendor or other.62 */63 static int request_get_type(uint8_t request_type)64 {65 return GET_MIDBITS(request_type, 2, 5);66 }67 79 68 80 /** Handle communication over control pipe zero. … … 77 89 } 78 90 79 usb_device_request_setup_packet_t *request = (usb_device_request_setup_packet_t *) transfer->request; 80 uint8_t *remaining_data = transfer->data; 91 usb_device_request_setup_packet_t *request 92 = (usb_device_request_setup_packet_t *) transfer->request; 93 printf("Request: %d,%d\n", request->request_type, request->request); 81 94 82 int type = request_get_type(request->request_type); 83 84 int rc = EOK; 85 86 device->lib_debug(device, 2, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO, 87 "request type: %s", str_request_type(type)); 88 89 switch (type) { 90 case REQUEST_TYPE_STANDARD: 91 rc = handle_std_request(device, request, remaining_data); 92 break; 93 case REQUEST_TYPE_CLASS: 94 if (DEVICE_HAS_OP(device, on_class_device_request)) { 95 rc = device->ops->on_class_device_request(device, 96 request, remaining_data); 97 } 98 break; 99 default: 100 break; 95 /* 96 * First, see whether user provided its own callback. 97 */ 98 int rc = EFORWARD; 99 if (device->ops) { 100 usbvirt_control_transfer_handler_t *user_handler 101 = find_handler(device->ops->control_transfer_handlers, 102 request); 103 if (user_handler != NULL) { 104 rc = user_handler->callback(device, request, 105 transfer->data); 106 } 107 } 108 109 /* 110 * If there was no user callback or the callback returned EFORWARD, 111 * we need to run a local handler. 112 */ 113 if (rc == EFORWARD) { 114 usbvirt_control_transfer_handler_t *lib_handler 115 = find_handler(control_pipe_zero_local_handlers, 116 request); 117 if (lib_handler != NULL) { 118 rc = lib_handler->callback(device, request, 119 transfer->data); 120 } 101 121 } 102 122 123 /* 124 * Check for SET_ADDRESS finalization. 125 */ 103 126 if (device->new_address != -1) { 104 127 /* -
uspace/lib/usbvirt/src/private.h
r8f8ae1fd r7feeb84 87 87 } 88 88 89 extern usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[]; 90 89 91 #endif 90 92 /** -
uspace/lib/usbvirt/src/stdreq.c
r8f8ae1fd r7feeb84 40 40 #include "private.h" 41 41 42 43 typedef int (*usbvirt_stdreq_handler_t)(usbvirt_device_t *,44 usb_device_request_setup_packet_t *, uint8_t *);45 46 42 /* 47 43 * All sub handlers must return EFORWARD to inform the caller that … … 177 173 } 178 174 179 static usbvirt_stdreq_handler_t local_handlers[USB_DEVREQ_LAST_STD] = { 180 [USB_DEVREQ_GET_DESCRIPTOR] = handle_get_descriptor, 181 [USB_DEVREQ_SET_ADDRESS] = handle_set_address, 182 [USB_DEVREQ_SET_CONFIGURATION] = handle_set_configuration 175 176 #define MAKE_BM_REQUEST(direction, recipient) \ 177 USBVIRT_MAKE_CONTROL_REQUEST_TYPE(direction, \ 178 USBVIRT_REQUEST_TYPE_STANDARD, recipient) 179 #define MAKE_BM_REQUEST_DEV(direction) \ 180 MAKE_BM_REQUEST(direction, USBVIRT_REQUEST_RECIPIENT_DEVICE) 181 182 usbvirt_control_transfer_handler_t control_pipe_zero_local_handlers[] = { 183 { 184 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_IN), 185 .request = USB_DEVREQ_GET_DESCRIPTOR, 186 .callback = handle_get_descriptor 187 }, 188 { 189 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT), 190 .request = USB_DEVREQ_SET_ADDRESS, 191 .callback = handle_set_address 192 }, 193 { 194 .request_type = MAKE_BM_REQUEST_DEV(USB_DIRECTION_OUT), 195 .request = USB_DEVREQ_SET_CONFIGURATION, 196 .callback = handle_set_configuration 197 }, 198 USBVIRT_CONTROL_TRANSFER_HANDLER_LAST 183 199 }; 184 185 /** Handle standard device request. */186 int handle_std_request(usbvirt_device_t *device,187 usb_device_request_setup_packet_t *request_packet, uint8_t *data)188 {189 int request = request_packet->request;190 191 device->lib_debug(device, 3, USBVIRT_DEBUGTAG_CONTROL_PIPE_ZERO,192 "handling standard request %d", request);193 194 if (request >= USB_DEVREQ_LAST_STD) {195 return ENOTSUP;196 }197 198 int rc = EFORWARD;199 if ((device->ops)200 && (device->ops->on_standard_request[request])) {201 rc = device->ops->on_standard_request[request](device,202 request_packet, data);203 }204 205 if (rc == EFORWARD) {206 if (local_handlers[request]) {207 rc = local_handlers[request](device,208 request_packet, data);209 } else {210 rc = ENOTSUP;211 }212 }213 214 assert(rc != EFORWARD);215 return rc;216 }217 200 218 201 /**
Note:
See TracChangeset
for help on using the changeset viewer.