[Prism54-devel] implementation of sub-ioctls

David Pufer root@seznam.cz
Sun, 30 Nov 2003 10:41:04 +0000 (Local time zone must be set--see zic manual page)


Hello all,
I have just started tweaking the driver. I would like to submit the 
following patch that adds sub-ioctls support to private ioctls. As a 
sample code I implemented more private ioctls (Preamble settings, 
operation mode profile setting, slot setting). I also moved 
getBeaconPeriod and setBeaconPeriod to the sub-ioctl handler. In addition 
I added these parameters to MIB. I tested the patch against 20031129 CVS 
tarball on my SMC 2802W and it seems to work withou problems.

David Pufer

Here it is:


diff -Naur ksrc/isl_ioctl.c /home/prism54-cvs20031129_modified/ksrc/isl_ioctl.c
--- ksrc/isl_ioctl.c	2003-11-29 04:51:48.000000000 +0000
+++ /home/prism54-cvs20031129_modified/ksrc/isl_ioctl.c	2003-11-30 09:08:12.000000000 +0000
@@ -163,6 +163,10 @@
 static int init_dot1x = CARD_DEFAULT_DOT1X;
 static int init_conformance = CARD_DEFAULT_CONFORMANCE;
 static int init_mlme = CARD_DEFAULT_MLME_MODE;
+static int init_beaconperiod = CARD_DEFAULT_BEACONPERIOD;
+static int init_opmodeprofile = CARD_DEFAULT_OPMODEPROFILE;
+static int init_preamble = CARD_DEFAULT_PREAMBLE;
+static int init_slotsetting = CARD_DEFAULT_SLOTSETTING;
 
 
 MODULE_PARM(init_mode, "i");
@@ -273,6 +277,10 @@
 	mib->dot1xenable = init_dot1x;
 	mib->mlmeautolevel = init_mlme;
 	mib->conformance = init_conformance;
+	mib->beaconperiod = init_beaconperiod;
+	mib->opmodeprofile = init_opmodeprofile;
+	mib->preamble = init_preamble;
+	mib->slotsetting = init_slotsetting;
 
 	for (idx = 0; idx < 4; ++idx) {
 		mib->defkey[idx].type = DOT11_PRIV_WEP;
@@ -361,6 +369,22 @@
 	MGT_SET_REQUEST_U32(priv, OID_INL_DOT11D_CONFORMANCE,
 			    priv->mib.conformance);
 
+	/* set the beacon period */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_BEACONPERIOD,
+			    priv->mib.beaconperiod);
+			    
+	/* set the operation mode profile */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_PROFILES,
+			    priv->mib.opmodeprofile);
+			    
+	/* set the preamble */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_PREAMBLESETTINGS,
+			    priv->mib.preamble);
+			    
+	/* set the slot setting */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_SLOTSETTINGS,
+			    priv->mib.slotsetting);
+			    
 	/* set the mlme mode object */
 	MGT_SET_REQUEST_U32(priv, DOT11_OID_MLMEAUTOLEVEL,
 			    priv->mib.mlmeautolevel);
@@ -368,6 +392,7 @@
 	/* set the mode again for actually starting the device */
 	MGT_SET_REQUEST_U32(priv, OID_INL_MODE, priv->mib.mode);
 
+
 	printk(KERN_DEBUG "%s: done with prism54_mib_init()!\n",
 	       priv->ndev->name);
 
@@ -680,6 +705,24 @@
 	/* the 2nd set-mode request! */
 	MGT_SET_REQUEST_U32(priv, OID_INL_MODE, cardmode);
 
