drivers/net/ieee802154/atusb.c

Source file repositories/reference/linux-study-clean/drivers/net/ieee802154/atusb.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ieee802154/atusb.c
Extension
.c
Size
30354 bytes
Lines
1114
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct atusb {
	struct ieee802154_hw *hw;
	struct usb_device *usb_dev;
	struct atusb_chip_data *data;
	int shutdown;			/* non-zero if shutting down */
	int err;			/* set by first error */

	/* RX variables */
	struct delayed_work work;	/* memory allocations */
	struct usb_anchor idle_urbs;	/* URBs waiting to be submitted */
	struct usb_anchor rx_urbs;	/* URBs waiting for reception */

	/* TX variables */
	struct usb_ctrlrequest tx_dr;
	struct urb *tx_urb;
	struct sk_buff *tx_skb;
	u8 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 */
};

struct atusb_chip_data {
	u16 t_channel_switch;
	int rssi_base_val;

	int (*set_channel)(struct ieee802154_hw*, u8, u8);
	int (*set_txpower)(struct ieee802154_hw*, s32);
};

static int atusb_write_subreg(struct atusb *atusb, u8 reg, u8 mask,
			      u8 shift, u8 value)
{
	struct usb_device *usb_dev = atusb->usb_dev;
	u8 orig, tmp;
	int ret = 0;

	dev_dbg(&usb_dev->dev, "%s: 0x%02x <- 0x%02x\n", __func__, reg, value);

	ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
				   0, reg, &orig, 1, 1000, GFP_KERNEL);
	if (ret < 0)
		return ret;

	/* Write the value only into that part of the register which is allowed
	 * by the mask. All other bits stay as before.
	 */
	tmp = orig & ~mask;
	tmp |= (value << shift) & mask;

	if (tmp != orig)
		ret = usb_control_msg_send(usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
					   tmp, reg, NULL, 0, 1000, GFP_KERNEL);

	return ret;
}

static int atusb_read_subreg(struct atusb *lp,
			     unsigned int addr, unsigned int mask,
			     unsigned int shift)
{
	int reg, ret;

	ret = usb_control_msg_recv(lp->usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
				   0, addr, &reg, 1, 1000, GFP_KERNEL);
	if (ret < 0)
		return ret;

	reg = (reg & mask) >> shift;

	return reg;
}

static int atusb_get_and_clear_error(struct atusb *atusb)
{
	int err = atusb->err;

	atusb->err = 0;
	return err;
}

/* ----- skb allocation ---------------------------------------------------- */

#define MAX_PSDU	127
#define MAX_RX_XFER	(1 + MAX_PSDU + 2 + 1)	/* PHR+PSDU+CRC+LQI */

#define SKB_ATUSB(skb)	(*(struct atusb **)(skb)->cb)

Annotation

Implementation Notes