1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <ddk/binding.h>
6 #include <ddk/debug.h>
7 #include <ddk/protocol/usb.h>
8 #include <ddk/protocol/usb/composite.h>
9 #include <usb/usb-request.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include "usb-composite.h"
15 #include "usb-interface.h"
16 
usb_interface_get_protocol(void * ctx,uint32_t proto_id,void * out)17 static zx_status_t usb_interface_get_protocol(void* ctx, uint32_t proto_id, void* out) {
18     usb_interface_t* intf = ctx;
19     switch (proto_id) {
20     case ZX_PROTOCOL_USB: {
21         usb_protocol_t* proto = (usb_protocol_t *)out;
22         proto->ctx = intf;
23         proto->ops = &usb_device_protocol;
24         return ZX_OK;
25     }
26     case ZX_PROTOCOL_USB_COMPOSITE: {
27         usb_composite_protocol_t* proto = (usb_composite_protocol_t *)out;
28         proto->ctx = intf;
29         proto->ops = &usb_composite_device_protocol;
30         return ZX_OK;
31     }
32     default:
33         return ZX_ERR_NOT_SUPPORTED;
34     }
35 }
36 
usb_interface_unbind(void * ctx)37 static void usb_interface_unbind(void* ctx) {
38     usb_interface_t* intf = ctx;
39     device_remove(intf->zxdev);
40 }
41 
usb_interface_release(void * ctx)42 static void usb_interface_release(void* ctx) {
43     usb_interface_t* intf = ctx;
44 
45     free(intf->descriptor);
46     free(intf);
47 }
48 
49 zx_protocol_device_t usb_interface_proto = {
50     .version = DEVICE_OPS_VERSION,
51     .get_protocol = usb_interface_get_protocol,
52     .unbind = usb_interface_unbind,
53     .release = usb_interface_release,
54 };
55 
56 #define NEXT_DESCRIPTOR(header) ((usb_descriptor_header_t*)((void*)header + header->bLength))
57 
58 // for determining index into active_endpoints[]
59 // bEndpointAddress has 4 lower order bits, plus high bit to signify direction
60 // shift high bit to bit 4 so index is in range 0 - 31.
61 #define get_usb_endpoint_index(ep) (((ep)->bEndpointAddress & 0x0F) | ((ep)->bEndpointAddress >> 3))
62 
usb_interface_configure_endpoints(usb_interface_t * intf,uint8_t interface_id,uint8_t alt_setting)63 zx_status_t usb_interface_configure_endpoints(usb_interface_t* intf, uint8_t interface_id,
64                                               uint8_t alt_setting) {
65     usb_endpoint_descriptor_t* new_endpoints[USB_MAX_EPS] = {};
66     bool interface_endpoints[USB_MAX_EPS] = {};
67     zx_status_t status = ZX_OK;
68 
69     // iterate through our descriptors to find which endpoints should be active
70     usb_descriptor_header_t* header = intf->descriptor;
71     usb_descriptor_header_t* end = (usb_descriptor_header_t*)((void*)header +
72                                                               intf->descriptor_length);
73     int cur_interface = -1;
74 
75     bool enable_endpoints = false;
76     while (header < end) {
77         if (header->bDescriptorType == USB_DT_INTERFACE) {
78             usb_interface_descriptor_t* intf_desc = (usb_interface_descriptor_t*)header;
79             cur_interface = intf_desc->bInterfaceNumber;
80             enable_endpoints = (intf_desc->bAlternateSetting == alt_setting);
81         } else if (header->bDescriptorType == USB_DT_ENDPOINT && cur_interface == interface_id) {
82             usb_endpoint_descriptor_t* ep = (usb_endpoint_descriptor_t*)header;
83             int ep_index = get_usb_endpoint_index(ep);
84             interface_endpoints[ep_index] = true;
85             if (enable_endpoints) {
86                 new_endpoints[ep_index] = ep;
87             }
88         }
89         header = NEXT_DESCRIPTOR(header);
90     }
91 
92     // update to new set of endpoints
93     // FIXME - how do we recover if we fail half way through processing the endpoints?
94     for (size_t i = 0; i < countof(new_endpoints); i++) {
95         if (interface_endpoints[i]) {
96             usb_endpoint_descriptor_t* old_ep = intf->active_endpoints[i];
97             usb_endpoint_descriptor_t* new_ep = new_endpoints[i];
98             if (old_ep != new_ep) {
99                 if (old_ep) {
100                     zx_status_t ret = usb_enable_endpoint(&intf->comp->usb, old_ep, NULL, false);
101                     if (ret != ZX_OK) status = ret;
102                 }
103                 if (new_ep) {
104                     usb_ss_ep_comp_descriptor_t* ss_comp_desc = NULL;
105                     usb_descriptor_header_t* next =
106                                     (usb_descriptor_header_t *)((void *)new_ep + new_ep->bLength);
107                     if (next + sizeof(*ss_comp_desc) <= end
108                         && next->bDescriptorType == USB_DT_SS_EP_COMPANION) {
109                         ss_comp_desc = (usb_ss_ep_comp_descriptor_t *)next;
110                     }
111                     zx_status_t ret = usb_enable_endpoint(&intf->comp->usb, new_ep, ss_comp_desc,
112                                                           true);
113                     if (ret != ZX_OK) {
114                         status = ret;
115                     }
116                 }
117                 intf->active_endpoints[i] = new_ep;
118             }
119         }
120     }
121     return status;
122 }
123 
usb_interface_control_out(void * ctx,uint8_t request_type,uint8_t request,uint16_t value,uint16_t index,zx_time_t timeout,const void * write_buffer,size_t write_size)124 static zx_status_t usb_interface_control_out(void* ctx, uint8_t request_type, uint8_t request,
125                                              uint16_t value, uint16_t index, zx_time_t timeout,
126                                              const void* write_buffer, size_t write_size) {
127     usb_interface_t* intf = ctx;
128     return usb_control_out(&intf->comp->usb, request_type, request, value, index, timeout,
129                            write_buffer, write_size);
130 }
131 
usb_interface_control_in(void * ctx,uint8_t request_type,uint8_t request,uint16_t value,uint16_t index,zx_time_t timeout,void * out_read_buffer,size_t read_size,size_t * out_read_actual)132 static zx_status_t usb_interface_control_in(void* ctx, uint8_t request_type, uint8_t request,
133                                             uint16_t value, uint16_t index, zx_time_t timeout,
134                                             void* out_read_buffer, size_t read_size,
135                                             size_t* out_read_actual) {
136     usb_interface_t* intf = ctx;
137     return usb_control_in(&intf->comp->usb, request_type, request, value, index, timeout,
138                           out_read_buffer, read_size, out_read_actual);
139 }
140 
usb_interface_request_queue(void * ctx,usb_request_t * usb_request,const usb_request_complete_t * complete_cb)141 static void usb_interface_request_queue(void* ctx, usb_request_t* usb_request,
142                                         const usb_request_complete_t* complete_cb) {
143     usb_interface_t* intf = ctx;
144     usb_request_queue(&intf->comp->usb, usb_request, complete_cb);
145 }
146 
usb_interface_configure_batch_callback(void * ctx,uint8_t ep_address,const usb_batch_request_complete_t * complete_cb)147 static zx_status_t usb_interface_configure_batch_callback(void* ctx, uint8_t ep_address,
148                                                           const usb_batch_request_complete_t*
149                                                                                 complete_cb) {
150     usb_interface_t* intf = ctx;
151     return usb_configure_batch_callback(&intf->comp->usb, ep_address, complete_cb);
152 }
153 
usb_interface_get_speed(void * ctx)154 static usb_speed_t usb_interface_get_speed(void* ctx) {
155     usb_interface_t* intf = ctx;
156     return usb_get_speed(&intf->comp->usb);
157 }
158 
usb_interface_set_interface(void * ctx,uint8_t interface_number,uint8_t alt_setting)159 static zx_status_t usb_interface_set_interface(void* ctx, uint8_t interface_number,
160                                                uint8_t alt_setting) {
161     usb_interface_t* intf = ctx;
162     return usb_composite_set_interface(intf->comp, interface_number, alt_setting);
163 }
164 
usb_interface_get_configuration(void * ctx)165 static uint8_t usb_interface_get_configuration(void* ctx) {
166     usb_interface_t* intf = ctx;
167     return usb_get_configuration(&intf->comp->usb);
168 }
169 
usb_interface_set_configuration(void * ctx,uint8_t configuration)170 static zx_status_t usb_interface_set_configuration(void* ctx, uint8_t configuration) {
171     usb_interface_t* intf = ctx;
172     return usb_set_configuration(&intf->comp->usb, configuration);
173 }
174 
usb_interface_enable_endpoint(void * ctx,const usb_endpoint_descriptor_t * ep_desc,const usb_ss_ep_comp_descriptor_t * ss_comp_desc,bool enable)175 static zx_status_t usb_interface_enable_endpoint(void* ctx,
176                                                  const usb_endpoint_descriptor_t* ep_desc,
177                                                  const usb_ss_ep_comp_descriptor_t* ss_comp_desc,
178                                                  bool enable) {
179     return ZX_ERR_NOT_SUPPORTED;
180 }
181 
usb_interface_reset_endpoint(void * ctx,uint8_t ep_address)182 static zx_status_t usb_interface_reset_endpoint(void* ctx, uint8_t ep_address) {
183     usb_interface_t* intf = ctx;
184     return usb_reset_endpoint(&intf->comp->usb, ep_address);
185 }
186 
usb_interface_reset_device(void * ctx)187 static zx_status_t usb_interface_reset_device(void* ctx) {
188     usb_interface_t* intf = ctx;
189     return usb_reset_device(&intf->comp->usb);
190 }
191 
usb_interface_get_max_transfer_size(void * ctx,uint8_t ep_address)192 static size_t usb_interface_get_max_transfer_size(void* ctx, uint8_t ep_address) {
193     usb_interface_t* intf = ctx;
194     return usb_get_max_transfer_size(&intf->comp->usb, ep_address);
195 }
196 
usb_interface_get_device_id(void * ctx)197 static uint32_t usb_interface_get_device_id(void* ctx) {
198     usb_interface_t* intf = ctx;
199     return usb_get_device_id(&intf->comp->usb);
200 }
201 
usb_interface_get_device_descriptor(void * ctx,usb_device_descriptor_t * out_desc)202 static void usb_interface_get_device_descriptor(void* ctx, usb_device_descriptor_t* out_desc) {
203     usb_interface_t* intf = ctx;
204     return usb_get_device_descriptor(&intf->comp->usb, out_desc);
205 }
206 
usb_interface_get_configuration_descriptor_length(void * ctx,uint8_t configuration,size_t * out_length)207 zx_status_t usb_interface_get_configuration_descriptor_length(void* ctx, uint8_t configuration,
208                                                               size_t* out_length) {
209     usb_interface_t* intf = ctx;
210     return usb_get_configuration_descriptor_length(&intf->comp->usb, configuration, out_length);
211 }
212 
usb_interface_get_configuration_descriptor(void * ctx,uint8_t configuration,void * out_desc_buffer,size_t desc_size,size_t * out_desc_actual)213 static zx_status_t usb_interface_get_configuration_descriptor(void* ctx, uint8_t configuration,
214                                                               void* out_desc_buffer,
215                                                               size_t desc_size,
216                                                               size_t* out_desc_actual) {
217     usb_interface_t* intf = ctx;
218     return usb_get_configuration_descriptor(&intf->comp->usb, configuration, out_desc_buffer,
219                                             desc_size, out_desc_actual);
220 }
221 
usb_interface_get_descriptors_length(void * ctx)222 static size_t usb_interface_get_descriptors_length(void* ctx) {
223     usb_interface_t* intf = ctx;
224     return intf->descriptor_length;
225 }
226 
usb_interface_get_descriptors(void * ctx,void * out_descs_buffer,size_t descs_size,size_t * out_descs_actual)227 static void usb_interface_get_descriptors(void* ctx, void* out_descs_buffer, size_t descs_size,
228                                           size_t* out_descs_actual) {
229     usb_interface_t* intf = ctx;
230     size_t length = intf->descriptor_length;
231     if (length > descs_size) {
232         length = descs_size;
233     }
234     memcpy(out_descs_buffer, intf->descriptor, length);
235     *out_descs_actual = length;
236 }
237 
usb_interface_get_additional_descriptor_length(void * ctx)238 static size_t usb_interface_get_additional_descriptor_length(void* ctx) {
239     usb_interface_t* intf = ctx;
240 
241     usb_composite_t* comp = intf->comp;
242     usb_configuration_descriptor_t* config = comp->config_desc;
243     usb_descriptor_header_t* header = NEXT_DESCRIPTOR(config);
244     usb_descriptor_header_t* end = (usb_descriptor_header_t*)((void*)config +
245                                                               le16toh(config->wTotalLength));
246 
247     usb_interface_descriptor_t* result = NULL;
248     while (header < end) {
249         if (header->bDescriptorType == USB_DT_INTERFACE) {
250             usb_interface_descriptor_t* test_intf = (usb_interface_descriptor_t*)header;
251             // We are only interested in descriptors past the last stored descriptor
252             // for the current interface.
253             if (test_intf->bAlternateSetting == 0 &&
254                 test_intf->bInterfaceNumber > intf->last_interface_id) {
255                 result = test_intf;
256                 break;
257             }
258         }
259         header = NEXT_DESCRIPTOR(header);
260     }
261     if (!result) {
262         return 0;
263     }
264     return (uint8_t*)end - (uint8_t*)result;
265 }
266 
usb_interface_get_additional_descriptor_list(void * ctx,uint8_t * out_desc_list,size_t desc_count,size_t * out_desc_actual)267 static zx_status_t usb_interface_get_additional_descriptor_list(void* ctx, uint8_t* out_desc_list,
268                                                                 size_t desc_count,
269                                                                 size_t* out_desc_actual) {
270     usb_interface_t* intf = ctx;
271     *out_desc_actual = 0;
272 
273     usb_composite_t* comp = intf->comp;
274     usb_configuration_descriptor_t* config = comp->config_desc;
275     usb_descriptor_header_t* header = NEXT_DESCRIPTOR(config);
276     usb_descriptor_header_t* end = (usb_descriptor_header_t*)((void*)config +
277                                                               le16toh(config->wTotalLength));
278 
279     usb_interface_descriptor_t* result = NULL;
280     while (header < end) {
281         if (header->bDescriptorType == USB_DT_INTERFACE) {
282             usb_interface_descriptor_t* test_intf = (usb_interface_descriptor_t*)header;
283             // We are only interested in descriptors past the last stored descriptor
284             // for the current interface.
285             if (test_intf->bAlternateSetting == 0 &&
286                 test_intf->bInterfaceNumber > intf->last_interface_id) {
287                 result = test_intf;
288                 break;
289             }
290         }
291         header = NEXT_DESCRIPTOR(header);
292     }
293     if (!result) {
294         return ZX_OK;
295     }
296     size_t length = (void*)end - (void*)result;
297     if (length > desc_count) {
298         return ZX_ERR_BUFFER_TOO_SMALL;
299     }
300     memcpy(out_desc_list, result, length);
301     *out_desc_actual = length;
302     return ZX_OK;
303 }
304 
usb_interface_get_string_descriptor(void * ctx,uint8_t desc_id,uint16_t lang_id,uint16_t * out_lang_id,void * out_string_buffer,size_t string_size,size_t * out_string_actual)305 zx_status_t usb_interface_get_string_descriptor(void* ctx, uint8_t desc_id, uint16_t lang_id,
306                                                 uint16_t* out_lang_id, void* out_string_buffer,
307                                                 size_t string_size, size_t* out_string_actual) {
308     usb_interface_t* intf = ctx;
309     return usb_get_string_descriptor(&intf->comp->usb, desc_id, lang_id, out_lang_id,
310                                      out_string_buffer, string_size, out_string_actual);
311 }
312 
usb_interface_claim_device_interface(void * ctx,const usb_interface_descriptor_t * desc,uint32_t claim_length)313 static zx_status_t usb_interface_claim_device_interface(void* ctx,
314                                                         const usb_interface_descriptor_t* desc,
315                                                         uint32_t claim_length) {
316     usb_interface_t* intf = ctx;
317 
318     zx_status_t status = usb_composite_do_claim_interface(intf->comp, desc->bInterfaceNumber);
319     if (status != ZX_OK) {
320         return status;
321     }
322     // Copy claimed interface descriptors to end of descriptor array.
323     void* descriptors = realloc(intf->descriptor,
324                                 intf->descriptor_length + claim_length);
325     if (!descriptors) {
326         return ZX_ERR_NO_MEMORY;
327     }
328     memcpy(descriptors + intf->descriptor_length, desc, claim_length);
329     intf->descriptor = descriptors;
330     intf->descriptor_length += claim_length;
331 
332     if (desc->bInterfaceNumber > intf->last_interface_id) {
333         intf->last_interface_id = desc->bInterfaceNumber;
334     }
335     return ZX_OK;
336 }
337 
usb_interface_cancel_all(void * ctx,uint8_t ep_address)338 static zx_status_t usb_interface_cancel_all(void* ctx, uint8_t ep_address) {
339     usb_interface_t* intf = ctx;
340     return usb_cancel_all(&intf->comp->usb, ep_address);
341 }
342 
usb_interface_get_current_frame(void * ctx)343 static uint64_t usb_interface_get_current_frame(void* ctx) {
344     usb_interface_t* intf = ctx;
345     return usb_get_current_frame(&intf->comp->usb);
346 }
347 
usb_interface_get_request_size(void * ctx)348 static size_t usb_interface_get_request_size(void* ctx) {
349     usb_interface_t* intf = ctx;
350     return usb_get_request_size(&intf->comp->usb);
351 }
352 
353 usb_protocol_ops_t usb_device_protocol = {
354     .control_out = usb_interface_control_out,
355     .control_in = usb_interface_control_in,
356     .request_queue = usb_interface_request_queue,
357     .configure_batch_callback = usb_interface_configure_batch_callback,
358     .get_speed = usb_interface_get_speed,
359     .set_interface = usb_interface_set_interface,
360     .get_configuration = usb_interface_get_configuration,
361     .set_configuration = usb_interface_set_configuration,
362     .enable_endpoint = usb_interface_enable_endpoint,
363     .reset_endpoint = usb_interface_reset_endpoint,
364     .reset_device = usb_interface_reset_device,
365     .get_max_transfer_size = usb_interface_get_max_transfer_size,
366     .get_device_id = usb_interface_get_device_id,
367     .get_device_descriptor = usb_interface_get_device_descriptor,
368     .get_configuration_descriptor_length = usb_interface_get_configuration_descriptor_length,
369     .get_configuration_descriptor = usb_interface_get_configuration_descriptor,
370     .get_descriptors_length = usb_interface_get_descriptors_length,
371     .get_descriptors = usb_interface_get_descriptors,
372     .get_string_descriptor = usb_interface_get_string_descriptor,
373     .cancel_all = usb_interface_cancel_all,
374     .get_current_frame = usb_interface_get_current_frame,
375     .get_request_size = usb_interface_get_request_size,
376 };
377 
378 usb_composite_protocol_ops_t usb_composite_device_protocol = {
379     .get_additional_descriptor_length = usb_interface_get_additional_descriptor_length,
380     .get_additional_descriptor_list = usb_interface_get_additional_descriptor_list,
381     .claim_interface = usb_interface_claim_device_interface,
382 };
383 
usb_interface_contains_interface(usb_interface_t * intf,uint8_t interface_id)384 bool usb_interface_contains_interface(usb_interface_t* intf, uint8_t interface_id) {
385     usb_descriptor_header_t* header = intf->descriptor;
386     usb_descriptor_header_t* end = (usb_descriptor_header_t*)((void*)header +
387                                                               intf->descriptor_length);
388 
389     while (header < end) {
390         if (header->bDescriptorType == USB_DT_INTERFACE) {
391             usb_interface_descriptor_t* intf_desc = (usb_interface_descriptor_t*)header;
392             if (intf_desc->bInterfaceNumber == interface_id) {
393                 return true;
394             }
395         }
396         header = NEXT_DESCRIPTOR(header);
397     }
398     return false;
399 }
400 
usb_interface_set_alt_setting(usb_interface_t * intf,uint8_t interface_id,uint8_t alt_setting)401 zx_status_t usb_interface_set_alt_setting(usb_interface_t* intf, uint8_t interface_id,
402                                           uint8_t alt_setting) {
403     zx_status_t status = usb_interface_configure_endpoints(intf, interface_id, alt_setting);
404     if (status != ZX_OK) {
405         return status;
406     }
407 
408     return usb_control_out(&intf->comp->usb, USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE,
409                            USB_REQ_SET_INTERFACE, alt_setting, interface_id, ZX_TIME_INFINITE,
410                            NULL, 0);
411 }
412