| 1 | /* |
| 2 | * PS3 gelic network driver. |
| 3 | * |
| 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
| 5 | * Copyright 2007 Sony Corporation |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation version 2. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 19 | */ |
| 20 | #ifndef _GELIC_WIRELESS_H |
| 21 | #define _GELIC_WIRELESS_H |
| 22 | |
| 23 | #include <linux/wireless.h> |
| 24 | #include <net/iw_handler.h> |
| 25 | |
| 26 | |
| 27 | /* return value from GELIC_LV1_GET_WLAN_EVENT netcontrol */ |
| 28 | enum gelic_lv1_wl_event { |
| 29 | GELIC_LV1_WL_EVENT_DEVICE_READY = 0x01, /* Eurus ready */ |
| 30 | GELIC_LV1_WL_EVENT_SCAN_COMPLETED = 0x02, /* Scan has completed */ |
| 31 | GELIC_LV1_WL_EVENT_DEAUTH = 0x04, /* Deauthed by the AP */ |
| 32 | GELIC_LV1_WL_EVENT_BEACON_LOST = 0x08, /* Beacon lost detected */ |
| 33 | GELIC_LV1_WL_EVENT_CONNECTED = 0x10, /* Connected to AP */ |
| 34 | GELIC_LV1_WL_EVENT_WPA_CONNECTED = 0x20, /* WPA connection */ |
| 35 | GELIC_LV1_WL_EVENT_WPA_ERROR = 0x40, /* MIC error */ |
| 36 | }; |
| 37 | |
| 38 | /* arguments for GELIC_LV1_POST_WLAN_COMMAND netcontrol */ |
| 39 | enum gelic_eurus_command { |
| 40 | GELIC_EURUS_CMD_ASSOC = 1, /* association start */ |
| 41 | GELIC_EURUS_CMD_DISASSOC = 2, /* disassociate */ |
| 42 | GELIC_EURUS_CMD_START_SCAN = 3, /* scan start */ |
| 43 | GELIC_EURUS_CMD_GET_SCAN = 4, /* get scan result */ |
| 44 | GELIC_EURUS_CMD_SET_COMMON_CFG = 5, /* set common config */ |
| 45 | GELIC_EURUS_CMD_GET_COMMON_CFG = 6, /* set common config */ |
| 46 | GELIC_EURUS_CMD_SET_WEP_CFG = 7, /* set WEP config */ |
| 47 | GELIC_EURUS_CMD_GET_WEP_CFG = 8, /* get WEP config */ |
| 48 | GELIC_EURUS_CMD_SET_WPA_CFG = 9, /* set WPA config */ |
| 49 | GELIC_EURUS_CMD_GET_WPA_CFG = 10, /* get WPA config */ |
| 50 | GELIC_EURUS_CMD_GET_RSSI_CFG = 11, /* get RSSI info. */ |
| 51 | GELIC_EURUS_CMD_MAX_INDEX |
| 52 | }; |
| 53 | |
| 54 | /* for GELIC_EURUS_CMD_COMMON_CFG */ |
| 55 | enum gelic_eurus_bss_type { |
| 56 | GELIC_EURUS_BSS_INFRA = 0, |
| 57 | GELIC_EURUS_BSS_ADHOC = 1, /* not supported */ |
| 58 | }; |
| 59 | |
| 60 | enum gelic_eurus_auth_method { |
| 61 | GELIC_EURUS_AUTH_OPEN = 0, /* FIXME: WLAN_AUTH_OPEN */ |
| 62 | GELIC_EURUS_AUTH_SHARED = 1, /* not supported */ |
| 63 | }; |
| 64 | |
| 65 | enum gelic_eurus_opmode { |
| 66 | GELIC_EURUS_OPMODE_11BG = 0, /* 802.11b/g */ |
| 67 | GELIC_EURUS_OPMODE_11B = 1, /* 802.11b only */ |
| 68 | GELIC_EURUS_OPMODE_11G = 2, /* 802.11g only */ |
| 69 | }; |
| 70 | |
| 71 | struct gelic_eurus_common_cfg { |
| 72 | /* all fields are big endian */ |
| 73 | u16 scan_index; |
| 74 | u16 bss_type; /* infra or adhoc */ |
| 75 | u16 auth_method; /* shared key or open */ |
| 76 | u16 op_mode; /* B/G */ |
| 77 | } __attribute__((packed)); |
| 78 | |
| 79 | |
| 80 | /* for GELIC_EURUS_CMD_WEP_CFG */ |
| 81 | enum gelic_eurus_wep_security { |
| 82 | GELIC_EURUS_WEP_SEC_NONE = 0, |
| 83 | GELIC_EURUS_WEP_SEC_40BIT = 1, |
| 84 | GELIC_EURUS_WEP_SEC_104BIT = 2, |
| 85 | }; |
| 86 | |
| 87 | struct gelic_eurus_wep_cfg { |
| 88 | /* all fields are big endian */ |
| 89 | u16 security; |
| 90 | u8 key[4][16]; |
| 91 | } __attribute__((packed)); |
| 92 | |
| 93 | /* for GELIC_EURUS_CMD_WPA_CFG */ |
| 94 | enum gelic_eurus_wpa_security { |
| 95 | GELIC_EURUS_WPA_SEC_NONE = 0x0000, |
| 96 | /* group=TKIP, pairwise=TKIP */ |
| 97 | GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP = 0x0001, |
| 98 | /* group=AES, pairwise=AES */ |
| 99 | GELIC_EURUS_WPA_SEC_WPA_AES_AES = 0x0002, |
| 100 | /* group=TKIP, pairwise=TKIP */ |
| 101 | GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP = 0x0004, |
| 102 | /* group=AES, pairwise=AES */ |
| 103 | GELIC_EURUS_WPA_SEC_WPA2_AES_AES = 0x0008, |
| 104 | /* group=TKIP, pairwise=AES */ |
| 105 | GELIC_EURUS_WPA_SEC_WPA_TKIP_AES = 0x0010, |
| 106 | /* group=TKIP, pairwise=AES */ |
| 107 | GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES = 0x0020, |
| 108 | }; |
| 109 | |
| 110 | enum gelic_eurus_wpa_psk_type { |
| 111 | GELIC_EURUS_WPA_PSK_PASSPHRASE = 0, /* passphrase string */ |
| 112 | GELIC_EURUS_WPA_PSK_BIN = 1, /* 32 bytes binary key */ |
| 113 | }; |
| 114 | |
| 115 | #define GELIC_WL_EURUS_PSK_MAX_LEN 64 |
| 116 | #define WPA_PSK_LEN 32 /* WPA spec says 256bit */ |
| 117 | |
| 118 | struct gelic_eurus_wpa_cfg { |
| 119 | /* all fields are big endian */ |
| 120 | u16 security; |
| 121 | u16 psk_type; /* psk key encoding type */ |
| 122 | u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; /* psk key; hex or passphrase */ |
| 123 | } __attribute__((packed)); |
| 124 | |
| 125 | /* for GELIC_EURUS_CMD_{START,GET}_SCAN */ |
| 126 | enum gelic_eurus_scan_capability { |
| 127 | GELIC_EURUS_SCAN_CAP_ADHOC = 0x0000, |
| 128 | GELIC_EURUS_SCAN_CAP_INFRA = 0x0001, |
| 129 | GELIC_EURUS_SCAN_CAP_MASK = 0x0001, |
| 130 | }; |
| 131 | |
| 132 | enum gelic_eurus_scan_sec_type { |
| 133 | GELIC_EURUS_SCAN_SEC_NONE = 0x0000, |
| 134 | GELIC_EURUS_SCAN_SEC_WEP = 0x0100, |
| 135 | GELIC_EURUS_SCAN_SEC_WPA = 0x0200, |
| 136 | GELIC_EURUS_SCAN_SEC_WPA2 = 0x0400, |
| 137 | GELIC_EURUS_SCAN_SEC_MASK = 0x0f00, |
| 138 | }; |
| 139 | |
| 140 | enum gelic_eurus_scan_sec_wep_type { |
| 141 | GELIC_EURUS_SCAN_SEC_WEP_UNKNOWN = 0x0000, |
| 142 | GELIC_EURUS_SCAN_SEC_WEP_40 = 0x0001, |
| 143 | GELIC_EURUS_SCAN_SEC_WEP_104 = 0x0002, |
| 144 | GELIC_EURUS_SCAN_SEC_WEP_MASK = 0x0003, |
| 145 | }; |
| 146 | |
| 147 | enum gelic_eurus_scan_sec_wpa_type { |
| 148 | GELIC_EURUS_SCAN_SEC_WPA_UNKNOWN = 0x0000, |
| 149 | GELIC_EURUS_SCAN_SEC_WPA_TKIP = 0x0001, |
| 150 | GELIC_EURUS_SCAN_SEC_WPA_AES = 0x0002, |
| 151 | GELIC_EURUS_SCAN_SEC_WPA_MASK = 0x0003, |
| 152 | }; |
| 153 | |
| 154 | /* |
| 155 | * hw BSS information structure returned from GELIC_EURUS_CMD_GET_SCAN |
| 156 | */ |
| 157 | struct gelic_eurus_scan_info { |
| 158 | /* all fields are big endian */ |
| 159 | __be16 size; |
| 160 | __be16 rssi; /* percentage */ |
| 161 | __be16 channel; /* channel number */ |
| 162 | __be16 beacon_period; /* FIXME: in msec unit */ |
| 163 | __be16 capability; |
| 164 | __be16 security; |
| 165 | u8 bssid[8]; /* last ETH_ALEN are valid. bssid[0],[1] are unused */ |
| 166 | u8 essid[32]; /* IW_ESSID_MAX_SIZE */ |
| 167 | u8 rate[16]; /* first 12 are valid */ |
| 168 | u8 ext_rate[16]; /* first 16 are valid */ |
| 169 | __be32 reserved1; |
| 170 | __be32 reserved2; |
| 171 | __be32 reserved3; |
| 172 | __be32 reserved4; |
| 173 | u8 elements[0]; /* ie */ |
| 174 | } __attribute__ ((packed)); |
| 175 | |
| 176 | /* the hypervisor returns bbs up to 16 */ |
| 177 | #define GELIC_EURUS_MAX_SCAN (16) |
| 178 | struct gelic_wl_scan_info { |
| 179 | struct list_head list; |
| 180 | struct gelic_eurus_scan_info *hwinfo; |
| 181 | |
| 182 | int valid; /* set 1 if this entry was in latest scanned list |
| 183 | * from Eurus */ |
| 184 | unsigned int eurus_index; /* index in the Eurus list */ |
| 185 | unsigned long last_scanned; /* acquired time */ |
| 186 | |
| 187 | unsigned int rate_len; |
| 188 | unsigned int rate_ext_len; |
| 189 | unsigned int essid_len; |
| 190 | }; |
| 191 | |
| 192 | /* for GELIC_EURUS_CMD_GET_RSSI */ |
| 193 | struct gelic_eurus_rssi_info { |
| 194 | /* big endian */ |
| 195 | __be16 rssi; |
| 196 | } __attribute__ ((packed)); |
| 197 | |
| 198 | |
| 199 | /* for 'stat' member of gelic_wl_info */ |
| 200 | enum gelic_wl_info_status_bit { |
| 201 | GELIC_WL_STAT_CONFIGURED, |
| 202 | GELIC_WL_STAT_CH_INFO, /* ch info aquired */ |
| 203 | GELIC_WL_STAT_ESSID_SET, /* ESSID specified by userspace */ |
| 204 | GELIC_WL_STAT_BSSID_SET, /* BSSID specified by userspace */ |
| 205 | GELIC_WL_STAT_WPA_PSK_SET, /* PMK specified by userspace */ |
| 206 | GELIC_WL_STAT_WPA_LEVEL_SET, /* WEP or WPA[2] selected */ |
| 207 | }; |
| 208 | |
| 209 | /* for 'scan_stat' member of gelic_wl_info */ |
| 210 | enum gelic_wl_scan_state { |
| 211 | /* just initialized or get last scan result failed */ |
| 212 | GELIC_WL_SCAN_STAT_INIT, |
| 213 | /* scan request issued, accepted or chip is scanning */ |
| 214 | GELIC_WL_SCAN_STAT_SCANNING, |
| 215 | /* scan results retrieved */ |
| 216 | GELIC_WL_SCAN_STAT_GOT_LIST, |
| 217 | }; |
| 218 | |
| 219 | /* for 'cipher_method' */ |
| 220 | enum gelic_wl_cipher_method { |
| 221 | GELIC_WL_CIPHER_NONE, |
| 222 | GELIC_WL_CIPHER_WEP, |
| 223 | GELIC_WL_CIPHER_TKIP, |
| 224 | GELIC_WL_CIPHER_AES, |
| 225 | }; |
| 226 | |
| 227 | /* for 'wpa_level' */ |
| 228 | enum gelic_wl_wpa_level { |
| 229 | GELIC_WL_WPA_LEVEL_NONE, |
| 230 | GELIC_WL_WPA_LEVEL_WPA, |
| 231 | GELIC_WL_WPA_LEVEL_WPA2, |
| 232 | }; |
| 233 | |
| 234 | /* for 'assoc_stat' */ |
| 235 | enum gelic_wl_assoc_state { |
| 236 | GELIC_WL_ASSOC_STAT_DISCONN, |
| 237 | GELIC_WL_ASSOC_STAT_ASSOCIATING, |
| 238 | GELIC_WL_ASSOC_STAT_ASSOCIATED, |
| 239 | }; |
| 240 | /* part of private data alloc_etherdev() allocated */ |
| 241 | #define GELIC_WEP_KEYS 4 |
| 242 | struct gelic_wl_info { |
| 243 | /* bss list */ |
| 244 | struct mutex scan_lock; |
| 245 | struct list_head network_list; |
| 246 | struct list_head network_free_list; |
| 247 | struct gelic_wl_scan_info *networks; |
| 248 | |
| 249 | unsigned long scan_age; /* last scanned time */ |
| 250 | enum gelic_wl_scan_state scan_stat; |
| 251 | struct completion scan_done; |
| 252 | |
| 253 | /* eurus command queue */ |
| 254 | struct workqueue_struct *eurus_cmd_queue; |
| 255 | struct completion cmd_done_intr; |
| 256 | |
| 257 | /* eurus event handling */ |
| 258 | struct workqueue_struct *event_queue; |
| 259 | struct delayed_work event_work; |
| 260 | |
| 261 | /* wl status bits */ |
| 262 | unsigned long stat; |
| 263 | enum gelic_eurus_auth_method auth_method; /* open/shared */ |
| 264 | enum gelic_wl_cipher_method group_cipher_method; |
| 265 | enum gelic_wl_cipher_method pairwise_cipher_method; |
| 266 | enum gelic_wl_wpa_level wpa_level; /* wpa/wpa2 */ |
| 267 | |
| 268 | /* association handling */ |
| 269 | struct mutex assoc_stat_lock; |
| 270 | struct delayed_work assoc_work; |
| 271 | enum gelic_wl_assoc_state assoc_stat; |
| 272 | struct completion assoc_done; |
| 273 | |
| 274 | spinlock_t lock; |
| 275 | u16 ch_info; /* available channels. bit0 = ch1 */ |
| 276 | /* WEP keys */ |
| 277 | u8 key[GELIC_WEP_KEYS][IW_ENCODING_TOKEN_MAX]; |
| 278 | unsigned long key_enabled; |
| 279 | unsigned int key_len[GELIC_WEP_KEYS]; |
| 280 | unsigned int current_key; |
| 281 | /* WWPA PSK */ |
| 282 | u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; |
| 283 | enum gelic_eurus_wpa_psk_type psk_type; |
| 284 | unsigned int psk_len; |
| 285 | |
| 286 | u8 essid[IW_ESSID_MAX_SIZE]; |
| 287 | u8 bssid[ETH_ALEN]; /* userland requested */ |
| 288 | u8 active_bssid[ETH_ALEN]; /* associated bssid */ |
| 289 | unsigned int essid_len; |
| 290 | |
| 291 | struct iw_public_data wireless_data; |
| 292 | struct iw_statistics iwstat; |
| 293 | }; |
| 294 | |
| 295 | #define GELIC_WL_BSS_MAX_ENT 32 |
| 296 | #define GELIC_WL_ASSOC_RETRY 50 |
| 297 | static inline struct gelic_port *wl_port(struct gelic_wl_info *wl) |
| 298 | { |
| 299 | return container_of((void *)wl, struct gelic_port, priv); |
| 300 | } |
| 301 | static inline struct gelic_wl_info *port_wl(struct gelic_port *port) |
| 302 | { |
| 303 | return port_priv(port); |
| 304 | } |
| 305 | |
| 306 | struct gelic_eurus_cmd { |
| 307 | struct work_struct work; |
| 308 | struct gelic_wl_info *wl; |
| 309 | unsigned int cmd; /* command code */ |
| 310 | u64 tag; |
| 311 | u64 size; |
| 312 | void *buffer; |
| 313 | unsigned int buf_size; |
| 314 | struct completion done; |
| 315 | int status; |
| 316 | u64 cmd_status; |
| 317 | }; |
| 318 | |
| 319 | /* private ioctls to pass PSK */ |
| 320 | #define GELIC_WL_PRIV_SET_PSK (SIOCIWFIRSTPRIV + 0) |
| 321 | #define GELIC_WL_PRIV_GET_PSK (SIOCIWFIRSTPRIV + 1) |
| 322 | |
| 323 | extern int gelic_wl_driver_probe(struct gelic_card *card); |
| 324 | extern int gelic_wl_driver_remove(struct gelic_card *card); |
| 325 | extern void gelic_wl_interrupt(struct net_device *netdev, u64 status); |
| 326 | #endif /* _GELIC_WIRELESS_H */ |