+
+	/* restore beacon period */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_BEACONPERIOD,
+			    priv->mib.beaconperiod);
+			    
+	/* restore operation mode profile */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_PROFILES,
+			    priv->mib.opmodeprofile);
+			    
+	/* restore preamble */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_PREAMBLESETTINGS,
+			    priv->mib.preamble);
+			    
+	/* restore slot setting */
+	MGT_SET_REQUEST_U32(priv, DOT11_OID_SLOTSETTINGS,
+			    priv->mib.slotsetting);
+
+
 	/* update MIB copy now that requests succeeded 
 	 * Note : there a small window  for race here : 
 	 * if the acl code replies to some message while priv->mib.mode=master
@@ -689,6 +732,7 @@
 	priv->mib.config = cardconfig;
 	priv->mib.mlmeautolevel = mlmeautolevel;
 
+
 	/* We need to reset the ssid for non-master modes, and also
 	 *  the 802.11d conformance. Don't do it if we are in master or
 	 *  monitor mode.
@@ -699,6 +743,7 @@
 
 	MGT_SET_REQUEST(priv, DOT11_OID_SSID, &priv->mib.ssid,
 			sizeof (struct obj_ssid));
+
 	MGT_SET_REQUEST_U32(priv, OID_INL_DOT11D_CONFORMANCE,
 			    priv->mib.conformance);
 
@@ -1610,24 +1655,6 @@
 	return 0;
 }
 
-int
-prism54_set_beacon(struct net_device *ndev, struct iw_request_info *info,
-		   __u32 *uwrq, char *extra)
-{
-	MGT_SET_REQUEST_U32(ndev->priv, DOT11_OID_BEACONPERIOD, *uwrq);
-
-	return 0;
-}
-
-int
-prism54_get_beacon(struct net_device *ndev, struct iw_request_info *info,
-		   __u32 *uwrq, char *extra)
-{
-	MGT_GET_REQUEST_U32(ndev->priv, DOT11_OID_BEACONPERIOD, uwrq);
-
-	return 0;
-}
-
 void
 prism54_acl_init(struct islpci_acl *acl)
 {
@@ -1875,6 +1902,123 @@
    return 0;
 }
 
+/* handlers for private sub-ioctls */
+int
+prism54_set_param(struct net_device *ndev, struct iw_request_info *info,
+		   void *wrq, char *extra)
+{
+	islpci_private *priv = ndev->priv;
+	u32 *i = (u32 *) extra;
+	u32 param = *i;
+	u32 value = *(i+1);
+	int ret = -EOPNOTSUPP;
+
+/*	printk(KERN_DEBUG "%s: param is %d, value is %d\n", ndev->name, param, value);
+*/	
+	switch(param) {
+	case PRISM54_PARAM_OPMODEPROFILE:
+		printk(KERN_DEBUG "%s: setting up operation mode profile to %d\n", ndev->name, value);
+		if(value >= 0 && value < 8) {
+		MGT_SET_REQUEST_U32(ndev->priv, DOT11_OID_PROFILES, value);
+		/* update mib */
+		priv->mib.opmodeprofile = value;
+		ret = 0;
+		}
+		else {
+		printk(KERN_DEBUG "%s: requested mode profile %d is out of range\n", ndev->name, value);
+		ret = -ERANGE;
+		}
+	break;
+	case PRISM54_PARAM_PREAMBLE:
+		printk(KERN_DEBUG "%s: setting up preamble setting to %d\n", ndev->name, value);
+		if(value >= 0 && value < 3) {
+		MGT_SET_REQUEST_U32(ndev->priv, DOT11_OID_PREAMBLESETTINGS, value);
+		/* update mib */
+		priv->mib.preamble = value;
+		ret = 0;
+		}
+		else {
+		printk(KERN_DEBUG "%s: requested preamble %d is out of range\n", ndev->name, value);
+		ret = -ERANGE;
+		}
+	break;
+	case PRISM54_PARAM_BEACONPERIOD:
+		printk(KERN_DEBUG "%s: setting up beacon period to %d\n", ndev->name, value);
+		if(value > 0 && value < 65536) { /*tested on SMC 2802W */ 
+		MGT_SET_REQUEST_U32(ndev->priv, DOT11_OID_BEACONPERIOD, value);
+		/* update mib */
+		priv->mib.beaconperiod = value;
+		ret = 0;
+		}
+		else {
+		printk(KERN_DEBUG "%s: requested beacon period %d is out of range\n", ndev->name, value);
+		ret = -ERANGE;
+		}
+	break;
+	case PRISM54_PARAM_SLOTSETTING:
+		printk(KERN_DEBUG "%s: setting up slot setting to %d\n", ndev->name, value);
+		if(value >= 0 && value < 3) {
+		MGT_SET_REQUEST_U32(ndev->priv, DOT11_OID_SLOTSETTINGS, value);
+		/* update mib */
+		priv->mib.slotsetting = value;
+		ret = 0;
+		}
+		else {
+		printk(KERN_DEBUG "%s: requested slot setting %d is out of range\n", ndev->name, value);
+		ret = -ERANGE;
+		}
+	break;
+	default:
+		printk(KERN_DEBUG "%s: prism54_set_param: unknown request %d\n", ndev->name, param);
+	}
+	/* commit settings.
+	necessary e.g. for beacon period setting to take effect. */
+	if(ret == 0)
+	    prism54_commit(ndev, info, (char *) wrq, extra);
+		
+	return ret;
+}
+
+
+int
+prism54_get_param(struct net_device *ndev, struct iw_request_info *info,
+		   void *wrq, char *extra)
+{
+	u32 *param = (u32 *) extra;
+	int ret = 0;
+
+/*	printk(KERN_DEBUG "%s: *param is %d\n", ndev->name, *param);
+*/	
+	switch(*param) {
+	case PRISM54_PARAM_OPMODEPROFILE:
+		printk(KERN_DEBUG "%s: reading operation mode profile\n", ndev->name);
+		MGT_GET_REQUEST_U32(ndev->priv, DOT11_OID_PROFILES, param);
+		ret = 0;
+	break;
+	case PRISM54_PARAM_PREAMBLE:
+		printk(KERN_DEBUG "%s: reading preamble setting\n", ndev->name);
+		MGT_GET_REQUEST_U32(ndev->priv, DOT11_OID_PREAMBLESETTINGS, param);
+		ret = 0;
+	break;
+	case PRISM54_PARAM_BEACONPERIOD:
+		printk(KERN_DEBUG "%s: reading beacon period setting\n", ndev->name);
+		MGT_GET_REQUEST_U32(ndev->priv, DOT11_OID_BEACONPERIOD, param);
+		ret = 0;
+	break;
+	case PRISM54_PARAM_SLOTSETTING:
+		printk(KERN_DEBUG "%s: reading slot setting\n", ndev->name);
+		MGT_GET_REQUEST_U32(ndev->priv, DOT11_OID_SLOTSETTINGS, param);
+		ret = 0;
+	break;
+	default:
+		printk(KERN_DEBUG "%s: prism54_get_param: unknown request %d\n", ndev->name, *param);
+		ret = -EOPNOTSUPP;
+	}
+	return ret;
+}
+
+
+
 /* Translate a TRAP oid into a wireless event. Called in islpci_mgt_receive. */
 
 #define STR_ADD(dest,src,length)do { \
