diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2015-01-02 12:39:18 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2015-01-08 16:45:22 +0100 |
commit | 1ab91550e6b7b4cd01350fea531447c1fa7d7250 (patch) | |
tree | 3bf70eea0ba519106547291fb12756255e3c184c | |
parent | ae37d1944fdc66f303749ee8c0613105e4d32b3d (diff) | |
download | rockbox-1ab91550e6b7b4cd01350fea531447c1fa7d7250.tar.gz rockbox-1ab91550e6b7b4cd01350fea531447c1fa7d7250.zip |
usb: document usb states, powering and detection
Change-Id: Ia3b7d6c6294bfb9272355c3f28a994dd0e83cbce
Reviewed-on: http://gerrit.rockbox.org/1096
Reviewed-by: Amaury Pouly <amaury.pouly@gmail.com>
-rw-r--r-- | firmware/export/usb.h | 128 |
1 files changed, 112 insertions, 16 deletions
diff --git a/firmware/export/usb.h b/firmware/export/usb.h index f13ade2acd..62bcffe666 100644 --- a/firmware/export/usb.h +++ b/firmware/export/usb.h | |||
@@ -25,6 +25,80 @@ | |||
25 | #include "kernel.h" | 25 | #include "kernel.h" |
26 | #include "button.h" | 26 | #include "button.h" |
27 | 27 | ||
28 | /** USB introduction | ||
29 | * Targets which do not have any hardware support for USB, and cannot even detect | ||
30 | * it must define USB_NONE. Otherwise, they must at least implement USB | ||
31 | * detection. | ||
32 | * | ||
33 | * USB architecture | ||
34 | * The USB code is split into several parts: | ||
35 | * - usb: manages the USB connection | ||
36 | * - usb_core: implements a software USB stack based on usb_drv | ||
37 | * - usb_drv: implements the USB protocol based on some hardware transceiver/core | ||
38 | * - usb_{hid,storage,...}: implement USB functionalities based on usb_core | ||
39 | * Note that not all those are compiled in, in particular in the case of a | ||
40 | * hardware USB stack, or when the driver doesn't support all types of transfers. | ||
41 | * | ||
42 | * Software versus hardware USB stack | ||
43 | * A very important thing to keep in mind is that there are two very different | ||
44 | * situations: | ||
45 | * - software USB stack: the device only provides a USB transceiver and the | ||
46 | * USB stack must be implemented entirely in software. In this case the target | ||
47 | * must define HAVE_USBSTACK, correctly set CONFIG_USBOTG and implement a driver | ||
48 | * for the transceiver. | ||
49 | * - hardware USB stack: the device has a dedicated chip which implements the | ||
50 | * USB stack in hardware. In this case the target must *NOT* define HAVE_USBSTACK | ||
51 | * but can still define CONFIG_USBOTG and implement a driver to enable/disable | ||
52 | * the USB hardware. | ||
53 | * | ||
54 | * USB ignore buttons | ||
55 | * In some cases, the user wants to prevent Rockbox from entering USB mode. It | ||
56 | * can do so by holding a button while inserting the cable. By default any button | ||
57 | * will prevent the USB mode from kicking-in, so targets can optionally define | ||
58 | * USBPOWER_BTN_IGNORE to a mask of buttons to ignore in this check. | ||
59 | * | ||
60 | * USB states | ||
61 | * It is important to understand that the usb code can be in one of three states: | ||
62 | * - extracted: no USB cable is plugged | ||
63 | * - powered-only: a USB cable is plugged but the USB mode will not be entered, | ||
64 | * either because no host was detected or because the user requested so. | ||
65 | * - inserted: a USB cable is plugged and the USB mode has been entered, either | ||
66 | * the software or hardware stack is running. | ||
67 | * | ||
68 | * USB exclusive mode | ||
69 | * Either in hardware or software stack, if the USB was configured to run in | ||
70 | * mass storage mode, it will require exclusive access to the disk and ask all | ||
71 | * threads to release any file handle and stop using the disks. It does so by | ||
72 | * broadcasting a SYS_USB_CONNECTED message, which threads must acknowledge using | ||
73 | * usb_acknowledge(SYS_USB_CONNECTED_ACK). They must not access the disk until | ||
74 | * SYS_USB_DISCONNECTED is broadcast. To ease waiting, threads can call | ||
75 | * usb_wait_for_disconnect() or usb_wait_for_disconnect_w_tmo() on their waiting | ||
76 | * queue. | ||
77 | * | ||
78 | * USB detection | ||
79 | * Except when no usb code is compiled at all (USB_NONE), the usb thread keeps | ||
80 | * track of the USB insertion state, which can be either USB_INSERTED (meaning | ||
81 | * 5v is present) or USB_EXTRACTED. Each target must implement usb_detect() | ||
82 | * to report the insertion state. | ||
83 | * Targets which support insertion/extraction interrupts must define | ||
84 | * USB_STATUS_BY_EVENT and notify the thread on changes by calling | ||
85 | * usb_status_event() with the new state. Other targets must *not* define | ||
86 | * USB_STATUS_BY_EVENT and the usb thread by regularly poll the insertion state | ||
87 | * using usb_detect(). | ||
88 | * | ||
89 | * USB powering & charging | ||
90 | * Device which can be powered from USB must define HAVE_USB_POWER. Note that | ||
91 | * powering doesn't imply charging (for example a AA-powered device can be | ||
92 | * powered from USB but not charged), charging sources are reported by the | ||
93 | * power subsystem (see power.h). The USB specification mandates the maximum | ||
94 | * current which can be drawn under which cirmcunstances. Device which cannot | ||
95 | * control the charge current should make sure it is always <100mA to meet the | ||
96 | * USB specification. Device with configurable charging current which support | ||
97 | * >=100mA must define HAVE_USB_CHARGING_ENABLE and implement | ||
98 | * usb_charging_maxcurrent_change() to let the usb thread control the maximum | ||
99 | * charging control. | ||
100 | * */ | ||
101 | |||
28 | #if defined(IPOD_COLOR) || defined(IPOD_4G) \ | 102 | #if defined(IPOD_COLOR) || defined(IPOD_4G) \ |
29 | || defined(IPOD_MINI) || defined(IPOD_MINI2G) | 103 | || defined(IPOD_MINI) || defined(IPOD_MINI2G) |
30 | #define USB_FIREWIRE_HANDLING | 104 | #define USB_FIREWIRE_HANDLING |
@@ -38,7 +112,7 @@ enum | |||
38 | #endif | 112 | #endif |
39 | USB_EXTRACTED = 0, /* Event+State */ | 113 | USB_EXTRACTED = 0, /* Event+State */ |
40 | USB_INSERTED, /* Event+State */ | 114 | USB_INSERTED, /* Event+State */ |
41 | USB_POWERED, /* State - transitional indicator if no power */ | 115 | USB_POWERED, /* State - transitional indicator if no host */ |
42 | #if (CONFIG_STORAGE & STORAGE_MMC) | 116 | #if (CONFIG_STORAGE & STORAGE_MMC) |
43 | USB_REENABLE, /* Event */ | 117 | USB_REENABLE, /* Event */ |
44 | #endif | 118 | #endif |
@@ -100,16 +174,26 @@ struct usb_transfer_completion_event_data | |||
100 | }; | 174 | }; |
101 | #endif /* HAVE_USBSTACK */ | 175 | #endif /* HAVE_USBSTACK */ |
102 | 176 | ||
177 | /* initialise the usb code and thread */ | ||
103 | void usb_init(void) INIT_ATTR; | 178 | void usb_init(void) INIT_ATTR; |
179 | /* target must implement this to enable/disable the usb transceiver/core */ | ||
104 | void usb_enable(bool on); | 180 | void usb_enable(bool on); |
105 | void usb_attach(void); | 181 | void usb_attach(void); |
182 | /* enable usb detection monitoring; before this function is called, all usb | ||
183 | * detection changes are ignored */ | ||
106 | void usb_start_monitoring(void) INIT_ATTR; | 184 | void usb_start_monitoring(void) INIT_ATTR; |
107 | void usb_close(void); | 185 | void usb_close(void); |
186 | /* acknowledge usb connection, typically with SYS_USB_CONNECTED_ACK */ | ||
108 | void usb_acknowledge(long id); | 187 | void usb_acknowledge(long id); |
188 | /* block the current thread until SYS_USB_DISCONNECTED has been broadcast */ | ||
109 | void usb_wait_for_disconnect(struct event_queue *q); | 189 | void usb_wait_for_disconnect(struct event_queue *q); |
190 | /* same as usb_wait_for_disconnect() but with a timeout, returns 1 on timeout */ | ||
110 | int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks); | 191 | int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks); |
111 | bool usb_inserted(void); /* return the official value, what's been reported to the threads */ | 192 | /* check whether USB is plugged, note that this is the official value which has |
112 | int usb_detect(void); /* return the raw hardware value - nothing/pc/charger */ | 193 | * been reported to the thread */ |
194 | bool usb_inserted(void); | ||
195 | /* check whether USB is plugged, note that this is the raw hardware value */ | ||
196 | int usb_detect(void); | ||
113 | #ifdef USB_STATUS_BY_EVENT | 197 | #ifdef USB_STATUS_BY_EVENT |
114 | /* Notify USB insertion state (USB_INSERTED or USB_EXTRACTED) */ | 198 | /* Notify USB insertion state (USB_INSERTED or USB_EXTRACTED) */ |
115 | void usb_status_event(int current_status); | 199 | void usb_status_event(int current_status); |
@@ -118,33 +202,37 @@ void usb_status_event(int current_status); | |||
118 | bool usb_powered(void); | 202 | bool usb_powered(void); |
119 | #ifdef HAVE_USB_CHARGING_ENABLE | 203 | #ifdef HAVE_USB_CHARGING_ENABLE |
120 | enum { | 204 | enum { |
121 | USB_CHARGING_DISABLE, | 205 | USB_CHARGING_DISABLE, /* the USB code will never ask for more than 100mA */ |
122 | USB_CHARGING_ENABLE, | 206 | USB_CHARGING_ENABLE, /* the code will ask for the maximum possible value */ |
123 | USB_CHARGING_FORCE | 207 | USB_CHARGING_FORCE /* the code will always ask for 500mA */ |
124 | }; | 208 | }; |
125 | /* called by app, implemented by usb_core on targets with rockbox usb | 209 | /* select the USB charging mode, typically used by apps/ to reflect user setting, |
126 | * or target-specific code on others | 210 | * implemented by usb_core on targets with a software stack, and by target code |
127 | */ | 211 | * on targets with a hardware stack */ |
128 | void usb_charging_enable(int state); | 212 | void usb_charging_enable(int state); |
129 | #ifdef HAVE_USBSTACK | 213 | #ifdef HAVE_USBSTACK |
214 | /* update the USB charging value based on the current USB state */ | ||
130 | void usb_charger_update(void); | 215 | void usb_charger_update(void); |
131 | #endif /* HAVE_USBSTACK */ | 216 | #endif /* HAVE_USBSTACK */ |
132 | /* hardware which knows how to control usb current should use one | 217 | /* limit the maximum USB current the charger can draw */ |
133 | * of the following to find out from the usb stack how much is ok | ||
134 | */ | ||
135 | /* implemented by target, called by usb when value changes */ | ||
136 | void usb_charging_maxcurrent_change(int maxcurrent); | 218 | void usb_charging_maxcurrent_change(int maxcurrent); |
137 | /* implemented by usb, called by target to get value */ | 219 | /* returns the maximum allowed USB current, based on USB charging mode and state */ |
138 | int usb_charging_maxcurrent(void); | 220 | int usb_charging_maxcurrent(void); |
139 | #endif /* HAVE_USB_CHARGING_ENABLE */ | 221 | #endif /* HAVE_USB_CHARGING_ENABLE */ |
140 | #endif /* HAVE_USB_POWER */ | 222 | #endif /* HAVE_USB_POWER */ |
141 | #ifdef HAVE_USBSTACK | 223 | #ifdef HAVE_USBSTACK |
224 | /* USB driver call this function to notify that a transfer has completed */ | ||
142 | void usb_signal_transfer_completion( | 225 | void usb_signal_transfer_completion( |
143 | struct usb_transfer_completion_event_data *event_data); | 226 | struct usb_transfer_completion_event_data *event_data); |
227 | /* notify the USB code that some important event has occurred which influences the | ||
228 | * USB state (like USB_NOTIFY_SET_ADDR). USB drivers should call usb_core_notify_* | ||
229 | * functions and not this function. */ | ||
144 | void usb_signal_notify(long id, intptr_t data); | 230 | void usb_signal_notify(long id, intptr_t data); |
231 | /* returns whether a USB_DRIVER_* is enabled (like HID, mass storage, ...) */ | ||
145 | bool usb_driver_enabled(int driver); | 232 | bool usb_driver_enabled(int driver); |
146 | bool usb_exclusive_storage(void); /* storage is available for usb */ | 233 | /* returns whether exclusive storage is available for USB */ |
147 | #endif | 234 | bool usb_exclusive_storage(void); |
235 | #endif /* HAVE_USBSTACK */ | ||
148 | int usb_release_exclusive_storage(void); | 236 | int usb_release_exclusive_storage(void); |
149 | 237 | ||
150 | #ifdef USB_FIREWIRE_HANDLING | 238 | #ifdef USB_FIREWIRE_HANDLING |
@@ -153,14 +241,22 @@ void usb_firewire_connect_event(void); | |||
153 | #endif | 241 | #endif |
154 | 242 | ||
155 | #ifdef USB_ENABLE_HID | 243 | #ifdef USB_ENABLE_HID |
244 | /* enable or disable the HID driver */ | ||
156 | void usb_set_hid(bool enable); | 245 | void usb_set_hid(bool enable); |
157 | #endif | 246 | #endif |
158 | 247 | ||
159 | #if defined(USB_ENABLE_STORAGE) && defined(HAVE_MULTIDRIVE) | 248 | #if defined(USB_ENABLE_STORAGE) && defined(HAVE_MULTIDRIVE) |
249 | /* when the target has several drives, decide whether mass storage should | ||
250 | * skip the first drive. This is useful when the second drive is a SD card | ||
251 | * and the host only supports access to the first USB drive (this is very common | ||
252 | * in car tuners and USB speakers) */ | ||
160 | void usb_set_skip_first_drive(bool skip); | 253 | void usb_set_skip_first_drive(bool skip); |
161 | #endif | 254 | #endif |
162 | 255 | ||
163 | #if !defined(SIMULATOR) && !defined(USB_NONE) | 256 | #if !defined(SIMULATOR) && !defined(USB_NONE) |
257 | /* initialise the USB hardware, this is a one-time init and it should setup what | ||
258 | * is necessary to do proper USB detection, and it should call usb_drv_startup() | ||
259 | * to do the one-time initialisation of the USB driver */ | ||
164 | void usb_init_device(void); | 260 | void usb_init_device(void); |
165 | #endif | 261 | #endif |
166 | 262 | ||