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