at v2.6.36 134 lines 4.1 kB view raw
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 "uwb-internal.h" 40 41 42/** 43 * Start/stop scanning in a radio controller 44 * 45 * @rc: UWB Radio Controlller 46 * @channel: Channel to scan; encodings in WUSB1.0[Table 5.12] 47 * @type: Type of scanning to do. 48 * @bpst_offset: value at which to start scanning (if type == 49 * UWB_SCAN_ONLY_STARTTIME) 50 * @returns: 0 if ok, < 0 errno code on error 51 * 52 * We put the command on kmalloc'ed memory as some arches cannot do 53 * USB from the stack. The reply event is copied from an stage buffer, 54 * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details. 55 */ 56int uwb_rc_scan(struct uwb_rc *rc, 57 unsigned channel, enum uwb_scan_type type, 58 unsigned bpst_offset) 59{ 60 int result; 61 struct uwb_rc_cmd_scan *cmd; 62 struct uwb_rc_evt_confirm reply; 63 64 result = -ENOMEM; 65 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 66 if (cmd == NULL) 67 goto error_kzalloc; 68 mutex_lock(&rc->uwb_dev.mutex); 69 cmd->rccb.bCommandType = UWB_RC_CET_GENERAL; 70 cmd->rccb.wCommand = cpu_to_le16(UWB_RC_CMD_SCAN); 71 cmd->bChannelNumber = channel; 72 cmd->bScanState = type; 73 cmd->wStartTime = cpu_to_le16(bpst_offset); 74 reply.rceb.bEventType = UWB_RC_CET_GENERAL; 75 reply.rceb.wEvent = UWB_RC_CMD_SCAN; 76 result = uwb_rc_cmd(rc, "SCAN", &cmd->rccb, sizeof(*cmd), 77 &reply.rceb, sizeof(reply)); 78 if (result < 0) 79 goto error_cmd; 80 if (reply.bResultCode != UWB_RC_RES_SUCCESS) { 81 dev_err(&rc->uwb_dev.dev, 82 "SCAN: command execution failed: %s (%d)\n", 83 uwb_rc_strerror(reply.bResultCode), reply.bResultCode); 84 result = -EIO; 85 goto error_cmd; 86 } 87 rc->scanning = channel; 88 rc->scan_type = type; 89error_cmd: 90 mutex_unlock(&rc->uwb_dev.mutex); 91 kfree(cmd); 92error_kzalloc: 93 return result; 94} 95 96/* 97 * Print scanning state 98 */ 99static ssize_t uwb_rc_scan_show(struct device *dev, 100 struct device_attribute *attr, char *buf) 101{ 102 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 103 struct uwb_rc *rc = uwb_dev->rc; 104 ssize_t result; 105 106 mutex_lock(&rc->uwb_dev.mutex); 107 result = sprintf(buf, "%d %d\n", rc->scanning, rc->scan_type); 108 mutex_unlock(&rc->uwb_dev.mutex); 109 return result; 110} 111 112/* 113 * 114 */ 115static ssize_t uwb_rc_scan_store(struct device *dev, 116 struct device_attribute *attr, 117 const char *buf, size_t size) 118{ 119 struct uwb_dev *uwb_dev = to_uwb_dev(dev); 120 struct uwb_rc *rc = uwb_dev->rc; 121 unsigned channel; 122 unsigned type; 123 unsigned bpst_offset = 0; 124 ssize_t result = -EINVAL; 125 126 result = sscanf(buf, "%u %u %u\n", &channel, &type, &bpst_offset); 127 if (result >= 2 && type < UWB_SCAN_TOP) 128 result = uwb_rc_scan(rc, channel, type, bpst_offset); 129 130 return result < 0 ? result : size; 131} 132 133/** Radio Control sysfs interface (declaration) */ 134DEVICE_ATTR(scan, S_IRUGO | S_IWUSR, uwb_rc_scan_show, uwb_rc_scan_store);