199 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 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 */
 |