/* * WiMAX stack operation: relay a message from user space * * @wimax_dev: device descriptor * @pipe_name: named pipe the message is for * @msg_buf: pointer to the message bytes * @msg_len: length of the buffer * @genl_info: passed by the generic netlink layer * * The WiMAX stack will call this function when a message was received * from user space. * * For the i2400m, this is an L3L4 message, as specified in * include/linux/wimax/i2400m.h, and thus prefixed with a 'struct * i2400m_l3l4_hdr'. Driver (and device) expect the messages to be * coded in Little Endian. * * This function just verifies that the header declaration and the * payload are consistent and then deals with it, either forwarding it * to the device or procesing it locally. * * In the i2400m, messages are basically commands that will carry an * ack, so we use i2400m_msg_to_dev() and then deliver the ack back to * user space. The rx.c code might intercept the response and use it * to update the driver's state, but then it will pass it on so it can * be relayed back to user space. * * Note that asynchronous events from the device are processed and * sent to user space in rx.c. */ static int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev, const char *pipe_name, const void *msg_buf, size_t msg_len, const struct genl_info *genl_info) { int result; struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev); struct device *dev = i2400m_dev(i2400m); struct sk_buff *ack_skb; d_fnstart(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p " "msg_len %zu genl_info %p)\n", wimax_dev, i2400m, msg_buf, msg_len, genl_info); ack_skb = i2400m_msg_to_dev(i2400m, msg_buf, msg_len); result = PTR_ERR(ack_skb); if (IS_ERR(ack_skb)) goto error_msg_to_dev; result = wimax_msg_send(&i2400m->wimax_dev, ack_skb); error_msg_to_dev: d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu " "genl_info %p) = %d\n", wimax_dev, i2400m, msg_buf, msg_len, genl_info, result); return result; }
/* * WiMAX stack operation: implement SW RFKill toggling * * @wimax_dev: device descriptor * @skb: skb where the message has been received; skb->data is * expected to point to the message payload. * @genl_info: passed by the generic netlink layer * * Generic Netlink will call this function when a message is sent from * userspace to change the software RF-Kill switch status. * <<<<<<< HEAD * This function will set the device's software RF-Kill switch state to ======= * This function will set the device's sofware RF-Kill switch state to >>>>>>> 296c66da8a02d52243f45b80521febece5ed498a * match what is requested. * * NOTE: the i2400m has a strict state machine; we can only set the * RF-Kill switch when it is on, the HW RF-Kill is on and the * device is initialized. So we ignore errors steaming from not * being in the right state (-EILSEQ). */ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, enum wimax_rf_state state) { int result; struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev); struct device *dev = i2400m_dev(i2400m); struct sk_buff *ack_skb; struct { struct i2400m_l3l4_hdr hdr; struct i2400m_tlv_rf_operation sw_rf; <<<<<<< HEAD } __packed *cmd;
int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, enum wimax_rf_state state) { int result; struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev); struct device *dev = i2400m_dev(i2400m); struct sk_buff *ack_skb; struct { struct i2400m_l3l4_hdr hdr; struct i2400m_tlv_rf_operation sw_rf; } __attribute__((packed)) *cmd; char strerr[32]; d_fnstart(4, dev, "(wimax_dev %p state %d)\n", wimax_dev, state); result = -ENOMEM; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) goto error_alloc; cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_RF_CONTROL); cmd->hdr.length = sizeof(cmd->sw_rf); cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION); cmd->sw_rf.hdr.type = cpu_to_le16(I2400M_TLV_RF_OPERATION); cmd->sw_rf.hdr.length = cpu_to_le16(sizeof(cmd->sw_rf.status)); switch (state) { case WIMAX_RF_OFF: cmd->sw_rf.status = cpu_to_le32(2); break; case WIMAX_RF_ON: cmd->sw_rf.status = cpu_to_le32(1); break; default: BUG(); } ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); result = PTR_ERR(ack_skb); if (IS_ERR(ack_skb)) { dev_err(dev, "Failed to issue 'RF Control' command: %d\n", result); goto error_msg_to_dev; } result = i2400m_msg_check_status(wimax_msg_data(ack_skb), strerr, sizeof(strerr)); if (result < 0) { dev_err(dev, "'RF Control' (0x%04x) command failed: %d - %s\n", I2400M_MT_CMD_RF_CONTROL, result, strerr); goto error_cmd; } result = wait_event_timeout( i2400m->state_wq, i2400m_radio_is(i2400m, state), 5 * HZ); if (result == 0) result = -ETIMEDOUT; if (result < 0) dev_err(dev, "Error waiting for device to toggle RF state: " "%d\n", result); result = 0; error_cmd: kfree_skb(ack_skb); error_msg_to_dev: error_alloc: d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n", wimax_dev, state, result); return result; }