Re: [PATCH] cxacru: Export detailed device info through sysfs.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 23/02/07 22:29, Simon Arlott wrote:
> When the device is polled for status there is a lot of useful status
> information available that is ignored. This patch stores the device
> info array when the status is polled and adds sysfs files to the usb
> device to allow userspace to query it. Since the device updates its
> status internally once a second the poll time is changed to this, and
> round_jiffies_relative is used to avoid waking the cpu unnecessarily.

I also have a patch that can call the ADSL start/stop function on the
device via sysfs, but it's inherently unstable because requests to start
when running or stop when stopped will blocking until the state is changed.

redrum 3-2:1.0 # echo no >adsl_running
Feb 23 22:35:28 redrum [ 8574.166565] ATM dev 0: ADSL line: down

redrum 3-2:1.0 # echo yes >adsl_running
Feb 23 22:35:34 redrum [ 8580.169400] ATM dev 0: ADSL line: initializing
---

diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index c8b69bf..33d6a7e 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -171,6 +171,9 @@ struct cxacru_data {
 	struct completion snd_done;
 };
 
+static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
+			u8 *wdata, int wsize, u8 *rdata, int rsize);
+
 /* Card info exported through sysfs */
 #define CXACRU__ATTR_INIT(_name) \
 static DEVICE_ATTR(_name, S_IRUGO, cxacru_sysfs_show_##_name, NULL)
@@ -186,10 +189,16 @@ static ssize_t cxacru_sysfs_show_##_name
 } \
 CXACRU__ATTR_INIT(_name)
 
+#define CXACRU_CMD_INIT(_name) \
+static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \
+	cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name)
+
 #define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name)
+#define CXACRU_CMD_CREATE(_name)          CXACRU_DEVICE_CREATE_FILE(_name)
 #define CXACRU__ATTR_CREATE(_name)        CXACRU_DEVICE_CREATE_FILE(_name)
 
 #define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name)
+#define CXACRU_CMD_REMOVE(_name)          CXACRU_DEVICE_REMOVE_FILE(_name)
 #define CXACRU__ATTR_REMOVE(_name)        CXACRU_DEVICE_REMOVE_FILE(_name)
 
 static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf)
@@ -213,6 +222,7 @@ static ssize_t cxacru_sysfs_showattr_dB(
 	}
 }
 
+/*
 static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
 {
 	switch (value) {
@@ -221,6 +231,7 @@ static ssize_t cxacru_sysfs_showattr_boo
 	default: return 0;
 	}
 }
+*/
 
 static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
 {
@@ -278,6 +289,66 @@ static ssize_t cxacru_sysfs_show_mac_add
 			atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]);
 }
 
+
+static ssize_t cxacru_sysfs_show_adsl_running(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
+	struct cxacru_data *instance = usbatm_instance->driver_data;
+
+	switch (instance->card_info[CXINF_LINE_STARTABLE]) {
+	case 0: return snprintf(buf, PAGE_SIZE, "yes\n");
+	case 1: return snprintf(buf, PAGE_SIZE, "no\n");
+	default: return 0;
+	}
+}
+
+static ssize_t cxacru_sysfs_store_adsl_running(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct usbatm_data *usbatm_instance = usb_get_intfdata(intf);
+	struct cxacru_data *instance = usbatm_instance->driver_data;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EACCES;
+
+	switch (instance->card_info[CXINF_LINE_STARTABLE]) {
+	case 0: /* ADSL running */
+		if (count != 3
+				|| strncmp(buf, "no", strlen("no"))
+				|| strncmp(buf, "no\n", strlen("no\n")))
+			return 0;
+			
+		ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_STOP, NULL, 0, NULL, 0);
+		if (ret < 0) {
+			atm_err(usbatm_instance, "cxacru_sysfs_store_atm_running:"
+					" CHIP_ADSL_LINE_STOP returned %d\n", ret);
+			return ret;
+		}
+		// TODO: poll twice more then stop
+		return strlen(buf);
+	case 1: /* ADSL not running */
+		if (count != 4
+				|| strncmp(buf, "yes", strlen("yes"))
+				|| strncmp(buf, "yes\n", strlen("yes\n")))
+			return 0;
+
+		ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
+		if (ret < 0) {
+			atm_err(usbatm_instance, "cxacru_sysfs_store_atm_running:"
+					" CHIP_ADSL_LINE_START returned %d\n", ret);
+			return ret;
+		}
+		// TODO: resume polling
+		return strlen(buf);
+	default:
+		return -EINVAL;
+	}
+}
+
 /*
  * All device attributes are included in CXACRU_ALL_FILES
  * so that the same list can be used multiple times:
@@ -308,11 +379,11 @@ CXACRU_ATTR_##_action(CXINF_UPSTREAM_FEC
 CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_FEC_ERRORS,     u32,  downstream_fec_errors); \
 CXACRU_ATTR_##_action(CXINF_UPSTREAM_HEC_ERRORS,       u32,  upstream_hec_errors); \
 CXACRU_ATTR_##_action(CXINF_DOWNSTREAM_HEC_ERRORS,     u32,  downstream_hec_errors); \
-CXACRU_ATTR_##_action(CXINF_LINE_STARTABLE,            bool, line_startable); \
 CXACRU_ATTR_##_action(CXINF_MODULATION,                MODU, modulation); \
 CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND,              u32,  adsl_headend); \
 CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT,  u32,  adsl_headend_environment); \
-CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION,        u32,  adsl_controller_version);
+CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION,        u32,  adsl_controller_version); \
+CXACRU_CMD_##_action(                                        adsl_running);
 
 CXACRU_ALL_FILES(INIT);
 

-- 
Simon Arlott

Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux