diff options
Diffstat (limited to 'drivers/net/wireless/purelifi/plfxlc/usb.h')
-rw-r--r-- | drivers/net/wireless/purelifi/plfxlc/usb.h | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/drivers/net/wireless/purelifi/plfxlc/usb.h b/drivers/net/wireless/purelifi/plfxlc/usb.h new file mode 100644 index 000000000..ba2defd59 --- /dev/null +++ b/drivers/net/wireless/purelifi/plfxlc/usb.h @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021 pureLiFi + */ + +#ifndef PLFXLC_USB_H +#define PLFXLC_USB_H + +#include <linux/completion.h> +#include <linux/netdevice.h> +#include <linux/spinlock.h> +#include <linux/skbuff.h> +#include <linux/usb.h> + +#include "intf.h" + +#define USB_BULK_MSG_TIMEOUT_MS 2000 + +#define PURELIFI_X_VENDOR_ID_0 0x16C1 +#define PURELIFI_X_PRODUCT_ID_0 0x1CDE +#define PURELIFI_XC_VENDOR_ID_0 0x2EF5 +#define PURELIFI_XC_PRODUCT_ID_0 0x0008 +#define PURELIFI_XL_VENDOR_ID_0 0x2EF5 +#define PURELIFI_XL_PRODUCT_ID_0 0x000A /* Station */ + +#define PLF_FPGA_STATUS_LEN 2 +#define PLF_FPGA_STATE_LEN 9 +#define PLF_BULK_TLEN 16384 +#define PLF_FPGA_MG 6 /* Magic check */ +#define PLF_XL_BUF_LEN 64 +#define PLF_MSG_STATUS_OFFSET 7 + +#define PLF_USB_TIMEOUT 1000 +#define PLF_MSLEEP_TIME 200 + +#define PURELIFI_URB_RETRY_MAX 5 + +#define plfxlc_usb_dev(usb) (&(usb)->intf->dev) + +/* Tx retry backoff timer (in milliseconds) */ +#define TX_RETRY_BACKOFF_MS 10 +#define STA_QUEUE_CLEANUP_MS 5000 + +/* Tx retry backoff timer (in jiffies) */ +#define TX_RETRY_BACKOFF_JIFF ((TX_RETRY_BACKOFF_MS * HZ) / 1000) +#define STA_QUEUE_CLEANUP_JIFF ((STA_QUEUE_CLEANUP_MS * HZ) / 1000) + +/* Ensures that MAX_TRANSFER_SIZE is even. */ +#define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1) +#define plfxlc_urb_dev(urb) (&(urb)->dev->dev) + +#define STATION_FIFO_ALMOST_FULL_MESSAGE 0 +#define STATION_FIFO_ALMOST_FULL_NOT_MESSAGE 1 +#define STATION_CONNECT_MESSAGE 2 +#define STATION_DISCONNECT_MESSAGE 3 + +int plfxlc_usb_wreq(struct usb_interface *ez_usb, void *buffer, int buffer_len, + enum plf_usb_req_enum usb_req_id); +void plfxlc_tx_urb_complete(struct urb *urb); + +enum { + USB_MAX_RX_SIZE = 4800, + USB_MAX_EP_INT_BUFFER = 64, +}; + +struct plfxlc_usb_interrupt { + spinlock_t lock; /* spin lock for usb interrupt buffer */ + struct urb *urb; + void *buffer; + int interval; +}; + +#define RX_URBS_COUNT 5 + +struct plfxlc_usb_rx { + spinlock_t lock; /* spin lock for rx urb */ + struct mutex setup_mutex; /* mutex lockt for rx urb */ + u8 fragment[2 * USB_MAX_RX_SIZE]; + unsigned int fragment_length; + unsigned int usb_packet_size; + struct urb **urbs; + int urbs_count; +}; + +struct plf_station { + /* 7...3 | 2 | 1 | 0 | + * Reserved | Heartbeat | FIFO full | Connected | + */ + unsigned char flag; + unsigned char mac[ETH_ALEN]; + struct sk_buff_head data_list; +}; + +struct plfxlc_firmware_file { + u32 total_files; + u32 total_size; + u32 size; + u32 start_addr; + u32 control_packets; +} __packed; + +#define STATION_CONNECTED_FLAG 0x1 +#define STATION_FIFO_FULL_FLAG 0x2 +#define STATION_HEARTBEAT_FLAG 0x4 +#define STATION_ACTIVE_FLAG 0xFD + +#define PURELIFI_SERIAL_LEN 256 +#define STA_BROADCAST_INDEX (AP_USER_LIMIT) +#define MAX_STA_NUM (AP_USER_LIMIT + 1) + +struct plfxlc_usb_tx { + unsigned long enabled; + spinlock_t lock; /* spinlock for USB tx */ + u8 mac_fifo_full; + struct sk_buff_head submitted_skbs; + struct usb_anchor submitted; + int submitted_urbs; + bool stopped; + struct timer_list tx_retry_timer; + struct plf_station station[MAX_STA_NUM]; +}; + +/* Contains the usb parts. The structure doesn't require a lock because intf + * will not be changed after initialization. + */ +struct plfxlc_usb { + struct timer_list sta_queue_cleanup; + struct plfxlc_usb_rx rx; + struct plfxlc_usb_tx tx; + struct usb_interface *intf; + struct usb_interface *ez_usb; + u8 req_buf[64]; /* plfxlc_usb_iowrite16v needs 62 bytes */ + u8 sidx; /* store last served */ + bool rx_usb_enabled; + bool initialized; + bool was_running; + bool link_up; +}; + +enum endpoints { + EP_DATA_IN = 2, + EP_DATA_OUT = 8, +}; + +enum devicetype { + DEVICE_LIFI_X = 0, + DEVICE_LIFI_XC = 1, + DEVICE_LIFI_XL = 1, +}; + +enum { + PLF_BIT_ENABLED = 1, + PLF_BIT_MAX = 2, +}; + +int plfxlc_usb_wreq_async(struct plfxlc_usb *usb, const u8 *buffer, + int buffer_len, enum plf_usb_req_enum usb_req_id, + usb_complete_t complete_fn, void *context); + +static inline struct usb_device * +plfxlc_usb_to_usbdev(struct plfxlc_usb *usb) +{ + return interface_to_usbdev(usb->intf); +} + +static inline struct ieee80211_hw * +plfxlc_intf_to_hw(struct usb_interface *intf) +{ + return usb_get_intfdata(intf); +} + +static inline struct ieee80211_hw * +plfxlc_usb_to_hw(struct plfxlc_usb *usb) +{ + return plfxlc_intf_to_hw(usb->intf); +} + +void plfxlc_usb_init(struct plfxlc_usb *usb, struct ieee80211_hw *hw, + struct usb_interface *intf); +void plfxlc_send_packet_from_data_queue(struct plfxlc_usb *usb); +void plfxlc_usb_release(struct plfxlc_usb *usb); +void plfxlc_usb_disable_rx(struct plfxlc_usb *usb); +void plfxlc_usb_enable_tx(struct plfxlc_usb *usb); +void plfxlc_usb_disable_tx(struct plfxlc_usb *usb); +int plfxlc_usb_tx(struct plfxlc_usb *usb, struct sk_buff *skb); +int plfxlc_usb_enable_rx(struct plfxlc_usb *usb); +int plfxlc_usb_init_hw(struct plfxlc_usb *usb); +const char *plfxlc_speed(enum usb_device_speed speed); + +/* Firmware declarations */ +int plfxlc_download_xl_firmware(struct usb_interface *intf); +int plfxlc_download_fpga(struct usb_interface *intf); + +int plfxlc_upload_mac_and_serial(struct usb_interface *intf, + unsigned char *hw_address, + unsigned char *serial_number); + +#endif /* PLFXLC_USB_H */ |