diff -Naur ksrc/isl_ioctl.h /home/prism54-cvs20031129_modified/ksrc/isl_ioctl.h
--- ksrc/isl_ioctl.h	2003-11-28 22:18:48.000000000 +0000
+++ /home/prism54-cvs20031129_modified/ksrc/isl_ioctl.h	2003-11-30 09:08:12.000000000 +0000
@@ -93,10 +93,6 @@
 
 int prism54_reset(struct net_device *, struct iw_request_info *,
 		  __u32 *, char *);
-int prism54_set_beacon(struct net_device *, struct iw_request_info *,
-		       __u32 *, char *);
-int prism54_get_beacon(struct net_device *, struct iw_request_info *,
-		       __u32 *, char *);
 
 int prism54_ioctl(struct net_device *, struct ifreq *, int);
 
@@ -127,6 +123,12 @@
 int prism54_kick_mac(struct net_device *, struct iw_request_info *,
 		  struct sockaddr *, char *);
 
+int prism54_get_param(struct net_device *, struct iw_request_info *,
+		  void *, char *);
+
+int prism54_set_param(struct net_device *, struct iw_request_info *,
+		  void *, char *);
+
 void prism54_send_trap(islpci_private *, u32, char *);
 
 int prism54_process_trap(islpci_private *);
