1 /* 2 * External connector (extcon) class driver 3 * 4 * Copyright (C) 2015 Samsung Electronics 5 * Author: Chanwoo Choi <[email protected]> 6 * 7 * Copyright (C) 2012 Samsung Electronics 8 * Author: Donggeun Kim <[email protected]> 9 * Author: MyungJoo Ham <[email protected]> 10 * 11 * based on switch class driver 12 * Copyright (C) 2008 Google, Inc. 13 * Author: Mike Lockwood <[email protected]> 14 * 15 * This software is licensed under the terms of the GNU General Public 16 * License version 2, as published by the Free Software Foundation, and 17 * may be copied, distributed, and modified under those terms. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 */ 25 26 #ifndef __LINUX_EXTCON_H__ 27 #define __LINUX_EXTCON_H__ 28 29 #include <linux/device.h> 30 31 /* 32 * Define the unique id of supported external connectors 33 */ 34 #define EXTCON_NONE 0 35 36 #define EXTCON_USB 1 /* USB connector */ 37 #define EXTCON_USB_HOST 2 38 39 #define EXTCON_TA 3 /* Charger connector */ 40 #define EXTCON_FAST_CHARGER 4 41 #define EXTCON_SLOW_CHARGER 5 42 #define EXTCON_CHARGE_DOWNSTREAM 6 43 44 #define EXTCON_LINE_IN 7 /* Audio/Video connector */ 45 #define EXTCON_LINE_OUT 8 46 #define EXTCON_MICROPHONE 9 47 #define EXTCON_HEADPHONE 10 48 #define EXTCON_HDMI 11 49 #define EXTCON_MHL 12 50 #define EXTCON_DVI 13 51 #define EXTCON_VGA 14 52 #define EXTCON_SPDIF_IN 15 53 #define EXTCON_SPDIF_OUT 16 54 #define EXTCON_VIDEO_IN 17 55 #define EXTCON_VIDEO_OUT 18 56 57 #define EXTCON_DOCK 19 /* Misc connector */ 58 #define EXTCON_JIG 20 59 #define EXTCON_MECHANICAL 21 60 61 struct extcon_cable; 62 63 /** 64 * struct extcon_dev - An extcon device represents one external connector. 65 * @name: The name of this extcon device. Parent device name is 66 * used if NULL. 67 * @supported_cable: Array of supported cable names ending with EXTCON_NONE. 68 * If supported_cable is NULL, cable name related APIs 69 * are disabled. 70 * @mutually_exclusive: Array of mutually exclusive set of cables that cannot 71 * be attached simultaneously. The array should be 72 * ending with NULL or be NULL (no mutually exclusive 73 * cables). For example, if it is { 0x7, 0x30, 0}, then, 74 * {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot 75 * be attached simulataneously. {0x7, 0} is equivalent to 76 * {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there 77 * can be no simultaneous connections. 78 * @dev: Device of this extcon. 79 * @state: Attach/detach state of this extcon. Do not provide at 80 * register-time. 81 * @nh: Notifier for the state change events from this extcon 82 * @entry: To support list of extcon devices so that users can 83 * search for extcon devices based on the extcon name. 84 * @lock: 85 * @max_supported: Internal value to store the number of cables. 86 * @extcon_dev_type: Device_type struct to provide attribute_groups 87 * customized for each extcon device. 88 * @cables: Sysfs subdirectories. Each represents one cable. 89 * 90 * In most cases, users only need to provide "User initializing data" of 91 * this struct when registering an extcon. In some exceptional cases, 92 * optional callbacks may be needed. However, the values in "internal data" 93 * are overwritten by register function. 94 */ 95 struct extcon_dev { 96 /* Optional user initializing data */ 97 const char *name; 98 const unsigned int *supported_cable; 99 const u32 *mutually_exclusive; 100 101 /* Internal data. Please do not set. */ 102 struct device dev; 103 struct raw_notifier_head *nh; 104 struct list_head entry; 105 int max_supported; 106 spinlock_t lock; /* could be called by irq handler */ 107 u32 state; 108 109 /* /sys/class/extcon/.../cable.n/... */ 110 struct device_type extcon_dev_type; 111 struct extcon_cable *cables; 112 113 /* /sys/class/extcon/.../mutually_exclusive/... */ 114 struct attribute_group attr_g_muex; 115 struct attribute **attrs_muex; 116 struct device_attribute *d_attrs_muex; 117 }; 118 119 /** 120 * struct extcon_cable - An internal data for each cable of extcon device. 121 * @edev: The extcon device 122 * @cable_index: Index of this cable in the edev 123 * @attr_g: Attribute group for the cable 124 * @attr_name: "name" sysfs entry 125 * @attr_state: "state" sysfs entry 126 * @attrs: Array pointing to attr_name and attr_state for attr_g 127 */ 128 struct extcon_cable { 129 struct extcon_dev *edev; 130 int cable_index; 131 132 struct attribute_group attr_g; 133 struct device_attribute attr_name; 134 struct device_attribute attr_state; 135 136 struct attribute *attrs[3]; /* to be fed to attr_g.attrs */ 137 }; 138 139 /** 140 * struct extcon_specific_cable_nb - An internal data for 141 * extcon_register_interest(). 142 * @user_nb: user provided notifier block for events from 143 * a specific cable. 144 * @cable_index: the target cable. 145 * @edev: the target extcon device. 146 * @previous_value: the saved previous event value. 147 */ 148 struct extcon_specific_cable_nb { 149 struct notifier_block *user_nb; 150 int cable_index; 151 struct extcon_dev *edev; 152 unsigned long previous_value; 153 }; 154 155 #if IS_ENABLED(CONFIG_EXTCON) 156 157 /* 158 * Following APIs are for notifiers or configurations. 159 * Notifiers are the external port and connection devices. 160 */ 161 extern int extcon_dev_register(struct extcon_dev *edev); 162 extern void extcon_dev_unregister(struct extcon_dev *edev); 163 extern int devm_extcon_dev_register(struct device *dev, 164 struct extcon_dev *edev); 165 extern void devm_extcon_dev_unregister(struct device *dev, 166 struct extcon_dev *edev); 167 extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); 168 169 /* 170 * Following APIs control the memory of extcon device. 171 */ 172 extern struct extcon_dev *extcon_dev_allocate(const unsigned int *cable); 173 extern void extcon_dev_free(struct extcon_dev *edev); 174 extern struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, 175 const unsigned int *cable); 176 extern void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev); 177 178 /* 179 * get/set/update_state access the 32b encoded state value, which represents 180 * states of all possible cables of the multistate port. For example, if one 181 * calls extcon_set_state(edev, 0x7), it may mean that all the three cables 182 * are attached to the port. 183 */ 184 static inline u32 extcon_get_state(struct extcon_dev *edev) 185 { 186 return edev->state; 187 } 188 189 extern int extcon_set_state(struct extcon_dev *edev, u32 state); 190 extern int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state); 191 192 /* 193 * get/set_cable_state access each bit of the 32b encoded state value. 194 * They are used to access the status of each cable based on the cable_name. 195 */ 196 extern int extcon_get_cable_state_(struct extcon_dev *edev, unsigned int id); 197 extern int extcon_set_cable_state_(struct extcon_dev *edev, unsigned int id, 198 bool cable_state); 199 200 extern int extcon_get_cable_state(struct extcon_dev *edev, 201 const char *cable_name); 202 extern int extcon_set_cable_state(struct extcon_dev *edev, 203 const char *cable_name, bool cable_state); 204 205 /* 206 * Following APIs are for notifiees (those who want to be notified) 207 * to register a callback for events from a specific cable of the extcon. 208 * Notifiees are the connected device drivers wanting to get notified by 209 * a specific external port of a connection device. 210 */ 211 extern int extcon_register_interest(struct extcon_specific_cable_nb *obj, 212 const char *extcon_name, 213 const char *cable_name, 214 struct notifier_block *nb); 215 extern int extcon_unregister_interest(struct extcon_specific_cable_nb *nb); 216 217 /* 218 * Following APIs are to monitor every action of a notifier. 219 * Registrar gets notified for every external port of a connection device. 220 * Probably this could be used to debug an action of notifier; however, 221 * we do not recommend to use this for normal 'notifiee' device drivers who 222 * want to be notified by a specific external port of the notifier. 223 */ 224 extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id, 225 struct notifier_block *nb); 226 extern int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id, 227 struct notifier_block *nb); 228 229 /* 230 * Following API get the extcon device from devicetree. 231 * This function use phandle of devicetree to get extcon device directly. 232 */ 233 extern struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, 234 int index); 235 236 /* Following API to get information of extcon device */ 237 extern const char *extcon_get_edev_name(struct extcon_dev *edev); 238 239 #else /* CONFIG_EXTCON */ 240 static inline int extcon_dev_register(struct extcon_dev *edev) 241 { 242 return 0; 243 } 244 245 static inline void extcon_dev_unregister(struct extcon_dev *edev) { } 246 247 static inline int devm_extcon_dev_register(struct device *dev, 248 struct extcon_dev *edev) 249 { 250 return -EINVAL; 251 } 252 253 static inline void devm_extcon_dev_unregister(struct device *dev, 254 struct extcon_dev *edev) { } 255 256 static inline struct extcon_dev *extcon_dev_allocate(const unsigned int *cable) 257 { 258 return ERR_PTR(-ENOSYS); 259 } 260 261 static inline void extcon_dev_free(struct extcon_dev *edev) { } 262 263 static inline struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, 264 const unsigned int *cable) 265 { 266 return ERR_PTR(-ENOSYS); 267 } 268 269 static inline void devm_extcon_dev_free(struct extcon_dev *edev) { } 270 271 static inline u32 extcon_get_state(struct extcon_dev *edev) 272 { 273 return 0; 274 } 275 276 static inline int extcon_set_state(struct extcon_dev *edev, u32 state) 277 { 278 return 0; 279 } 280 281 static inline int extcon_update_state(struct extcon_dev *edev, u32 mask, 282 u32 state) 283 { 284 return 0; 285 } 286 287 static inline int extcon_get_cable_state_(struct extcon_dev *edev, 288 unsigned int id) 289 { 290 return 0; 291 } 292 293 static inline int extcon_set_cable_state_(struct extcon_dev *edev, 294 unsigned int id, bool cable_state) 295 { 296 return 0; 297 } 298 299 static inline int extcon_get_cable_state(struct extcon_dev *edev, 300 const char *cable_name) 301 { 302 return 0; 303 } 304 305 static inline int extcon_set_cable_state(struct extcon_dev *edev, 306 const char *cable_name, int state) 307 { 308 return 0; 309 } 310 311 static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) 312 { 313 return NULL; 314 } 315 316 static inline int extcon_register_notifier(struct extcon_dev *edev, 317 unsigned int id, 318 struct notifier_block *nb) 319 { 320 return 0; 321 } 322 323 static inline int extcon_unregister_notifier(struct extcon_dev *edev, 324 unsigned int id, 325 struct notifier_block *nb) 326 { 327 return 0; 328 } 329 330 static inline int extcon_register_interest(struct extcon_specific_cable_nb *obj, 331 const char *extcon_name, 332 const char *cable_name, 333 struct notifier_block *nb) 334 { 335 return 0; 336 } 337 338 static inline int extcon_unregister_interest(struct extcon_specific_cable_nb 339 *obj) 340 { 341 return 0; 342 } 343 344 static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, 345 int index) 346 { 347 return ERR_PTR(-ENODEV); 348 } 349 #endif /* CONFIG_EXTCON */ 350 #endif /* __LINUX_EXTCON_H__ */ 351