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