// SPDX-License-Identifier: GPL-2.0-or-later /* * dock.c - ACPI dock station driver * * Copyright (C) 2006, 2014, Intel Corp. * Author: Kristen Carlson Accardi <[email protected]> * Rafael J. Wysocki <[email protected]> */ #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/types.h> #include <linux/notifier.h> #include <linux/platform_device.h> #include <linux/jiffies.h> #include <linux/stddef.h> #include <linux/acpi.h> #include "internal.h" static bool immediate_undock = …; module_param(immediate_undock, bool, 0644); MODULE_PARM_DESC(…) …; struct dock_station { … }; static LIST_HEAD(dock_stations); static int dock_station_count; struct dock_dependent_device { … }; #define DOCK_DOCKING … #define DOCK_UNDOCKING … #define DOCK_IS_DOCK … #define DOCK_IS_ATA … #define DOCK_IS_BAT … #define DOCK_EVENT … #define UNDOCK_EVENT … enum dock_callback_type { … }; /***************************************************************************** * Dock Dependent device functions * *****************************************************************************/ /** * add_dock_dependent_device - associate a device with the dock station * @ds: Dock station. * @adev: Dependent ACPI device object. * * Add the dependent device to the dock's dependent device list. */ static int add_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev) { … } static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, enum dock_callback_type cb_type) { … } static struct dock_station *find_dock_station(acpi_handle handle) { … } /** * find_dock_dependent_device - get a device dependent on this dock * @ds: the dock station * @adev: ACPI device object to find. * * iterate over the dependent device list for this dock. If the * dependent device matches the handle, return. */ static struct dock_dependent_device * find_dock_dependent_device(struct dock_station *ds, struct acpi_device *adev) { … } void register_dock_dependent_device(struct acpi_device *adev, acpi_handle dshandle) { … } /***************************************************************************** * Dock functions * *****************************************************************************/ /** * is_dock_device - see if a device is on a dock station * @adev: ACPI device object to check. * * If this device is either the dock station itself, * or is a device dependent on the dock station, then it * is a dock device */ int is_dock_device(struct acpi_device *adev) { … } EXPORT_SYMBOL_GPL(…); /** * dock_present - see if the dock station is present. * @ds: the dock station * * execute the _STA method. note that present does not * imply that we are docked. */ static int dock_present(struct dock_station *ds) { … } /** * hot_remove_dock_devices - Remove dock station devices. * @ds: Dock station. */ static void hot_remove_dock_devices(struct dock_station *ds) { … } /** * hotplug_dock_devices - Insert devices on a dock station. * @ds: the dock station * @event: either bus check or device check request * * Some devices on the dock station need to have drivers called * to perform hotplug operations after a dock event has occurred. * Traverse the list of dock devices that have registered a * hotplug handler, and call the handler. */ static void hotplug_dock_devices(struct dock_station *ds, u32 event) { … } static void dock_event(struct dock_station *ds, u32 event, int num) { … } /** * handle_dock - handle a dock event * @ds: the dock station * @dock: to dock, or undock - that is the question * * Execute the _DCK method in response to an acpi event */ static void handle_dock(struct dock_station *ds, int dock) { … } static inline void dock(struct dock_station *ds) { … } static inline void undock(struct dock_station *ds) { … } static inline void begin_dock(struct dock_station *ds) { … } static inline void complete_dock(struct dock_station *ds) { … } static inline void begin_undock(struct dock_station *ds) { … } static inline void complete_undock(struct dock_station *ds) { … } /** * dock_in_progress - see if we are in the middle of handling a dock event * @ds: the dock station * * Sometimes while docking, false dock events can be sent to the driver * because good connections aren't made or some other reason. Ignore these * if we are in the middle of doing something. */ static int dock_in_progress(struct dock_station *ds) { … } /** * handle_eject_request - handle an undock request checking for error conditions * @ds: The dock station to undock. * @event: The ACPI event number associated with the undock request. * * Check to make sure the dock device is still present, then undock and * hotremove all the devices that may need removing. */ static int handle_eject_request(struct dock_station *ds, u32 event) { … } /** * dock_notify - Handle ACPI dock notification. * @adev: Dock station's ACPI device object. * @event: Event code. * * If we are notified to dock, then check to see if the dock is * present and then dock. Notify all drivers of the dock event, * and then hotplug and devices that may need hotplugging. */ int dock_notify(struct acpi_device *adev, u32 event) { … } /* * show_docked - read method for "docked" file in sysfs */ static ssize_t docked_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(docked); /* * show_flags - read method for flags file in sysfs */ static ssize_t flags_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(flags); /* * write_undock - write method for "undock" file in sysfs */ static ssize_t undock_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static DEVICE_ATTR_WO(undock); /* * show_dock_uid - read method for "uid" file in sysfs */ static ssize_t uid_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(uid); static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(type); static struct attribute *dock_attributes[] = …; static const struct attribute_group dock_attribute_group = …; /** * acpi_dock_add - Add a new dock station * @adev: Dock station ACPI device object. * * allocated and initialize a new dock station device. */ void acpi_dock_add(struct acpi_device *adev) { … }