1/* 2 * Ultra Wide Band 3 * Scanning management 4 * 5 * Copyright (C) 2005-2006 Intel Corporation 6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License version 10 * 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 * 02110-1301, USA. 21 * 22 * 23 * 24 * FIXME: docs 25 * FIXME: there are issues here on how BEACON and SCAN on USB RCI deal 26 * with each other. Currently seems that START_BEACON while 27 * SCAN_ONLY will cancel the scan, so we need to update the 28 * state here. Clarification request sent by email on 29 * 10/05/2005. 30 * 10/28/2005 No clear answer heard--maybe we'll hack the API 31 * so that when we start beaconing, if the HC is 32 * scanning in a mode not compatible with beaconing 33 * we just fail. 34 */ 35 36#include <linux/device.h> 37#include <linux/err.h> 38#include <linux/slab.h> 39#include <linux/stat.h> 40#include "uwb-internal.h" 41 42 43/** 44 * Start/stop scanning in a radio controller 45 * 46 * @rc: UWB Radio Controller 47 * @channel: Channel to scan; encodings in WUSB1.0[Table 5.12] 48 * @type: Type of scanning to do. 49 * @bpst_offset: value at which to start scanning (if type == 50 * UWB_SCAN_ONLY_STARTTIME) 51 * @returns: 0 if ok, < 0 errno code on error 52 * 53 * We put the command on kmalloc'ed memory as some arches cannot do 54 * USB from the stack. The reply event is copied from an stage buffer, 55 * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details. 56 */ 57int uwb_rc_scan(struct uwb_rc *rc, 58 unsigned channel, enum uwb_scan_type type, 59 unsigned bpst_offset) 60{ 61 int result; 62 struct uwb_rc_cmd_scan *cmd; 63 struct uwb_rc_evt_confirm reply; 64 65 result = -ENOMEM; 66 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 67 if (cmd == NULL) 68 goto error_kzalloc; 69 mutex_lock(&rc->uwb_dev.mutex); 70 cmd->rccb.bCommandType = UWB_RC_CET_GENERAL; 71 cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SCAN); 72 cmd->bChannelNumber = channel; 73 cmd->bScanState = type; 74 cmd->wStartTime = cpu_to_le16(bpst_offset); 75 reply.rceb.bEventType = UWB_RC_CET_GENERAL; 76 reply.rceb.wEvent = UWB_RC_CMD_SCAN; 77 result = uwb_rc_cmd(rc, "SCAN", &cmd->rccb, sizeof(*cmd), 78 &reply.rceb, sizeof(reply)); 79 if (result < 0) 80 goto error_cmd; 81 if (reply.bResultCode != UWB_RC_RES_SUCCESS) { 82 dev_err(&rc->uwb_dev.dev, 83 "SCAN: command execution failed: %s (%d)\n", 84 uwb_rc_strerror(reply.bResultCode), reply.bResultCode); 85 result = -EIO; 86 goto error_cmd; 87 } 88 rc->scanning = channel; 89 rc->scan_type = type; 90error_cmd: 91 mutex_unlock(&rc->uwb_dev.mutex); 92 kfree(cmd); 93error_kzalloc: 94 return result; 95} 96 97/* 98 * Print scanning state 99 */ 100static ssize_t uwb_rc_scan_show(struct device *dev, 101 struct device_attribute *attr, char *buf) 102{ 103 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 104 struct uwb_rc *rc = uwb_dev->rc; 105 ssize_t result; 106 107 mutex_lock(&rc->uwb_dev.mutex); 108 result = sprintf(buf, "%d %d\n", rc->scanning, rc->scan_type); 109 mutex_unlock(&rc->uwb_dev.mutex); 110 return result; 111} 112 113/* 114 * 115 */ 116static ssize_t uwb_rc_scan_store(struct device *dev, 117 struct device_attribute *attr, 118 const char *buf, size_t size) 119{ 120 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 121 struct uwb_rc *rc = uwb_dev->rc; 122 unsigned channel; 123 unsigned type; 124 unsigned bpst_offset = 0; 125 ssize_t result = -EINVAL; 126 127 result = sscanf(buf, "%u %u %u\n", &channel, &type, &bpst_offset); 128 if (result >= 2 && type < UWB_SCAN_TOP) 129 result = uwb_rc_scan(rc, channel, type, bpst_offset); 130 131 return result < 0 ? result : size; 132} 133 134/** Radio Control sysfs interface (declaration) */ 135DEVICE_ATTR(scan, S_IRUGO | S_IWUSR, uwb_rc_scan_show, uwb_rc_scan_store); 136