View | Details | Raw Unified | Return to bug 142988 | Differences between
and this patch

Collapse All | Expand All

(-)hald/freebsd/hf-usb2.c (+296 lines)
Line 0 Link Here
1
/***************************************************************************
2
 * CVSID: $Id$
3
 *
4
 * hf-usb.c : USB support
5
 *
6
 * Copyright (C) 2009 Joe Marcus Clarke <marcus@FreeBSD.org>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
 *
22
 **************************************************************************/
23
24
#ifdef HAVE_CONFIG_H
25
#  include <config.h>
26
#endif
27
28
#include <string.h>
29
#include <errno.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
#include <libusb20.h>
33
34
#include "../logger.h"
35
#include "../osspec.h"
36
37
#include "hf-usb.h"
38
#include "hf-usb2.h"
39
#include "hf-devtree.h"
40
#include "hf-util.h"
41
42
static struct libusb20_backend *hf_usb2_be = NULL;
43
44
static void
45
hf_usb2_probe_interfaces(HalDevice *parent)
46
{
47
  int num_interfaces;
48
  int i;
49
50
  g_return_if_fail(HAL_IS_DEVICE(parent));
51
52
  if (hal_device_property_get_bool(parent, "info.ignore"))
53
    return;
54
55
  num_interfaces = hal_device_property_get_int(parent,
56
    "usb_device.num_interfaces");
57
58
  for (i = 0; i < num_interfaces; i++)
59
    {
60
      HalDevice *device;
61
62
      device = hf_device_new(parent);
63
64
      hal_device_property_set_string(device, "info.subsystem", "usb");
65
      hal_device_property_set_int(device, "usb.interface.number", i);
66
      hal_device_copy_property(parent, "info.product", device, "info.product");
67
      hal_device_copy_property(parent, "info.vendor", device, "info.vendor");
68
      hal_device_merge_with_rewrite(device, parent, "usb.", "usb_device.");
69
70
      if (hf_device_preprobe(device))
71
        {
72
          const char *driver, *devname;
73
74
          hf_runner_run_sync(device, 0, "hald-probe-usb2-interface", NULL);
75
76
	  devname = hal_device_property_get_string(device,
77
            "usb.freebsd.devname");
78
	  if (devname)
79
            hf_devtree_device_set_name(device, devname);
80
81
	  driver = hal_device_property_get_string(device, "freebsd.driver");
82
	  if (driver)
83
            {
84
	      if (! strcmp(driver, "ukbd"))
85
                hf_device_set_input(device, "keyboard", NULL);
86
	      else if (! strcmp(driver, "ums") || ! strcmp(driver, "atp"))
87
                {
88
                  hf_device_set_input(device, "mouse", devname);
89
	          hf_runner_run_sync(device, 0, "hald-probe-mouse", NULL);
90
	        }
91
	      else if (! strcmp(driver, "uhid"))
92
                {
93
                  hal_device_property_set_string(device, "info.category",
94
                    "hiddev");
95
	          hal_device_add_capability(device, "hiddev");
96
	          hf_device_property_set_string_printf(device, "hiddev.device",
97
                    "/dev/%s", devname);
98
	          hal_device_copy_property(device, "info.product", device,
99
                    "hiddev.product");
100
	          hf_runner_run_sync(device, 0, "hald-probe-hiddev", NULL);
101
	        }
102
	      else if (! strcmp(driver, "ldev"))
103
                {
104
                  /* Linux driver (webcam) */
105
106
	          /*
107
                   * XXX This is a hack.  Currently, all ldev devices are
108
		   * webcams.  That may not always be the case.  Hopefully,
109
		   * when other Linux driver support is added, there will be
110
		   * a sysctl or some other way to determine device class.
111
	           */
112
                  hf_usb_add_webcam_properties(device);
113
	        }
114
	      else if (! strcmp(driver, "pwc"))
115
                {
116
                  /* Phillips Web Cam */
117
                  hf_usb_add_webcam_properties(device);
118
	        }
119
	    }
120
121
	  hf_usb_device_compute_udi(device);
122
	  hf_device_add(device);
123
	}
124
    }
125
}
126
127
static void
128
hf_usb2_probe_device (HalDevice *parent, int bus, int addr)
129
{
130
  HalDevice *device;
131
132
  g_return_if_fail(HAL_IS_DEVICE(parent));
133
134
  device = hf_device_new(parent);
135
136
  hal_device_property_set_string(device, "info.subsystem", "usb_device");
137
  hal_device_property_set_int(device, "usb_device.bus_number", bus);
138
  hal_device_property_set_int(device, "usb_device.level_number", addr - 1);
139
  hal_device_property_set_int(device, "usb_device.port_number", addr);
140
141
  if (hf_device_preprobe(device))
142
    {
143
      hf_runner_run_sync(device, 0, "hald-probe-usb2-device", NULL);
144
      hf_usb_device_compute_udi(device);
145
146
      hf_device_add(device);
147
    }
148
  else
149
    return;
150
151
  hf_usb2_probe_interfaces(device);
152
}
153
154
static void
155
hf_usb2_privileged_init (void)
156
{
157
  hf_usb2_be = libusb20_be_alloc_default();
158
  if (hf_usb2_be == NULL)
159
    HAL_INFO(("unable to open USB backend: %s", g_strerror(errno)));
160
}
161
162
static void
163
hf_usb2_probe (void)
164
{
165
  struct libusb20_device *pdev = NULL;
166
167
  if (hf_usb2_be == NULL)
168
    return;
169
170
  while ((pdev = libusb20_be_device_foreach(hf_usb2_be, pdev)))
171
    {
172
      HalDevice *parent;
173
      int bus, addr;
174
175
      bus = libusb20_dev_get_bus_number(pdev);
176
      addr = libusb20_dev_get_address(pdev);
177
178
      if (addr == 1)
179
        parent = hf_devtree_find_from_info(hald_get_gdl(), "usbus", bus);
180
      else
181
        parent = hf_device_store_match(hald_get_gdl(), "usb_device.bus_number",
182
          HAL_PROPERTY_TYPE_INT32, bus, "usb_device.port_number",
183
	  HAL_PROPERTY_TYPE_INT32, addr - 1, "info.bus",
184
	  HAL_PROPERTY_TYPE_STRING, "usb_device", NULL);
185
      if (! parent || hal_device_property_get_bool(parent, "info.ignore"))
186
        continue;
187
188
      hf_usb2_probe_device(parent, bus, addr);
189
    }
190
191
  libusb20_be_free(hf_usb2_be);
192
  hf_usb2_be = NULL;
193
}
194
195
static gboolean
196
hf_usb2_devd_add (const char *name,
197
		  GHashTable *params,
198
		  GHashTable *at,
199
		  const char *parent)