@@ -197,46 +199,92 @@
 
 /* The low order bit identify a SET (0) or a GET (1) ioctl.  */
 
-#define PRISM54_RESET		SIOCIWFIRSTPRIV
-#define PRISM54_GET_BEACON	SIOCIWFIRSTPRIV+1
-#define PRISM54_SET_BEACON	SIOCIWFIRSTPRIV+2
-#define PRISM54_GET_POLICY SIOCIWFIRSTPRIV+3
-#define PRISM54_SET_POLICY SIOCIWFIRSTPRIV+4
-#define PRISM54_GET_MAC 	   SIOCIWFIRSTPRIV+5
-#define PRISM54_ADD_MAC 	   SIOCIWFIRSTPRIV+6
+/* sub-ioctl handlers */
+#define PRISM54_SET_PARAM	SIOCIWFIRSTPRIV+0
+#define PRISM54_GET_PARAM	SIOCIWFIRSTPRIV+1
+
+/* other handlers */
+#define PRISM54_RESET		SIOCIWFIRSTPRIV+2
+
+#define PRISM54_GET_POLICY	SIOCIWFIRSTPRIV+3
+#define PRISM54_SET_POLICY	SIOCIWFIRSTPRIV+4
+#define PRISM54_GET_MAC		SIOCIWFIRSTPRIV+5
+#define PRISM54_ADD_MAC		SIOCIWFIRSTPRIV+6
+
+#define PRISM54_DEL_MAC		SIOCIWFIRSTPRIV+8
 
-#define PRISM54_DEL_MAC    SIOCIWFIRSTPRIV+8
+#define PRISM54_KICK_MAC	SIOCIWFIRSTPRIV+10
 
-#define PRISM54_KICK_MAC   SIOCIWFIRSTPRIV+10
+#define PRISM54_KICK_ALL	SIOCIWFIRSTPRIV+12
 
