Skip to content

Commit

Permalink
wireless: add plfxlc driver for pureLiFi X, XL, XC devices
Browse files Browse the repository at this point in the history
This is a driver for pureLiFi X, XL, XC devices which use light to transmit
data, so they are not compatible with normal Wi-Fi devices. The driver uses
separate NL80211_BAND_LC band to distinguish from Wi-Fi.  The driver is based
on 802.11 softMAC Architecture and uses native 802.11 for configuration and
management. Station and Ad-Hoc modes are supported.

The driver is compiled and tested in ARM, x86 architectures and compiled in
powerpc architecture. This driver implementation has been based on the zd1211rw
driver.

Signed-off-by: Srinivasan Raju <srini.raju@purelifi.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220224182042.132466-3-srini.raju@purelifi.com
  • Loading branch information
srini-purelifi authored and Kalle Valo committed Apr 25, 2022
1 parent 2fb822f commit 68d57a0
Show file tree
Hide file tree
Showing 15 changed files with 2,569 additions and 0 deletions.
6 changes: 6 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -15970,6 +15970,12 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/admin-guide/media/pulse8-cec.rst
F: drivers/media/cec/usb/pulse8/

PURELIFI PLFXLC DRIVER
M: Srinivasan Raju <srini.raju@purelifi.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/purelifi/plfxlc/

PVRUSB2 VIDEO4LINUX DRIVER
M: Mike Isely <isely@pobox.com>
L: pvrusb2@isely.net (subscribers-only)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ source "drivers/net/wireless/intersil/Kconfig"
source "drivers/net/wireless/marvell/Kconfig"
source "drivers/net/wireless/mediatek/Kconfig"
source "drivers/net/wireless/microchip/Kconfig"
source "drivers/net/wireless/purelifi/Kconfig"
source "drivers/net/wireless/ralink/Kconfig"
source "drivers/net/wireless/realtek/Kconfig"
source "drivers/net/wireless/rsi/Kconfig"
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ obj-$(CONFIG_WLAN_VENDOR_INTERSIL) += intersil/
obj-$(CONFIG_WLAN_VENDOR_MARVELL) += marvell/
obj-$(CONFIG_WLAN_VENDOR_MEDIATEK) += mediatek/
obj-$(CONFIG_WLAN_VENDOR_MICROCHIP) += microchip/
obj-$(CONFIG_WLAN_VENDOR_PURELIFI) += purelifi/
obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/
obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
Expand Down
17 changes: 17 additions & 0 deletions drivers/net/wireless/purelifi/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-2.0-only
config WLAN_VENDOR_PURELIFI
bool "pureLiFi devices"
default y
help
If you have a pureLiFi device, say Y.

Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all the
questions about these cards. If you say Y, you will be asked for
your specific card in the following questions.

if WLAN_VENDOR_PURELIFI

source "drivers/net/wireless/purelifi/plfxlc/Kconfig"

endif # WLAN_VENDOR_PURELIFI
2 changes: 2 additions & 0 deletions drivers/net/wireless/purelifi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PLFXLC) := plfxlc/
14 changes: 14 additions & 0 deletions drivers/net/wireless/purelifi/plfxlc/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-only
config PLFXLC
tristate "pureLiFi X, XL, XC device support"
depends on CFG80211 && MAC80211 && USB
help
This option adds support for pureLiFi LiFi wireless USB
adapters. The pureLiFi X, XL, XC USB devices are based on
802.11 OFDM PHY but uses light as the transmission medium.
The driver supports common 802.11 encryption/authentication
methods including Open, WPA, WPA2-Personal and
WPA2-Enterprise (802.1X).

To compile this driver as a module, choose m here. The module will
be called plfxlc.
3 changes: 3 additions & 0 deletions drivers/net/wireless/purelifi/plfxlc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PLFXLC) := plfxlc.o
plfxlc-objs += chip.o firmware.o usb.o mac.o
99 changes: 99 additions & 0 deletions drivers/net/wireless/purelifi/plfxlc/chip.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021 pureLiFi
*/

#include <linux/kernel.h>
#include <linux/errno.h>

#include "chip.h"
#include "mac.h"
#include "usb.h"

void plfxlc_chip_init(struct plfxlc_chip *chip,
struct ieee80211_hw *hw,
struct usb_interface *intf)
{
memset(chip, 0, sizeof(*chip));
mutex_init(&chip->mutex);
plfxlc_usb_init(&chip->usb, hw, intf);
}

void plfxlc_chip_release(struct plfxlc_chip *chip)
{
plfxlc_usb_release(&chip->usb);
mutex_destroy(&chip->mutex);
}