200
{
201
  HalDevice *parent_device;
202
  int bus, addr, pbus, paddr;
203
204
  if (! parent)
205
    return FALSE;
206
207
  if (strncmp(name, "ugen", strlen("ugen")) &&
208
      ! strncmp(parent, "uhub", strlen("uhub")))
209
    return TRUE;
210
  else if (strncmp(name, "ugen", strlen("ugen")))
211
    return FALSE;
212
  else if (strncmp(parent, "ugen", strlen("ugen")))
213
    return TRUE;
214
215
  if (sscanf(name, "ugen%i.%i", &bus, &addr) != 2)
216
    return FALSE;
217
218
  if (sscanf(parent, "ugen%i.%i", &pbus, &paddr) != 2)
219
    return FALSE;
220
221
  HAL_INFO(("received devd add event for device '%s' with parent '%s'",
222
           name, parent));
223
224
  parent_device = hf_device_store_match(hald_get_gdl(),
225
    "usb_device.bus_number", HAL_PROPERTY_TYPE_INT32, pbus,
226
    "usb_device.port_number", HAL_PROPERTY_TYPE_INT32, paddr, "info.bus",
227
    HAL_PROPERTY_TYPE_STRING, "usb_device", NULL);
228
229
  if (parent_device && ! hal_device_property_get_bool(parent_device,
230
      "info.ignore"))
231
    {
232
      hf_usb2_probe_device(parent_device, bus, addr);
233
      return TRUE;
234
    }
235
236
  return FALSE;
237
}
238
239
static gboolean
240
hf_usb2_devd_remove (const char *name,
241
		     GHashTable *params,
242
		     GHashTable *at,
243
		     const char *parent)
244
{
245
  HalDevice *device;
246
  int bus, addr;
247
248
  if (strncmp(name, "ugen", strlen("ugen")))
249
    return FALSE;
250
251
  if (sscanf(name, "ugen%i.%i", &bus, &addr) != 2)
252
    return FALSE;
253
254
  HAL_INFO(("received devd remove event, device %s", name));
255
256
  device = hf_device_store_match(hald_get_gdl(), "usb_device.bus_number",
257
    HAL_PROPERTY_TYPE_INT32, bus, "usb_device.port_number",
258
    HAL_PROPERTY_TYPE_INT32, addr, "info.bus",
259
    HAL_PROPERTY_TYPE_STRING, "usb_device", NULL);
260
261
  if (device)
262
    {
263
      hf_device_remove_tree(device);
264
      return TRUE;
265
    }
266
267
  return FALSE;
268
}
269
270
static gboolean
271
hf_usb2_devd_notify (const char *system,
272
		     const char *subsystem,
273
		     const char *type,
274
		     const char *data)
275
{
276
  if (! data || strcmp(system, "DEVFS") || strcmp(subsystem, "CDEV") ||
277
      (strcmp(type, "CREATE") && strcmp(type, "DESTROY")))
278
    return FALSE;
279
280
  if (! strncmp(data, "cdev=ugen", strlen("cdev=ugen")) ||
281
      ! strncmp(data, "cdev=usb", strlen("cdev=usb")))
282
    return TRUE;
283
284
  return FALSE;
285
}
286
287
HFHandler hf_usb2_handler = {
288
  .privileged_init	= hf_usb2_privileged_init,
289
  .probe		= hf_usb2_probe
290
};
291
292
HFDevdHandler hf_usb2_devd_handler = {
293
  .add =	hf_usb2_devd_add,
294
  .remove =	hf_usb2_devd_remove,
295
  .notify =     hf_usb2_devd_notify
296
};

Return to bug 142988