-#define PRISM54_KICK_ALL   SIOCIWFIRSTPRIV+12
+
+/* sub-ioctl functions identifiers */
+/* isn't it better to move simple ioctls to sub-ioctl handler
+ to make fields for other e.g. more complicated handlers? */
+#define PRISM54_PARAM_OPMODEPROFILE 1
+#define PRISM54_PARAM_PREAMBLE 2
+#define PRISM54_PARAM_BEACONPERIOD 3
+#define PRISM54_PARAM_SLOTSETTING 4
 
 
 static const struct iw_priv_args prism54_private_args[] = {
 /*{ cmd, set_args, get_args, name } */
-	{PRISM54_RESET, 0, 0, "reset"},
-	{PRISM54_GET_BEACON, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	 "getBeaconPeriod"},
-	{PRISM54_SET_BEACON, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
-	 "setBeaconPeriod"},
+/* WARNING name must be up to 15 characters long */
+	{PRISM54_RESET, 0, 0,
+	 "reset"},
 	{PRISM54_GET_POLICY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 	 "getPolicy"},
 	{PRISM54_SET_POLICY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
 	 "setPolicy"},
-	{ PRISM54_GET_MAC, 0, IW_PRIV_TYPE_ADDR | 64, "getMac" },
+	{ PRISM54_GET_MAC, 0, IW_PRIV_TYPE_ADDR | 64,
+	 "getMac" },
 	{ PRISM54_ADD_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,
 	 "addMac" },
 	{ PRISM54_DEL_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,
 	 "delMac" },
 	{ PRISM54_KICK_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0,
 	 "kickMac" },
-	{ PRISM54_KICK_ALL, 0, 0, "kickAll" }
+	{ PRISM54_KICK_ALL, 0, 0,
+	 "kickAll" },
+	 /* sub-ioctl parameter wrappers */
+	{PRISM54_GET_PARAM,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "handleGetParam"},
+	{PRISM54_SET_PARAM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0,
+	 "handleSetParam"},
+	 /* sub-ioctl handlers */
+	{PRISM54_GET_PARAM, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 ""},
+	{PRISM54_SET_PARAM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 ""},
+	 /* --- sub-ioctl functions --- */
+	 /* operation mode profile defined by DOT11_OID_PROFILE_XXX */
+	{PRISM54_PARAM_OPMODEPROFILE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getOpModeProf"},
+	{PRISM54_PARAM_OPMODEPROFILE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "setOpModeProf"},
+	 /* preamble settings defined by DOT11_PREAMBLESETTING_XXX */
+	{PRISM54_PARAM_PREAMBLE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getPreamble"},
+	{PRISM54_PARAM_PREAMBLE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "setPreamble"},
+	 /* beacon period defined by DOT11_OID_BEACONPERIOD */
+	{PRISM54_PARAM_BEACONPERIOD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getBeaconPeriod"},
+	{PRISM54_PARAM_BEACONPERIOD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "setBeaconPeriod"},
+	 /* slot settings defined by DOT11_SLOTSETTING_XXX */
+	{PRISM54_PARAM_SLOTSETTING, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getSlotSetting"},
+	{PRISM54_PARAM_SLOTSETTING, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,
+	 "setSlotSetting"},
 };
 
 static const iw_handler prism54_private_handler[] = {
+	(iw_handler) prism54_set_param,
+	(iw_handler) prism54_get_param,
 	(iw_handler) prism54_reset,
-	(iw_handler) prism54_get_beacon,
-	(iw_handler) prism54_set_beacon,
 	(iw_handler) prism54_get_policy,
 	(iw_handler) prism54_set_policy,
 	(iw_handler) prism54_get_mac,
@@ -252,8 +300,7 @@
 static const struct iw_handler_def prism54_handler_def = {
 	.num_standard = sizeof (prism54_handler) / sizeof (iw_handler),
 	.num_private = sizeof (prism54_private_handler) / sizeof (iw_handler),
-	.num_private_args =
-	    sizeof (prism54_private_args) / sizeof (struct iw_priv_args),
+	.num_private_args = sizeof (prism54_private_args) / sizeof (struct iw_priv_args),
 	.standard = (iw_handler *) prism54_handler,
 	.private = (iw_handler *) prism54_private_handler,
 	.private_args = (struct iw_priv_args *) prism54_private_args,
diff -Naur ksrc/islpci_dev.h /home/prism54-cvs20031129_modified/ksrc/islpci_dev.h
--- ksrc/islpci_dev.h	2003-11-24 16:48:22.000000000 +0000
+++ /home/prism54-cvs20031129_modified/ksrc/islpci_dev.h	2003-11-30 09:08:12.000000000 +0000
@@ -72,6 +72,11 @@
 	u32 exunencrypted;
 	u32 conformance;
 	u32 dot1xenable;
+	u32 beaconperiod;
+	u32 opmodeprofile;
+	u32 preamble;
+	u32 slotsetting;
+	
 };
 
 /* some states might not be superflous and may be removed when
diff -Naur ksrc/islpci_mgt.h /home/prism54-cvs20031129_modified/ksrc/islpci_mgt.h
--- ksrc/islpci_mgt.h	2003-11-24 16:48:22.000000000 +0000
+++ /home/prism54-cvs20031129_modified/ksrc/islpci_mgt.h	2003-11-30 09:08:12.000000000 +0000
@@ -48,6 +48,11 @@
 #define	CARD_DEFAULT_DOT1X			0
 #define CARD_DEFAULT_MLME_MODE			DOT11_MLME_AUTO
 #define CARD_DEFAULT_CONFORMANCE                OID_INL_CONFORMANCE_NONE
+#define CARD_DEFAULT_BEACONPERIOD               100
+#define CARD_DEFAULT_PREAMBLE                   2 /* dynamic */
+#define CARD_DEFAULT_OPMODEPROFILE              1 /* mixed */
+#define CARD_DEFAULT_SLOTSETTING                2 /* dynamic */
+
 
 /* PIMFOR package definitions */
 #define PIMFOR_ETHERTYPE                        0x8828