From c84d59e72830ce7a7ce67cf7509d37342aa235db Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Mon, 5 Dec 2016 14:47:17 +0100 Subject: ieee802154: atusb: sync header file from firmware for new features This file is shared between the atusb firmware and the kernel driver. In this update it brings the new interfaces from version 0.3 of the firmware. Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/atusb.h b/drivers/net/ieee802154/atusb.h index 0690edcad57b..b22bbaa77590 100644 --- a/drivers/net/ieee802154/atusb.h +++ b/drivers/net/ieee802154/atusb.h @@ -13,8 +13,8 @@ * Firmware: ben-wpan/atusb/fw/include/atusb/atusb.h */ -#ifndef _ATUSB_H -#define _ATUSB_H +#ifndef _ATUSB_H +#define _ATUSB_H #define ATUSB_VENDOR_ID 0x20b7 /* Qi Hardware*/ #define ATUSB_PRODUCT_ID 0x1540 /* 802.15.4, device 0 */ @@ -46,9 +46,12 @@ enum atusb_requests { ATUSB_SPI_WRITE2_SYNC, ATUSB_RX_MODE = 0x40, /* HardMAC group */ ATUSB_TX, + ATUSB_EUI64_WRITE = 0x50, /* Parameter in EEPROM grp */ + ATUSB_EUI64_READ, }; -/* Direction bRequest wValue wIndex wLength +/* + * Direction bRequest wValue wIndex wLength * * ->host ATUSB_ID - - 3 * ->host ATUSB_BUILD - - #bytes @@ -76,6 +79,8 @@ enum atusb_requests { * * host-> ATUSB_RX_MODE on - 0 * host-> ATUSB_TX flags ack_seq #bytes + * host-> ATUSB_EUI64_WRITE - - #bytes (8) + * ->host ATUSB_EUI64_READ - - #bytes (8) */ #define ATUSB_REQ_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN) -- cgit From 46551564a28e07325140057876f92881d58a219a Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Mon, 5 Dec 2016 14:47:18 +0100 Subject: ieee802154: atusb: store firmware version after retrieval for later use The firmware versions will be used to enable selective features based on the available firmware on the device. Make sure we do not need to fetch it for every check but store it after the initial retrieval. Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 322864a1a94b..9fdea642ffad 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -58,6 +58,11 @@ struct atusb { struct urb *tx_urb; struct sk_buff *tx_skb; uint8_t tx_ack_seq; /* current TX ACK sequence number */ + + /* Firmware variable */ + unsigned char fw_ver_maj; /* Firmware major version number */ + unsigned char fw_ver_min; /* Firmware minor version number */ + unsigned char fw_hw_type; /* Firmware hardware type */ }; /* ----- USB commands without data ----------------------------------------- */ @@ -594,14 +599,19 @@ static int atusb_get_and_show_revision(struct atusb *atusb) ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0), ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0, buffer, 3, 1000); - if (ret >= 0) + if (ret >= 0) { + atusb->fw_ver_maj = buffer[0]; + atusb->fw_ver_min = buffer[1]; + atusb->fw_hw_type = buffer[2]; + dev_info(&usb_dev->dev, "Firmware: major: %u, minor: %u, hardware type: %u\n", - buffer[0], buffer[1], buffer[2]); - if (buffer[0] == 0 && buffer[1] < 2) { + atusb->fw_ver_maj, atusb->fw_ver_min, atusb->fw_hw_type); + } + if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 2) { dev_info(&usb_dev->dev, - "Firmware version (%u.%u) is predates our first public release.", - buffer[0], buffer[1]); + "Firmware version (%u.%u) predates our first public release.", + atusb->fw_ver_maj, atusb->fw_ver_min); dev_info(&usb_dev->dev, "Please update to version 0.2 or newer"); } -- cgit From 6cc33eba232cebc9918c558b21b1e3b5fcab27b7 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Mon, 5 Dec 2016 14:47:19 +0100 Subject: ieee802154: atusb: try to read permanent extended address from device With version 0.3 the atusb firmware offers an interface to read a permanent EUI64 address from the devices EEPROM. This patch checks if the firmware is new enough and tries to read out and use the address. If this does not work we fall back to the original randomly generated address. Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 9fdea642ffad..3ed34cc8a2f8 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -679,6 +679,43 @@ fail: return -ENODEV; } +static int atusb_set_extended_addr(struct atusb *atusb) +{ + struct usb_device *usb_dev = atusb->usb_dev; + unsigned char buffer[IEEE802154_EXTENDED_ADDR_LEN]; + __le64 extended_addr; + u64 addr; + int ret; + + /* Firmware versions before 0.3 do not support the EUI64_READ command. + * Just use a random address and be done */ + if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 3) { + ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr); + return 0; + } + + /* Firmware is new enough so we fetch the address from EEPROM */ + ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0), + ATUSB_EUI64_READ, ATUSB_REQ_FROM_DEV, 0, 0, + buffer, IEEE802154_EXTENDED_ADDR_LEN, 1000); + if (ret < 0) + dev_err(&usb_dev->dev, "failed to fetch extended address\n"); + + memcpy(&extended_addr, buffer, IEEE802154_EXTENDED_ADDR_LEN); + /* Check if read address is not empty and the unicast bit is set correctly */ + if (!ieee802154_is_valid_extended_unicast_addr(extended_addr)) { + dev_info(&usb_dev->dev, "no permanent extended address found, random address set\n"); + ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr); + } else { + atusb->hw->phy->perm_extended_addr = extended_addr; + addr = swab64((__force u64)atusb->hw->phy->perm_extended_addr); + dev_info(&usb_dev->dev, "Read permanent extended address %8phC from device\n", + &addr); + } + + return ret; +} + /* ----- Setup ------------------------------------------------------------- */ static int atusb_probe(struct usb_interface *interface, @@ -738,13 +775,14 @@ static int atusb_probe(struct usb_interface *interface, hw->phy->supported.tx_powers = atusb_powers; hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->transmit_power = hw->phy->supported.tx_powers[0]; - ieee802154_random_extended_addr(&hw->phy->perm_extended_addr); hw->phy->cca_ed_level = hw->phy->supported.cca_ed_levels[7]; atusb_command(atusb, ATUSB_RF_RESET, 0); atusb_get_and_show_chip(atusb); atusb_get_and_show_revision(atusb); atusb_get_and_show_build(atusb); + atusb_set_extended_addr(atusb); + ret = atusb_get_and_clear_error(atusb); if (ret) { dev_err(&atusb->usb_dev->dev, -- cgit From 5d82288b93db3bc7e943464f89079f1360ac3c50 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Mon, 5 Dec 2016 14:47:20 +0100 Subject: ieee802154: atusb: implement .set_frame_retries ops callback From firmware version 0.3 onwards we use the TX_ARET mode allowing for automatic frame retransmissions. To actually make use of this feature we need to implement the callback for setting the frame retries. If the firmware version is to old print a warning and return with invalid value. Signed-off-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 3ed34cc8a2f8..1253f864737a 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -545,6 +545,21 @@ atusb_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries return atusb_write_subreg(atusb, SR_MAX_CSMA_RETRIES, retries); } +static int +atusb_set_frame_retries(struct ieee802154_hw *hw, s8 retries) +{ + struct atusb *atusb = hw->priv; + struct device *dev = &atusb->usb_dev->dev; + + if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 3) { + dev_info(dev, "Automatic frame retransmission is only available from " + "firmware version 0.3. Please update if you want this feature."); + return -EINVAL; + } + + return atusb_write_subreg(atusb, SR_MAX_FRAME_RETRIES, retries); +} + static int atusb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on) { @@ -584,6 +599,7 @@ static const struct ieee802154_ops atusb_ops = { .set_cca_mode = atusb_set_cca_mode, .set_cca_ed_level = atusb_set_cca_ed_level, .set_csma_params = atusb_set_csma_params, + .set_frame_retries = atusb_set_frame_retries, .set_promiscuous_mode = atusb_set_promiscuous_mode, }; @@ -754,7 +770,8 @@ static int atusb_probe(struct usb_interface *interface, hw->parent = &usb_dev->dev; hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | - IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS; + IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS | + IEEE802154_HW_FRAME_RETRIES; hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL | WPAN_PHY_FLAG_CCA_MODE; -- cgit