* updated kollision (21.12.1 -> 21.12.2), untested
[t2-trunk.git] / architecture / powerpc64 / package / linux / 0150-ps3jupiter.patch
blobd6024d5417de2f2f62120d8792082bccc407a03e
1 # --- T2-COPYRIGHT-NOTE-BEGIN ---
2 # This copyright note is auto-generated by scripts/Create-CopyPatch.
3 #
4 # T2 SDE: architecture/powerpc64/package/.../0150-ps3jupiter.patch
5 # Copyright (C) 2020 The T2 SDE Project
6 #
7 # More information can be found in the files COPYING and README.
8 #
9 # This patch file is dual-licensed. It is available under the license the
10 # patched project is licensed under, as long as it is an OpenSource license
11 # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
12 # of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
14 # version.
15 # --- T2-COPYRIGHT-NOTE-END ---
17 --- linux-4.19/drivers/net/wireless/Kconfig.vanilla 2018-11-18 12:59:31.411583091 +0000
18 +++ linux-4.19/drivers/net/wireless/Kconfig 2018-11-18 13:00:06.115582569 +0000
19 @@ -42,6 +42,7 @@
20 source "drivers/net/wireless/ralink/Kconfig"
21 source "drivers/net/wireless/realtek/Kconfig"
22 source "drivers/net/wireless/rsi/Kconfig"
23 +source "drivers/net/wireless/ps3jupiter/Kconfig"
24 source "drivers/net/wireless/st/Kconfig"
25 source "drivers/net/wireless/ti/Kconfig"
26 source "drivers/net/wireless/zydas/Kconfig"
27 --- linux-4.19/drivers/net/wireless/Makefile.vanilla 2018-11-18 12:59:43.451582909 +0000
28 +++ linux-4.19/drivers/net/wireless/Makefile 2018-11-18 12:59:54.823582738 +0000
29 @@ -15,6 +15,7 @@
30 obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/
31 obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
32 obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
33 +obj-$(CONFIG_PS3_JUPITER) += ps3jupiter/
34 obj-$(CONFIG_WLAN_VENDOR_ST) += st/
35 obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
36 obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
37 --- /dev/null 2012-01-06 10:29:22.673734242 +0100
38 +++ b/drivers/net/wireless/ps3jupiter/Kconfig 2012-01-06 12:13:47.507142753 +0100
39 @@ -0,0 +1,16 @@
41 +config PS3_JUPITER
42 + tristate "PS3 Jupiter 802.11bg support"
43 + depends on PPC_PS3 && USB
44 + help
45 + A driver for the PS3 Jupiter
46 + 802.11bg wireless network adapter.
48 +config PS3_JUPITER_STA
49 + tristate "PS3 Jupiter 802.11bg station support"
50 + depends on PS3_JUPITER
51 + select WIRELESS_EXT
52 + select WEXT_PRIV
53 + help
54 + A station driver for the PS3 Jupiter
55 + 802.11bg wireless network adapter.
56 --- /dev/null 2012-01-06 10:29:22.673734242 +0100
57 +++ b/drivers/net/wireless/ps3jupiter/Makefile 2012-01-06 12:07:05.647715657 +0100
58 @@ -0,0 +1,3 @@
60 +obj-$(CONFIG_PS3_JUPITER) += ps3_jupiter.o
61 +obj-$(CONFIG_PS3_JUPITER_STA) += ps3_jupiter_sta.o
62 --- /dev/null 2012-11-01 00:09:58.397610712 -0800
63 +++ b/drivers/net/wireless/ps3jupiter/ps3_eurus.h 2012-11-01 03:22:11.000000000 -0800
64 @@ -0,0 +1,604 @@
65 +/*
66 + * PS3 Eurus
67 + *
68 + * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
69 + * All rights reserved.
70 + *
71 + * This program is free software; you can redistribute it and/or modify it
72 + * under the terms of the GNU General Public License as published
73 + * by the Free Software Foundation; version 2 of the License.
74 + *
75 + * This program is distributed in the hope that it will be useful, but
76 + * WITHOUT ANY WARRANTY; without even the implied warranty of
77 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
78 + * General Public License for more details.
79 + *
80 + * You should have received a copy of the GNU General Public License along
81 + * with this program; if not, write to the Free Software Foundation, Inc.,
82 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
83 + */
85 +#ifndef _PS3_EURUS_H
86 +#define _PS3_EURUS_H
88 +enum ps3_eurus_cmd_id {
89 + PS3_EURUS_CMD_0x1 = 0x0001,
90 + PS3_EURUS_CMD_GET_AP_SSID = 0x0003,
91 + PS3_EURUS_CMD_SET_AP_SSID = 0x0005,
92 + PS3_EURUS_CMD_GET_CHANNEL = 0x000f,
93 + PS3_EURUS_CMD_SET_CHANNEL = 0x0011,
94 + PS3_EURUS_CMD_SET_ANTENNA = 0x0029,
95 + PS3_EURUS_CMD_GET_AP_WEP_CONFIG = 0x0059,
96 + PS3_EURUS_CMD_SET_AP_WEP_CONFIG = 0x005b,
97 + PS3_EURUS_CMD_0x61 = 0x0061,
98 + PS3_EURUS_CMD_0x65 = 0x0065,
99 + PS3_EURUS_CMD_GET_FW_VERSION = 0x0099,
100 + PS3_EURUS_CMD_GET_AP_OPMODE = 0x00b7,
101 + PS3_EURUS_CMD_SET_AP_OPMODE = 0x00b9,
102 + PS3_EURUS_CMD_0xc5 = 0x00c5,
103 + PS3_EURUS_CMD_GET_AP_WPA_AKM_SUITE = 0x00c8,
104 + PS3_EURUS_CMD_SET_AP_WPA_AKM_SUITE = 0x00c9,
105 + PS3_EURUS_CMD_GET_AP_WPA_GROUP_CIPHER_SUITE = 0x00cd,
106 + PS3_EURUS_CMD_SET_AP_WPA_GROUP_CIPHER_SUITE = 0x00cf,
107 + PS3_EURUS_CMD_GET_AP_WPA_PSK_PASSPHRASE = 0x00d1,
108 + PS3_EURUS_CMD_SET_AP_WPA_PSK_PASSPHRASE = 0x00d3,
109 + PS3_EURUS_CMD_0xd5 = 0x00d5,
110 + PS3_EURUS_CMD_0x127 = 0x0127,
111 + PS3_EURUS_CMD_0x12b = 0x012b,
112 + PS3_EURUS_CMD_GET_AP_WPA_PSK_BIN = 0x017b,
113 + PS3_EURUS_CMD_SET_AP_WPA_PSK_BIN = 0x017d,
114 + PS3_EURUS_CMD_GET_AP_WPA_PAIRWISE_CIPHER_SUITE = 0x01bd,
115 + PS3_EURUS_CMD_SET_AP_WPA_PAIRWISE_CIPHER_SUITE = 0x01bf,
116 + PS3_EURUS_CMD_0x1d9 = 0x01d9,
117 + PS3_EURUS_CMD_START_AP = 0x01dd,
118 + PS3_EURUS_CMD_0x1ed = 0x01ed,
119 + PS3_EURUS_CMD_GET_HW_REVISION = 0x01fb,
120 + PS3_EURUS_CMD_0x203 = 0x0203,
121 + PS3_EURUS_CMD_0x207 = 0x0207,
122 + PS3_EURUS_CMD_ASSOCIATE = 0x1001,
123 + PS3_EURUS_CMD_GET_COMMON_CONFIG = 0x1003,
124 + PS3_EURUS_CMD_SET_COMMON_CONFIG = 0x1005,
125 + PS3_EURUS_CMD_GET_WEP_CONFIG = 0x1013,
126 + PS3_EURUS_CMD_SET_WEP_CONFIG = 0x1015,
127 + PS3_EURUS_CMD_GET_WPA_CONFIG = 0x1017,
128 + PS3_EURUS_CMD_SET_WPA_CONFIG = 0x1019,
129 + PS3_EURUS_CMD_0x1025 = 0x1025,
130 + PS3_EURUS_CMD_0x1031 = 0x1031,
131 + PS3_EURUS_CMD_GET_SCAN_RESULTS = 0x1033,
132 + PS3_EURUS_CMD_START_SCAN = 0x1035,
133 + PS3_EURUS_CMD_DISASSOCIATE = 0x1037,
134 + PS3_EURUS_CMD_GET_RSSI = 0x103d,
135 + PS3_EURUS_CMD_GET_MAC_ADDR = 0x103f,
136 + PS3_EURUS_CMD_SET_MAC_ADDR = 0x1041,
137 + PS3_EURUS_CMD_0x104d = 0x104d,
138 + PS3_EURUS_CMD_0x104f = 0x104f,
139 + PS3_EURUS_CMD_0x105f = 0x105f,
140 + PS3_EURUS_CMD_0x1109 = 0x1109,
141 + PS3_EURUS_CMD_0x110b = 0x110b,
142 + PS3_EURUS_CMD_0x110d = 0x110d,
143 + PS3_EURUS_CMD_0x1133 = 0x1133,
144 + PS3_EURUS_CMD_0x114b = 0x114b,
145 + PS3_EURUS_CMD_0x114f = 0x114f,
146 + PS3_EURUS_CMD_0x115b = 0x115b,
147 + PS3_EURUS_CMD_0x115d = 0x115d,
148 + PS3_EURUS_CMD_0x115f = 0x115f,
149 + PS3_EURUS_CMD_SET_MCAST_ADDR_FILTER = 0x1161,
150 + PS3_EURUS_CMD_CLEAR_MCAST_ADDR_FILTER = 0x1163,
151 + PS3_EURUS_CMD_GET_MCAST_ADDR_FILTER = 0x1165,
152 + PS3_EURUS_CMD_0x116d = 0x116d,
153 + PS3_EURUS_CMD_0x116f = 0x116f,
154 + PS3_EURUS_CMD_GET_MAC_ADDR_LIST = 0x1117,
155 + PS3_EURUS_CMD_0x1171 = 0x1171,
156 + PS3_EURUS_CMD_GET_CHANNEL_INFO = 0xfffd,
159 +enum ps3_eurus_cmd_status {
160 + PS3_EURUS_CMD_OK = 0x0001,
161 + PS3_EURUS_CMD_INVALID_LENGTH = 0x0002,
162 + PS3_EURUS_CMD_UNSUPPORTED = 0x0003,
163 + PS3_EURUS_CMD_INVALID_PARAMETER = 0x0004,
166 +enum ps3_eurus_event_type {
167 + PS3_EURUS_EVENT_TYPE_0x8 = 0x00000008,
168 + PS3_EURUS_EVENT_TYPE_0x10 = 0x00000010,
169 + PS3_EURUS_EVENT_TYPE_0x40 = 0x00000040,
170 + PS3_EURUS_EVENT_TYPE_0x80 = 0x00000080,
171 + PS3_EURUS_EVENT_TYPE_0x100 = 0x00000100,
172 + PS3_EURUS_EVENT_TYPE_0x400 = 0x00000400,
173 + PS3_EURUS_EVENT_TYPE_0x80000000 = 0x80000000
176 +enum ps3_eurus_event_id {
177 + /* event type 0x00000008 */
179 + PS3_EURUS_EVENT_STA_CONNECTED = 0x00000010,
181 + /* event type 0x00000010 */
183 + PS3_EURUS_EVENT_STA_DISCONNECTED = 0x00000002,
184 + PS3_EURUS_EVENT_AP_STOPPED = 0x00000004,
186 + /* event type 0x00000040 */
188 + PS3_EURUS_EVENT_DEAUTH = 0x00000001,
190 + /* event type 0x00000080 */
192 + PS3_EURUS_EVENT_BEACON_LOST = 0x00000001,
193 + PS3_EURUS_EVENT_CONNECTED = 0x00000002,
194 + PS3_EURUS_EVENT_SCAN_COMPLETED = 0x00000004,
195 + PS3_EURUS_EVENT_WPA_CONNECTED = 0x00000020,
196 + PS3_EURUS_EVENT_WPA_ERROR = 0x00000040,
198 + /* event type 0x00000100 */
200 + PS3_EURUS_EVENT_0x100_0x2 = 0x00000002,
201 + PS3_EURUS_EVENT_AP_STARTED = 0x00000010,
202 + PS3_EURUS_EVENT_STA_WPA_CONNECTED = 0x00000020,
203 + PS3_EURUS_EVENT_0x100_0x40 = 0x00000040,
205 + /* event type 0x80000000 */
207 + PS3_EURUS_EVENT_DEVICE_READY = 0x00000001,
210 +enum ps3_eurus_ap_opmode {
211 + PS3_EURUS_AP_OPMODE_11B = 0x00000000,
212 + PS3_EURUS_AP_OPMODE_11G = 0x00000001,
213 + PS3_EURUS_AP_OPMODE_11BG = 0x00000002,
216 +enum ps3_eurus_bss_type {
217 + PS3_EURUS_BSS_INFRA = 0x00,
218 + PS3_EURUS_BSS_ADHOC = 0x02,
221 +enum ps3_eurus_auth_mode {
222 + PS3_EURUS_AUTH_OPEN = 0x00,
223 + PS3_EURUS_AUTH_SHARED_KEY = 0x01,
226 +enum ps3_eurus_opmode {
227 + PS3_EURUS_OPMODE_11BG = 0x00,
228 + PS3_EURUS_OPMODE_11B = 0x01,
229 + PS3_EURUS_OPMODE_11G = 0x02,
232 +enum ps3_eurus_preamble_mode {
233 + PS3_EURUS_PREAMBLE_SHORT = 0x00,
234 + PS3_EURUS_PREAMBLE_LONG = 0x01,
237 +enum ps3_eurus_wep_security_mode {
238 + PS3_EURUS_WEP_SECURITY_NONE = 0x00,
239 + PS3_EURUS_WEP_SECURITY_40BIT = 0x01,
240 + PS3_EURUS_WEP_SECURITY_104BIT = 0x02,
243 +enum ps3_eurus_wpa_security_mode {
244 + PS3_EURUS_WPA_SECURITY_WPA = 0x00,
245 + PS3_EURUS_WPA_SECURITY_WPA2 = 0x01,
248 +enum ps3_eurus_wpa_psk_type {
249 + PS3_EURUS_WPA_PSK_PASSPHRASE = 0x00,
250 + PS3_EURUS_WPA_PSK_BIN = 0x01,
253 +enum ps3_eurus_wpa_cipher_suite {
254 + PS3_EURUS_WPA_CIPHER_SUITE_WPA_TKIP = 0x0050f202,
255 + PS3_EURUS_WPA_CIPHER_SUITE_WPA_AES = 0x0050f204,
256 + PS3_EURUS_WPA_CIPHER_SUITE_WPA2_TKIP = 0x000fac02,
257 + PS3_EURUS_WPA_CIPHER_SUITE_WPA2_AES = 0x000fac04,
260 +enum ps3_eurus_wpa_akm_suite {
261 + PS3_EURUS_WPA_AKM_SUITE_WPA_PSK = 0x0050f202,
262 + PS3_EURUS_WPA_AKM_SUITE_WPA2_PSK = 0x000fac02,
265 +struct ps3_eurus_cmd_hdr {
266 + __le16 id; /* enum ps3_eurus_cmd_id */
267 + __le16 tag;
268 + __le16 status; /* enum ps3_eurus_cmd_status */
269 + __le16 payload_length;
270 + u8 res[4];
271 +} __packed;
273 +struct ps3_eurus_cmd_0x1 {
274 + u8 unknown;
275 + u8 res[3];
276 +} __packed;
278 +struct ps3_eurus_cmd_ap_ssid {
279 + u8 ssid[32];
280 + u8 res[4];
281 +} __packed;
283 +struct ps3_eurus_cmd_get_channel {
284 + u8 unknown[35];
285 + __le16 channel;
286 +} __packed;
288 +struct ps3_eurus_cmd_set_channel {
289 + u8 channel;
290 +} __packed;
292 +struct ps3_eurus_cmd_set_antenna {
293 + u8 unknown1;
294 + u8 unknown2;
295 +} __packed;
297 +struct ps3_eurus_cmd_ap_wep_config {
298 + u8 unknown1;
299 + u8 unknown2;
300 + u8 security_mode; /* enum ps3_eurus_wep_security_mode */
301 + u8 unknown3;
302 + u8 key[4][18];
303 +} __packed;
305 +struct ps3_eurus_cmd_0x61 {
306 + u8 unknown;
307 +} __packed;
309 +struct ps3_eurus_cmd_0x65 {
310 + u8 unknown;
311 +} __packed;
313 +struct ps3_eurus_cmd_get_fw_version {
314 + u8 version[62]; /* string */
315 +} __packed;
317 +struct ps3_eurus_cmd_ap_opmode {
318 + __le32 opmode; /* enum ps3_eurus_ap_opmode */
319 +} __packed;
321 +struct ps3_eurus_cmd_0xc5 {
322 + __le32 unknown;
323 +} __packed;
325 +struct ps3_eurus_cmd_ap_wpa_akm_suite {
326 + __be32 suite; /* enum ps3_eurus_wpa_akm_suite */
327 + u8 unknown;
328 +} __packed;
330 +struct ps3_eurus_cmd_ap_wpa_group_cipher_suite {
331 + __be32 cipher_suite; /* enum ps3_eurus_wpa_cipher_suite */
332 +} __packed;
334 +struct ps3_eurus_cmd_ap_wpa_psk_passphrase {
335 + u8 passphrase[64];
336 +} __packed;
338 +struct ps3_eurus_cmd_0xd5 {
339 + __le32 unknown;
340 +} __packed;
342 +struct ps3_eurus_cmd_0x127 {
343 + u8 res[4];
344 +} __packed;
346 +struct ps3_eurus_cmd_0x12b {
347 + u8 res[4];
348 +} __packed;
350 +struct ps3_eurus_cmd_ap_wpa_psk_bin {
351 + u8 enable;
352 + u8 psk[32];
353 +} __packed;
355 +struct ps3_eurus_cmd_ap_wpa_pairwise_cipher_suite {
356 + __be32 cipher_suite; /* enum ps3_eurus_wpa_cipher_suite */
357 + u8 unknown;
358 +} __packed;
360 +struct ps3_eurus_cmd_0x1d9 {
361 + u8 unknown1;
362 + u8 unknown2;
363 + u8 res[2];
364 +} __packed;
366 +struct ps3_eurus_cmd_start_ap {
367 + u8 unknown;
368 +} __packed;
370 +struct ps3_eurus_cmd_0x1ed {
371 + __le32 unknown1;
372 + u8 unknown2;
373 + u8 unknown3;
374 + u8 unknown4;
375 + u8 unknown5;
376 + u8 unknown6;
377 + u8 unknown7;
378 + u8 unknown8;
379 +} __packed;
381 +struct ps3_eurus_cmd_get_hw_revision {
382 + u8 unknown[4];
383 +} __packed;
385 +struct ps3_eurus_cmd_0x203 {
386 + __le32 unknown;
387 +} __packed;
389 +struct ps3_eurus_cmd_0x207 {
390 + __le32 unknown;
391 +} __packed;
393 +struct ps3_eurus_cmd_associate {
394 + u8 unknown;
395 +} __packed;
397 +struct ps3_eurus_cmd_common_config {
398 + u8 bss_type; /* enum ps3_eurus_bss_type */
399 + u8 auth_mode; /* enum ps3_eurus_auth_mode */
400 + u8 opmode; /* enum ps3_eurus_opmode */
401 + u8 unknown;
402 + u8 bssid[6];
403 + __le16 capability;
404 + u8 ie[0];
405 +} __packed;
407 +struct ps3_eurus_cmd_wep_config {
408 + u8 unknown1;
409 + u8 security_mode; /* enum ps3_eurus_wep_security_mode */
410 + __le16 unknown2;
411 + u8 key[4][16];
412 +} __packed;
414 +struct ps3_eurus_cmd_wpa_config {
415 + u8 unknown;
416 + u8 security_mode; /* enum ps3_eurus_wpa_security_mode */
417 + u8 psk_type; /* enum ps3_eurus_wpa_psk_type */
418 + u8 psk[64];
419 + __be32 group_cipher_suite; /* enum ps3_eurus_wpa_cipher_suite */
420 + __be32 pairwise_cipher_suite; /* enum ps3_eurus_wpa_cipher_suite */
421 + __be32 akm_suite; /* enum ps3_eurus_wpa_akm_suite */
422 +} __packed;
424 +struct ps3_eurus_cmd_0x1025 {
425 + u8 preamble_mode; /* enum ps3_eurus_preamble_mode */
426 + u8 res[3];
427 +} __packed;
429 +struct ps3_eurus_cmd_0x1031 {
430 + u8 unknown1;
431 + u8 unknown2;
432 +} __packed;
434 +struct ps3_eurus_scan_result {
435 + __le16 length;
436 + u8 bssid[6];
437 + u8 rssi;
438 + __le64 timestamp;
439 + __le16 beacon_period; /* in msec */
440 + __le16 capability;
441 + u8 ie[0];
442 +} __packed;
444 +#define PS3_EURUS_SCAN_RESULTS_MAXSIZE 0x5b0
446 +struct ps3_eurus_cmd_get_scan_results {
447 + u8 count;
448 + struct ps3_eurus_scan_result result[0];
449 +} __packed;
451 +struct ps3_eurus_cmd_start_scan {
452 + u8 unknown1;
453 + u8 unknown2;
454 + __le16 channel_dwell; /* in msec */
455 + u8 res[6];
456 + u8 ie[0];
457 +} __packed;
459 +struct ps3_eurus_cmd_disassociate {
460 + u8 unknown;
461 +} __packed;
463 +struct ps3_eurus_cmd_get_rssi {
464 + u8 res[10];
465 + u8 rssi;
466 +} __packed;
468 +struct ps3_eurus_cmd_get_mac_addr {
469 + u8 unknown;
470 + u8 mac_addr[6];
471 +} __packed;
473 +struct ps3_eurus_cmd_set_mac_addr {
474 + u8 mac_addr[6];
475 +} __packed;
477 +struct ps3_eurus_cmd_0x104d {
478 + u8 unknown;
479 +} __packed;
481 +struct ps3_eurus_cmd_0x104f {
482 + u8 unknown;
483 +} __packed;
485 +struct ps3_eurus_cmd_0x105f {
486 + __le16 channel_info;
487 + u8 mac_addr[6];
488 + u8 unknown1;
489 + u8 unknown2;
490 +} __packed;
492 +struct ps3_eurus_cmd_0x1109 {
493 + __le16 unknown1;
494 + __le16 unknown2;
495 + __le16 unknown3;
496 + __le16 unknown4;
497 + __le16 unknown5;
498 + __le16 unknown6;
499 + __le16 unknown7;
500 + u8 unknown8;
501 + u8 res;
502 + u8 unknown9;
503 + u8 unknown10;
504 + __le16 unknown11;
505 + __le16 unknown12;
506 +} __packed;
508 +struct ps3_eurus_cmd_0x110b {
509 + __le32 unknown1;
510 + u8 res[4];
511 + __le32 unknown2;
512 +} __packed;
514 +struct ps3_eurus_cmd_0x110d {
515 + u8 res1[12];
516 + __le32 unknown1;
517 + __le32 unknown2;
518 + __le32 unknown3;
519 + __le32 unknown4;
520 + __le32 unknown5;
521 + __le32 unknown6;
522 + __le32 unknown7;
523 + u8 res2[88];
524 +} __packed;
526 +struct ps3_eurus_cmd_0x1133 {
527 + u8 unknown1;
528 + u8 unknown2;
529 + u8 unknown3;
530 + u8 unknown4;
531 + __le32 unknown5;
532 + u8 res[6];
533 +} __packed;
535 +struct ps3_eurus_cmd_0x114f {
536 + u8 res[1304];
537 +} __packed;
539 +struct ps3_eurus_cmd_0x115b {
540 + __le16 unknown1;
541 + __le16 unknown2;
542 + u8 mac_addr[6];
543 + u8 res[84];
544 +} __packed;
546 +struct ps3_eurus_cmd_mcast_addr_filter {
547 + __le32 word[8];
548 +} __packed;
550 +struct ps3_eurus_cmd_0x116d {
551 + __le32 unknown;
552 +} __packed;
554 +struct ps3_eurus_cmd_0x116f {
555 + __le32 unknown;
556 +} __packed;
558 +#define PS3_EURUS_MAC_ADDR_LIST_MAXSIZE 0xc2
560 +struct ps3_eurus_cmd_get_mac_addr_list {
561 + __le16 count; /* number of MAC addresses */
562 + u8 mac_addr[0];
563 +} __packed;
565 +struct ps3_eurus_cmd_get_channel_info {
566 + u16 channel_info;
567 +} __packed;
569 +struct ps3_eurus_event_hdr {
570 + __le32 type; /* enum ps3_eurus_event_type */
571 + __le32 id; /* enum ps3_eurus_event_id */
572 + __le32 timestamp;
573 + __le32 payload_length;
574 + __le32 unknown;
575 +} __packed;
577 +struct ps3_eurus_event {
578 + struct ps3_eurus_event_hdr hdr;
579 + u8 payload[44];
580 +} __packed;
583 + * ps3_eurus_rssi2percentage
584 + */
585 +static inline u8 ps3_eurus_rssi2percentage(u8 rssi)
587 + if (rssi > 89)
588 + return 1;
589 + else if (rssi < 50)
590 + return 100;
591 + else
592 + return ((90 - rssi) * 100) / 40;
595 +#define PS3_EURUS_MCAST_ADDR_HASH2VAL(h) (1 << ((h) & 0x1f))
596 +#define PS3_EURUS_MCAST_ADDR_HASH2POS(h) (((h) >> 5) & 0x7)
599 + * ps3_eurus_mcast_addr_hash
600 + */
601 +static inline u8 ps3_eurus_mcast_addr_hash(const u8 mac_addr[ETH_ALEN])
603 + u8 buf[ETH_ALEN];
604 + u32 h;
605 + unsigned int i, j;
607 + memcpy(buf, mac_addr, ETH_ALEN);
609 + /* reverse bits in each byte */
611 + for (i = 0; i < ETH_ALEN; i++) {
612 + buf[i] = (buf[i] >> 4) | ((buf[i] & 0xf) << 4);
613 + buf[i] = ((buf[i] & 0xcc) >> 2) | ((buf[i] & 0x33) << 2);
614 + buf[i] = ((buf[i] & 0xaa) >> 1) | ((buf[i] & 0x55) << 1);
617 + h = 0xffffffff;
619 + for (i = 0; i < ETH_ALEN; i++) {
620 + h = (((unsigned int) buf[i]) << 24) ^ h;
622 + for (j = 0; j < 8; j++) {
623 + if (((int) h) >= 0) {
624 + h = h << 1;
625 + } else {
626 + h = (h << 1) ^ 0x4c10000;
627 + h = h ^ 0x1db7;
632 + h = ((h >> 24) & 0xf8) | (h & 0x7);
634 + return (h & 0xff);
638 + * ps3_eurus_make_cmd_0x1109
639 + */
640 +static inline void ps3_eurus_make_cmd_0x1109(struct ps3_eurus_cmd_0x1109 *cmd_0x1109,
641 + u8 arg1, u16 arg2, u16 arg3, u16 arg4, u16 arg5)
643 + memset(cmd_0x1109, 0, sizeof(*cmd_0x1109));
645 + cmd_0x1109->unknown1 = cpu_to_le16(0x1);
646 + cmd_0x1109->unknown8 = arg1;
648 + if (arg1 == 0x0) {
649 + cmd_0x1109->unknown6 = cpu_to_le16(0xa);
650 + } else if (arg1 == 0x1) {
651 + cmd_0x1109->unknown2 = cpu_to_le16(arg2);
652 + cmd_0x1109->unknown3 = cpu_to_le16(arg3);
653 + cmd_0x1109->unknown4 = cpu_to_le16(arg5);
655 + if (arg2 == 0x0)
656 + cmd_0x1109->unknown5 = cpu_to_le16(0x6);
657 + else
658 + cmd_0x1109->unknown5 = cpu_to_le16(0x2);
660 + cmd_0x1109->unknown7 = cpu_to_le16(arg4);
661 + cmd_0x1109->unknown9 = 0xff;
662 + cmd_0x1109->unknown10 = 0xff;
663 + cmd_0x1109->unknown11 = 0xffff;
664 + cmd_0x1109->unknown12 = 0xffff;
668 +#endif
669 --- /dev/null 2012-11-01 00:09:58.397610712 -0800
670 +++ b/drivers/net/wireless/ps3jupiter/ps3_jupiter.h 2012-11-01 03:22:23.000000000 -0800
671 @@ -0,0 +1,34 @@
674 + * PS3 Jupiter
676 + * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
677 + * All rights reserved.
679 + * This program is free software; you can redistribute it and/or modify it
680 + * under the terms of the GNU General Public License as published
681 + * by the Free Software Foundation; version 2 of the License.
683 + * This program is distributed in the hope that it will be useful, but
684 + * WITHOUT ANY WARRANTY; without even the implied warranty of
685 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
686 + * General Public License for more details.
688 + * You should have received a copy of the GNU General Public License along
689 + * with this program; if not, write to the Free Software Foundation, Inc.,
690 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
691 + */
693 +#ifndef _PS3_JUPITER_H
694 +#define _PS3_JUPITER_H
696 +int ps3_jupiter_register_event_listener(struct notifier_block *listener);
698 +int ps3_jupiter_unregister_event_listener(struct notifier_block *listener);
700 +int ps3_jupiter_exec_eurus_cmd(enum ps3_eurus_cmd_id cmd,
701 + void *payload, unsigned int payload_length,
702 + unsigned int *response_status,
703 + unsigned int *response_length, void *response);
705 +#endif
706 --- /dev/null 2012-11-01 00:09:58.397610712 -0800
707 +++ b/drivers/net/wireless/ps3jupiter/ps3_jupiter.c 2012-11-01 03:22:27.000000000 -0800
708 @@ -0,0 +1,1244 @@
710 + * PS3 Jupiter
712 + * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
713 + * All rights reserved.
715 + * This program is free software; you can redistribute it and/or modify it
716 + * under the terms of the GNU General Public License as published
717 + * by the Free Software Foundation; version 2 of the License.
719 + * This program is distributed in the hope that it will be useful, but
720 + * WITHOUT ANY WARRANTY; without even the implied warranty of
721 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
722 + * General Public License for more details.
724 + * You should have received a copy of the GNU General Public License along
725 + * with this program; if not, write to the Free Software Foundation, Inc.,
726 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
727 + */
729 +#include <linux/module.h>
730 +#include <linux/kernel.h>
731 +#include <linux/init.h>
732 +#include <linux/slab.h>
733 +#include <linux/usb.h>
734 +#include <linux/notifier.h>
736 +#include <linux/etherdevice.h>
737 +#include <linux/if_ether.h>
739 +#include <asm/byteorder.h>
740 +#include <asm/ps3.h>
741 +#include <asm/lv1call.h>
743 +#include "ps3_eurus.h"
744 +#include "ps3_jupiter.h"
746 +#define PS3_JUPITER_EP 0x5
748 +#define PS3_JUPITER_IRQ_BUFSIZE 2048
749 +#define PS3_JUPITER_CMD_BUFSIZE 2048
751 +#define LV1_SB_BUS_ID 0x1
752 +#define LV1_GELIC_DEV_ID 0x0
753 +#define LV1_GET_MAC_ADDRESS 0x1
754 +#define LV1_GET_CHANNEL_INFO 0x6
756 +enum ps3_jupiter_pkt_type {
757 + PS3_JUPITER_PKT_CMD = 6,
758 + PS3_JUPITER_PKT_EVENT = 8,
761 +struct ps3_jupiter_dev {
762 + struct usb_device *udev;
763 + struct urb *irq_urb, *cmd_urb;
764 + void *irq_buf, *cmd_buf;
766 + u16 cmd_tag, eurus_cmd, eurus_tag;
767 + struct completion cmd_done_comp;
768 + spinlock_t cmd_lock;
769 + int cmd_busy, cmd_err;
771 + struct workqueue_struct *event_queue;
772 + struct delayed_work event_work;
773 + struct blocking_notifier_head event_listeners;
774 + struct list_head event_list;
775 + spinlock_t event_list_lock;
777 + struct notifier_block event_listener;
778 + struct completion event_comp;
780 + unsigned char mac_addr[ETH_ALEN];
781 + u64 channel_info;
783 + u16 dev_status;
784 + int dev_ready;
787 +struct ps3_jupiter_pkt_hdr {
788 + u8 unknown1;
789 + u8 unknown2;
790 + u8 type;
791 +} __packed;
793 +struct ps3_jupiter_cmd_hdr {
794 + u8 unknown1;
795 + __le16 unknown2;
796 + u8 res1[2];
797 + __le16 tag;
798 + u8 res2[14];
799 +} __packed;
801 +struct ps3_jupiter_event_hdr {
802 + u8 count;
803 +} __packed;
805 +struct ps3_jupiter_list_event {
806 + struct list_head list;
807 + struct ps3_eurus_event event;
810 +static struct ps3_jupiter_dev *ps3jd;
812 +static unsigned char ps3_jupiter_devkey[] = {
813 + 0x76, 0x4e, 0x4b, 0x07, 0x24, 0x42, 0x53, 0xfb, 0x5a, 0xc7, 0xcc, 0x1d, 0xae, 0x00, 0xc6, 0xd8,
814 + 0x14, 0x40, 0x61, 0x8b, 0x13, 0x17, 0x4d, 0x7c, 0x3b, 0xb6, 0x90, 0xb8, 0x6e, 0x8b, 0xbb, 0x1d,
818 + * ps3_jupiter_event_worker
819 + */
820 +static void ps3_jupiter_event_worker(struct work_struct *work)
822 + struct ps3_jupiter_dev *jd = container_of(work, struct ps3_jupiter_dev, event_work.work);
823 + struct ps3_jupiter_list_event *list_event;
824 + unsigned long flags;
826 + /* dispatch received events to each listener */
828 + while (1) {
829 + spin_lock_irqsave(&jd->event_list_lock, flags);
831 + if (list_empty(&jd->event_list)) {
832 + spin_unlock_irqrestore(&jd->event_list_lock, flags);
833 + break;
836 + list_event = list_entry(jd->event_list.next, struct ps3_jupiter_list_event, list);
837 + list_del(&list_event->list);
839 + spin_unlock_irqrestore(&jd->event_list_lock, flags);
841 + blocking_notifier_call_chain(&jd->event_listeners, 0, &list_event->event);
843 + kfree(list_event);
848 + * ps3_jupiter_event_irq
849 + */
850 +static void ps3_jupiter_event_irq(struct ps3_jupiter_dev *jd,
851 + void *buf, unsigned int length)
853 + struct usb_device *udev = jd->udev;
854 + struct ps3_jupiter_pkt_hdr *pkt_hdr;
855 + struct ps3_jupiter_event_hdr *event_hdr;
856 + struct ps3_jupiter_list_event *list_event;
857 + unsigned long flags;
858 + int i;
860 + dev_dbg(&udev->dev, "got event IRQ packet\n");
862 + if (length < sizeof(*pkt_hdr) + sizeof(*event_hdr)) {
863 + dev_err(&udev->dev, "got event IRQ packet with invalid length (%d)\n",
864 + length);
865 + return;
868 + pkt_hdr = (struct ps3_jupiter_pkt_hdr *) buf;
869 + event_hdr = (struct ps3_jupiter_event_hdr *) (pkt_hdr + 1);
871 + if (length < sizeof(*pkt_hdr) + sizeof(*event_hdr) +
872 + event_hdr->count * sizeof(struct ps3_eurus_event)) {
873 + dev_err(&udev->dev, "got event IRQ packet with invalid length (%d)\n",
874 + length);
875 + return;
878 + dev_dbg(&udev->dev, "got %d event(s)\n", event_hdr->count);
880 + for (i = 0; i < event_hdr->count; i++) {
881 + list_event = kmalloc(sizeof(*list_event), GFP_ATOMIC);
882 + if (!list_event) {
883 + dev_err(&udev->dev, "could not allocate memory for new event\n");
884 + continue;
887 + memcpy(&list_event->event, (unsigned char *) event_hdr + sizeof(*event_hdr) +
888 + i * sizeof(struct ps3_eurus_event), sizeof(struct ps3_eurus_event));
889 + list_event->event.hdr.type = le32_to_cpu(list_event->event.hdr.type);
890 + list_event->event.hdr.id = le32_to_cpu(list_event->event.hdr.id);
891 + list_event->event.hdr.timestamp = le32_to_cpu(list_event->event.hdr.timestamp);
892 + list_event->event.hdr.payload_length = le32_to_cpu(list_event->event.hdr.payload_length);
893 + list_event->event.hdr.unknown = le32_to_cpu(list_event->event.hdr.unknown);
895 + spin_lock_irqsave(&jd->event_list_lock, flags);
896 + list_add_tail(&list_event->list, &jd->event_list);
897 + spin_unlock_irqrestore(&jd->event_list_lock, flags);
900 + if (event_hdr->count)
901 + queue_delayed_work(jd->event_queue, &jd->event_work, 0);
905 + * ps3_jupiter_cmd_irq
906 + */
907 +static void ps3_jupiter_cmd_irq(struct ps3_jupiter_dev *jd,
908 + void *buf, unsigned int length)
910 + struct usb_device *udev = jd->udev;
911 + struct ps3_jupiter_pkt_hdr *pkt_hdr;
912 + struct ps3_jupiter_cmd_hdr *cmd_hdr;
913 + struct ps3_eurus_cmd_hdr *eurus_cmd_hdr;
914 + u16 cmd_tag, eurus_cmd, eurus_tag, payload_length;
916 + dev_dbg(&udev->dev, "got command IRQ packet\n");
918 + if (length < sizeof(*pkt_hdr) + sizeof(*cmd_hdr) + sizeof(*eurus_cmd_hdr)) {
919 + dev_err(&udev->dev, "got command IRQ packet with invalid length (%d)\n",
920 + length);
921 + return;
924 + pkt_hdr = (struct ps3_jupiter_pkt_hdr *) buf;
925 + cmd_hdr = (struct ps3_jupiter_cmd_hdr *) (pkt_hdr + 1);
926 + eurus_cmd_hdr = (struct ps3_eurus_cmd_hdr *) (cmd_hdr + 1);
927 + payload_length = le16_to_cpu(eurus_cmd_hdr->payload_length);
929 + if (length < sizeof(*pkt_hdr) + sizeof(*cmd_hdr) + sizeof(*eurus_cmd_hdr) + payload_length) {
930 + dev_err(&udev->dev, "got command IRQ packet with invalid length (%d)\n",
931 + length);
932 + return;
935 + cmd_tag = le16_to_cpu(cmd_hdr->tag);
937 + if (jd->cmd_tag != cmd_tag)
938 + dev_err(&udev->dev, "got command IRQ packet with invalid command tag, "
939 + "got (0x%04x), expected (0x%04x)\n", cmd_tag, jd->cmd_tag);
941 + eurus_cmd = le16_to_cpu(eurus_cmd_hdr->id);
943 + if ((jd->eurus_cmd + 1) != eurus_cmd)
944 + dev_err(&udev->dev, "got command IRQ packet with invalid EURUS command, "
945 + "got (0x%04x), expected (0x%04x)\n", eurus_cmd, jd->eurus_cmd);
947 + eurus_tag = le16_to_cpu(eurus_cmd_hdr->tag);
949 + if (jd->eurus_tag != eurus_tag)
950 + dev_err(&udev->dev, "got command IRQ packet with invalid EURUS tag, "
951 + "got (0x%04x), expected (0x%04x)\n", eurus_tag, jd->eurus_tag);
953 + memcpy(jd->cmd_buf, buf, length);
955 + jd->cmd_err = 0;
956 + complete(&jd->cmd_done_comp);
960 + * ps3_jupiter_irq_urb_complete
961 + */
962 +static void ps3_jupiter_irq_urb_complete(struct urb *urb)
964 + struct ps3_jupiter_dev *jd = urb->context;
965 + struct usb_device *udev = jd->udev;
966 + struct ps3_jupiter_pkt_hdr *pkt_hdr;
967 + int err;
969 + dev_dbg(&udev->dev, "IRQ URB completed (%d)\n", urb->status);
971 + switch (urb->status) {
972 + case 0:
973 + if (urb->actual_length < sizeof(*pkt_hdr)) {
974 + dev_err(&udev->dev, "got IRQ packet with invalid length (%d)\n",
975 + urb->actual_length);
976 + break;
979 + pkt_hdr = (struct ps3_jupiter_pkt_hdr *) jd->irq_buf;
981 + switch (pkt_hdr->type) {
982 + case PS3_JUPITER_PKT_CMD:
983 + ps3_jupiter_cmd_irq(jd, pkt_hdr, urb->actual_length);
984 + break;
985 + case PS3_JUPITER_PKT_EVENT:
986 + ps3_jupiter_event_irq(jd, pkt_hdr, urb->actual_length);
987 + break;
988 + default:
989 + dev_err(&udev->dev, "got unknown IRQ packet type (%d)\n",
990 + pkt_hdr->type);
992 + break;
993 + case -EINPROGRESS:
994 + /* ignore */
995 + break;
996 + case -ECONNRESET:
997 + case -ENOENT:
998 + case -ESHUTDOWN:
999 + case -ENODEV:
1000 + return;
1001 + default:
1002 + dev_err(&udev->dev, "IRQ URB failed (%d)\n", urb->status);
1005 + err = usb_submit_urb(jd->irq_urb, GFP_ATOMIC);
1006 + if (err)
1007 + dev_err(&udev->dev, "could not submit IRQ URB (%d)\n", err);
1011 + * ps3_jupiter_cmd_urb_complete
1012 + */
1013 +static void ps3_jupiter_cmd_urb_complete(struct urb *urb)
1015 + struct ps3_jupiter_dev *jd = urb->context;
1016 + struct usb_device *udev = jd->udev;
1018 + dev_dbg(&udev->dev, "command URB completed (%d)\n", urb->status);
1020 + switch (urb->status) {
1021 + case 0:
1022 + /* success */
1023 + break;
1024 + case -EINPROGRESS:
1025 + /* ignore */
1026 + break;
1027 + case -ECONNRESET:
1028 + case -ENOENT:
1029 + case -ESHUTDOWN:
1030 + case -ENODEV:
1031 + default:
1032 + dev_err(&udev->dev, "command URB failed (%d)\n", urb->status);
1033 + jd->cmd_err = urb->status;
1034 + complete(&jd->cmd_done_comp);
1039 + * _ps3_jupiter_register_event_listener
1040 + */
1041 +static int _ps3_jupiter_register_event_listener(struct ps3_jupiter_dev *jd,
1042 + struct notifier_block *listener)
1044 + BUG_ON(!jd);
1046 + return blocking_notifier_chain_register(&jd->event_listeners, listener);
1050 + * ps3_jupiter_register_event_listener
1051 + */
1052 +int ps3_jupiter_register_event_listener(struct notifier_block *listener)
1054 + struct ps3_jupiter_dev *jd = ps3jd;
1055 + int err;
1057 + if (!jd || !jd->dev_ready)
1058 + return -ENODEV;
1060 + err = _ps3_jupiter_register_event_listener(jd, listener);
1062 + return err;
1065 +EXPORT_SYMBOL_GPL(ps3_jupiter_register_event_listener);
1068 + * _ps3_jupiter_unregister_event_listener
1069 + */
1070 +static int _ps3_jupiter_unregister_event_listener(struct ps3_jupiter_dev *jd,
1071 + struct notifier_block *listener)
1073 + BUG_ON(!jd);
1075 + return blocking_notifier_chain_unregister(&jd->event_listeners, listener);
1079 + * ps3_jupiter_unregister_event_listener
1080 + */
1081 +int ps3_jupiter_unregister_event_listener(struct notifier_block *listener)
1083 + struct ps3_jupiter_dev *jd = ps3jd;
1084 + int err;
1086 + if (!jd || !jd->dev_ready)
1087 + return -ENODEV;
1089 + err = _ps3_jupiter_unregister_event_listener(jd, listener);
1091 + return err;
1094 +EXPORT_SYMBOL_GPL(ps3_jupiter_unregister_event_listener);
1097 + * _ps3_jupiter_exec_eurus_cmd
1098 + */
1099 +static int _ps3_jupiter_exec_eurus_cmd(struct ps3_jupiter_dev *jd,
1100 + enum ps3_eurus_cmd_id cmd,
1101 + void *payload, unsigned int payload_length,
1102 + unsigned int *response_status,
1103 + unsigned int *response_length, void *response)
1105 + struct usb_device *udev = jd->udev;
1106 + struct ps3_jupiter_pkt_hdr *pkt_hdr;
1107 + struct ps3_jupiter_cmd_hdr *cmd_hdr;
1108 + struct ps3_eurus_cmd_hdr *eurus_cmd_hdr;
1109 + struct ps3_eurus_cmd_get_channel_info *eurus_cmd_get_channel_info;
1110 + u16 status;
1111 + unsigned long flags;
1112 + int err;
1114 + BUG_ON(!jd);
1116 + if (!payload && payload_length)
1117 + return -EINVAL;
1119 + spin_lock_irqsave(&jd->cmd_lock, flags);
1121 + if (jd->cmd_busy) {
1122 + spin_unlock_irqrestore(&jd->cmd_lock, flags);
1123 + dev_dbg(&udev->dev,
1124 + "trying to execute multiple commands at the same time\n");
1125 + return -EAGAIN;
1128 + jd->cmd_busy = 1;
1130 + spin_unlock_irqrestore(&jd->cmd_lock, flags);
1132 + dev_dbg(&udev->dev, "EURUS command 0x%04x payload length %d\n",
1133 + cmd, payload_length);
1135 + /* internal commands */
1137 + if (cmd == PS3_EURUS_CMD_GET_CHANNEL_INFO) {
1138 + if (payload_length < sizeof(*eurus_cmd_get_channel_info)) {
1139 + err = -EINVAL;
1140 + goto done;
1143 + if (response_status)
1144 + *response_status = PS3_EURUS_CMD_OK;
1146 + if (response_length && response) {
1147 + *response_length = sizeof(*eurus_cmd_get_channel_info);
1148 + eurus_cmd_get_channel_info = (struct ps3_eurus_cmd_get_channel_info *) response;
1149 + memset(eurus_cmd_get_channel_info, 0, sizeof(*eurus_cmd_get_channel_info));
1150 + eurus_cmd_get_channel_info->channel_info = jd->channel_info >> 48;
1153 + err = 0;
1155 + goto done;
1158 + pkt_hdr = (struct ps3_jupiter_pkt_hdr *) jd->cmd_buf;
1159 + memset(pkt_hdr, 0, sizeof(*pkt_hdr));
1160 + pkt_hdr->unknown1 = 1;
1161 + pkt_hdr->unknown2 = 1;
1162 + pkt_hdr->type = PS3_JUPITER_PKT_CMD;
1164 + cmd_hdr = (struct ps3_jupiter_cmd_hdr *) (pkt_hdr + 1);
1165 + memset(cmd_hdr, 0, sizeof(*cmd_hdr));
1166 + jd->cmd_tag++;
1167 + cmd_hdr->unknown1 = 0;
1168 + cmd_hdr->unknown2 = cpu_to_le16(1);
1169 + cmd_hdr->tag = cpu_to_le16(jd->cmd_tag);
1171 + eurus_cmd_hdr = (struct ps3_eurus_cmd_hdr *) (cmd_hdr + 1);
1172 + memset(eurus_cmd_hdr, 0, sizeof(*eurus_cmd_hdr));
1173 + jd->eurus_cmd = cmd;
1174 + eurus_cmd_hdr->id = cpu_to_le16(cmd);
1175 + jd->eurus_tag++;
1176 + eurus_cmd_hdr->tag = cpu_to_le16(jd->eurus_tag);
1177 + eurus_cmd_hdr->status = cpu_to_le16(0xa);
1178 + eurus_cmd_hdr->payload_length = cpu_to_le16(payload_length);
1180 + if (payload_length)
1181 + memcpy(eurus_cmd_hdr + 1, payload, payload_length);
1183 + init_completion(&jd->cmd_done_comp);
1185 + usb_fill_int_urb(jd->cmd_urb, udev, usb_sndintpipe(udev, PS3_JUPITER_EP),
1186 + jd->cmd_buf, sizeof(*pkt_hdr) + sizeof(*cmd_hdr) + sizeof(*eurus_cmd_hdr) + payload_length,
1187 + ps3_jupiter_cmd_urb_complete, jd, 1);
1189 + err = usb_submit_urb(jd->cmd_urb, GFP_KERNEL);
1190 + if (err) {
1191 + dev_err(&udev->dev, "could not submit command URB (%d)\n", err);
1192 + goto done;
1195 + err = wait_for_completion_timeout(&jd->cmd_done_comp, HZ);
1196 + if (!err) {
1197 + err = -ETIMEDOUT;
1198 + goto done;
1201 + err = jd->cmd_err;
1202 + if (!err) {
1203 + status = le16_to_cpu(eurus_cmd_hdr->status);
1205 + if (response_status)
1206 + *response_status = status;
1208 + if (response_length && response) {
1209 + *response_length = le16_to_cpu(eurus_cmd_hdr->payload_length);
1210 + memcpy(response, eurus_cmd_hdr + 1, *response_length);
1213 + if (status != PS3_EURUS_CMD_OK)
1214 + dev_err(&udev->dev, "EURUS command 0x%04x status (0x%04x)\n", cmd, status);
1217 +done:
1219 + if (err)
1220 + dev_err(&udev->dev, "EURUS command 0x%04x failed (%d)\n", cmd, err);
1222 + jd->cmd_busy = 0;
1224 + return err;
1228 + * _ps3_jupiter_exec_eurus_cmd
1229 + */
1230 +int ps3_jupiter_exec_eurus_cmd(enum ps3_eurus_cmd_id cmd,
1231 + void *payload, unsigned int payload_length,
1232 + unsigned int *response_status,
1233 + unsigned int *response_length, void *response)
1235 + struct ps3_jupiter_dev *jd = ps3jd;
1236 + int err;
1238 + if (!jd || !jd->dev_ready)
1239 + return -ENODEV;
1241 + err = _ps3_jupiter_exec_eurus_cmd(jd, cmd, payload, payload_length,
1242 + response_status, response_length, response);
1244 + return err;
1247 +EXPORT_SYMBOL_GPL(ps3_jupiter_exec_eurus_cmd);
1250 + * ps3_jupiter_create_event_worker
1251 + */
1252 +static int ps3_jupiter_create_event_worker(struct ps3_jupiter_dev *jd)
1254 + jd->event_queue = create_singlethread_workqueue("ps3_jupiter_event");
1255 + if (!jd->event_queue)
1256 + return -ENOMEM;
1258 + INIT_DELAYED_WORK(&jd->event_work, ps3_jupiter_event_worker);
1260 + return 0;
1264 + * ps3_jupiter_destroy_event_worker
1265 + */
1266 +static void ps3_jupiter_destroy_event_worker(struct ps3_jupiter_dev *jd)
1268 + if (jd->event_queue) {
1269 + cancel_delayed_work(&jd->event_work);
1270 + flush_workqueue(jd->event_queue);
1271 + destroy_workqueue(jd->event_queue);
1272 + jd->event_queue = NULL;
1277 + * ps3_jupiter_free_event_list
1278 + */
1279 +static void ps3_jupiter_free_event_list(struct ps3_jupiter_dev *jd)
1281 + struct ps3_jupiter_list_event *event, *tmp;
1283 + list_for_each_entry_safe(event, tmp, &jd->event_list, list) {
1284 + list_del(&event->list);
1285 + kfree(event);
1290 + * ps3_jupiter_alloc_urbs
1291 + */
1292 +static int ps3_jupiter_alloc_urbs(struct ps3_jupiter_dev *jd)
1294 + struct usb_device *udev = jd->udev;
1296 + jd->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
1297 + if (!jd->irq_urb)
1298 + return -ENOMEM;
1300 + jd->irq_buf = usb_alloc_coherent(udev, PS3_JUPITER_IRQ_BUFSIZE,
1301 + GFP_KERNEL, &jd->irq_urb->transfer_dma);
1302 + if (!jd->irq_buf)
1303 + return -ENOMEM;
1305 + usb_fill_int_urb(jd->irq_urb, udev, usb_rcvintpipe(udev, PS3_JUPITER_EP),
1306 + jd->irq_buf, PS3_JUPITER_IRQ_BUFSIZE, ps3_jupiter_irq_urb_complete, jd, 1);
1307 + jd->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1309 + jd->cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
1310 + if (!jd->cmd_urb)
1311 + return -ENOMEM;
1313 + jd->cmd_buf = usb_alloc_coherent(udev, PS3_JUPITER_CMD_BUFSIZE,
1314 + GFP_KERNEL, &jd->cmd_urb->transfer_dma);
1315 + if (!jd->cmd_buf)
1316 + return -ENOMEM;
1318 + usb_fill_int_urb(jd->cmd_urb, udev, usb_sndintpipe(udev, PS3_JUPITER_EP),
1319 + jd->cmd_buf, PS3_JUPITER_CMD_BUFSIZE, ps3_jupiter_cmd_urb_complete, jd, 1);
1320 + jd->cmd_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1322 + return 0;
1326 + * ps3_jupiter_free_urbs
1327 + */
1328 +static void ps3_jupiter_free_urbs(struct ps3_jupiter_dev *jd)
1330 + struct usb_device *udev = jd->udev;
1332 + if (jd->irq_urb) {
1333 + usb_kill_urb(jd->irq_urb);
1335 + if (jd->irq_buf)
1336 + usb_free_coherent(udev, PS3_JUPITER_IRQ_BUFSIZE,
1337 + jd->irq_buf, jd->irq_urb->transfer_dma);
1339 + usb_free_urb(jd->irq_urb);
1342 + if (jd->cmd_urb) {
1343 + usb_kill_urb(jd->cmd_urb);
1345 + if (jd->cmd_buf)
1346 + usb_free_coherent(udev, PS3_JUPITER_CMD_BUFSIZE,
1347 + jd->cmd_buf, jd->cmd_urb->transfer_dma);
1349 + usb_free_urb(jd->cmd_urb);
1354 + * ps3_jupiter_dev_auth
1355 + */
1356 +static int ps3_jupiter_dev_auth(struct ps3_jupiter_dev *jd)
1358 + struct usb_device *udev = jd->udev;
1359 + void *buf;
1360 + int err;
1362 + buf = kmalloc(sizeof(ps3_jupiter_devkey), GFP_KERNEL);
1363 + if (!buf)
1364 + return -ENOMEM;
1366 + memcpy(buf, ps3_jupiter_devkey, sizeof(ps3_jupiter_devkey));
1368 + err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
1369 + 0x1, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, 0x9, 0x0,
1370 + buf, sizeof(ps3_jupiter_devkey), USB_CTRL_SET_TIMEOUT);
1371 + if (err < 0) {
1372 + dev_dbg(&udev->dev, "could not send device key (%d)\n", err);
1373 + return err;
1376 + kfree(buf);
1378 + err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
1379 + 0x0, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, 0x2, 0x0,
1380 + &jd->dev_status, sizeof(jd->dev_status), USB_CTRL_GET_TIMEOUT);
1381 + if (err < 0) {
1382 + dev_dbg(&udev->dev, "could not read device status (%d)\n", err);
1383 + return err;
1386 + dev_info(&udev->dev, "device status (0x%04x)\n", jd->dev_status);
1388 + return 0;
1392 + * ps3_jupiter_event_handler
1393 + */
1394 +static int ps3_jupiter_event_handler(struct notifier_block *n,
1395 + unsigned long val, void *v)
1397 + struct ps3_jupiter_dev *jd = container_of(n, struct ps3_jupiter_dev, event_listener);
1398 + struct usb_device *udev = jd->udev;
1399 + struct ps3_eurus_event *event = v;
1401 + dev_dbg(&udev->dev, "got event (0x%08x 0x%08x 0x%08x 0x%08x 0x%08x)\n",
1402 + event->hdr.type, event->hdr.id, event->hdr.timestamp, event->hdr.payload_length,
1403 + event->hdr.unknown);
1405 + if (event->hdr.type == PS3_EURUS_EVENT_TYPE_0x400) {
1406 + if ((event->hdr.id == 0x8) || (event->hdr.id == 0x10))
1407 + complete(&jd->event_comp);
1410 + return NOTIFY_OK;
1414 + * ps3_jupiter_dev_init
1415 + */
1416 +static int ps3_jupiter_dev_init(struct ps3_jupiter_dev *jd)
1418 + struct usb_device *udev = jd->udev;
1419 + struct ps3_eurus_cmd_0x114f *eurus_cmd_0x114f;
1420 + struct ps3_eurus_cmd_0x116f *eurus_cmd_0x116f;
1421 + struct ps3_eurus_cmd_0x115b *eurus_cmd_0x115b;
1422 + const u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1423 + u8 h;
1424 + struct ps3_eurus_cmd_mcast_addr_filter *eurus_cmd_mcast_addr_filter;
1425 + struct ps3_eurus_cmd_0x110d *eurus_cmd_0x110d;
1426 + struct ps3_eurus_cmd_0x1031 *eurus_cmd_0x1031;
1427 + struct ps3_eurus_cmd_set_mac_addr *eurus_cmd_set_mac_addr;
1428 + struct ps3_eurus_cmd_set_antenna *eurus_cmd_set_antenna;
1429 + struct ps3_eurus_cmd_0x110b *eurus_cmd_0x110b;
1430 + struct ps3_eurus_cmd_0x1109 *eurus_cmd_0x1109;
1431 + struct ps3_eurus_cmd_0x207 *eurus_cmd_0x207;
1432 + struct ps3_eurus_cmd_0x203 *eurus_cmd_0x203;
1433 + struct ps3_eurus_cmd_0x105f *eurus_cmd_0x105f;
1434 + struct ps3_eurus_cmd_get_fw_version *eurus_cmd_get_fw_version;
1435 + unsigned char *buf;
1436 + unsigned int status, response_length;
1437 + int err;
1439 + buf = kmalloc(PS3_JUPITER_CMD_BUFSIZE, GFP_KERNEL);
1440 + if (!buf)
1441 + return -ENOMEM;
1443 + /* state 1 */
1445 + eurus_cmd_0x114f = (struct ps3_eurus_cmd_0x114f *) buf;
1446 + memset(eurus_cmd_0x114f, 0, sizeof(*eurus_cmd_0x114f));
1448 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x114f,
1449 + eurus_cmd_0x114f, sizeof(*eurus_cmd_0x114f), &status, NULL, NULL);
1450 + if (err)
1451 + goto done;
1453 + /* do not check command status here !!! */
1455 + /* state 2 */
1457 + init_completion(&jd->event_comp);
1459 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x1171, NULL, 0, &status, NULL, NULL);
1460 + if (err)
1461 + goto done;
1463 + if (status != PS3_EURUS_CMD_OK) {
1464 + err = -EIO;
1465 + goto done;
1468 + /* state 3 */
1470 + err = wait_for_completion_timeout(&jd->event_comp, HZ);
1471 + if (!err) {
1472 + err = -ETIMEDOUT;
1473 + goto done;
1476 + /* state 4 */
1478 + eurus_cmd_0x116f = (struct ps3_eurus_cmd_0x116f *) buf;
1479 + memset(eurus_cmd_0x116f, 0, sizeof(*eurus_cmd_0x116f));
1480 + eurus_cmd_0x116f->unknown = cpu_to_le32(0x1);
1482 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x116f,
1483 + eurus_cmd_0x116f, sizeof(*eurus_cmd_0x116f), &status, NULL, NULL);
1484 + if (err)
1485 + goto done;
1487 + if (status != PS3_EURUS_CMD_OK) {
1488 + err = -EIO;
1489 + goto done;
1492 + /* state 5 */
1494 + eurus_cmd_0x115b = (struct ps3_eurus_cmd_0x115b *) buf;
1495 + memset(eurus_cmd_0x115b, 0, sizeof(*eurus_cmd_0x115b));
1496 + eurus_cmd_0x115b->unknown1 = cpu_to_le16(0x1);
1497 + eurus_cmd_0x115b->unknown2 = cpu_to_le16(0x0);
1498 + memcpy(eurus_cmd_0x115b->mac_addr, jd->mac_addr, sizeof(jd->mac_addr));
1500 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x115b,
1501 + eurus_cmd_0x115b, sizeof(*eurus_cmd_0x115b), &status, NULL, NULL);
1502 + if (err)
1503 + goto done;
1505 + if (status != PS3_EURUS_CMD_OK) {
1506 + err = -EIO;
1507 + goto done;
1510 + /* state 6 */
1512 + h = ps3_eurus_mcast_addr_hash(bcast_addr);
1514 + eurus_cmd_mcast_addr_filter = (struct ps3_eurus_cmd_mcast_addr_filter *) buf;
1515 + memset(eurus_cmd_mcast_addr_filter, 0, sizeof(*eurus_cmd_mcast_addr_filter));
1516 + eurus_cmd_mcast_addr_filter->word[PS3_EURUS_MCAST_ADDR_HASH2POS(h)] |=
1517 + cpu_to_le32(PS3_EURUS_MCAST_ADDR_HASH2VAL(h));
1519 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_SET_MCAST_ADDR_FILTER,
1520 + eurus_cmd_mcast_addr_filter, sizeof(*eurus_cmd_mcast_addr_filter), &status, NULL, NULL);
1521 + if (err)
1522 + goto done;
1524 + if (status != PS3_EURUS_CMD_OK) {
1525 + err = -EIO;
1526 + goto done;
1529 + /* state 7 */
1531 + eurus_cmd_0x110d = (struct ps3_eurus_cmd_0x110d *) buf;
1532 + memset(eurus_cmd_0x110d, 0, sizeof(*eurus_cmd_0x110d));
1533 + eurus_cmd_0x110d->unknown1 = cpu_to_le32(0xffffffff);
1534 + eurus_cmd_0x110d->unknown2 = cpu_to_le32(0xffffffff);
1535 + eurus_cmd_0x110d->unknown3 = cpu_to_le32(0xffffffff);
1536 + eurus_cmd_0x110d->unknown4 = cpu_to_le32(0xffffffff);
1537 + eurus_cmd_0x110d->unknown5 = cpu_to_le32(0xffffffff);
1538 + eurus_cmd_0x110d->unknown6 = cpu_to_le32(0xffffffff);
1539 + eurus_cmd_0x110d->unknown7 = cpu_to_le32(0xffffffff);
1541 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x110d,
1542 + eurus_cmd_0x110d, sizeof(*eurus_cmd_0x110d), &status, NULL, NULL);
1543 + if (err)
1544 + goto done;
1546 + if (status != PS3_EURUS_CMD_OK) {
1547 + err = -EIO;
1548 + goto done;
1551 + /* state 8 */
1553 + eurus_cmd_0x1031 = (struct ps3_eurus_cmd_0x1031 *) buf;
1554 + memset(eurus_cmd_0x1031, 0, sizeof(*eurus_cmd_0x1031));
1555 + eurus_cmd_0x1031->unknown1 = 0x0;
1556 + eurus_cmd_0x1031->unknown2 = 0x0;
1558 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x1031,
1559 + eurus_cmd_0x1031, sizeof(*eurus_cmd_0x1031), &status, NULL, NULL);
1560 + if (err)
1561 + goto done;
1563 + if (status != PS3_EURUS_CMD_OK) {
1564 + err = -EIO;
1565 + goto done;
1568 + /* state 9 */
1570 + eurus_cmd_set_mac_addr = (struct ps3_eurus_cmd_set_mac_addr *) buf;
1571 + memset(eurus_cmd_set_mac_addr, 0, sizeof(*eurus_cmd_set_mac_addr));
1572 + memcpy(eurus_cmd_set_mac_addr->mac_addr, jd->mac_addr, sizeof(jd->mac_addr));
1574 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_SET_MAC_ADDR,
1575 + eurus_cmd_set_mac_addr, sizeof(*eurus_cmd_set_mac_addr), &status, NULL, NULL);
1576 + if (err)
1577 + goto done;
1579 + if (status != PS3_EURUS_CMD_OK) {
1580 + err = -EIO;
1581 + goto done;
1584 + /* state 10 */
1586 + eurus_cmd_set_antenna = (struct ps3_eurus_cmd_set_antenna *) buf;
1587 + memset(eurus_cmd_set_antenna, 0, sizeof(*eurus_cmd_set_antenna));
1589 + if (((jd->channel_info >> 40) & 0xff) == 0x1) {
1590 + eurus_cmd_set_antenna->unknown1 = 0x1;
1591 + eurus_cmd_set_antenna->unknown2 = 0x0;
1592 + } else if (((jd->channel_info >> 40) & 0xff) == 0x2) {
1593 + eurus_cmd_set_antenna->unknown1 = 0x1;
1594 + eurus_cmd_set_antenna->unknown2 = 0x1;
1595 + } else {
1596 + eurus_cmd_set_antenna->unknown1 = 0x2;
1597 + eurus_cmd_set_antenna->unknown2 = 0x2;
1600 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_SET_ANTENNA,
1601 + eurus_cmd_set_antenna, sizeof(*eurus_cmd_set_antenna), &status, NULL, NULL);
1602 + if (err)
1603 + goto done;
1605 + if (status != PS3_EURUS_CMD_OK) {
1606 + err = -EIO;
1607 + goto done;
1610 + /* state 11 */
1612 + eurus_cmd_0x110b = (struct ps3_eurus_cmd_0x110b *) buf;
1613 + memset(eurus_cmd_0x110b, 0, sizeof(*eurus_cmd_0x110b));
1614 + eurus_cmd_0x110b->unknown1 = cpu_to_le32(0x1);
1615 + eurus_cmd_0x110b->unknown2 = cpu_to_le32(0x200000);
1617 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x110b,
1618 + eurus_cmd_0x110b, sizeof(*eurus_cmd_0x110b), &status, NULL, NULL);
1619 + if (err)
1620 + goto done;
1622 + if (status != PS3_EURUS_CMD_OK) {
1623 + err = -EIO;
1624 + goto done;
1627 + /* state 12 */
1629 + eurus_cmd_0x1109 = (struct ps3_eurus_cmd_0x1109 *) buf;
1630 + ps3_eurus_make_cmd_0x1109(eurus_cmd_0x1109, 0x1, 0x0, 0x2715, 0x9, 0x12);
1632 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x1109,
1633 + eurus_cmd_0x1109, sizeof(*eurus_cmd_0x1109), &status, NULL, NULL);
1634 + if (err)
1635 + goto done;
1637 + if (status != PS3_EURUS_CMD_OK) {
1638 + err = -EIO;
1639 + goto done;
1642 + /* state 13 */
1644 + eurus_cmd_0x207 = (struct ps3_eurus_cmd_0x207 *) buf;
1645 + memset(eurus_cmd_0x207, 0, sizeof(*eurus_cmd_0x207));
1646 + eurus_cmd_0x207->unknown = cpu_to_le32(0x1);
1648 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x207,
1649 + eurus_cmd_0x207, sizeof(*eurus_cmd_0x207), &status, NULL, NULL);
1650 + if (err)
1651 + goto done;
1653 + if (status != PS3_EURUS_CMD_OK) {
1654 + err = -EIO;
1655 + goto done;
1658 + /* state 14 */
1660 + eurus_cmd_0x203 = (struct ps3_eurus_cmd_0x203 *) buf;
1661 + memset(eurus_cmd_0x203, 0, sizeof(*eurus_cmd_0x203));
1662 + eurus_cmd_0x203->unknown = cpu_to_le32(0x1);
1664 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x203,
1665 + eurus_cmd_0x203, sizeof(*eurus_cmd_0x203), &status, NULL, NULL);
1666 + if (err)
1667 + goto done;
1669 + if (status != PS3_EURUS_CMD_OK) {
1670 + err = -EIO;
1671 + goto done;
1674 + /* state 15 */
1676 + eurus_cmd_0x105f = (struct ps3_eurus_cmd_0x105f *) buf;
1677 + memset(eurus_cmd_0x105f, 0, sizeof(*eurus_cmd_0x105f));
1678 + eurus_cmd_0x105f->channel_info = cpu_to_le16(jd->channel_info >> 48);
1679 + memcpy(eurus_cmd_0x105f->mac_addr, jd->mac_addr, sizeof(jd->mac_addr));
1681 + if (((jd->channel_info >> 40) & 0xff) == 0x1) {
1682 + eurus_cmd_0x105f->unknown1 = 0x1;
1683 + eurus_cmd_0x105f->unknown2 = 0x0;
1684 + } else if (((jd->channel_info >> 40) & 0xff) == 0x2) {
1685 + eurus_cmd_0x105f->unknown1 = 0x1;
1686 + eurus_cmd_0x105f->unknown2 = 0x1;
1687 + } else {
1688 + eurus_cmd_0x105f->unknown1 = 0x2;
1689 + eurus_cmd_0x105f->unknown2 = 0x2;
1692 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_0x105f,
1693 + eurus_cmd_0x105f, sizeof(*eurus_cmd_0x105f), &status, NULL, NULL);
1694 + if (err)
1695 + goto done;
1697 + if (status != PS3_EURUS_CMD_OK) {
1698 + err = -EIO;
1699 + goto done;
1702 + /* device is ready now */
1704 + /* read firmware version */
1706 + eurus_cmd_get_fw_version = (struct ps3_eurus_cmd_get_fw_version *) buf;
1707 + memset(eurus_cmd_get_fw_version, 0, sizeof(*eurus_cmd_get_fw_version));
1709 + err = _ps3_jupiter_exec_eurus_cmd(jd, PS3_EURUS_CMD_GET_FW_VERSION,
1710 + eurus_cmd_get_fw_version, sizeof(*eurus_cmd_get_fw_version),
1711 + &status, &response_length, eurus_cmd_get_fw_version);
1712 + if (err)
1713 + goto done;
1715 + if (status != PS3_EURUS_CMD_OK) {
1716 + err = -EIO;
1717 + goto done;
1720 + dev_info(&udev->dev, "firmware version: %s\n", (char *) eurus_cmd_get_fw_version->version);
1722 + err = 0;
1724 +done:
1726 + kfree(buf);
1728 + return err;
1732 + * ps3_jupiter_probe
1733 + */
1734 +static int ps3_jupiter_probe(struct usb_interface *interface,
1735 + const struct usb_device_id *id)
1737 + struct usb_device *udev = interface_to_usbdev(interface);
1738 + struct ps3_jupiter_dev *jd;
1739 + u64 v1, v2;
1740 + int err;
1742 + if (ps3jd) {
1743 + dev_err(&udev->dev, "only one device is supported\n");
1744 + return -EBUSY;
1747 + ps3jd = jd = kzalloc(sizeof(struct ps3_jupiter_dev), GFP_KERNEL);
1748 + if (!jd)
1749 + return -ENOMEM;
1751 + jd->udev = usb_get_dev(udev);
1752 + usb_set_intfdata(interface, jd);
1754 + spin_lock_init(&jd->cmd_lock);
1756 + BLOCKING_INIT_NOTIFIER_HEAD(&jd->event_listeners);
1757 + INIT_LIST_HEAD(&jd->event_list);
1758 + spin_lock_init(&jd->event_list_lock);
1760 + init_completion(&jd->event_comp);
1762 + jd->event_listener.notifier_call = ps3_jupiter_event_handler;
1764 + err = _ps3_jupiter_register_event_listener(jd, &jd->event_listener);
1765 + if (err) {
1766 + dev_err(&udev->dev, "could not register event listener (%d)\n", err);
1767 + goto fail;
1770 + err = ps3_jupiter_create_event_worker(jd);
1771 + if (err) {
1772 + dev_err(&udev->dev, "could not create event work queue (%d)\n", err);
1773 + goto fail;
1776 + err = ps3_jupiter_alloc_urbs(jd);
1777 + if (err) {
1778 + dev_err(&udev->dev, "could not allocate URBs (%d)\n", err);
1779 + goto fail;
1782 + err = usb_submit_urb(jd->irq_urb, GFP_KERNEL);
1783 + if (err) {
1784 + dev_err(&udev->dev, "could not submit IRQ URB (%d)\n", err);
1785 + goto fail;
1788 + err = ps3_jupiter_dev_auth(jd);
1789 + if (err) {
1790 + dev_err(&udev->dev, "could not authenticate device (%d)\n", err);
1791 + goto fail;
1794 + /* get MAC address */
1796 + err = lv1_net_control(LV1_SB_BUS_ID, LV1_GELIC_DEV_ID,
1797 + LV1_GET_MAC_ADDRESS, 0, 0, 0, &v1, &v2);
1798 + if (err) {
1799 + dev_err(&udev->dev, "could not get MAC address (%d)\n", err);
1800 + err = -ENODEV;
1801 + goto fail;
1804 + v1 <<= 16;
1806 + if (!is_valid_ether_addr((unsigned char *) &v1)) {
1807 + dev_err(&udev->dev, "got invalid MAC address\n");
1808 + err = -ENODEV;
1809 + goto fail;
1812 + memcpy(jd->mac_addr, &v1, ETH_ALEN);
1814 + dev_info(&udev->dev, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
1815 + jd->mac_addr[0], jd->mac_addr[1], jd->mac_addr[2],
1816 + jd->mac_addr[3], jd->mac_addr[4], jd->mac_addr[5]);
1818 + /* get channel info */
1820 + err = lv1_net_control(LV1_SB_BUS_ID, LV1_GELIC_DEV_ID,
1821 + LV1_GET_CHANNEL_INFO, 0, 0, 0, &v1, &v2);
1822 + if (err) {
1823 + /* don't quit here and try to recover later */
1824 + dev_err(&udev->dev, "could not get channel info (%d)\n", err);
1827 + if (err)
1828 + jd->channel_info = (0x7ffull << 48);
1829 + else
1830 + jd->channel_info = v1;
1832 + dev_info(&udev->dev, "channel info: %016llx\n", jd->channel_info);
1834 + err = ps3_jupiter_dev_init(jd);
1835 + if (err) {
1836 + dev_err(&udev->dev, "could not initialize device (%d)\n", err);
1837 + goto fail;
1840 + jd->dev_ready = 1;
1842 + return 0;
1844 +fail:
1846 + ps3_jupiter_free_urbs(jd);
1848 + ps3_jupiter_destroy_event_worker(jd);
1850 + ps3_jupiter_free_event_list(jd);
1852 + usb_set_intfdata(interface, NULL);
1853 + usb_put_dev(udev);
1855 + kfree(jd);
1856 + ps3jd = NULL;
1858 + return err;
1862 + * ps3_jupiter_disconnect
1863 + */
1864 +static void ps3_jupiter_disconnect(struct usb_interface *interface)
1866 + struct ps3_jupiter_dev *jd = usb_get_intfdata(interface);
1867 + struct usb_device *udev = jd->udev;
1869 + jd->dev_ready = 0;
1871 + ps3_jupiter_free_urbs(jd);
1873 + ps3_jupiter_destroy_event_worker(jd);
1875 + ps3_jupiter_free_event_list(jd);
1877 + usb_set_intfdata(interface, NULL);
1878 + usb_put_dev(udev);
1880 + kfree(jd);
1881 + ps3jd = NULL;
1884 +#ifdef CONFIG_PM
1886 + * ps3_jupiter_suspend
1887 + */
1888 +static int ps3_jupiter_suspend(struct usb_interface *interface, pm_message_t state)
1890 + /*XXX: implement */
1892 + return 0;
1896 + * ps3_jupiter_resume
1897 + */
1898 +static int ps3_jupiter_resume(struct usb_interface *interface)
1900 + /*XXX: implement */
1902 + return 0;
1904 +#endif /* CONFIG_PM */
1906 +static struct usb_device_id ps3_jupiter_devtab[] = {
1908 + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO,
1909 + .idVendor = 0x054c,
1910 + .idProduct = 0x036f,
1911 + .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
1912 + .bInterfaceSubClass = 2,
1913 + .bInterfaceProtocol = 1
1914 + },
1915 + { }
1918 +static struct usb_driver ps3_jupiter_drv = {
1919 + .name = KBUILD_MODNAME,
1920 + .id_table = ps3_jupiter_devtab,
1921 + .probe = ps3_jupiter_probe,
1922 + .disconnect = ps3_jupiter_disconnect,
1923 +#ifdef CONFIG_PM
1924 + .suspend = ps3_jupiter_suspend,
1925 + .resume = ps3_jupiter_resume,
1926 +#endif /* CONFIG_PM */
1930 + * ps3_jupiter_init
1931 + */
1932 +static int __init ps3_jupiter_init(void)
1934 + return usb_register(&ps3_jupiter_drv);
1938 + * ps3_jupiter_exit
1939 + */
1940 +static void __exit ps3_jupiter_exit(void)
1942 + usb_deregister(&ps3_jupiter_drv);
1945 +module_init(ps3_jupiter_init);
1946 +module_exit(ps3_jupiter_exit);
1948 +/*MODULE_SUPPORTED_DEVICE("PS3 Jupiter");*/
1949 +MODULE_DEVICE_TABLE(usb, ps3_jupiter_devtab);
1950 +MODULE_DESCRIPTION("PS3 Jupiter");
1951 +MODULE_AUTHOR("glevand");
1952 +MODULE_LICENSE("GPL");
1953 --- /dev/null 2012-11-01 00:09:58.397610712 -0800
1954 +++ b/drivers/net/wireless/ps3jupiter/ps3_jupiter_sta.c 2012-11-01 03:22:36.000000000 -0800
1955 @@ -0,0 +1,2934 @@
1958 + * PS3 Jupiter STA
1960 + * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
1961 + * All rights reserved.
1963 + * This program is free software; you can redistribute it and/or modify it
1964 + * under the terms of the GNU General Public License as published
1965 + * by the Free Software Foundation; version 2 of the License.
1967 + * This program is distributed in the hope that it will be useful, but
1968 + * WITHOUT ANY WARRANTY; without even the implied warranty of
1969 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1970 + * General Public License for more details.
1972 + * You should have received a copy of the GNU General Public License along
1973 + * with this program; if not, write to the Free Software Foundation, Inc.,
1974 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1975 + */
1977 +#include <linux/module.h>
1978 +#include <linux/kernel.h>
1979 +#include <linux/init.h>
1980 +#include <linux/slab.h>
1981 +#include <linux/usb.h>
1982 +#include <linux/interrupt.h>
1983 +#include <linux/notifier.h>
1985 +#include <linux/etherdevice.h>
1986 +#include <linux/ethtool.h>
1987 +#include <linux/if_arp.h>
1988 +#include <linux/ieee80211.h>
1989 +#include <net/iw_handler.h>
1991 +#include "ps3_eurus.h"
1992 +#include "ps3_jupiter.h"
1994 +#define PS3_JUPITER_STA_CMD_BUFSIZE 2048
1996 +#define PS3_JUPITER_STA_IFACE 0x4
1997 +#define PS3_JUPITER_STA_EP 0x6
1999 +#define PS3_JUPITER_STA_WEP_KEYS 4
2001 +#define PS3_JUPITER_STA_WPA_PSK_LENGTH 32
2003 +#define PS3_JUPITER_STA_RX_URBS 4
2004 +#define PS3_JUPITER_STA_RX_BUFSIZE 0x620
2006 +#define PS3_JUPITER_STA_TX_URBS 16
2008 +#define PS3_JUPITER_STA_CHANNEL_DWELL 0x64
2010 +#define PS3_JUPITER_STA_SCAN_VALID_TIME_SEC 60
2012 +enum ps3_jupiter_sta_status {
2013 + PS3_JUPITER_STA_READY = 0,
2016 +enum ps3_jupiter_sta_scan_status {
2017 + PS3_JUPITER_STA_SCAN_INVALID = 0,
2018 + PS3_JUPITER_STA_SCAN_IN_PROGRESS,
2019 + PS3_JUPITER_STA_SCAN_OK
2022 +enum ps3_jupiter_sta_assoc_status {
2023 + PS3_JUPITER_STA_ASSOC_INVALID = 0,
2024 + PS3_JUPITER_STA_ASSOC_IN_PROGRESS,
2025 + PS3_JUPITER_STA_ASSOC_OK
2028 +enum ps3_jupiter_sta_config_bits {
2029 + PS3_JUPITER_STA_CONFIG_ESSID_SET = 0,
2030 + PS3_JUPITER_STA_CONFIG_BSSID_SET,
2031 + PS3_JUPITER_STA_CONFIG_CHANNEL_SET,
2032 + PS3_JUPITER_STA_CONFIG_WPA_PSK_SET
2035 +enum ps3_jupiter_sta_bss_type {
2036 + PS3_JUPITER_STA_BSS_TYPE_INFRA = 0,
2037 + PS3_JUPITER_STA_BSS_TYPE_ADHOC,
2040 +enum ps3_jupiter_sta_opmode {
2041 + PS3_JUPITER_STA_OPMODE_11B = 0,
2042 + PS3_JUPITER_STA_OPMODE_11G,
2043 + PS3_JUPITER_STA_OPMODE_11BG
2046 +enum ps3_jupiter_sta_auth_mode {
2047 + PS3_JUPITER_STA_AUTH_OPEN = 0,
2048 + PS3_JUPITER_STA_AUTH_SHARED_KEY
2051 +enum ps3_jupiter_sta_wpa_mode {
2052 + PS3_JUPITER_STA_WPA_MODE_NONE = 0,
2053 + PS3_JUPITER_STA_WPA_MODE_WPA,
2054 + PS3_JUPITER_STA_WPA_MODE_WPA2
2057 +enum ps3_jupiter_sta_cipher_mode {
2058 + PS3_JUPITER_STA_CIPHER_NONE = 0,
2059 + PS3_JUPITER_STA_CIPHER_WEP,
2060 + PS3_JUPITER_STA_CIPHER_TKIP,
2061 + PS3_JUPITER_STA_CIPHER_AES
2064 +struct ps3_jupiter_sta_scan_result {
2065 + struct list_head list;
2067 + u8 bssid[6];
2068 + u16 capability;
2069 + u8 rssi;
2071 + u8 *essid_ie;
2072 + u8 *ds_param_set_ie;
2073 + u8 *supp_rates_ie;
2074 + u8 *ext_supp_rates_ie;
2075 + u8 *rsn_ie;
2076 + u8 *wpa_ie;
2078 + unsigned int ie_length;
2079 + u8 ie[0];
2082 +struct ps3_jupiter_sta_dev {
2083 + struct net_device *netdev;
2085 + struct usb_device *udev;
2087 + spinlock_t lock;
2089 + unsigned long status;
2091 + struct iw_public_data wireless_data;
2092 + struct iw_statistics wireless_stat;
2094 + struct notifier_block event_listener;
2096 + u16 channel_info;
2098 + struct mutex scan_lock;
2099 + struct list_head scan_result_list;
2100 + enum ps3_jupiter_sta_scan_status scan_status;
2101 + struct completion scan_done_comp;
2102 + unsigned long scan_expires;
2104 + unsigned long config_status;
2106 + enum ps3_jupiter_sta_bss_type bss_type;
2108 + enum ps3_jupiter_sta_opmode opmode;
2110 + enum ps3_jupiter_sta_auth_mode auth_mode;
2112 + enum ps3_jupiter_sta_wpa_mode wpa_mode;
2113 + enum ps3_jupiter_sta_cipher_mode group_cipher_mode;
2114 + enum ps3_jupiter_sta_cipher_mode pairwise_cipher_mode;
2116 + u8 essid[IW_ESSID_MAX_SIZE];
2117 + unsigned int essid_length;
2119 + u8 desired_bssid[ETH_ALEN];
2120 + u8 bssid[ETH_ALEN];
2122 + u8 channel;
2124 + unsigned long key_config_status;
2125 + u8 key[PS3_JUPITER_STA_WEP_KEYS][IW_ENCODING_TOKEN_MAX];
2126 + unsigned int key_length[PS3_JUPITER_STA_WEP_KEYS];
2127 + unsigned int curr_key_index;
2129 + u8 psk[PS3_JUPITER_STA_WPA_PSK_LENGTH];
2131 + struct mutex assoc_lock;
2132 + struct workqueue_struct *assoc_queue;
2133 + struct delayed_work assoc_work;
2134 + enum ps3_jupiter_sta_assoc_status assoc_status;
2135 + struct completion assoc_done_comp;
2137 + struct usb_anchor rx_urb_anchor;
2138 + struct sk_buff_head rx_skb_queue;
2139 + struct tasklet_struct rx_tasklet;
2141 + struct usb_anchor tx_urb_anchor;
2142 + atomic_t tx_submitted_urbs;
2145 +static int max_txurbs = PS3_JUPITER_STA_TX_URBS;
2146 +module_param(max_txurbs, int, S_IRUGO);
2147 +MODULE_PARM_DESC(max_txurbs, "Maximum number of Tx URBs");
2149 +static const int ps3_jupiter_sta_channel_freq[] = {
2150 + 2412,
2151 + 2417,
2152 + 2422,
2153 + 2427,
2154 + 2432,
2155 + 2437,
2156 + 2442,
2157 + 2447,
2158 + 2452,
2159 + 2457,
2160 + 2462,
2161 + 2467,
2162 + 2472,
2163 + 2484
2166 +static const int ps3_jupiter_sta_bitrate[] = {
2167 + 1000000,
2168 + 2000000,
2169 + 5500000,
2170 + 11000000,
2171 + 6000000,
2172 + 9000000,
2173 + 12000000,
2174 + 18000000,
2175 + 24000000,
2176 + 36000000,
2177 + 48000000,
2178 + 54000000
2181 +static void ps3_jupiter_sta_free_scan_results(struct ps3_jupiter_sta_dev *jstad);
2183 +static int ps3_jupiter_sta_start_scan(struct ps3_jupiter_sta_dev *jstad,
2184 + u8 *essid, size_t essid_length, u16 channels, u8 active, u16 channel_dwell);
2186 +static char *ps3_jupiter_sta_translate_scan_result(struct ps3_jupiter_sta_dev *jstad,
2187 + struct ps3_jupiter_sta_scan_result *scan_result,
2188 + struct iw_request_info *info, char *stream, char *ends);
2190 +static void ps3_jupiter_sta_start_assoc(struct ps3_jupiter_sta_dev *jstad);
2192 +static int ps3_jupiter_sta_disassoc(struct ps3_jupiter_sta_dev *jstad);
2194 +static void ps3_jupiter_sta_reset_state(struct ps3_jupiter_sta_dev *jstad);
2196 +static int ps3_jupiter_sta_prepare_rx_urb(struct ps3_jupiter_sta_dev *jstad,
2197 + struct urb *urb);
2199 +static void ps3_jupiter_sta_purge_rx_skb_queue(struct ps3_jupiter_sta_dev *jstad);
2201 +static void ps3_jupiter_sta_free_tx_urbs(struct ps3_jupiter_sta_dev *jstad);
2203 +static int ps3_jupiter_sta_tx_skb(struct ps3_jupiter_sta_dev *jstad, struct sk_buff *skb);
2206 + * ps3_jupiter_sta_freq_to_channel
2207 + */
2208 +static u8 ps3_jupiter_sta_freq_to_channel(u32 freq)
2210 + int i;
2212 + for (i = 0; i < ARRAY_SIZE(ps3_jupiter_sta_channel_freq); i++) {
2213 + if (ps3_jupiter_sta_channel_freq[i] == freq)
2214 + return (i + 1);
2217 + return 0;
2221 + * ps3_jupiter_sta_send_iw_ap_event
2222 + */
2223 +static void ps3_jupiter_sta_send_iw_ap_event(struct ps3_jupiter_sta_dev *jstad, u8 *bssid)
2225 + union iwreq_data iwrd;
2227 + memset(&iwrd, 0, sizeof(iwrd));
2229 + if (bssid)
2230 + memcpy(iwrd.ap_addr.sa_data, bssid, ETH_ALEN);
2232 + iwrd.ap_addr.sa_family = ARPHRD_ETHER;
2234 + wireless_send_event(jstad->netdev, SIOCGIWAP, &iwrd, NULL);
2238 + * ps3_jupiter_sta_get_name
2239 + */
2240 +static int ps3_jupiter_sta_get_name(struct net_device *netdev,
2241 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2243 + strcpy(wrqu->name, "IEEE 802.11bg");
2245 + return 0;
2249 + * ps3_jupiter_sta_get_nick
2250 + */
2251 +static int ps3_jupiter_sta_get_nick(struct net_device *netdev,
2252 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2254 + strcpy(extra, "ps3_jupiter_sta");
2255 + wrqu->data.length = strlen(extra);
2256 + wrqu->data.flags = 1;
2258 + return 0;
2262 + * ps3_jupiter_sta_get_range
2263 + */
2264 +static int ps3_jupiter_sta_get_range(struct net_device *netdev,
2265 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2267 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2268 + struct iw_point *point = &wrqu->data;
2269 + struct iw_range *range = (struct iw_range *) extra;
2270 + unsigned int i, chan;
2272 + point->length = sizeof(struct iw_range);
2273 + memset(range, 0, sizeof(struct iw_range));
2275 + range->we_version_compiled = WIRELESS_EXT;
2276 + range->we_version_source = 22;
2278 + for (i = 0, chan = 0;
2279 + (i < ARRAY_SIZE(ps3_jupiter_sta_channel_freq)) && (chan < IW_MAX_FREQUENCIES); i++) {
2280 + if (jstad->channel_info & (1 << i)) {
2281 + range->freq[chan].i = i + 1;
2282 + range->freq[chan].m = ps3_jupiter_sta_channel_freq[i];
2283 + range->freq[chan].e = 6;
2284 + chan++;
2288 + range->num_frequency = chan;
2289 + range->old_num_frequency = chan;
2290 + range->num_channels = chan;
2291 + range->old_num_channels = chan;
2293 + for (i = 0; i < ARRAY_SIZE(ps3_jupiter_sta_bitrate); i++)
2294 + range->bitrate[i] = ps3_jupiter_sta_bitrate[i];
2295 + range->num_bitrates = i;
2297 + range->max_qual.qual = 100;
2298 + range->max_qual.level = 100;
2299 + range->avg_qual.qual = 50;
2300 + range->avg_qual.level = 50;
2301 + range->sensitivity = 0;
2303 + IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
2304 + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
2305 + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
2307 + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
2308 + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP |
2309 + IW_ENC_CAPA_4WAY_HANDSHAKE;
2311 + range->encoding_size[0] = 5;
2312 + range->encoding_size[1] = 13;
2313 + range->encoding_size[2] = 32;
2314 + range->num_encoding_sizes = 3;
2315 + range->max_encoding_tokens = 4;
2317 + range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_CHANNEL;
2319 + return 0;
2323 + * ps3_jupiter_sta_set_mode
2324 + */
2325 +static int ps3_jupiter_sta_set_mode(struct net_device *netdev,
2326 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2328 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2330 + switch (wrqu->mode) {
2331 + case IW_MODE_INFRA:
2332 + jstad->bss_type = PS3_JUPITER_STA_BSS_TYPE_INFRA;
2333 + break;
2334 + case IW_MODE_ADHOC:
2335 + jstad->bss_type = PS3_JUPITER_STA_BSS_TYPE_ADHOC;
2336 + break;
2337 + default:
2338 + return -EOPNOTSUPP;
2341 + return 0;
2345 + * ps3_jupiter_sta_get_mode
2346 + */
2347 +static int ps3_jupiter_sta_get_mode(struct net_device *netdev,
2348 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2350 + wrqu->mode = IW_MODE_INFRA;
2352 + return 0;
2356 + * ps3_jupiter_sta_set_freq
2357 + */
2358 +static int ps3_jupiter_sta_set_freq(struct net_device *netdev,
2359 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2361 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2362 + struct iw_freq *freq = &wrqu->freq;
2363 + __u8 channel;
2364 + unsigned long irq_flags;
2365 + int err;
2367 + spin_lock_irqsave(&jstad->lock, irq_flags);
2369 + if (!freq->m) {
2370 + jstad->channel = 0;
2371 + clear_bit(PS3_JUPITER_STA_CONFIG_CHANNEL_SET, &jstad->config_status);
2372 + } else {
2373 + if (freq->e == 1)
2374 + channel = ps3_jupiter_sta_freq_to_channel(freq->m / 100000);
2375 + else
2376 + channel = freq->m;
2378 + if (!channel || !(jstad->channel_info & (1 << (channel - 1)))) {
2379 + err = -EINVAL;
2380 + goto done;
2383 + jstad->channel = channel;
2384 + set_bit(PS3_JUPITER_STA_CONFIG_CHANNEL_SET, &jstad->config_status);
2387 + err = 0;
2389 +done:
2391 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2393 + return err;
2397 + * ps3_jupiter_sta_get_freq
2398 + */
2399 +static int ps3_jupiter_sta_get_freq(struct net_device *netdev,
2400 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2402 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2403 + struct iw_freq *freq = &wrqu->freq;
2404 + unsigned long irq_flags;
2406 + pr_debug("%s: called\n", __func__);
2408 + spin_lock_irqsave(&jstad->lock, irq_flags);
2410 + if (test_bit(PS3_JUPITER_STA_CONFIG_CHANNEL_SET, &jstad->config_status)) {
2411 + freq->e = 1;
2412 + freq->m = ps3_jupiter_sta_channel_freq[jstad->channel - 1] * 100000;
2413 + } else {
2414 + freq->e = 0;
2415 + freq->m = 0;
2418 + pr_debug("%s: done\n", __func__);
2420 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2422 + return 0;
2426 + * ps3_jupiter_sta_set_scan
2427 + */
2428 +static int ps3_jupiter_sta_set_scan(struct net_device *netdev,
2429 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2431 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2432 + struct iw_scan_req *scan_req;
2433 + u8 *essid = NULL;
2434 + size_t essid_length = 0;
2435 + u16 channels = jstad->channel_info;
2436 + __u8 channel;
2437 + u8 active = 1;
2438 + u16 channel_dwell = PS3_JUPITER_STA_CHANNEL_DWELL;
2439 + int i;
2440 + int err;
2442 + pr_debug("%s: called\n", __func__);
2444 + if (wrqu->data.length == sizeof(*scan_req)) {
2445 + scan_req = (struct iw_scan_req *) extra;
2447 + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
2448 + essid = scan_req->essid;
2449 + essid_length = scan_req->essid_len;
2451 + pr_debug("%s: essid %s\n", __func__, essid);
2454 + if (scan_req->num_channels > 0)
2455 + channels = 0;
2457 + for (i = 0; i < scan_req->num_channels; i++) {
2458 + if (scan_req->channel_list[i].e == 1)
2459 + channel = ps3_jupiter_sta_freq_to_channel(scan_req->channel_list[i].m / 100000);
2460 + else
2461 + channel = scan_req->channel_list[i].m;
2463 + channels |= 1 << (channel - 1);
2466 + pr_debug("%s: channels 0x%04x\n", __func__, channels);
2468 + active = (scan_req->scan_type == IW_SCAN_TYPE_ACTIVE);
2471 + err = ps3_jupiter_sta_start_scan(jstad, essid, essid_length, channels,
2472 + active, channel_dwell);
2474 + pr_debug("%s: done\n", __func__);
2476 + return err;
2480 + * ps3_jupiter_sta_get_scan
2481 + */
2482 +static int ps3_jupiter_sta_get_scan(struct net_device *netdev,
2483 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2485 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2486 + struct ps3_jupiter_sta_scan_result *scan_result;
2487 + char *stream = extra;
2488 + char *ends = stream + wrqu->data.length;
2489 + int err;
2491 + if (mutex_lock_interruptible(&jstad->scan_lock))
2492 + return -EAGAIN;
2494 + if (jstad->scan_status == PS3_JUPITER_STA_SCAN_IN_PROGRESS) {
2495 + err = -EAGAIN;
2496 + goto done;
2497 + } else if (jstad->scan_status == PS3_JUPITER_STA_SCAN_INVALID) {
2498 + err = -ENODEV;
2499 + goto done;
2502 + /* translate scan results */
2504 + list_for_each_entry(scan_result, &jstad->scan_result_list, list) {
2505 + stream = ps3_jupiter_sta_translate_scan_result(jstad, scan_result,
2506 + info, stream, ends);
2508 + if ((ends - stream) <= IW_EV_ADDR_LEN) {
2509 + err = -E2BIG;
2510 + goto done;
2514 + wrqu->data.length = stream - extra;
2515 + wrqu->data.flags = 0;
2517 + err = 0;
2519 +done:
2521 + mutex_unlock(&jstad->scan_lock);
2523 + return err;
2527 + * ps3_jupiter_sta_set_auth
2528 + */
2529 +static int ps3_jupiter_sta_set_auth(struct net_device *netdev,
2530 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2532 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2533 + struct iw_param *param = &wrqu->param;
2534 + unsigned long irq_flags;
2535 + int err = 0;
2537 + spin_lock_irqsave(&jstad->lock, irq_flags);
2539 + switch (param->flags & IW_AUTH_INDEX) {
2540 + case IW_AUTH_WPA_VERSION:
2541 + if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
2542 + jstad->wpa_mode = PS3_JUPITER_STA_WPA_MODE_NONE;
2543 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_WEP;
2544 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_WEP;
2545 + } else if (param->value & IW_AUTH_WPA_VERSION_WPA) {
2546 + jstad->wpa_mode = PS3_JUPITER_STA_WPA_MODE_WPA;
2547 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_TKIP;
2548 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_TKIP;
2549 + } else if (param->value & IW_AUTH_WPA_VERSION_WPA2) {
2550 + jstad->wpa_mode = PS3_JUPITER_STA_WPA_MODE_WPA2;
2551 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_AES;
2552 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_AES;
2554 + break;
2555 + case IW_AUTH_CIPHER_GROUP:
2556 + if (param->value & IW_AUTH_CIPHER_NONE)
2557 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
2558 + else if (param->value & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
2559 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_WEP;
2560 + else if (param->value & IW_AUTH_CIPHER_TKIP)
2561 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_TKIP;
2562 + else if (param->value & IW_AUTH_CIPHER_CCMP)
2563 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_AES;
2564 + break;
2565 + case IW_AUTH_CIPHER_PAIRWISE:
2566 + if (param->value & IW_AUTH_CIPHER_NONE)
2567 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
2568 + else if (param->value & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
2569 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_WEP;
2570 + else if (param->value & IW_AUTH_CIPHER_TKIP)
2571 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_TKIP;
2572 + else if (param->value & IW_AUTH_CIPHER_CCMP)
2573 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_AES;
2574 + break;
2575 + case IW_AUTH_80211_AUTH_ALG:
2576 + if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
2577 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_OPEN;
2578 + else if (param->value & IW_AUTH_ALG_SHARED_KEY)
2579 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_SHARED_KEY;
2580 + else
2581 + err = -EINVAL;
2582 + break;
2583 + case IW_AUTH_WPA_ENABLED:
2584 + if (param->value)
2585 + jstad->wpa_mode = PS3_JUPITER_STA_WPA_MODE_WPA;
2586 + else
2587 + jstad->wpa_mode = PS3_JUPITER_STA_WPA_MODE_NONE;
2588 + break;
2589 + case IW_AUTH_KEY_MGMT:
2590 + if (!(param->value & IW_AUTH_KEY_MGMT_PSK))
2591 + err = -EOPNOTSUPP;
2592 + break;
2593 + default:
2594 + err = -EOPNOTSUPP;
2597 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2599 + return err;
2603 + * ps3_jupiter_sta_get_auth
2604 + */
2605 +static int ps3_jupiter_sta_get_auth(struct net_device *netdev,
2606 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2608 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2609 + struct iw_param *param = &wrqu->param;
2610 + unsigned long irq_flags;
2611 + int err = 0;
2613 + spin_lock_irqsave(&jstad->lock, irq_flags);
2615 + switch (param->flags & IW_AUTH_INDEX) {
2616 + case IW_AUTH_WPA_VERSION:
2617 + switch (jstad->wpa_mode) {
2618 + case PS3_JUPITER_STA_WPA_MODE_WPA:
2619 + param->value |= IW_AUTH_WPA_VERSION_WPA;
2620 + break;
2621 + case PS3_JUPITER_STA_WPA_MODE_WPA2:
2622 + param->value |= IW_AUTH_WPA_VERSION_WPA2;
2623 + break;
2624 + default:
2625 + param->value |= IW_AUTH_WPA_VERSION_DISABLED;
2627 + break;
2628 + case IW_AUTH_80211_AUTH_ALG:
2629 + switch (jstad->auth_mode) {
2630 + case PS3_JUPITER_STA_AUTH_OPEN:
2631 + param->value |= IW_AUTH_ALG_OPEN_SYSTEM;
2632 + break;
2633 + case PS3_JUPITER_STA_AUTH_SHARED_KEY:
2634 + param->value |= IW_AUTH_ALG_SHARED_KEY;
2635 + break;
2637 + break;
2638 + case IW_AUTH_WPA_ENABLED:
2639 + switch (jstad->wpa_mode) {
2640 + case PS3_JUPITER_STA_WPA_MODE_WPA:
2641 + case PS3_JUPITER_STA_WPA_MODE_WPA2:
2642 + param->value = 1;
2643 + break;
2644 + default:
2645 + param->value = 0;
2647 + break;
2648 + default:
2649 + err = -EOPNOTSUPP;
2652 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2654 + return err;
2658 + * ps3_jupiter_sta_set_essid
2659 + */
2660 +static int ps3_jupiter_sta_set_essid(struct net_device *netdev,
2661 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2663 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2664 + unsigned long irq_flags;
2666 + pr_debug("%s: called\n", __func__);
2668 + if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
2669 + return -EINVAL;
2671 + spin_lock_irqsave(&jstad->lock, irq_flags);
2673 + if (wrqu->essid.flags) {
2674 + memcpy(jstad->essid, extra, wrqu->essid.length);
2675 + jstad->essid_length = wrqu->essid.length;
2676 + set_bit(PS3_JUPITER_STA_CONFIG_ESSID_SET, &jstad->config_status);
2678 + pr_debug("%s: essid %s\n", __func__, extra);
2679 + } else {
2680 + clear_bit(PS3_JUPITER_STA_CONFIG_ESSID_SET, &jstad->config_status);
2682 + pr_debug("%s: essid any\n", __func__);
2685 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2687 + ps3_jupiter_sta_start_assoc(jstad);
2689 + pr_debug("%s: done\n", __func__);
2691 + return 0;
2695 + * ps3_jupiter_sta_get_essid
2696 + */
2697 +static int ps3_jupiter_sta_get_essid(struct net_device *netdev,
2698 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2700 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2701 + unsigned long irq_flags;
2703 + spin_lock_irqsave(&jstad->lock, irq_flags);
2705 + if (test_bit(PS3_JUPITER_STA_CONFIG_ESSID_SET, &jstad->config_status)) {
2706 + memcpy(extra, jstad->essid, jstad->essid_length);
2707 + wrqu->essid.length = jstad->essid_length;
2708 + wrqu->essid.flags = 1;
2709 + } else {
2710 + wrqu->essid.flags = 0;
2713 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2715 + return 0;
2719 + * ps3_jupiter_sta_set_ap
2720 + */
2721 +static int ps3_jupiter_sta_set_ap(struct net_device *netdev,
2722 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2724 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2725 + unsigned long irq_flags;
2727 + if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
2728 + return -EINVAL;
2730 + spin_lock_irqsave(&jstad->lock, irq_flags);
2732 + if (is_valid_ether_addr(wrqu->ap_addr.sa_data)) {
2733 + memcpy(jstad->desired_bssid, wrqu->ap_addr.sa_data, ETH_ALEN);
2734 + set_bit(PS3_JUPITER_STA_CONFIG_BSSID_SET, &jstad->config_status);
2735 + } else {
2736 + memset(jstad->desired_bssid, 0, ETH_ALEN);
2739 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2741 + return 0;
2745 + * ps3_jupiter_sta_get_ap
2746 + */
2747 +static int ps3_jupiter_sta_get_ap(struct net_device *netdev,
2748 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2750 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2751 + unsigned long irq_flags;
2753 + spin_lock_irqsave(&jstad->lock, irq_flags);
2755 + wrqu->ap_addr.sa_family = ARPHRD_ETHER;
2756 + memcpy(wrqu->ap_addr.sa_data, jstad->desired_bssid, ETH_ALEN);
2758 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2760 + return 0;
2764 + * ps3_jupiter_sta_set_encode
2765 + */
2766 +static int ps3_jupiter_sta_set_encode(struct net_device *netdev,
2767 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2769 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2770 + struct iw_point *enc = &wrqu->encoding;
2771 + __u16 flags = enc->flags & IW_ENCODE_FLAGS;
2772 + int key_index = enc->flags & IW_ENCODE_INDEX;
2773 + int key_index_provided;
2774 + unsigned long irq_flags;
2775 + int err = 0;
2777 + if (key_index > PS3_JUPITER_STA_WEP_KEYS)
2778 + return -EINVAL;
2780 + spin_lock_irqsave(&jstad->lock, irq_flags);
2782 + if (key_index) {
2783 + key_index--;
2784 + key_index_provided = 1;
2785 + } else {
2786 + key_index = jstad->curr_key_index;
2787 + key_index_provided = 0;
2790 + if (flags & IW_ENCODE_NOKEY) {
2791 + if (!(flags & ~IW_ENCODE_NOKEY) && key_index_provided) {
2792 + jstad->curr_key_index = key_index;
2793 + goto done;
2796 + if (flags & IW_ENCODE_DISABLED) {
2797 + if (key_index_provided) {
2798 + clear_bit(key_index, &jstad->key_config_status);
2799 + } else {
2800 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
2801 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
2802 + jstad->key_config_status = 0;
2806 + if (flags & IW_ENCODE_OPEN)
2807 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_OPEN;
2808 + else if (flags & IW_ENCODE_RESTRICTED)
2809 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_SHARED_KEY;
2810 + } else {
2811 + if (enc->length > IW_ENCODING_TOKEN_MAX) {
2812 + err = -EINVAL;
2813 + goto done;
2816 + memcpy(jstad->key[key_index], extra, enc->length);
2817 + jstad->key_length[key_index] = enc->length;
2818 + set_bit(key_index, &jstad->key_config_status);
2820 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_WEP;
2821 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_WEP;
2824 +done:
2826 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2828 + return err;
2832 + * ps3_jupiter_sta_get_encode
2833 + */
2834 +static int ps3_jupiter_sta_get_encode(struct net_device *netdev,
2835 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2837 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2838 + struct iw_point *enc = &wrqu->encoding;
2839 + int key_index = enc->flags & IW_ENCODE_INDEX;
2840 + int key_index_provided;
2841 + unsigned long irq_flags;
2842 + int err = 0;
2844 + if (key_index > PS3_JUPITER_STA_WEP_KEYS)
2845 + return -EINVAL;
2847 + spin_lock_irqsave(&jstad->lock, irq_flags);
2849 + if (key_index) {
2850 + key_index--;
2851 + key_index_provided = 1;
2852 + } else {
2853 + key_index = jstad->curr_key_index;
2854 + key_index_provided = 0;
2857 + if (jstad->group_cipher_mode == PS3_JUPITER_STA_CIPHER_WEP) {
2858 + switch (jstad->auth_mode) {
2859 + case PS3_JUPITER_STA_AUTH_OPEN:
2860 + enc->flags |= IW_ENCODE_OPEN;
2861 + break;
2862 + case PS3_JUPITER_STA_AUTH_SHARED_KEY:
2863 + enc->flags |= IW_ENCODE_RESTRICTED;
2864 + break;
2866 + } else {
2867 + enc->flags = IW_ENCODE_DISABLED;
2870 + if (test_bit(key_index, &jstad->key_config_status)) {
2871 + if (enc->length < jstad->key_length[key_index]) {
2872 + err = -EINVAL;
2873 + goto done;
2876 + memcpy(extra, jstad->key[key_index], jstad->key_length[key_index]);
2877 + enc->length = jstad->key_length[key_index];
2878 + } else {
2879 + enc->length = 0;
2880 + enc->flags |= IW_ENCODE_NOKEY;
2883 + enc->flags |= (key_index + 1);
2885 +done:
2887 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2889 + return err;
2893 + * ps3_jupiter_sta_set_encodeext
2894 + */
2895 +static int ps3_jupiter_sta_set_encodeext(struct net_device *netdev,
2896 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2898 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2899 + struct iw_point *enc = &wrqu->encoding;
2900 + struct iw_encode_ext *enc_ext = (struct iw_encode_ext *) extra;
2901 + __u16 flags = enc->flags & IW_ENCODE_FLAGS;
2902 + int key_index = enc->flags & IW_ENCODE_INDEX;
2903 + unsigned long irq_flags;
2904 + int err = 0;
2906 + if (key_index > PS3_JUPITER_STA_WEP_KEYS)
2907 + return -EINVAL;
2909 + spin_lock_irqsave(&jstad->lock, irq_flags);
2911 + if (key_index)
2912 + key_index--;
2913 + else
2914 + key_index = jstad->curr_key_index;
2916 + if (!enc->length && (enc_ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
2917 + jstad->curr_key_index = key_index;
2918 + } else if ((enc_ext->alg == IW_ENCODE_ALG_NONE) || (flags & IW_ENCODE_DISABLED)) {
2919 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_OPEN;
2920 + jstad->wpa_mode = PS3_JUPITER_STA_WPA_MODE_NONE;
2921 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
2922 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
2923 + } else if (enc_ext->alg == IW_ENCODE_ALG_WEP) {
2924 + if (flags & IW_ENCODE_OPEN)
2925 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_OPEN;
2926 + else if (flags & IW_ENCODE_RESTRICTED)
2927 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_SHARED_KEY;
2929 + if (enc_ext->key_len > IW_ENCODING_TOKEN_MAX) {
2930 + err = -EINVAL;
2931 + goto done;
2934 + memcpy(jstad->key[key_index], enc_ext->key, enc_ext->key_len);
2935 + jstad->key_length[key_index] = enc_ext->key_len;
2936 + set_bit(key_index, &jstad->key_config_status);
2937 + } else if (enc_ext->alg == IW_ENCODE_ALG_PMK) {
2938 + if (enc_ext->key_len != PS3_JUPITER_STA_WPA_PSK_LENGTH) {
2939 + err = -EINVAL;
2940 + goto done;
2943 + memcpy(jstad->psk, enc_ext->key, enc_ext->key_len);
2944 + set_bit(PS3_JUPITER_STA_CONFIG_WPA_PSK_SET, &jstad->config_status);
2947 +done:
2949 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
2951 + return err;
2955 + * ps3_jupiter_sta_get_encodeext
2956 + */
2957 +static int ps3_jupiter_sta_get_encodeext(struct net_device *netdev,
2958 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
2960 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
2961 + struct iw_point *enc = &wrqu->encoding;
2962 + struct iw_encode_ext *enc_ext = (struct iw_encode_ext *) extra;
2963 + int key_index = enc->flags & IW_ENCODE_INDEX;
2964 + unsigned long irq_flags;
2965 + int err = 0;
2967 + if ((enc->length - sizeof(struct iw_encode_ext)) < 0)
2968 + return -EINVAL;
2970 + if (key_index > PS3_JUPITER_STA_WEP_KEYS)
2971 + return -EINVAL;
2973 + spin_lock_irqsave(&jstad->lock, irq_flags);
2975 + if (key_index)
2976 + key_index--;
2977 + else
2978 + key_index = jstad->curr_key_index;
2980 + memset(enc_ext, 0, sizeof(*enc_ext));
2982 + switch (jstad->group_cipher_mode) {
2983 + case PS3_JUPITER_STA_CIPHER_WEP:
2984 + enc_ext->alg = IW_ENCODE_ALG_WEP;
2985 + enc->flags |= IW_ENCODE_ENABLED;
2986 + break;
2987 + case PS3_JUPITER_STA_CIPHER_TKIP:
2988 + enc_ext->alg = IW_ENCODE_ALG_TKIP;
2989 + enc->flags |= IW_ENCODE_ENABLED;
2990 + break;
2991 + case PS3_JUPITER_STA_CIPHER_AES:
2992 + enc_ext->alg = IW_ENCODE_ALG_CCMP;
2993 + enc->flags |= IW_ENCODE_ENABLED;
2994 + break;
2995 + default:
2996 + enc_ext->alg = IW_ENCODE_ALG_NONE;
2997 + enc->flags |= IW_ENCODE_NOKEY;
3000 + if (!(enc->flags & IW_ENCODE_NOKEY)) {
3001 + if ((enc->length - sizeof(struct iw_encode_ext)) < jstad->key_length[key_index]) {
3002 + err = -E2BIG;
3003 + goto done;
3006 + if (test_bit(key_index, &jstad->key_config_status))
3007 + memcpy(enc_ext->key, jstad->key[key_index], jstad->key_length[key_index]);
3010 +done:
3012 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
3014 + return err;
3018 + * ps3_jupiter_sta_set_genie
3019 + */
3020 +static int ps3_jupiter_sta_set_genie(struct net_device *netdev,
3021 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
3023 + /* XXX: implement */
3025 + return 0;
3029 + * ps3_jupiter_sta_get_genie
3030 + */
3031 +static int ps3_jupiter_sta_get_genie(struct net_device *netdev,
3032 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
3034 + /* XXX: implement */
3036 + return 0;
3040 + * ps3_jupiter_sta_set_mlme
3041 + */
3042 +static int ps3_jupiter_sta_set_mlme(struct net_device *netdev,
3043 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
3045 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
3046 + struct iw_mlme *mlme = (struct iw_mlme *) extra;
3048 + switch (mlme->cmd) {
3049 + case IW_MLME_DEAUTH:
3050 + break;
3051 + case IW_MLME_DISASSOC:
3052 + ps3_jupiter_sta_disassoc(jstad);
3053 + break;
3054 + default:
3055 + return -EOPNOTSUPP;
3058 + return 0;
3061 +#ifdef CONFIG_WEXT_PRIV
3063 + * ps3_jupiter_sta_set_opmode
3064 + */
3065 +static int ps3_jupiter_sta_set_opmode(struct net_device *netdev,
3066 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
3068 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
3069 + int opmode = *(int *) extra;
3070 + unsigned long irq_flags;
3071 + int err = 0;
3073 + spin_lock_irqsave(&jstad->lock, irq_flags);
3075 + switch (opmode) {
3076 + case PS3_JUPITER_STA_OPMODE_11B:
3077 + case PS3_JUPITER_STA_OPMODE_11G:
3078 + case PS3_JUPITER_STA_OPMODE_11BG:
3079 + jstad->opmode = opmode;
3080 + break;
3081 + default:
3082 + err = -EINVAL;
3085 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
3087 + return err;
3091 + * ps3_jupiter_sta_get_opmode
3092 + */
3093 +static int ps3_jupiter_sta_get_opmode(struct net_device *netdev,
3094 + struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
3096 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
3097 + unsigned long irq_flags;
3099 + spin_lock_irqsave(&jstad->lock, irq_flags);
3101 + memcpy(extra, &jstad->opmode, sizeof(jstad->opmode));
3102 + wrqu->data.length = sizeof(jstad->opmode);
3104 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
3106 + return 0;
3108 +#endif
3111 + * ps3_jupiter_sta_get_wireless_stats
3112 + */
3113 +static struct iw_statistics *ps3_jupiter_sta_get_wireless_stats(struct net_device *netdev)
3115 + /* XXX: implement */
3117 + return NULL;
3121 + * ps3_jupiter_sta_open
3122 + */
3123 +static int ps3_jupiter_sta_open(struct net_device *netdev)
3125 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
3127 + pr_debug("%s: called\n", __func__);
3129 + usb_unpoison_anchored_urbs(&jstad->tx_urb_anchor);
3131 + ps3_jupiter_sta_start_assoc(jstad);
3133 + netif_start_queue(netdev);
3135 + pr_debug("%s: done\n", __func__);
3137 + return 0;
3141 + * ps3_jupiter_sta_stop
3142 + */
3143 +static int ps3_jupiter_sta_stop(struct net_device *netdev)
3145 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
3147 + pr_debug("%s: called\n", __func__);
3149 + netif_stop_queue(netdev);
3151 + cancel_delayed_work(&jstad->assoc_work);
3153 + if (jstad->assoc_status == PS3_JUPITER_STA_ASSOC_OK)
3154 + ps3_jupiter_sta_disassoc(jstad);
3156 + tasklet_kill(&jstad->rx_tasklet);
3157 + ps3_jupiter_sta_purge_rx_skb_queue(jstad);
3159 + ps3_jupiter_sta_free_tx_urbs(jstad);
3161 + ps3_jupiter_sta_free_scan_results(jstad);
3163 + ps3_jupiter_sta_reset_state(jstad);
3165 + pr_debug("%s: done\n", __func__);
3167 + return 0;
3171 + * ps3_jupiter_sta_start_xmit
3172 + */
3173 +static int ps3_jupiter_sta_start_xmit(struct sk_buff *skb, struct net_device *netdev)
3175 + struct ps3_jupiter_sta_dev *jstad = netdev_priv(netdev);
3177 + return ps3_jupiter_sta_tx_skb(jstad, skb);
3181 + * ps3_jupiter_sta_set_rx_mode
3182 + */
3183 +static void ps3_jupiter_sta_set_rx_mode(struct net_device *netdev)
3185 + /* XXX: implement */
3189 + * ps3_jupiter_sta_change_mtu
3190 + */
3191 +static int ps3_jupiter_sta_change_mtu(struct net_device *netdev, int new_mtu)
3193 + /* XXX: implement */
3195 + return 0;
3199 + * ps3_jupiter_sta_tx_timeout
3200 + */
3201 +static void ps3_jupiter_sta_tx_timeout(struct net_device *netdev, unsigned int txqueue)
3203 + /* XXX: implement */
3207 + * ps3_jupiter_sta_get_drvinfo
3208 + */
3209 +static void ps3_jupiter_sta_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
3211 + /* XXX: implement */
3215 + * ps3_jupiter_sta_get_link
3216 + */
3217 +static u32 ps3_jupiter_sta_get_link(struct net_device *netdev)
3219 + /* XXX: implement */
3221 + return 0;
3224 +static const iw_handler ps3_jupiter_sta_iw_handler[] =
3226 + IW_HANDLER(SIOCGIWNAME, ps3_jupiter_sta_get_name),
3227 + IW_HANDLER(SIOCGIWNICKN, ps3_jupiter_sta_get_nick),
3228 + IW_HANDLER(SIOCGIWRANGE, ps3_jupiter_sta_get_range),
3229 + IW_HANDLER(SIOCSIWMODE, ps3_jupiter_sta_set_mode),
3230 + IW_HANDLER(SIOCGIWMODE, ps3_jupiter_sta_get_mode),
3231 + IW_HANDLER(SIOCSIWFREQ, ps3_jupiter_sta_set_freq),
3232 + IW_HANDLER(SIOCGIWFREQ, ps3_jupiter_sta_get_freq),
3233 + IW_HANDLER(SIOCSIWSCAN, ps3_jupiter_sta_set_scan),
3234 + IW_HANDLER(SIOCGIWSCAN, ps3_jupiter_sta_get_scan),
3235 + IW_HANDLER(SIOCSIWAUTH, ps3_jupiter_sta_set_auth),
3236 + IW_HANDLER(SIOCGIWAUTH, ps3_jupiter_sta_get_auth),
3237 + IW_HANDLER(SIOCSIWESSID, ps3_jupiter_sta_set_essid),
3238 + IW_HANDLER(SIOCGIWESSID, ps3_jupiter_sta_get_essid),
3239 + IW_HANDLER(SIOCSIWAP, ps3_jupiter_sta_set_ap),
3240 + IW_HANDLER(SIOCGIWAP, ps3_jupiter_sta_get_ap),
3241 + IW_HANDLER(SIOCSIWENCODE, ps3_jupiter_sta_set_encode),
3242 + IW_HANDLER(SIOCGIWENCODE, ps3_jupiter_sta_get_encode),
3243 + IW_HANDLER(SIOCSIWENCODEEXT, ps3_jupiter_sta_set_encodeext),
3244 + IW_HANDLER(SIOCGIWENCODEEXT, ps3_jupiter_sta_get_encodeext),
3245 + IW_HANDLER(SIOCSIWGENIE, ps3_jupiter_sta_set_genie),
3246 + IW_HANDLER(SIOCGIWGENIE, ps3_jupiter_sta_get_genie),
3247 + IW_HANDLER(SIOCSIWMLME, ps3_jupiter_sta_set_mlme),
3250 +#ifdef CONFIG_WEXT_PRIV
3251 +static const iw_handler ps3_jupiter_sta_iw_priv_handler[] = {
3252 + ps3_jupiter_sta_set_opmode,
3253 + ps3_jupiter_sta_get_opmode,
3256 +enum {
3257 + PS3_JUPITER_STA_IW_PRIV_SET_OPMODE = SIOCIWFIRSTPRIV,
3258 + PS3_JUPITER_STA_IW_PRIV_GET_OPMODE,
3261 +static struct iw_priv_args ps3_jupiter_sta_iw_priv_args[] = {
3263 + .cmd = PS3_JUPITER_STA_IW_PRIV_SET_OPMODE,
3264 + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3265 + .name = "set_opmode"
3266 + },
3268 + .cmd = PS3_JUPITER_STA_IW_PRIV_GET_OPMODE,
3269 + .get_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3270 + .name = "get_opmode"
3271 + },
3273 +#endif
3275 +static const struct iw_handler_def ps3_jupiter_sta_iw_handler_def = {
3276 + .standard = ps3_jupiter_sta_iw_handler,
3277 + .num_standard = ARRAY_SIZE(ps3_jupiter_sta_iw_handler),
3278 +#ifdef CONFIG_WEXT_PRIV
3279 + .private = ps3_jupiter_sta_iw_priv_handler,
3280 + .num_private = ARRAY_SIZE(ps3_jupiter_sta_iw_priv_handler),
3281 + .private_args = ps3_jupiter_sta_iw_priv_args,
3282 + .num_private_args = ARRAY_SIZE(ps3_jupiter_sta_iw_priv_args),
3283 +#endif
3284 + .get_wireless_stats = ps3_jupiter_sta_get_wireless_stats,
3287 +static const struct net_device_ops ps3_jupiter_sta_net_device_ops = {
3288 + .ndo_open = ps3_jupiter_sta_open,
3289 + .ndo_stop = ps3_jupiter_sta_stop,
3290 + .ndo_start_xmit = ps3_jupiter_sta_start_xmit,
3291 + .ndo_set_rx_mode = ps3_jupiter_sta_set_rx_mode,
3292 + .ndo_change_mtu = ps3_jupiter_sta_change_mtu,
3293 + .ndo_tx_timeout = ps3_jupiter_sta_tx_timeout,
3294 + .ndo_set_mac_address = eth_mac_addr,
3295 + .ndo_validate_addr = eth_validate_addr,
3298 +static const struct ethtool_ops ps3_jupiter_sta_ethtool_ops = {
3299 + .get_drvinfo = ps3_jupiter_sta_get_drvinfo,
3300 + .get_link = ps3_jupiter_sta_get_link,
3304 + * ps3_jupiter_sta_rx_urb_complete
3305 + */
3306 +static void ps3_jupiter_sta_rx_urb_complete(struct urb *urb)
3308 + struct ps3_jupiter_sta_dev *jstad = usb_get_intfdata(usb_ifnum_to_if(urb->dev, PS3_JUPITER_STA_IFACE));
3309 + struct usb_device *udev = jstad->udev;
3310 + struct net_device *netdev = jstad->netdev;
3311 + struct sk_buff *skb = urb->context;
3312 + int err;
3314 + dev_dbg(&udev->dev, "Rx URB completed (%d)\n", urb->status);
3316 + switch (urb->status) {
3317 + case 0:
3318 + /* success */
3320 + if (urb->actual_length == 0x10) {
3321 + dev_info(&udev->dev, "got empty Rx URB\n");
3322 + break;
3325 + skb_put(skb, urb->actual_length);
3327 + err = ps3_jupiter_sta_prepare_rx_urb(jstad, urb);
3328 + if (err) {
3329 + dev_err(&udev->dev, "could not prepare Rx URB (%d)\n", err);
3330 + break;
3333 + skb_queue_tail(&jstad->rx_skb_queue, skb);
3335 + tasklet_schedule(&jstad->rx_tasklet);
3336 + break;
3337 + case -ECONNRESET:
3338 + case -ENOENT:
3339 + case -ESHUTDOWN:
3340 + case -ENODEV:
3341 + goto free_skb;
3342 + break;
3343 + default:
3344 + netdev->stats.rx_errors++;
3345 + dev_err(&udev->dev, "Rx URB failed (%d)\n", urb->status);
3348 + /* resubmit */
3350 + skb = urb->context;
3351 + skb_reset_tail_pointer(skb);
3352 + skb_trim(skb, 0);
3354 + usb_anchor_urb(urb, &jstad->rx_urb_anchor);
3356 + err = usb_submit_urb(urb, GFP_ATOMIC);
3357 + if (err) {
3358 + netdev->stats.rx_errors++;
3359 + usb_unanchor_urb(urb);
3360 + dev_err(&udev->dev, "could not submit Rx URB (%d)\n", err);
3361 + goto free_skb;
3364 + return;
3366 +free_skb:
3368 + dev_kfree_skb_irq(skb);
3372 + * ps3_jupiter_sta_tx_urb_complete
3373 + */
3374 +static void ps3_jupiter_sta_tx_urb_complete(struct urb *urb)
3376 + struct ps3_jupiter_sta_dev *jstad = usb_get_intfdata(usb_ifnum_to_if(urb->dev, PS3_JUPITER_STA_IFACE));
3377 + struct usb_device *udev = jstad->udev;
3378 + struct net_device *netdev = jstad->netdev;
3379 + struct sk_buff *skb = urb->context;
3380 + unsigned long irq_flags;
3382 + dev_dbg(&udev->dev, "Tx URB completed (%d)\n", urb->status);
3384 + switch (urb->status) {
3385 + case 0:
3386 + /* success */
3388 + spin_lock_irqsave(&jstad->lock, irq_flags);
3390 + netdev->stats.tx_packets++;
3391 + netdev->stats.tx_bytes += skb->len;
3393 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
3395 + atomic_dec(&jstad->tx_submitted_urbs);
3396 + break;
3397 + case -ECONNRESET:
3398 + case -ENOENT:
3399 + case -ESHUTDOWN:
3400 + case -ENODEV:
3401 + break;
3402 + default:
3403 + netdev->stats.tx_errors++;
3404 + dev_err(&udev->dev, "Tx URB failed (%d)\n", urb->status);
3407 + dev_kfree_skb_irq(skb);
3411 + * ps3_jupiter_sta_tx_skb
3412 + */
3413 +static int ps3_jupiter_sta_tx_skb(struct ps3_jupiter_sta_dev *jstad, struct sk_buff *skb)
3415 + struct usb_device *udev = jstad->udev;
3416 + struct net_device *netdev = jstad->netdev;
3417 + struct urb *urb;
3418 + unsigned long irq_flags;
3419 + int err;
3421 + pr_debug("%s: called\n", __func__);
3423 + if (jstad->assoc_status != PS3_JUPITER_STA_ASSOC_OK) {
3424 + err = 0;
3425 + goto drop;
3428 + spin_lock_irqsave(&jstad->lock, irq_flags);
3430 + if (atomic_read(&jstad->tx_submitted_urbs) >= max_txurbs) {
3431 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
3432 + dev_err(&udev->dev, "no free Tx URBs\n");
3433 + err = -EBUSY;
3434 + goto drop;
3437 + atomic_inc(&jstad->tx_submitted_urbs);
3439 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
3441 + urb = usb_alloc_urb(0, GFP_ATOMIC);
3442 + if (!urb) {
3443 + atomic_dec(&jstad->tx_submitted_urbs);
3444 + dev_err(&udev->dev, "could not allocate Tx URB\n");
3445 + err = -ENOMEM;
3446 + goto drop;
3449 + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, PS3_JUPITER_STA_EP),
3450 + skb->data, skb->len, ps3_jupiter_sta_tx_urb_complete, skb);
3451 + urb->transfer_flags |= URB_ZERO_PACKET;
3453 + usb_anchor_urb(urb, &jstad->tx_urb_anchor);
3454 + usb_free_urb(urb);
3456 + err = usb_submit_urb(urb, GFP_ATOMIC);
3457 + if (err) {
3458 + atomic_dec(&jstad->tx_submitted_urbs);
3459 + usb_unanchor_urb(urb);
3460 + dev_err(&udev->dev, "could not submit Tx URB (%d)\n", err);
3461 + goto drop;
3464 + pr_debug("%s: done\n", __func__);
3466 + return 0;
3468 +drop:
3470 + spin_lock_irqsave(&jstad->lock, irq_flags);
3471 + netdev->stats.tx_dropped++;
3472 + spin_unlock_irqrestore(&jstad->lock, irq_flags);
3473 + dev_kfree_skb_any(skb);
3475 + return err;
3479 + * ps3_jupiter_sta_free_scan_results
3480 + */
3481 +static void ps3_jupiter_sta_free_scan_results(struct ps3_jupiter_sta_dev *jstad)
3483 + struct ps3_jupiter_sta_scan_result *scan_result, *tmp;
3485 + list_for_each_entry_safe(scan_result, tmp, &jstad->scan_result_list, list) {
3486 + list_del(&scan_result->list);
3487 + kfree(scan_result);
3492 + * ps3_jupiter_sta_start_scan
3493 + */
3494 +static int ps3_jupiter_sta_start_scan(struct ps3_jupiter_sta_dev *jstad,
3495 + u8 *essid, size_t essid_length, u16 channels, u8 active, u16 channel_dwell)
3497 + struct ps3_eurus_cmd_start_scan *eurus_cmd_start_scan;
3498 + struct usb_device *udev = jstad->udev;
3499 + unsigned char *buf = NULL;
3500 + unsigned int payload_length, status;
3501 + unsigned int i, chan;
3502 + u8 *chan_ie, *essid_ie;
3503 + int err;
3505 + pr_debug("%s: called\n", __func__);
3507 +#ifdef DEBUG
3508 + if (essid && essid_length)
3509 + pr_debug("%s: essid %s\n", __func__, essid);
3510 +#endif
3512 + if (mutex_lock_interruptible(&jstad->scan_lock))
3513 + return -ERESTARTSYS;
3515 + if (jstad->scan_status == PS3_JUPITER_STA_SCAN_IN_PROGRESS) {
3516 + err = 0;
3517 + goto done;
3520 + dev_dbg(&udev->dev, "starting new scan\n");
3522 + buf = kmalloc(PS3_JUPITER_STA_CMD_BUFSIZE, GFP_KERNEL);
3523 + if (!buf) {
3524 + err = -ENOMEM;
3525 + goto done;
3528 + eurus_cmd_start_scan = (struct ps3_eurus_cmd_start_scan *) buf;
3529 + memset(eurus_cmd_start_scan, 0, 0x100);
3530 + eurus_cmd_start_scan->unknown2 = active;
3531 + eurus_cmd_start_scan->channel_dwell = cpu_to_le16(channel_dwell);
3533 + chan_ie = eurus_cmd_start_scan->ie;
3534 + chan_ie[0] = WLAN_EID_DS_PARAMS; /* ie id */
3535 + chan_ie[1] = 0x0; /* ie length */
3537 + for (i = 0, chan = 0; i < ARRAY_SIZE(ps3_jupiter_sta_channel_freq); i++) {
3538 + if (channels & (1 << i)) {
3539 + chan_ie[2 + chan] = i + 1;
3540 + chan++;
3544 + chan_ie[1] = chan; /* ie length */
3545 + payload_length = chan_ie + 2 + chan_ie[1] - (u8 *) eurus_cmd_start_scan;
3547 + if (essid && essid_length) {
3548 + essid_ie = chan_ie + 2 + chan_ie[1];
3549 + essid_ie[0] = WLAN_EID_SSID; /* ie id */
3550 + essid_ie[1] = essid_length; /* ie length */
3551 + memcpy(essid_ie + 2, essid, essid_length);
3553 + payload_length += 2 + essid_ie[1];
3556 + init_completion(&jstad->scan_done_comp);
3558 + jstad->scan_status = PS3_JUPITER_STA_SCAN_IN_PROGRESS;
3560 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_START_SCAN,
3561 + eurus_cmd_start_scan, payload_length, &status, NULL, NULL);
3562 + if (err)
3563 + goto done;
3565 + if (status != PS3_EURUS_CMD_OK) {
3566 + err = -EIO;
3567 + goto done;
3570 + err = 0;
3572 + pr_debug("%s: done\n", __func__);
3574 +done:
3576 + if (err)
3577 + jstad->scan_status = PS3_JUPITER_STA_SCAN_INVALID;
3579 + if (buf)
3580 + kfree(buf);
3582 + mutex_unlock(&jstad->scan_lock);
3584 + return err;
3588 + * ps3_jupiter_sta_get_scan_results
3589 + */
3590 +static int ps3_jupiter_sta_get_scan_results(struct ps3_jupiter_sta_dev *jstad)
3592 + struct ps3_eurus_cmd_get_scan_results *eurus_cmd_get_scan_results;
3593 + struct ps3_eurus_scan_result *eurus_scan_result;
3594 + struct ps3_jupiter_sta_scan_result *scan_result;
3595 + unsigned char *buf;
3596 + unsigned int status, response_length;
3597 + size_t eurus_scan_result_length, ie_length;
3598 + unsigned int i;
3599 + u8 *ie;
3600 + int err;
3602 + pr_debug("%s: called\n", __func__);
3604 + buf = kmalloc(PS3_JUPITER_STA_CMD_BUFSIZE, GFP_KERNEL);
3605 + if (!buf)
3606 + return -ENOMEM;
3608 + eurus_cmd_get_scan_results = (struct ps3_eurus_cmd_get_scan_results *) buf;
3609 + memset(eurus_cmd_get_scan_results, 0, PS3_EURUS_SCAN_RESULTS_MAXSIZE);
3611 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_GET_SCAN_RESULTS,
3612 + eurus_cmd_get_scan_results, PS3_EURUS_SCAN_RESULTS_MAXSIZE, &status,
3613 + &response_length, eurus_cmd_get_scan_results);
3614 + if (err)
3615 + goto done;
3617 + if (status != PS3_EURUS_CMD_OK) {
3618 + err = -EIO;
3619 + goto done;
3622 + /* free old scan results */
3624 + ps3_jupiter_sta_free_scan_results(jstad);
3626 + pr_debug("%s: number of scan results %d\n", __func__, eurus_cmd_get_scan_results->count);
3628 + /* add each scan result to list */
3630 + for (i = 0, eurus_scan_result = eurus_cmd_get_scan_results->result;
3631 + i < eurus_cmd_get_scan_results->count; i++) {
3632 + eurus_scan_result_length = le16_to_cpu(eurus_scan_result->length) +
3633 + sizeof(eurus_scan_result->length);
3634 + ie_length = (u8 *) eurus_scan_result + eurus_scan_result_length - eurus_scan_result->ie;
3636 + scan_result = kzalloc(sizeof(*scan_result) + ie_length, GFP_KERNEL);
3637 + if (!scan_result)
3638 + goto next;
3640 + memcpy(scan_result->bssid, eurus_scan_result->bssid, sizeof(eurus_scan_result->bssid));
3641 + scan_result->capability = le16_to_cpu(eurus_scan_result->capability);
3642 + scan_result->rssi = eurus_scan_result->rssi;
3644 + memcpy(scan_result->ie, eurus_scan_result->ie, ie_length);
3645 + scan_result->ie_length = ie_length;
3647 + for (ie = scan_result->ie;
3648 + ie < (scan_result->ie + scan_result->ie_length);
3649 + ie += (2 + ie[1])) {
3650 + switch (ie[0]) {
3651 + case WLAN_EID_SSID:
3652 + scan_result->essid_ie = ie;
3653 + break;
3654 + case WLAN_EID_SUPP_RATES:
3655 + scan_result->supp_rates_ie = ie;
3656 + break;
3657 + case WLAN_EID_DS_PARAMS:
3658 + scan_result->ds_param_set_ie = ie;
3659 + break;
3660 + case WLAN_EID_RSN:
3661 + scan_result->rsn_ie = ie;
3662 + break;
3663 + case WLAN_EID_EXT_SUPP_RATES:
3664 + scan_result->ext_supp_rates_ie = ie;
3665 + break;
3666 + case WLAN_EID_VENDOR_SPECIFIC:
3668 + /* WPA */
3670 + static const u8 wpa_oui[] = { 0x00, 0x50, 0xf2 };
3672 + if (((sizeof(wpa_oui) + 1) <= ie[1]) &&
3673 + !memcmp(&ie[2], wpa_oui, sizeof(wpa_oui)) &&
3674 + (ie[2 + sizeof(wpa_oui)] == 0x1))
3675 + scan_result->wpa_ie = ie;
3677 + break;
3681 + list_add_tail(&scan_result->list, &jstad->scan_result_list);
3683 + next:
3685 + /* move to next scan result */
3687 + eurus_scan_result = (struct ps3_eurus_scan_result *) ((u8 *) eurus_scan_result +
3688 + eurus_scan_result_length);
3691 + err = 0;
3693 + pr_debug("%s: done\n", __func__);
3695 +done:
3697 + kfree(buf);
3699 + return err;
3703 + * ps3_jupiter_sta_translate_scan_result
3704 + */
3705 +static char *ps3_jupiter_sta_translate_scan_result(struct ps3_jupiter_sta_dev *jstad,
3706 + struct ps3_jupiter_sta_scan_result *scan_result,
3707 + struct iw_request_info *info, char *stream, char *ends)
3709 + struct iw_event iwe;
3710 + char *tmp;
3711 + unsigned int i;
3713 + memset(&iwe, 0, sizeof(iwe));
3714 + iwe.cmd = SIOCGIWAP;
3715 + iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
3716 + memcpy(iwe.u.ap_addr.sa_data, scan_result->bssid, ETH_ALEN);
3717 + stream = iwe_stream_add_event(info, stream, ends, &iwe, IW_EV_ADDR_LEN);
3719 + if (scan_result->essid_ie) {
3720 + memset(&iwe, 0, sizeof(iwe));
3721 + iwe.cmd = SIOCGIWESSID;
3722 + iwe.u.data.flags = 1;
3723 + iwe.u.data.length = scan_result->essid_ie[1];
3724 + stream = iwe_stream_add_point(info, stream, ends, &iwe, &scan_result->essid_ie[2]);
3727 + if (scan_result->ds_param_set_ie) {
3728 + memset(&iwe, 0, sizeof(iwe));
3729 + iwe.cmd = SIOCGIWFREQ;
3730 + iwe.u.freq.m = scan_result->ds_param_set_ie[2];
3731 + iwe.u.freq.e = 0;
3732 + iwe.u.freq.i = 0;
3733 + stream = iwe_stream_add_event(info, stream, ends, &iwe, IW_EV_FREQ_LEN);
3736 + tmp = stream + iwe_stream_lcp_len(info);
3738 + if (scan_result->supp_rates_ie) {
3739 + for (i = 0; i < scan_result->supp_rates_ie[1]; i++) {
3740 + memset(&iwe, 0, sizeof(iwe));
3741 + iwe.cmd = SIOCGIWRATE;
3742 + iwe.u.bitrate.fixed = 0;
3743 + iwe.u.bitrate.disabled = 0;
3744 + iwe.u.bitrate.value = (scan_result->supp_rates_ie[2 + i] & 0x7f) * 500000;
3745 + tmp = iwe_stream_add_value(info, stream, tmp, ends, &iwe, IW_EV_PARAM_LEN);
3749 + if (scan_result->ext_supp_rates_ie) {
3750 + for (i = 0; i < scan_result->ext_supp_rates_ie[1]; i++) {
3751 + memset(&iwe, 0, sizeof(iwe));
3752 + iwe.cmd = SIOCGIWRATE;
3753 + iwe.u.bitrate.fixed = 0;
3754 + iwe.u.bitrate.disabled = 0;
3755 + iwe.u.bitrate.value = (scan_result->ext_supp_rates_ie[2 + i] & 0x7f) * 500000;
3756 + tmp = iwe_stream_add_value(info, stream, tmp, ends, &iwe, IW_EV_PARAM_LEN);
3760 + stream = tmp;
3762 + iwe.cmd = SIOCGIWMODE;
3763 + if (scan_result->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
3764 + if (scan_result->capability & WLAN_CAPABILITY_ESS)
3765 + iwe.u.mode = IW_MODE_MASTER;
3766 + else
3767 + iwe.u.mode = IW_MODE_ADHOC;
3768 + stream = iwe_stream_add_event(info, stream, ends, &iwe, IW_EV_UINT_LEN);
3771 + memset(&iwe, 0, sizeof(iwe));
3772 + iwe.cmd = SIOCGIWENCODE;
3773 + if (scan_result->capability & WLAN_CAPABILITY_PRIVACY)
3774 + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
3775 + else
3776 + iwe.u.data.flags = IW_ENCODE_DISABLED;
3777 + iwe.u.data.length = 0;
3778 + stream = iwe_stream_add_point(info, stream, ends, &iwe, scan_result->bssid);
3780 + if (scan_result->rsn_ie) {
3781 + memset(&iwe, 0, sizeof(iwe));
3782 + iwe.cmd = IWEVGENIE;
3783 + iwe.u.data.length = 2 + scan_result->rsn_ie[1];
3784 + stream = iwe_stream_add_point(info, stream, ends, &iwe, scan_result->rsn_ie);
3787 + if (scan_result->wpa_ie) {
3788 + memset(&iwe, 0, sizeof(iwe));
3789 + iwe.cmd = IWEVGENIE;
3790 + iwe.u.data.length = 2 + scan_result->wpa_ie[1];
3791 + stream = iwe_stream_add_point(info, stream, ends, &iwe, scan_result->wpa_ie);
3794 + memset(&iwe, 0, sizeof(iwe));
3795 + iwe.cmd = IWEVQUAL;
3796 + iwe.u.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID;
3797 + iwe.u.qual.level = ps3_eurus_rssi2percentage(scan_result->rssi);
3798 + iwe.u.qual.qual = ps3_eurus_rssi2percentage(scan_result->rssi);
3799 + iwe.u.qual.noise = 0;
3800 + stream = iwe_stream_add_event(info, stream, ends, &iwe, IW_EV_QUAL_LEN);
3802 + return stream;
3806 + * ps3_jupiter_sta_find_best_scan_result
3807 + */
3808 +static struct ps3_jupiter_sta_scan_result *ps3_jupiter_sta_find_best_scan_result(struct ps3_jupiter_sta_dev *jstad)
3810 + struct ps3_jupiter_sta_scan_result *scan_result, *best_scan_result;
3811 + u8 *essid;
3812 + unsigned int essid_length;
3814 + best_scan_result = NULL;
3816 + /* traverse scan results */
3818 + list_for_each_entry(scan_result, &jstad->scan_result_list, list) {
3819 + if (scan_result->essid_ie) {
3820 + essid = &scan_result->essid_ie[2];
3821 + essid_length = scan_result->essid_ie[1];
3822 + } else {
3823 + essid = NULL;
3824 + essid_length = 0;
3827 + if ((essid_length != jstad->essid_length) ||
3828 + strncmp(essid, jstad->essid, essid_length))
3829 + continue;
3831 + if (test_bit(PS3_JUPITER_STA_CONFIG_BSSID_SET, &jstad->config_status)) {
3832 + if (!ether_addr_equal(jstad->desired_bssid, scan_result->bssid)) {
3833 + best_scan_result = scan_result;
3834 + break;
3835 + } else {
3836 + continue;
3840 + switch (jstad->wpa_mode) {
3841 + case PS3_JUPITER_STA_WPA_MODE_NONE:
3842 + if ((jstad->group_cipher_mode == PS3_JUPITER_STA_CIPHER_WEP) &&
3843 + !(scan_result->capability & WLAN_CAPABILITY_PRIVACY))
3844 + continue;
3845 + break;
3846 + case PS3_JUPITER_STA_WPA_MODE_WPA:
3847 + if (!scan_result->wpa_ie)
3848 + continue;
3849 + break;
3850 + case PS3_JUPITER_STA_WPA_MODE_WPA2:
3851 + if (!scan_result->rsn_ie)
3852 + continue;
3853 + break;
3856 + if (!best_scan_result || (best_scan_result->rssi > scan_result->rssi))
3857 + best_scan_result = scan_result;
3860 + return best_scan_result;
3864 + * ps3_jupiter_sta_assoc
3865 + */
3866 +static int ps3_jupiter_sta_assoc(struct ps3_jupiter_sta_dev *jstad,
3867 + struct ps3_jupiter_sta_scan_result *scan_result)
3869 + struct ps3_eurus_cmd_0x1ed *eurus_cmd_0x1ed;
3870 + struct ps3_eurus_cmd_0x1025 *eurus_cmd_0x1025;
3871 + struct ps3_eurus_cmd_common_config *eurus_cmd_common_config;
3872 + struct ps3_eurus_cmd_wep_config *eurus_cmd_wep_config;
3873 + struct ps3_eurus_cmd_wpa_config *eurus_cmd_wpa_config;
3874 + struct ps3_eurus_cmd_associate *eurus_cmd_associate;
3875 + unsigned char *buf = NULL;
3876 + unsigned int payload_length, status;
3877 + u8 *ie;
3878 + int err;
3880 + buf = kmalloc(PS3_JUPITER_STA_CMD_BUFSIZE, GFP_KERNEL);
3881 + if (!buf)
3882 + return -ENOMEM;
3884 + eurus_cmd_0x1ed = (struct ps3_eurus_cmd_0x1ed *) buf;
3885 + memset(eurus_cmd_0x1ed, 0, sizeof(*eurus_cmd_0x1ed));
3886 + eurus_cmd_0x1ed->unknown2 = 0x1;
3887 + eurus_cmd_0x1ed->unknown3 = 0x2;
3888 + eurus_cmd_0x1ed->unknown4 = 0xff;
3889 + eurus_cmd_0x1ed->unknown5 = 0x16; /*XXX: 0x4 if AP doesn't support rate 54Mbps */
3890 + eurus_cmd_0x1ed->unknown6 = 0x4;
3891 + eurus_cmd_0x1ed->unknown7 = 0xa;
3892 + eurus_cmd_0x1ed->unknown8 = 0x16; /*XXX: 0x4 if AP doesn't support rate 54Mbps */
3894 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_0x1ed,
3895 + eurus_cmd_0x1ed, sizeof(*eurus_cmd_0x1ed), &status, NULL, NULL);
3896 + if (err)
3897 + goto done;
3899 + if (status != PS3_EURUS_CMD_OK) {
3900 + err = -EIO;
3901 + goto done;
3904 + /* set preamble mode */
3906 + eurus_cmd_0x1025 = (struct ps3_eurus_cmd_0x1025 *) buf;
3907 + memset(eurus_cmd_0x1025, 0, sizeof(*eurus_cmd_0x1025));
3909 + if (scan_result->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
3910 + eurus_cmd_0x1025->preamble_mode = PS3_EURUS_PREAMBLE_SHORT;
3911 + else
3912 + eurus_cmd_0x1025->preamble_mode = PS3_EURUS_PREAMBLE_LONG;
3914 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_0x1025,
3915 + eurus_cmd_0x1025, sizeof(*eurus_cmd_0x1025), &status, NULL, NULL);
3916 + if (err)
3917 + goto done;
3919 + if (status != PS3_EURUS_CMD_OK) {
3920 + err = -EIO;
3921 + goto done;
3924 + /* set common configuration */
3926 + eurus_cmd_common_config = (struct ps3_eurus_cmd_common_config *) buf;
3927 + memset(eurus_cmd_common_config, 0, sizeof(*eurus_cmd_common_config));
3929 + switch (jstad->bss_type) {
3930 + case PS3_JUPITER_STA_BSS_TYPE_INFRA:
3931 + eurus_cmd_common_config->bss_type = PS3_EURUS_BSS_INFRA;
3932 + break;
3933 + case PS3_JUPITER_STA_BSS_TYPE_ADHOC:
3934 + eurus_cmd_common_config->bss_type = PS3_EURUS_BSS_ADHOC;
3935 + break;
3938 + switch (jstad->auth_mode) {
3939 + case PS3_JUPITER_STA_AUTH_OPEN:
3940 + eurus_cmd_common_config->auth_mode = PS3_EURUS_AUTH_OPEN;
3941 + break;
3942 + case PS3_JUPITER_STA_AUTH_SHARED_KEY:
3943 + eurus_cmd_common_config->auth_mode = PS3_EURUS_AUTH_SHARED_KEY;
3944 + break;
3947 + switch (jstad->opmode) {
3948 + case PS3_JUPITER_STA_OPMODE_11B:
3949 + eurus_cmd_common_config->opmode = PS3_EURUS_OPMODE_11B;
3950 + break;
3951 + case PS3_JUPITER_STA_OPMODE_11G:
3952 + eurus_cmd_common_config->opmode = PS3_EURUS_OPMODE_11G;
3953 + break;
3954 + case PS3_JUPITER_STA_OPMODE_11BG:
3955 + eurus_cmd_common_config->opmode = PS3_EURUS_OPMODE_11BG;
3956 + break;
3959 + memcpy(eurus_cmd_common_config->bssid, scan_result->bssid, sizeof(scan_result->bssid));
3961 + eurus_cmd_common_config->capability = cpu_to_le16(scan_result->capability & ~WLAN_CAPABILITY_QOS);
3963 + payload_length = sizeof(*eurus_cmd_common_config);
3965 + ie = eurus_cmd_common_config->ie;
3967 + ie[0] = WLAN_EID_SSID;
3968 + ie[1] = jstad->essid_length;
3969 + memcpy(&ie[2], jstad->essid, jstad->essid_length);
3971 + payload_length += (2 + ie[1]);
3972 + ie += (2 + ie[1]);
3974 + if (scan_result->ds_param_set_ie) {
3975 + memcpy(ie, scan_result->ds_param_set_ie, 2 + scan_result->ds_param_set_ie[1]);
3977 + payload_length += (2 + ie[1]);
3978 + ie += (2 + ie[1]);
3981 + if (scan_result->supp_rates_ie) {
3982 + memcpy(ie, scan_result->supp_rates_ie, 2 + scan_result->supp_rates_ie[1]);
3984 + payload_length += (2 + scan_result->supp_rates_ie[1]);
3985 + ie += (2 + scan_result->supp_rates_ie[1]);
3988 + if (scan_result->ext_supp_rates_ie) {
3989 + memcpy(ie, scan_result->ext_supp_rates_ie, 2 + scan_result->ext_supp_rates_ie[1]);
3991 + payload_length += (2 + scan_result->ext_supp_rates_ie[1]);
3992 + ie += (2 + scan_result->ext_supp_rates_ie[1]);
3995 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_SET_COMMON_CONFIG,
3996 + eurus_cmd_common_config, payload_length, &status, NULL, NULL);
3997 + if (err)
3998 + goto done;
4000 + if (status != PS3_EURUS_CMD_OK) {
4001 + err = -EIO;
4002 + goto done;
4005 + if (jstad->wpa_mode == PS3_JUPITER_STA_WPA_MODE_NONE) {
4006 + /* set WEP configuration */
4008 + /* XXX: implement */
4010 + eurus_cmd_wep_config = (struct ps3_eurus_cmd_wep_config *) buf;
4011 + memset(eurus_cmd_wep_config, 0, sizeof(*eurus_cmd_wep_config));
4013 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_SET_WEP_CONFIG,
4014 + eurus_cmd_wep_config, sizeof(*eurus_cmd_wep_config), &status, NULL, NULL);
4015 + if (err)
4016 + goto done;
4018 + if (status != PS3_EURUS_CMD_OK) {
4019 + err = -EIO;
4020 + goto done;
4022 + } else {
4023 + /* set WPA configuration */
4025 + eurus_cmd_wpa_config = (struct ps3_eurus_cmd_wpa_config *) buf;
4026 + memset(eurus_cmd_wpa_config, 0, sizeof(*eurus_cmd_wpa_config));
4028 + eurus_cmd_wpa_config->unknown = 0x1;
4030 + switch (jstad->wpa_mode) {
4031 + case PS3_JUPITER_STA_WPA_MODE_WPA:
4032 + eurus_cmd_wpa_config->security_mode = PS3_EURUS_WPA_SECURITY_WPA;
4033 + if (jstad->group_cipher_mode == PS3_JUPITER_STA_CIPHER_TKIP)
4034 + eurus_cmd_wpa_config->group_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA_TKIP;
4035 + else
4036 + eurus_cmd_wpa_config->group_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA_AES;
4037 + if (jstad->pairwise_cipher_mode == PS3_JUPITER_STA_CIPHER_TKIP)
4038 + eurus_cmd_wpa_config->pairwise_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA_TKIP;
4039 + else
4040 + eurus_cmd_wpa_config->pairwise_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA_AES;
4041 + eurus_cmd_wpa_config->akm_suite = PS3_EURUS_WPA_AKM_SUITE_WPA_PSK;
4042 + break;
4043 + case PS3_JUPITER_STA_WPA_MODE_WPA2:
4044 + eurus_cmd_wpa_config->security_mode = PS3_EURUS_WPA_SECURITY_WPA2;
4045 + if (jstad->group_cipher_mode == PS3_JUPITER_STA_CIPHER_TKIP)
4046 + eurus_cmd_wpa_config->group_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA2_TKIP;
4047 + else
4048 + eurus_cmd_wpa_config->group_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA2_AES;
4049 + if (jstad->pairwise_cipher_mode == PS3_JUPITER_STA_CIPHER_TKIP)
4050 + eurus_cmd_wpa_config->pairwise_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA2_TKIP;
4051 + else
4052 + eurus_cmd_wpa_config->pairwise_cipher_suite = PS3_EURUS_WPA_CIPHER_SUITE_WPA2_AES;
4053 + eurus_cmd_wpa_config->akm_suite = PS3_EURUS_WPA_AKM_SUITE_WPA2_PSK;
4054 + break;
4055 + default:
4056 + /* should never happen */
4057 + BUG();
4060 + eurus_cmd_wpa_config->psk_type = PS3_EURUS_WPA_PSK_BIN;
4061 + memcpy(eurus_cmd_wpa_config->psk, jstad->psk, sizeof(jstad->psk));
4063 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_SET_WPA_CONFIG,
4064 + eurus_cmd_wpa_config, sizeof(*eurus_cmd_wpa_config), &status, NULL, NULL);
4065 + if (err)
4066 + goto done;
4068 + if (status != PS3_EURUS_CMD_OK) {
4069 + err = -EIO;
4070 + goto done;
4074 + init_completion(&jstad->assoc_done_comp);
4076 + jstad->assoc_status = PS3_JUPITER_STA_ASSOC_IN_PROGRESS;
4078 + eurus_cmd_associate = (struct ps3_eurus_cmd_associate *) buf;
4079 + memset(eurus_cmd_associate, 0, sizeof(*eurus_cmd_associate));
4081 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_ASSOCIATE,
4082 + eurus_cmd_associate, sizeof(*eurus_cmd_associate), &status, NULL, NULL);
4083 + if (err)
4084 + goto done;
4086 + if (status != PS3_EURUS_CMD_OK) {
4087 + err = -EIO;
4088 + goto done;
4091 + err = wait_for_completion_timeout(&jstad->assoc_done_comp, 5 * HZ);
4092 + if (!err) {
4093 + /* timeout */
4094 + ps3_jupiter_sta_disassoc(jstad);
4095 + err = -EIO;
4096 + goto done;
4099 + jstad->assoc_status = PS3_JUPITER_STA_ASSOC_OK;
4101 + memcpy(jstad->bssid, scan_result->bssid, sizeof(scan_result->bssid));
4103 + err = 0;
4105 +done:
4107 + if (err)
4108 + jstad->assoc_status = PS3_JUPITER_STA_ASSOC_INVALID;
4110 + kfree(buf);
4112 + return err;
4116 + * ps3_jupiter_sta_assoc_worker
4117 + */
4118 +static void ps3_jupiter_sta_assoc_worker(struct work_struct *work)
4120 + struct ps3_jupiter_sta_dev *jstad = container_of(work, struct ps3_jupiter_sta_dev, assoc_work.work);
4121 + struct usb_device *udev = jstad->udev;
4122 + u8 *essid;
4123 + unsigned int essid_length;
4124 + int scan_lock = 0;
4125 + struct ps3_jupiter_sta_scan_result *best_scan_result;
4126 + int err;
4128 + mutex_lock(&jstad->assoc_lock);
4130 + if (jstad->assoc_status != PS3_JUPITER_STA_ASSOC_INVALID) {
4131 + mutex_unlock(&jstad->assoc_lock);
4132 + return;
4135 + dev_dbg(&udev->dev, "starting new association\n");
4137 + if ((jstad->scan_status != PS3_JUPITER_STA_SCAN_OK) ||
4138 + time_after_eq(jiffies, jstad->scan_expires)) {
4139 + /* start scan and wait for scan results */
4141 + if (test_bit(PS3_JUPITER_STA_CONFIG_ESSID_SET, &jstad->config_status)) {
4142 + essid = jstad->essid;
4143 + essid_length = jstad->essid_length;
4144 + } else {
4145 + essid = NULL;
4146 + essid_length = 0;
4149 + err = ps3_jupiter_sta_start_scan(jstad, essid, essid_length, jstad->channel_info,
4150 + 1, PS3_JUPITER_STA_CHANNEL_DWELL);
4151 + if (err)
4152 + goto done;
4154 + wait_for_completion(&jstad->scan_done_comp);
4157 + mutex_lock(&jstad->scan_lock);
4158 + scan_lock = 1;
4160 + if (jstad->scan_status != PS3_JUPITER_STA_SCAN_OK)
4161 + goto done;
4163 + best_scan_result = ps3_jupiter_sta_find_best_scan_result(jstad);
4164 + if (!best_scan_result) {
4165 + dev_dbg(&udev->dev, "no suitable scan result was found\n");
4166 + goto done;
4169 + err = ps3_jupiter_sta_assoc(jstad, best_scan_result);
4170 + if (err) {
4171 + dev_dbg(&udev->dev, "association failed (%d)\n", err);
4172 + goto done;
4175 +done:
4177 + if (scan_lock)
4178 + mutex_unlock(&jstad->scan_lock);
4180 + if (jstad->assoc_status == PS3_JUPITER_STA_ASSOC_OK)
4181 + ps3_jupiter_sta_send_iw_ap_event(jstad, jstad->bssid);
4182 + else
4183 + ps3_jupiter_sta_send_iw_ap_event(jstad, NULL);
4185 + mutex_unlock(&jstad->assoc_lock);
4189 + * ps3_jupiter_sta_start_assoc
4190 + */
4191 +static void ps3_jupiter_sta_start_assoc(struct ps3_jupiter_sta_dev *jstad)
4193 + pr_debug("%s: called\n", __func__);
4195 + if (!test_bit(PS3_JUPITER_STA_READY, &jstad->status))
4196 + return;
4198 + if (!test_bit(PS3_JUPITER_STA_CONFIG_ESSID_SET, &jstad->config_status))
4199 + return;
4201 + if ((jstad->wpa_mode == PS3_JUPITER_STA_WPA_MODE_NONE) &&
4202 + (jstad->group_cipher_mode == PS3_JUPITER_STA_CIPHER_WEP) &&
4203 + !jstad->key_config_status)
4204 + return;
4206 + if ((jstad->wpa_mode != PS3_JUPITER_STA_WPA_MODE_NONE) &&
4207 + !test_bit(PS3_JUPITER_STA_CONFIG_WPA_PSK_SET, &jstad->config_status))
4208 + return;
4210 + queue_delayed_work(jstad->assoc_queue, &jstad->assoc_work, 0);
4212 + pr_debug("%s: done\n", __func__);
4216 + * ps3_jupiter_sta_disassoc
4217 + */
4218 +static int ps3_jupiter_sta_disassoc(struct ps3_jupiter_sta_dev *jstad)
4220 + struct ps3_eurus_cmd_disassociate *eurus_cmd_disassociate;
4221 + unsigned char *buf = NULL;
4222 + unsigned int status;
4223 + int err;
4225 + buf = kmalloc(PS3_JUPITER_STA_CMD_BUFSIZE, GFP_KERNEL);
4226 + if (!buf)
4227 + return -ENOMEM;
4229 + eurus_cmd_disassociate = (struct ps3_eurus_cmd_disassociate *) buf;
4230 + memset(eurus_cmd_disassociate, 0, sizeof(*eurus_cmd_disassociate));
4232 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_DISASSOCIATE,
4233 + eurus_cmd_disassociate, sizeof(*eurus_cmd_disassociate), &status, NULL, NULL);
4234 + if (err)
4235 + goto done;
4237 + if (status != PS3_EURUS_CMD_OK) {
4238 + err = -EIO;
4239 + goto done;
4242 + err = 0;
4244 +done:
4246 + kfree(buf);
4248 + return err;
4252 + * ps3_jupiter_sta_event_scan_completed
4253 + */
4254 +static void ps3_jupiter_sta_event_scan_completed(struct ps3_jupiter_sta_dev *jstad)
4256 + union iwreq_data iwrd;
4257 + int err;
4259 + mutex_lock(&jstad->scan_lock);
4261 + err = ps3_jupiter_sta_get_scan_results(jstad);
4262 + if (err)
4263 + goto done;
4265 + jstad->scan_expires = jiffies + PS3_JUPITER_STA_SCAN_VALID_TIME_SEC * HZ;
4266 + jstad->scan_status = PS3_JUPITER_STA_SCAN_OK;
4268 + complete(&jstad->scan_done_comp);
4270 + memset(&iwrd, 0, sizeof(iwrd));
4271 + wireless_send_event(jstad->netdev, SIOCGIWSCAN, &iwrd, NULL);
4273 +done:
4275 + if (err)
4276 + jstad->scan_status = PS3_JUPITER_STA_SCAN_INVALID;
4278 + mutex_unlock(&jstad->scan_lock);
4282 + * ps3_jupiter_sta_event_connected
4283 + */
4284 +static void ps3_jupiter_sta_event_connected(struct ps3_jupiter_sta_dev *jstad, u32 event_id)
4286 + u32 expected_event_id = 0;
4288 + switch (jstad->wpa_mode) {
4289 + case PS3_JUPITER_STA_WPA_MODE_NONE:
4290 + expected_event_id = PS3_EURUS_EVENT_CONNECTED;
4291 + break;
4292 + case PS3_JUPITER_STA_WPA_MODE_WPA:
4293 + case PS3_JUPITER_STA_WPA_MODE_WPA2:
4294 + expected_event_id = PS3_EURUS_EVENT_WPA_CONNECTED;
4295 + break;
4296 + default:
4297 + return;
4300 + if (expected_event_id == event_id) {
4301 + complete(&jstad->assoc_done_comp);
4302 + netif_carrier_on(jstad->netdev);
4307 + * ps3_jupiter_sta_event_disconnected
4308 + */
4309 +static void ps3_jupiter_sta_event_disconnected(struct ps3_jupiter_sta_dev *jstad)
4311 + int assoc_lock = 0;
4313 + if (mutex_trylock(&jstad->assoc_lock))
4314 + assoc_lock = 1;
4316 + ps3_jupiter_sta_disassoc(jstad);
4318 + if (jstad->assoc_status == PS3_JUPITER_STA_ASSOC_OK)
4319 + ps3_jupiter_sta_send_iw_ap_event(jstad, NULL);
4321 + jstad->assoc_status = PS3_JUPITER_STA_ASSOC_INVALID;
4323 + netif_carrier_off(jstad->netdev);
4325 + if (assoc_lock)
4326 + mutex_unlock(&jstad->assoc_lock);
4330 + * ps3_jupiter_sta_event_handler
4331 + */
4332 +static int ps3_jupiter_sta_event_handler(struct notifier_block *n,
4333 + unsigned long val, void *v)
4335 + struct ps3_jupiter_sta_dev *jstad = container_of(n, struct ps3_jupiter_sta_dev, event_listener);
4336 + struct usb_device *udev = jstad->udev;
4337 + struct ps3_eurus_event *event = v;
4339 + dev_dbg(&udev->dev, "got event (0x%08x 0x%08x 0x%08x 0x%08x 0x%08x)\n",
4340 + event->hdr.type, event->hdr.id, event->hdr.timestamp,
4341 + event->hdr.payload_length, event->hdr.unknown);
4343 + switch (event->hdr.type) {
4344 + case PS3_EURUS_EVENT_TYPE_0x40:
4345 + switch (event->hdr.id) {
4346 + case PS3_EURUS_EVENT_DEAUTH:
4347 + ps3_jupiter_sta_event_disconnected(jstad);
4348 + break;
4350 + break;
4351 + case PS3_EURUS_EVENT_TYPE_0x80:
4352 + switch (event->hdr.id) {
4353 + case PS3_EURUS_EVENT_SCAN_COMPLETED:
4354 + ps3_jupiter_sta_event_scan_completed(jstad);
4355 + break;
4356 + case PS3_EURUS_EVENT_CONNECTED:
4357 + case PS3_EURUS_EVENT_WPA_CONNECTED:
4358 + ps3_jupiter_sta_event_connected(jstad, event->hdr.id);
4359 + break;
4360 + case PS3_EURUS_EVENT_BEACON_LOST:
4361 + ps3_jupiter_sta_event_disconnected(jstad);
4362 + break;
4364 + break;
4367 + return NOTIFY_OK;
4371 + * ps3_jupiter_sta_set_mac_addr
4372 + */
4373 +static int ps3_jupiter_sta_set_mac_addr(struct ps3_jupiter_sta_dev *jstad)
4375 + struct usb_device *udev = jstad->udev;
4376 + struct net_device *netdev = jstad->netdev;
4377 + struct ps3_eurus_cmd_get_mac_addr_list *eurus_cmd_get_mac_addr_list;
4378 + struct ps3_eurus_cmd_set_mac_addr *eurus_cmd_set_mac_addr;
4379 + struct ps3_eurus_cmd_0x115b *eurus_cmd_0x115b;
4380 + unsigned char *buf = NULL;
4381 + unsigned int status, response_length;
4382 + int err;
4384 + buf = kmalloc(PS3_JUPITER_STA_CMD_BUFSIZE, GFP_KERNEL);
4385 + if (!buf)
4386 + return -ENOMEM;
4388 + /* get MAC address list */
4390 + eurus_cmd_get_mac_addr_list = (struct ps3_eurus_cmd_get_mac_addr_list *) buf;
4391 + memset(eurus_cmd_get_mac_addr_list, 0, PS3_EURUS_MAC_ADDR_LIST_MAXSIZE);
4393 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_GET_MAC_ADDR_LIST,
4394 + eurus_cmd_get_mac_addr_list, PS3_EURUS_MAC_ADDR_LIST_MAXSIZE, &status,
4395 + &response_length, eurus_cmd_get_mac_addr_list);
4396 + if (err)
4397 + goto done;
4399 + if (status != PS3_EURUS_CMD_OK) {
4400 + err = -EIO;
4401 + goto done;
4404 + /* use first MAC address */
4406 + memcpy(netdev->dev_addr, eurus_cmd_get_mac_addr_list->mac_addr, ETH_ALEN);
4408 + dev_info(&udev->dev, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
4409 + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
4410 + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
4412 + /* set MAC address */
4414 + eurus_cmd_set_mac_addr = (struct ps3_eurus_cmd_set_mac_addr *) buf;
4415 + memset(eurus_cmd_set_mac_addr, 0, sizeof(*eurus_cmd_set_mac_addr));
4416 + memcpy(eurus_cmd_set_mac_addr->mac_addr, netdev->dev_addr, ETH_ALEN);
4418 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_SET_MAC_ADDR,
4419 + eurus_cmd_set_mac_addr, sizeof(*eurus_cmd_set_mac_addr), &status, NULL, NULL);
4420 + if (err)
4421 + goto done;
4423 + if (status != PS3_EURUS_CMD_OK) {
4424 + err = -EIO;
4425 + goto done;
4428 + eurus_cmd_0x115b = (struct ps3_eurus_cmd_0x115b *) buf;
4429 + memset(eurus_cmd_0x115b, 0, sizeof(*eurus_cmd_0x115b));
4430 + eurus_cmd_0x115b->unknown1 = cpu_to_le16(0x1);
4431 + eurus_cmd_0x115b->unknown2 = cpu_to_le16(0x0);
4432 + memcpy(eurus_cmd_0x115b->mac_addr, netdev->dev_addr, ETH_ALEN);
4434 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_0x115b,
4435 + eurus_cmd_0x115b, sizeof(*eurus_cmd_0x115b), &status, NULL, NULL);
4436 + if (err)
4437 + goto done;
4439 + if (status != PS3_EURUS_CMD_OK) {
4440 + err = -EIO;
4441 + goto done;
4444 + err = 0;
4446 +done:
4448 + kfree(buf);
4450 + return err;
4454 + * ps3_jupiter_sta_get_channel_info
4455 + */
4456 +static int ps3_jupiter_sta_get_channel_info(struct ps3_jupiter_sta_dev *jstad)
4458 + struct ps3_eurus_cmd_get_channel_info *eurus_cmd_get_channel_info;
4459 + unsigned char *buf = NULL;
4460 + unsigned int status, response_length;
4461 + int err;
4463 + buf = kmalloc(PS3_JUPITER_STA_CMD_BUFSIZE, GFP_KERNEL);
4464 + if (!buf)
4465 + return -ENOMEM;
4467 + eurus_cmd_get_channel_info = (struct ps3_eurus_cmd_get_channel_info *) buf;
4468 + memset(eurus_cmd_get_channel_info, 0, sizeof(*eurus_cmd_get_channel_info));
4470 + err = ps3_jupiter_exec_eurus_cmd(PS3_EURUS_CMD_GET_CHANNEL_INFO,
4471 + eurus_cmd_get_channel_info, sizeof(*eurus_cmd_get_channel_info), &status,
4472 + &response_length, eurus_cmd_get_channel_info);
4473 + if (err)
4474 + goto done;
4476 + if (status != PS3_EURUS_CMD_OK) {
4477 + err = -EIO;
4478 + goto done;
4481 + jstad->channel_info = eurus_cmd_get_channel_info->channel_info;
4483 + err = 0;
4485 +done:
4487 + kfree(buf);
4489 + return err;
4493 + * ps3_jupiter_sta_reset_state
4494 + */
4495 +static void ps3_jupiter_sta_reset_state(struct ps3_jupiter_sta_dev *jstad)
4497 + jstad->scan_status = PS3_JUPITER_STA_SCAN_INVALID;
4499 + jstad->config_status = 0;
4501 + jstad->opmode = PS3_JUPITER_STA_OPMODE_11G;
4503 + jstad->auth_mode = PS3_JUPITER_STA_AUTH_OPEN;
4505 + jstad->wpa_mode = PS3_JUPITER_STA_WPA_MODE_NONE;
4506 + jstad->group_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
4507 + jstad->pairwise_cipher_mode = PS3_JUPITER_STA_CIPHER_NONE;
4509 + memset(jstad->essid, 0, sizeof(jstad->essid));
4510 + jstad->essid_length = 0;
4512 + memset(jstad->desired_bssid, 0, sizeof(jstad->desired_bssid));
4514 + jstad->channel = 0;
4516 + jstad->key_config_status = 0;
4517 + jstad->curr_key_index = 0;
4519 + jstad->assoc_status = PS3_JUPITER_STA_ASSOC_INVALID;
4523 + * ps3_jupiter_sta_create_assoc_worker
4524 + */
4525 +static int ps3_jupiter_sta_create_assoc_worker(struct ps3_jupiter_sta_dev *jstad)
4527 + jstad->assoc_queue = create_singlethread_workqueue("ps3_jupiter_sta_assoc");
4528 + if (!jstad->assoc_queue)
4529 + return -ENOMEM;
4531 + INIT_DELAYED_WORK(&jstad->assoc_work, ps3_jupiter_sta_assoc_worker);
4533 + return 0;
4537 + * ps3_jupiter_sta_destroy_assoc_worker
4538 + */
4539 +static void ps3_jupiter_sta_destroy_assoc_worker(struct ps3_jupiter_sta_dev *jstad)
4541 + if (jstad->assoc_queue) {
4542 + cancel_delayed_work(&jstad->assoc_work);
4543 + flush_workqueue(jstad->assoc_queue);
4544 + destroy_workqueue(jstad->assoc_queue);
4545 + jstad->assoc_queue = NULL;
4550 + * ps3_jupiter_sta_prepare_rx_urb
4551 + */
4552 +static int ps3_jupiter_sta_prepare_rx_urb(struct ps3_jupiter_sta_dev *jstad,
4553 + struct urb *urb)
4555 + struct usb_device *udev = jstad->udev;
4556 + struct sk_buff *skb;
4558 + skb = dev_alloc_skb(PS3_JUPITER_STA_RX_BUFSIZE);
4559 + if (!skb)
4560 + return -ENOMEM;
4562 + usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, PS3_JUPITER_STA_EP),
4563 + skb->data, PS3_JUPITER_STA_RX_BUFSIZE, ps3_jupiter_sta_rx_urb_complete, skb);
4565 + return 0;
4569 + * ps3_jupiter_sta_alloc_rx_urbs
4570 + */
4571 +static int ps3_jupiter_sta_alloc_rx_urbs(struct ps3_jupiter_sta_dev *jstad)
4573 + struct usb_device *udev = jstad->udev;
4574 + struct urb *urb;
4575 + unsigned int i;
4576 + int err;
4578 + pr_debug("%s: called\n", __func__);
4580 + init_usb_anchor(&jstad->rx_urb_anchor);
4582 + for (i = 0; i < PS3_JUPITER_STA_RX_URBS; i++) {
4583 + urb = usb_alloc_urb(0, GFP_KERNEL);
4584 + if (!urb) {
4585 + dev_err(&udev->dev, "could not allocate Rx URB\n");
4586 + err = -ENOMEM;
4587 + goto done;
4590 + err = ps3_jupiter_sta_prepare_rx_urb(jstad, urb);
4591 + if (err) {
4592 + dev_err(&udev->dev, "could not prepare Rx URB (%d)\n", err);
4593 + usb_free_urb(urb);
4594 + goto done;
4597 + usb_anchor_urb(urb, &jstad->rx_urb_anchor);
4598 + usb_free_urb(urb);
4600 + err = usb_submit_urb(urb, GFP_KERNEL);
4601 + if (err) {
4602 + dev_err(&udev->dev, "could not submit Rx URB (%d)\n", err);
4603 + dev_kfree_skb_any(urb->context);
4604 + usb_unanchor_urb(urb);
4605 + goto done;
4609 + err = 0;
4611 + pr_debug("%s: done\n", __func__);
4613 +done:
4615 + if (err)
4616 + usb_kill_anchored_urbs(&jstad->rx_urb_anchor);
4618 + return err;
4622 + * ps3_jupiter_sta_free_rx_urbs
4623 + */
4624 +static void ps3_jupiter_sta_free_rx_urbs(struct ps3_jupiter_sta_dev *jstad)
4626 + usb_kill_anchored_urbs(&jstad->rx_urb_anchor);
4628 + usb_poison_anchored_urbs(&jstad->rx_urb_anchor);
4632 + * ps3_jupiter_sta_rx_tasklet
4633 + */
4634 +static void ps3_jupiter_sta_rx_tasklet(unsigned long data)
4636 + struct ps3_jupiter_sta_dev *jstad = (struct ps3_jupiter_sta_dev *) data;
4637 + struct net_device *netdev = jstad->netdev;
4638 + struct sk_buff *skb;
4640 + while ((skb = skb_dequeue(&jstad->rx_skb_queue))) {
4641 + skb->protocol = eth_type_trans(skb, netdev);
4643 + netdev->stats.rx_packets++;
4644 + netdev->stats.rx_bytes += skb->len;
4646 + netif_receive_skb(skb);
4651 + * ps3_jupiter_sta_purge_rx_skb_queue
4652 + */
4653 +static void ps3_jupiter_sta_purge_rx_skb_queue(struct ps3_jupiter_sta_dev *jstad)
4655 + struct sk_buff *skb;
4656 + unsigned long irq_flags;
4658 + spin_lock_irqsave(&jstad->rx_skb_queue.lock, irq_flags);
4660 + while ((skb = __skb_dequeue(&jstad->rx_skb_queue)))
4661 + dev_kfree_skb_any(skb);
4663 + spin_unlock_irqrestore(&jstad->rx_skb_queue.lock, irq_flags);
4667 + * ps3_jupiter_sta_free_tx_urbs
4668 + */
4669 +static void ps3_jupiter_sta_free_tx_urbs(struct ps3_jupiter_sta_dev *jstad)
4671 + usb_wait_anchor_empty_timeout(&jstad->tx_urb_anchor, msecs_to_jiffies(100));
4673 + usb_kill_anchored_urbs(&jstad->tx_urb_anchor);
4675 + usb_poison_anchored_urbs(&jstad->tx_urb_anchor);
4679 + * ps3_jupiter_sta_probe
4680 + */
4681 +static int ps3_jupiter_sta_probe(struct usb_interface *interface,
4682 + const struct usb_device_id *id)
4684 + struct usb_device *udev = interface_to_usbdev(interface);
4685 + struct ps3_jupiter_sta_dev *jstad;
4686 + struct net_device *netdev;
4687 + int err;
4689 + netdev = alloc_etherdev(sizeof(struct ps3_jupiter_sta_dev));
4690 + if (!netdev)
4691 + return -ENOMEM;
4693 + SET_NETDEV_DEV(netdev, &udev->dev);
4695 + strcpy(netdev->name, "wlan%d");
4697 + netdev->ethtool_ops = &ps3_jupiter_sta_ethtool_ops;
4698 + netdev->netdev_ops = &ps3_jupiter_sta_net_device_ops;
4699 + netdev->wireless_data = &jstad->wireless_data;
4700 + netdev->wireless_handlers = &ps3_jupiter_sta_iw_handler_def;
4702 + jstad = netdev_priv(netdev);
4703 + jstad->netdev = netdev;
4705 + jstad->udev = usb_get_dev(udev);
4706 + usb_set_intfdata(interface, jstad);
4708 + err = ps3_jupiter_sta_set_mac_addr(jstad);
4709 + if (err) {
4710 + dev_err(&udev->dev, "could not setup network device (%d)\n", err);
4711 + goto fail_free_netdev;
4714 + spin_lock_init(&jstad->lock);
4716 + jstad->event_listener.notifier_call = ps3_jupiter_sta_event_handler;
4718 + err = ps3_jupiter_register_event_listener(&jstad->event_listener);
4719 + if (err) {
4720 + dev_err(&udev->dev, "could not register event listener (%d)\n", err);
4721 + goto fail_free_netdev;
4724 + mutex_init(&jstad->scan_lock);
4725 + INIT_LIST_HEAD(&jstad->scan_result_list);
4727 + err = ps3_jupiter_sta_get_channel_info(jstad);
4728 + if (err) {
4729 + dev_err(&udev->dev, "could not get channel info (%d)\n", err);
4730 + goto fail_unregister_event_listener;
4733 + mutex_init(&jstad->assoc_lock);
4735 + err = ps3_jupiter_sta_create_assoc_worker(jstad);
4736 + if (err) {
4737 + dev_err(&udev->dev, "could not create assoc work queue (%d)\n", err);
4738 + goto fail_unregister_event_listener;
4741 + skb_queue_head_init(&jstad->rx_skb_queue);
4742 + tasklet_init(&jstad->rx_tasklet, ps3_jupiter_sta_rx_tasklet, (unsigned long) jstad);
4744 + err = ps3_jupiter_sta_alloc_rx_urbs(jstad);
4745 + if (err) {
4746 + dev_err(&udev->dev, "could not allocate Rx URBs (%d)\n", err);
4747 + goto fail_destroy_assoc_worker;
4750 + init_usb_anchor(&jstad->tx_urb_anchor);
4751 + atomic_set(&jstad->tx_submitted_urbs, 0);
4753 + ps3_jupiter_sta_reset_state(jstad);
4755 + set_bit(PS3_JUPITER_STA_READY, &jstad->status);
4757 + err = register_netdev(netdev);
4758 + if (err) {
4759 + dev_dbg(&udev->dev, "could not register network device %s (%d)\n", netdev->name, err);
4760 + goto fail_free_rx_urbs;
4763 + return 0;
4765 +fail_free_rx_urbs:
4767 + ps3_jupiter_sta_free_rx_urbs(jstad);
4769 +fail_destroy_assoc_worker:
4771 + ps3_jupiter_sta_destroy_assoc_worker(jstad);
4773 +fail_unregister_event_listener:
4775 + ps3_jupiter_unregister_event_listener(&jstad->event_listener);
4777 +fail_free_netdev:
4779 + usb_set_intfdata(interface, NULL);
4780 + usb_put_dev(udev);
4782 + free_netdev(netdev);
4784 + return err;
4788 + * ps3_jupiter_sta_disconnect
4789 + */
4790 +static void ps3_jupiter_sta_disconnect(struct usb_interface *interface)
4792 + struct ps3_jupiter_sta_dev *jstad = usb_get_intfdata(interface);
4793 + struct usb_device *udev = jstad->udev;
4794 + struct net_device *netdev = jstad->netdev;
4796 + clear_bit(PS3_JUPITER_STA_READY, &jstad->status);
4798 + unregister_netdev(netdev);
4800 + if (jstad->assoc_status == PS3_JUPITER_STA_ASSOC_OK)
4801 + ps3_jupiter_sta_disassoc(jstad);
4803 + ps3_jupiter_sta_destroy_assoc_worker(jstad);
4805 + ps3_jupiter_sta_free_rx_urbs(jstad);
4806 + tasklet_kill(&jstad->rx_tasklet);
4807 + ps3_jupiter_sta_purge_rx_skb_queue(jstad);
4809 + ps3_jupiter_sta_free_tx_urbs(jstad);
4811 + ps3_jupiter_sta_free_scan_results(jstad);
4813 + ps3_jupiter_unregister_event_listener(&jstad->event_listener);
4815 + usb_set_intfdata(interface, NULL);
4816 + usb_put_dev(udev);
4818 + free_netdev(netdev);
4821 +#ifdef CONFIG_PM
4823 + * ps3_jupiter_sta_suspend
4824 + */
4825 +static int ps3_jupiter_sta_suspend(struct usb_interface *interface, pm_message_t state)
4827 + /* XXX: implement */
4829 + return 0;
4833 + * ps3_jupiter_sta_resume
4834 + */
4835 +static int ps3_jupiter_sta_resume(struct usb_interface *interface)
4837 + /* XXX: implement */
4839 + return 0;
4841 +#endif /* CONFIG_PM */
4843 +static struct usb_device_id ps3_jupiter_sta_devtab[] = {
4845 + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO,
4846 + .idVendor = 0x054c,
4847 + .idProduct = 0x036f,
4848 + .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
4849 + .bInterfaceSubClass = 2,
4850 + .bInterfaceProtocol = 2
4851 + },
4852 + { }
4855 +static struct usb_driver ps3_jupiter_sta_drv = {
4856 + .name = KBUILD_MODNAME,
4857 + .id_table = ps3_jupiter_sta_devtab,
4858 + .probe = ps3_jupiter_sta_probe,
4859 + .disconnect = ps3_jupiter_sta_disconnect,
4860 +#ifdef CONFIG_PM
4861 + .suspend = ps3_jupiter_sta_suspend,
4862 + .resume = ps3_jupiter_sta_resume,
4863 +#endif /* CONFIG_PM */
4867 + * ps3_jupiter_sta_init
4868 + */
4869 +static int __init ps3_jupiter_sta_init(void)
4871 + return usb_register(&ps3_jupiter_sta_drv);
4875 + * ps3_jupiter_sta_exit
4876 + */
4877 +static void __exit ps3_jupiter_sta_exit(void)
4879 + usb_deregister(&ps3_jupiter_sta_drv);
4882 +module_init(ps3_jupiter_sta_init);
4883 +module_exit(ps3_jupiter_sta_exit);
4885 +/*MODULE_SUPPORTED_DEVICE("PS3 Jupiter STA");*/
4886 +MODULE_DEVICE_TABLE(usb, ps3_jupiter_sta_devtab);
4887 +MODULE_DESCRIPTION("PS3 Jupiter STA");
4888 +MODULE_AUTHOR("glevand");
4889 +MODULE_LICENSE("GPL");