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

Reply via email to