int plfxlc_set_beacon_interval(struct plfxlc_chip *chip, u16 interval,
u8 dtim_period, int type)
{
if (!interval ||
(chip->beacon_set &&
le16_to_cpu(chip->beacon_interval) == interval))
return 0;

chip->beacon_interval = cpu_to_le16(interval);
chip->beacon_set = true;
return plfxlc_usb_wreq(chip->usb.ez_usb,
&chip->beacon_interval,
sizeof(chip->beacon_interval),
USB_REQ_BEACON_INTERVAL_WR);
}

int plfxlc_chip_init_hw(struct plfxlc_chip *chip)
{
unsigned char *addr = plfxlc_mac_get_perm_addr(plfxlc_chip_to_mac(chip));
struct usb_device *udev = interface_to_usbdev(chip->usb.intf);

pr_info("plfxlc chip %04x:%04x v%02x %pM %s\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct),
le16_to_cpu(udev->descriptor.bcdDevice),
addr,
plfxlc_speed(udev->speed));

return plfxlc_set_beacon_interval(chip, 100, 0, 0);
}

int plfxlc_chip_switch_radio(struct plfxlc_chip *chip, u16 value)
{
int r;
__le16 radio_on = cpu_to_le16(value);

r = plfxlc_usb_wreq(chip->usb.ez_usb, &radio_on,
sizeof(value), USB_REQ_POWER_WR);
if (r)
dev_err(plfxlc_chip_dev(chip), "POWER_WR failed (%d)\n", r);
return r;
}

int plfxlc_chip_enable_rxtx(struct plfxlc_chip *chip)
{
plfxlc_usb_enable_tx(&chip->usb);
return plfxlc_usb_enable_rx(&chip->usb);
}

void plfxlc_chip_disable_rxtx(struct plfxlc_chip *chip)
{
u8 value = 0;

plfxlc_usb_wreq(chip->usb.ez_usb,
&value, sizeof(value), USB_REQ_RXTX_WR);
plfxlc_usb_disable_rx(&chip->usb);
plfxlc_usb_disable_tx(&chip->usb);
}

int plfxlc_chip_set_rate(struct plfxlc_chip *chip, u8 rate)
{
int r;

if (!chip)
return -EINVAL;

r = plfxlc_usb_wreq(chip->usb.ez_usb,
&rate, sizeof(rate), USB_REQ_RATE_WR);
if (r)
dev_err(plfxlc_chip_dev(chip), "RATE_WR failed (%d)\n", r);
return r;
}
70 changes: 70 additions & 0 deletions drivers/net/wireless/purelifi/plfxlc/chip.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021 pureLiFi
*/

#ifndef PLFXLC_CHIP_H
#define PLFXLC_CHIP_H

#include <net/mac80211.h>

#include "usb.h"

enum unit_type {
STA = 0,
AP = 1,
};

enum {
PLFXLC_RADIO_OFF = 0,
PLFXLC_RADIO_ON = 1,
};

struct plfxlc_chip {
struct plfxlc_usb usb;
struct mutex mutex; /* lock to protect chip data */
enum unit_type unit_type;
u16 link_led;
u8 beacon_set;
u16 beacon_interval;
};

struct plfxlc_mc_hash {
u32 low;
u32 high;
};

#define plfxlc_chip_dev(chip) (&(chip)->usb.intf->dev)

void plfxlc_chip_init(struct plfxlc_chip *chip,
struct ieee80211_hw *hw,
struct usb_interface *intf);

void plfxlc_chip_release(struct plfxlc_chip *chip);

void plfxlc_chip_disable_rxtx(struct plfxlc_chip *chip);

int plfxlc_chip_init_hw(struct plfxlc_chip *chip);

int plfxlc_chip_enable_rxtx(struct plfxlc_chip *chip);

int plfxlc_chip_set_rate(struct plfxlc_chip *chip, u8 rate);

int plfxlc_set_beacon_interval(struct plfxlc_chip *chip, u16 interval,
u8 dtim_period, int type);

int plfxlc_chip_switch_radio(struct plfxlc_chip *chip, u16 value);

static inline struct plfxlc_chip *plfxlc_usb_to_chip(struct plfxlc_usb
*usb)
{
return container_of(usb, struct plfxlc_chip, usb);
}

static inline void plfxlc_mc_add_all(struct plfxlc_mc_hash *hash)
{
hash->low = 0xffffffff;
hash->high = 0xffffffff;
}

#endif /* PLFXLC_CHIP_H */
Loading

0 comments on commit 68d57a0

Please sign in to comment.