1 // Copyright 2016 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 #pragma once
6 
7 #include <ddk/binding.h>
8 #include <ddk/device.h>
9 #include <ddk/protocol/usb/hci.h>
10 #include <ddk/protocol/usb/hub.h>
11 #include <usb/usb-request.h>
12 #include <lib/sync/completion.h>
13 #include <zircon/hw/usb.h>
14 
15 #include <threads.h>
16 #include <stdatomic.h>
17 
18 typedef struct usb_bus usb_bus_t;
19 
20 // Represents a USB top-level device
21 typedef struct usb_device {
22     zx_device_t* zxdev;
23     zx_device_t* hci_zxdev;
24     usb_hci_protocol_t hci;
25     usb_bus_t* bus;
26 
27     // ID assigned by host controller
28     uint32_t device_id;
29     // device_id of the hub we are attached to (or zero for root hub)
30     uint32_t hub_id;
31     usb_speed_t speed;
32 
33     // Interface to talk to the hub driver
34     usb_hub_interface_t hub_intf;
35 
36     usb_device_descriptor_t device_desc;
37     usb_configuration_descriptor_t** config_descs;
38     uint8_t current_config_index;
39     uint8_t num_configurations;
40 
41     atomic_bool langids_fetched;
42     atomic_uintptr_t lang_ids;
43 
44     bool resetting;
45     // mutex that protects the resetting state member
46     mtx_t state_lock;
47 
48     // thread for calling client's usb request complete callback
49     thrd_t callback_thread;
50     bool callback_thread_stop;
51     // completion used for signalling callback_thread
52     sync_completion_t callback_thread_completion;
53     // list of requests that need to have client's completion callback called
54     list_node_t completed_reqs;
55     // mutex that protects the callback_* members above
56     mtx_t callback_lock;
57 
58     // pool of requests that can be reused
59     usb_request_pool_t free_reqs;
60     size_t parent_req_size;
61     size_t req_size;
62 } usb_device_t;
63 
64 void usb_device_set_hub_interface(usb_device_t* dev, const usb_hub_interface_t* hub_intf);
65 
66 zx_status_t usb_device_add(usb_bus_t* bus, uint32_t device_id, uint32_t hub_id,
67                            usb_speed_t speed, usb_device_t** out_device);
68 
69 zx_status_t usb_device_reinitialize(usb_device_t* dev);
70 
71 #define USB_REQ_TO_DEV_INTERNAL(req, size) \
72     ((usb_device_req_internal_t *)((uintptr_t)(req) + (size)))
73 #define DEV_INTERNAL_TO_USB_REQ(ctx, size) ((usb_request_t *)((uintptr_t)(ctx) - (size)))
74