Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
bfa414e2
Commit
bfa414e2
authored
Sep 16, 2002
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
USB: Convert the core code to use struct device_driver.
parent
7c3ccad2
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
289 additions
and
559 deletions
+289
-559
drivers/usb/core/devices.c
drivers/usb/core/devices.c
+0
-1
drivers/usb/core/devio.c
drivers/usb/core/devio.c
+17
-44
drivers/usb/core/hcd.c
drivers/usb/core/hcd.c
+3
-5
drivers/usb/core/hcd.h
drivers/usb/core/hcd.h
+1
-7
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+78
-82
drivers/usb/core/hub.h
drivers/usb/core/hub.h
+1
-1
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+172
-393
include/linux/usb.h
include/linux/usb.h
+17
-26
No files found.
drivers/usb/core/devices.c
View file @
bfa414e2
...
...
@@ -111,7 +111,6 @@ static char *format_endpt =
/*
* Need access to the driver and USB bus lists.
* extern struct list_head usb_driver_list;
* extern struct list_head usb_bus_list;
* However, these will come from functions that return ptrs to each of them.
*/
...
...
drivers/usb/core/devio.c
View file @
bfa414e2
...
...
@@ -298,15 +298,15 @@ static void destroy_all_async(struct dev_state *ps)
* they're also undone when devices disconnect.
*/
static
void
*
driver_probe
(
struct
usb_device
*
dev
,
unsigned
int
intf
,
static
int
driver_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
return
NULL
;
return
-
ENODEV
;
}
static
void
driver_disconnect
(
struct
usb_
device
*
dev
,
void
*
context
)
static
void
driver_disconnect
(
struct
usb_
interface
*
intf
)
{
struct
dev_state
*
ps
=
(
struct
dev_state
*
)
context
;
struct
dev_state
*
ps
=
dev_get_drvdata
(
&
intf
->
dev
)
;
if
(
!
ps
)
return
;
...
...
@@ -317,6 +317,7 @@ static void driver_disconnect(struct usb_device *dev, void *context)
/* prevent new I/O requests */
ps
->
dev
=
0
;
ps
->
ifclaimed
=
0
;
dev_set_drvdata
(
&
intf
->
dev
,
NULL
);
/* force async requests to complete */
destroy_all_async
(
ps
);
...
...
@@ -427,30 +428,6 @@ static int findintfif(struct usb_device *dev, unsigned int ifn)
return
-
ENOENT
;
}
extern
struct
list_head
usb_driver_list
;
#if 0
static int finddriver(struct usb_driver **driver, char *name)
{
struct list_head *tmp;
tmp = usb_driver_list.next;
while (tmp != &usb_driver_list) {
struct usb_driver *d = list_entry(tmp, struct usb_driver,
driver_list);
if (!strcmp(d->name, name)) {
*driver = d;
return 0;
}
tmp = tmp->next;
}
return -EINVAL;
}
#endif
static
int
check_ctrlrecip
(
struct
dev_state
*
ps
,
unsigned
int
requesttype
,
unsigned
int
index
)
{
int
ret
;
...
...
@@ -723,11 +700,10 @@ static int proc_resetdevice(struct dev_state *ps)
if
(
test_bit
(
i
,
&
ps
->
ifclaimed
))
continue
;
lock_kernel
(
);
err
(
"%s - this function is broken"
,
__FUNCTION__
);
if
(
intf
->
driver
&&
ps
->
dev
)
{
usb_
bind_driver
(
intf
->
driver
,
intf
);
usb_
device_probe
(
&
intf
->
dev
);
}
unlock_kernel
();
}
return
0
;
...
...
@@ -1090,22 +1066,19 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
/* disconnect kernel driver from interface, leaving it unbound. */
case
USBDEVFS_DISCONNECT
:
/* this function is voodoo. without locking it is a maybe thing */
lock_kernel
();
/* this function is voodoo. */
driver
=
ifp
->
driver
;
if
(
driver
)
{
dbg
(
"disconnect '%s' from dev %d interface %d"
,
driver
->
name
,
ps
->
dev
->
devnum
,
ctrl
.
ifno
);
usb_unbind_driver
(
ps
->
dev
,
ifp
);
usb_driver_release_interface
(
driver
,
ifp
);
usb_device_remove
(
&
ifp
->
dev
);
}
else
retval
=
-
EINVAL
;
unlock_kernel
();
break
;
/* let kernel drivers try to (re)bind to the interface */
case
USBDEVFS_CONNECT
:
usb_find_interface_driver
(
ps
->
dev
,
ifp
);
retval
=
usb_device_probe
(
&
ifp
->
dev
);
break
;
/* talk directly to the interface's driver */
...
...
drivers/usb/core/hcd.c
View file @
bfa414e2
...
...
@@ -722,12 +722,10 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
{
int
retval
;
usb_dev
->
dev
.
parent
=
parent_dev
;
strcpy
(
&
usb_dev
->
dev
.
name
[
0
],
"usb_name"
);
strcpy
(
&
usb_dev
->
dev
.
bus_id
[
0
],
"usb_bus"
);
retval
=
usb_new_device
(
usb_dev
);
sprintf
(
&
usb_dev
->
dev
.
bus_id
[
0
],
"usb%d"
,
usb_dev
->
bus
->
busnum
);
retval
=
usb_new_device
(
usb_dev
,
parent_dev
);
if
(
retval
)
put_device
(
&
usb_dev
->
dev
);
err
(
"%s - usb_new_device failed with value %d"
,
__FUNCTION__
,
retval
);
return
retval
;
}
EXPORT_SYMBOL
(
usb_register_root_hub
);
...
...
drivers/usb/core/hcd.h
View file @
bfa414e2
...
...
@@ -270,7 +270,7 @@ extern void usb_hc_died (struct usb_hcd *hcd);
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern
int
usb_new_device
(
struct
usb_device
*
dev
);
extern
int
usb_new_device
(
struct
usb_device
*
dev
,
struct
device
*
parent
);
extern
void
usb_connect
(
struct
usb_device
*
dev
);
extern
void
usb_disconnect
(
struct
usb_device
**
);
...
...
@@ -396,12 +396,6 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
/* for probe/disconnect with correct module usage counting */
void
*
usb_bind_driver
(
struct
usb_driver
*
driver
,
struct
usb_interface
*
intf
);
void
usb_unbind_driver
(
struct
usb_device
*
device
,
struct
usb_interface
*
intf
);
extern
struct
list_head
usb_driver_list
;
/*
* USB device fs stuff
*/
...
...
drivers/usb/core/hub.c
View file @
bfa414e2
...
...
@@ -175,6 +175,7 @@ static void hub_tt_kevent (void *arg)
while
(
!
list_empty
(
&
hub
->
tt
.
clear_list
))
{
struct
list_head
*
temp
;
struct
usb_tt_clear
*
clear
;
struct
usb_device
*
dev
;
int
status
;
temp
=
hub
->
tt
.
clear_list
.
next
;
...
...
@@ -183,13 +184,13 @@ static void hub_tt_kevent (void *arg)
/* drop lock so HCD can concurrently report other TT errors */
spin_unlock_irqrestore
(
&
hub
->
tt
.
lock
,
flags
);
status
=
hub_clear_tt_buffer
(
hub
->
dev
,
clear
->
devinfo
,
clear
->
tt
);
dev
=
interface_to_usbdev
(
hub
->
intf
);
status
=
hub_clear_tt_buffer
(
dev
,
clear
->
devinfo
,
clear
->
tt
);
spin_lock_irqsave
(
&
hub
->
tt
.
lock
,
flags
);
if
(
status
)
err
(
"usb-%s-%s clear tt %d (%04x) error %d"
,
hub
->
dev
->
bus
->
bus_name
,
hub
->
dev
->
devpath
,
dev
->
bus
->
bus_name
,
dev
->
devpath
,
clear
->
tt
,
clear
->
devinfo
,
status
);
kfree
(
clear
);
}
...
...
@@ -245,12 +246,14 @@ void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe)
static
void
usb_hub_power_on
(
struct
usb_hub
*
hub
)
{
struct
usb_device
*
dev
;
int
i
;
/* Enable power to the ports */
dbg
(
"enabling power on all ports"
);
dev
=
interface_to_usbdev
(
hub
->
intf
);
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
usb_set_port_feature
(
hub
->
dev
,
i
+
1
,
USB_PORT_FEAT_POWER
);
usb_set_port_feature
(
dev
,
i
+
1
,
USB_PORT_FEAT_POWER
);
/* Wait for power to be enabled */
wait_ms
(
hub
->
descriptor
->
bPwrOn2PwrGood
*
2
);
...
...
@@ -259,7 +262,7 @@ static void usb_hub_power_on(struct usb_hub *hub)
static
int
usb_hub_configure
(
struct
usb_hub
*
hub
,
struct
usb_endpoint_descriptor
*
endpoint
)
{
struct
usb_device
*
dev
=
hub
->
dev
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
hub
->
intf
)
;
struct
usb_hub_status
hubstatus
;
unsigned
int
pipe
;
int
maxp
,
ret
;
...
...
@@ -425,39 +428,81 @@ static int usb_hub_configure(struct usb_hub *hub,
return
0
;
}
static
void
*
hub_probe
(
struct
usb_device
*
dev
,
unsigned
int
i
,
const
struct
usb_device_id
*
id
)
static
void
hub_disconnect
(
struct
usb_interface
*
intf
)
{
struct
usb_hub
*
hub
=
dev_get_drvdata
(
&
intf
->
dev
);
unsigned
long
flags
;
if
(
!
hub
)
return
;
dev_set_drvdata
(
&
intf
->
dev
,
NULL
);
spin_lock_irqsave
(
&
hub_event_lock
,
flags
);
/* Delete it and then reset it */
list_del
(
&
hub
->
event_list
);
INIT_LIST_HEAD
(
&
hub
->
event_list
);
list_del
(
&
hub
->
hub_list
);
INIT_LIST_HEAD
(
&
hub
->
hub_list
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
down
(
&
hub
->
khubd_sem
);
/* Wait for khubd to leave this hub alone. */
up
(
&
hub
->
khubd_sem
);
/* assuming we used keventd, it must quiesce too */
if
(
hub
->
tt
.
hub
)
flush_scheduled_tasks
();
if
(
hub
->
urb
)
{
usb_unlink_urb
(
hub
->
urb
);
usb_free_urb
(
hub
->
urb
);
hub
->
urb
=
NULL
;
}
if
(
hub
->
descriptor
)
{
kfree
(
hub
->
descriptor
);
hub
->
descriptor
=
NULL
;
}
/* Free the memory */
kfree
(
hub
);
}
static
int
hub_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_interface_descriptor
*
interface
;
struct
usb_interface_descriptor
*
desc
;
struct
usb_endpoint_descriptor
*
endpoint
;
struct
usb_device
*
dev
;
struct
usb_hub
*
hub
;
unsigned
long
flags
;
interface
=
&
dev
->
actconfig
->
interface
[
i
].
altsetting
[
0
];
desc
=
intf
->
altsetting
+
intf
->
act_altsetting
;
dev
=
interface_to_usbdev
(
intf
);
/* Some hubs have a subclass of 1, which AFAICT according to the */
/* specs is not defined, but it works */
if
((
interface
->
bInterfaceSubClass
!=
0
)
&&
(
interface
->
bInterfaceSubClass
!=
1
))
{
if
((
desc
->
bInterfaceSubClass
!=
0
)
&&
(
desc
->
bInterfaceSubClass
!=
1
))
{
err
(
"invalid subclass (%d) for USB hub device #%d"
,
interface
->
bInterfaceSubClass
,
dev
->
devnum
);
return
NULL
;
desc
->
bInterfaceSubClass
,
dev
->
devnum
);
return
-
EIO
;
}
/* Multiple endpoints? What kind of mutant ninja-hub is this? */
if
(
interface
->
bNumEndpoints
!=
1
)
{
if
(
desc
->
bNumEndpoints
!=
1
)
{
err
(
"invalid bNumEndpoints (%d) for USB hub device #%d"
,
interface
->
bNumEndpoints
,
dev
->
devnum
);
return
NULL
;
desc
->
bNumEndpoints
,
dev
->
devnum
);
return
-
EIO
;
}
endpoint
=
&
interface
->
endpoint
[
0
];
endpoint
=
&
desc
->
endpoint
[
0
];
/* Output endpoint? Curiousier and curiousier.. */
if
(
!
(
endpoint
->
bEndpointAddress
&
USB_DIR_IN
))
{
err
(
"Device #%d is hub class, but has output endpoint?"
,
dev
->
devnum
);
return
NULL
;
return
-
EIO
;
}
/* If it's not an interrupt endpoint, we'd better punt! */
...
...
@@ -465,7 +510,7 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
!=
USB_ENDPOINT_XFER_INT
)
{
err
(
"Device #%d is hub class, but endpoint is not interrupt?"
,
dev
->
devnum
);
return
NULL
;
return
-
EIO
;
}
/* We found a hub */
...
...
@@ -474,13 +519,13 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
hub
=
kmalloc
(
sizeof
(
*
hub
),
GFP_KERNEL
);
if
(
!
hub
)
{
err
(
"couldn't kmalloc hub struct"
);
return
NULL
;
return
-
ENOMEM
;
}
memset
(
hub
,
0
,
sizeof
(
*
hub
));
INIT_LIST_HEAD
(
&
hub
->
event_list
);
hub
->
dev
=
dev
;
hub
->
intf
=
intf
;
init_MUTEX
(
&
hub
->
khubd_sem
);
/* Record the new hub's existence */
...
...
@@ -489,65 +534,17 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
list_add
(
&
hub
->
hub_list
,
&
hub_list
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
dev_set_drvdata
(
&
intf
->
dev
,
hub
);
if
(
usb_hub_configure
(
hub
,
endpoint
)
>=
0
)
{
strcpy
(
dev
->
actconfig
->
interface
[
i
].
dev
.
name
,
"Hub/Port Status Changes"
);
return
hub
;
strcpy
(
intf
->
dev
.
name
,
"Hub/Port Status Changes"
);
return
0
;
}
err
(
"hub configuration failed for device at %s"
,
dev
->
devpath
);
/* free hub, but first clean up its list. */
spin_lock_irqsave
(
&
hub_event_lock
,
flags
);
/* Delete it and then reset it */
list_del
(
&
hub
->
event_list
);
INIT_LIST_HEAD
(
&
hub
->
event_list
);
list_del
(
&
hub
->
hub_list
);
INIT_LIST_HEAD
(
&
hub
->
hub_list
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
kfree
(
hub
);
return
NULL
;
}
static
void
hub_disconnect
(
struct
usb_device
*
dev
,
void
*
ptr
)
{
struct
usb_hub
*
hub
=
(
struct
usb_hub
*
)
ptr
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
hub_event_lock
,
flags
);
/* Delete it and then reset it */
list_del
(
&
hub
->
event_list
);
INIT_LIST_HEAD
(
&
hub
->
event_list
);
list_del
(
&
hub
->
hub_list
);
INIT_LIST_HEAD
(
&
hub
->
hub_list
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
down
(
&
hub
->
khubd_sem
);
/* Wait for khubd to leave this hub alone. */
up
(
&
hub
->
khubd_sem
);
/* assuming we used keventd, it must quiesce too */
if
(
hub
->
tt
.
hub
)
flush_scheduled_tasks
();
if
(
hub
->
urb
)
{
usb_unlink_urb
(
hub
->
urb
);
usb_free_urb
(
hub
->
urb
);
hub
->
urb
=
NULL
;
}
if
(
hub
->
descriptor
)
{
kfree
(
hub
->
descriptor
);
hub
->
descriptor
=
NULL
;
}
/* Free the memory */
kfree
(
hub
);
hub_disconnect
(
intf
);
return
-
ENODEV
;
}
static
int
hub_ioctl
(
struct
usb_device
*
hub
,
unsigned
int
code
,
void
*
user_data
)
...
...
@@ -584,7 +581,7 @@ static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
static
int
usb_hub_reset
(
struct
usb_hub
*
hub
)
{
struct
usb_device
*
dev
=
hub
->
dev
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
hub
->
intf
)
;
int
i
;
/* Disconnect any attached devices */
...
...
@@ -796,7 +793,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
static
void
usb_hub_port_connect_change
(
struct
usb_hub
*
hubstate
,
int
port
,
u16
portstatus
,
u16
portchange
)
{
struct
usb_device
*
hub
=
hubstate
->
dev
;
struct
usb_device
*
hub
=
interface_to_usbdev
(
hubstate
->
intf
)
;
struct
usb_device
*
dev
;
unsigned
int
delay
=
HUB_SHORT_RESET_TIME
;
int
i
;
...
...
@@ -891,11 +888,10 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
/* put the device in the global device tree. the hub port
* is the "bus_id"; hubs show in hierarchy like bridges
*/
dev
->
dev
.
parent
=
&
dev
->
parent
->
dev
;
sprintf
(
&
dev
->
dev
.
bus_id
[
0
],
"%d"
,
port
+
1
);
dev
->
dev
.
parent
=
dev
->
parent
->
dev
.
parent
->
parent
;
/* Run it through the hoops (find a driver, etc) */
if
(
!
usb_new_device
(
dev
))
if
(
!
usb_new_device
(
dev
,
&
hub
->
dev
))
goto
done
;
/* Free the configuration if there was an error */
...
...
@@ -940,7 +936,7 @@ static void usb_hub_events(void)
tmp
=
hub_event_list
.
next
;
hub
=
list_entry
(
tmp
,
struct
usb_hub
,
event_list
);
dev
=
hub
->
dev
;
dev
=
interface_to_usbdev
(
hub
->
intf
)
;
list_del
(
tmp
);
INIT_LIST_HEAD
(
tmp
);
...
...
@@ -1081,8 +1077,8 @@ MODULE_DEVICE_TABLE (usb, hub_id_table);
static
struct
usb_driver
hub_driver
=
{
.
name
=
"hub"
,
.
probe
=
hub_probe
,
.
ioctl
=
hub_ioctl
,
.
disconnect
=
hub_disconnect
,
.
ioctl
=
hub_ioctl
,
.
id_table
=
hub_id_table
,
};
...
...
drivers/usb/core/hub.h
View file @
bfa414e2
...
...
@@ -170,7 +170,7 @@ struct usb_tt_clear {
extern
void
usb_hub_tt_clear_buffer
(
struct
usb_device
*
dev
,
int
pipe
);
struct
usb_hub
{
struct
usb_
device
*
dev
;
/* the "real" device */
struct
usb_
interface
*
intf
;
/* the "real" device */
struct
urb
*
urb
;
/* for interrupt polling pipe */
/* buffer for urb ... 1 bit each for hub and children, rounded up */
...
...
drivers/usb/core/usb.c
View file @
bfa414e2
...
...
@@ -48,225 +48,139 @@ extern void usb_hub_cleanup(void);
extern
int
usb_major_init
(
void
);
extern
void
usb_major_cleanup
(
void
);
/*
* Prototypes for the device driver probing/loading functions
*/
static
void
usb_find_drivers
(
struct
usb_device
*
);
static
void
usb_check_support
(
struct
usb_device
*
);
/*
* We have a per-interface "registered driver" list.
*/
LIST_HEAD
(
usb_driver_list
);
/**
* usb_register - register a USB driver
* @new_driver: USB operations for the driver
*
* Registers a USB driver with the USB core. The list of unattached
* interfaces will be rescanned whenever a new driver is added, allowing
* the new driver to attach to any recognized devices.
* Returns a negative error code on failure and 0 on success.
*
* NOTE: if you want your driver to use the USB major number, you must call
* usb_register_dev() to enable that functionality. This function no longer
* takes care of that.
*/
int
usb_register
(
struct
usb_driver
*
new_driver
)
static
int
generic_probe
(
struct
device
*
dev
)
{
int
retval
=
0
;
info
(
"registered new driver %s"
,
new_driver
->
name
);
init_MUTEX
(
&
new_driver
->
serialize
);
return
0
;
}
static
int
generic_remove
(
struct
device
*
dev
)
{
return
0
;
}
static
void
generic_release
(
struct
device_driver
*
drv
)
{
}
/* Add it to the list of known drivers */
list_add_tail
(
&
new_driver
->
driver_list
,
&
usb_driver_list
);
static
struct
device_driver
usb_generic_driver
=
{
.
name
=
"generic usb driver"
,
.
probe
=
generic_probe
,
.
remove
=
generic_remove
,
.
release
=
generic_release
,
};
usb_scan_devices
();
int
usb_device_probe
(
struct
device
*
dev
)
{
struct
usb_interface
*
intf
=
to_usb_interface
(
dev
);
struct
usb_driver
*
driver
=
to_usb_driver
(
dev
->
driver
);
const
struct
usb_device_id
*
id
;
int
error
=
-
ENODEV
;
int
m
;
usbfs_update_special
(
);
dbg
(
"%s"
,
__FUNCTION__
);
return
retval
;
}
if
(
!
driver
->
probe
)
return
error
;
if
(
driver
->
owner
)
{
m
=
try_inc_mod_count
(
driver
->
owner
);
if
(
m
==
0
)
return
error
;
}
/**
* usb_scan_devices - scans all unclaimed USB interfaces
* Context: !in_interrupt ()
*
* Goes through all unclaimed USB interfaces, and offers them to all
* registered USB drivers through the 'probe' function.
* This will automatically be called after usb_register is called.
* It is called by some of the subsystems layered over USB
* after one of their subdrivers are registered.
*/
void
usb_scan_devices
(
void
)
{
struct
list_head
*
tmp
;
id
=
usb_match_id
(
intf
,
driver
->
id_table
);
if
(
id
)
{
dbg
(
"%s - got id"
,
__FUNCTION__
);
down
(
&
driver
->
serialize
);
error
=
driver
->
probe
(
intf
,
id
);
up
(
&
driver
->
serialize
);
}
if
(
!
error
)
intf
->
driver
=
driver
;
down
(
&
usb_bus_list_lock
);
tmp
=
usb_bus_list
.
next
;
while
(
tmp
!=
&
usb_bus_list
)
{
struct
usb_bus
*
bus
=
list_entry
(
tmp
,
struct
usb_bus
,
bus_list
);
if
(
driver
->
owner
)
__MOD_DEC_USE_COUNT
(
driver
->
owner
);
tmp
=
tmp
->
next
;
usb_check_support
(
bus
->
root_hub
);
}
up
(
&
usb_bus_list_lock
);
return
error
;
}
/**
* usb_unbind_driver - disconnects a driver from a device (usbcore-internal)
* @device: usb device to be disconnected
* @intf: interface of the device to be disconnected
* Context: BKL held
*
* Handles module usage count correctly
*/
void
usb_unbind_driver
(
struct
usb_device
*
device
,
struct
usb_interface
*
intf
)
int
usb_device_remove
(
struct
device
*
dev
)
{
struct
usb_interface
*
intf
;
struct
usb_driver
*
driver
;
void
*
priv
;
int
m
;
intf
=
list_entry
(
dev
,
struct
usb_interface
,
dev
);
driver
=
to_usb_driver
(
dev
->
driver
);
driver
=
intf
->
driver
;
priv
=
intf
->
private_data
;
if
(
!
driver
||
!
driver
->
disconnect
)
return
;
if
(
!
driver
)
{
err
(
"%s does not have a valid driver to work with!"
,
__FUNCTION__
);
return
-
ENODEV
;
}
/* as soon as we increase the module use count we drop the BKL
before that we must not sleep */
if
(
driver
->
owner
)
{
m
=
try_inc_mod_count
(
driver
->
owner
);
if
(
m
==
0
)
{
err
(
"Dieing driver still bound to device.
\n
"
);
return
;
return
-
EIO
;
}
unlock_kernel
();
}
down
(
&
driver
->
serialize
);
/* if we sleep here on an umanaged driver
the holder of the lock guards against
module unload */
driver
->
disconnect
(
device
,
priv
);
/* if we sleep here on an umanaged driver
* the holder of the lock guards against
* module unload */
down
(
&
driver
->
serialize
);
if
(
intf
->
driver
&&
intf
->
driver
->
disconnect
)
intf
->
driver
->
disconnect
(
intf
);
/* if driver->disconnect didn't release the interface */
if
(
intf
->
driver
)
usb_driver_release_interface
(
driver
,
intf
);
up
(
&
driver
->
serialize
);
if
(
driver
->
owner
)
{
lock_kernel
();
if
(
driver
->
owner
)
__MOD_DEC_USE_COUNT
(
driver
->
owner
);
}
return
0
;
}
/**
* usb_bind_driver - connect a driver to a device's interface (usbcore-internal)
* @driver: device driver to be bound to interface
* @interface: interface that the driver will be using
* Context: BKL held
* usb_register - register a USB driver
* @new_driver: USB operations for the driver
*
* Does a safe binding of a driver to one of a device's interfaces.
* Returns the driver's data for the binding, or null indicating
* that the driver did not bind to this interface.
* Registers a USB driver with the USB core. The list of unattached
* interfaces will be rescanned whenever a new driver is added, allowing
* the new driver to attach to any recognized devices.
* Returns a negative error code on failure and 0 on success.
*
*
This differs from usb_driver_claim_interface(), which is called from
*
drivers and neither calls the driver's probe() entry nor does any
*
locking to guard against removing driver modules
.
*
NOTE: if you want your driver to use the USB major number, you must call
*
usb_register_dev() to enable that functionality. This function no longer
*
takes care of that
.
*/
void
*
usb_bind_driver
(
struct
usb_driver
*
driver
,
struct
usb_interface
*
interface
)
int
usb_register
(
struct
usb_driver
*
new_driver
)
{
int
i
,
m
;
void
*
private
=
NULL
;
const
struct
usb_device_id
*
id
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
interface
);
int
ifnum
;
if
(
driver
->
owner
)
{
m
=
try_inc_mod_count
(
driver
->
owner
);
if
(
m
==
0
)
return
NULL
;
/* this horse is dead - don't ride*/
unlock_kernel
();
}
// START TEMPORARY
// driver->probe() hasn't yet changed to take interface not dev+ifnum,
// so we still need ifnum here.
for
(
ifnum
=
0
;
ifnum
<
dev
->
actconfig
->
bNumInterfaces
;
ifnum
++
)
if
(
&
dev
->
actconfig
->
interface
[
ifnum
]
==
interface
)
break
;
BUG_ON
(
ifnum
==
dev
->
actconfig
->
bNumInterfaces
);
// END TEMPORARY
id
=
driver
->
id_table
;
/* new style driver? */
if
(
id
)
{
for
(
i
=
0
;
i
<
interface
->
num_altsetting
;
i
++
)
{
interface
->
act_altsetting
=
i
;
id
=
usb_match_id
(
interface
,
id
);
if
(
id
)
{
down
(
&
driver
->
serialize
);
private
=
driver
->
probe
(
dev
,
ifnum
,
id
);
up
(
&
driver
->
serialize
);
if
(
private
!=
NULL
)
break
;
}
}
int
retval
=
0
;
/* if driver not bound, leave defaults unchanged */
if
(
private
==
NULL
)
interface
->
act_altsetting
=
0
;
}
else
{
/* "old style" driver */
down
(
&
driver
->
serialize
);
private
=
driver
->
probe
(
dev
,
ifnum
,
NULL
);
up
(
&
driver
->
serialize
);
}
if
(
driver
->
owner
)
{
lock_kernel
();
__MOD_DEC_USE_COUNT
(
driver
->
owner
);
}
new_driver
->
driver
.
name
=
(
char
*
)
new_driver
->
name
;
new_driver
->
driver
.
bus
=
&
usb_bus_type
;
new_driver
->
driver
.
probe
=
usb_device_probe
;
new_driver
->
driver
.
remove
=
usb_device_remove
;
return
private
;
}
init_MUTEX
(
&
new_driver
->
serialize
);
/*
* This function is part of a depth-first search down the device tree,
* removing any instances of a device driver.
*/
static
void
usb_drivers_purge
(
struct
usb_driver
*
driver
,
struct
usb_device
*
dev
)
{
int
i
;
retval
=
driver_register
(
&
new_driver
->
driver
);
if
(
!
dev
)
{
err
(
"null device being purged!!!"
);
return
;
if
(
!
retval
)
{
info
(
"registered new driver %s"
,
new_driver
->
name
);
usbfs_update_special
();
}
else
{
err
(
"problem %d when registering driver %s"
,
retval
,
new_driver
->
name
);
}
for
(
i
=
0
;
i
<
USB_MAXCHILDREN
;
i
++
)
if
(
dev
->
children
[
i
])
usb_drivers_purge
(
driver
,
dev
->
children
[
i
]);
if
(
!
dev
->
actconfig
)
return
;
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
interface
=
&
dev
->
actconfig
->
interface
[
i
];
if
(
interface
->
driver
==
driver
)
{
usb_unbind_driver
(
dev
,
interface
);
/* if driver->disconnect didn't release the interface */
if
(
interface
->
driver
)
usb_driver_release_interface
(
driver
,
interface
);
/*
* This will go through the list looking for another
* driver that can handle the device
*/
usb_find_interface_driver
(
dev
,
interface
);
}
}
return
retval
;
}
/**
...
...
@@ -282,25 +196,9 @@ static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
*/
void
usb_deregister
(
struct
usb_driver
*
driver
)
{
struct
list_head
*
tmp
;
info
(
"deregistering driver %s"
,
driver
->
name
);
/*
* first we remove the driver, to be sure it doesn't get used by
* another thread while we are stepping through removing entries
*/
list_del
(
&
driver
->
driver_list
);
down
(
&
usb_bus_list_lock
);
tmp
=
usb_bus_list
.
next
;
while
(
tmp
!=
&
usb_bus_list
)
{
struct
usb_bus
*
bus
=
list_entry
(
tmp
,
struct
usb_bus
,
bus_list
);
tmp
=
tmp
->
next
;
usb_drivers_purge
(
driver
,
bus
->
root_hub
);
}
up
(
&
usb_bus_list_lock
);
remove_driver
(
&
driver
->
driver
);
usbfs_update_special
();
}
...
...
@@ -359,34 +257,6 @@ struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, uns
return
NULL
;
}
/*
* This function is for doing a depth-first search for devices which
* have support, for dynamic loading of driver modules.
*/
static
void
usb_check_support
(
struct
usb_device
*
dev
)
{
int
i
;
if
(
!
dev
)
{
err
(
"null device being checked!!!"
);
return
;
}
for
(
i
=
0
;
i
<
USB_MAXCHILDREN
;
i
++
)
if
(
dev
->
children
[
i
])
usb_check_support
(
dev
->
children
[
i
]);
if
(
!
dev
->
actconfig
)
return
;
/* now we check this device */
if
(
dev
->
devnum
>
0
)
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
usb_find_interface_driver
(
dev
,
dev
->
actconfig
->
interface
+
i
);
}
/**
* usb_driver_claim_interface - bind a driver to an interface
* @driver: the driver to be bound
...
...
@@ -418,7 +288,7 @@ void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface
iface
->
driver
=
driver
;
iface
->
private_data
=
priv
;
}
/* usb_driver_claim_interface() */
}
/**
* usb_interface_claimed - returns true iff an interface is claimed
...
...
@@ -463,7 +333,6 @@ void usb_driver_release_interface(struct usb_driver *driver, struct usb_interfac
iface
->
private_data
=
NULL
;
}
/**
* usb_match_id - find first usb_device_id matching device or interface
* @interface: the interface of interest
...
...
@@ -595,72 +464,25 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
return
NULL
;
}
/*
* This entrypoint gets called for unclaimed interfaces.
*
* We now walk the list of registered USB drivers,
* looking for one that will accept this interface.
*
* "New Style" drivers use a table describing the devices and interfaces
* they handle. Those tables are available to user mode tools deciding
* whether to load driver modules for a new device.
*
* The probe return value is changed to be a private pointer. This way
* the drivers don't have to dig around in our structures to set the
* private pointer if they only need one interface.
*
* Returns: 0 if a driver accepted the interface, -1 otherwise
*/
int
usb_find_interface_driver
(
struct
usb_device
*
dev
,
struct
usb_interface
*
interface
)
static
int
usb_device_match
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
struct
list_head
*
tmp
;
void
*
private
;
struct
usb_driver
*
driver
;
int
ifnum
;
down
(
&
dev
->
serialize
);
/* FIXME It's just luck that for some devices with drivers that set
* configuration in probe(), the interface numbers still make sense.
* That's one of several unsafe assumptions involved in configuring
* devices, and in binding drivers to their interfaces.
*/
for
(
ifnum
=
0
;
ifnum
<
dev
->
actconfig
->
bNumInterfaces
;
ifnum
++
)
if
(
&
dev
->
actconfig
->
interface
[
ifnum
]
==
interface
)
break
;
BUG_ON
(
ifnum
==
dev
->
actconfig
->
bNumInterfaces
);
if
(
usb_interface_claimed
(
interface
))
goto
out_err
;
struct
usb_interface
*
intf
;
struct
usb_driver
*
usb_drv
;
const
struct
usb_device_id
*
id
;
private
=
NULL
;
lock_kernel
();
for
(
tmp
=
usb_driver_list
.
next
;
tmp
!=
&
usb_driver_list
;)
{
driver
=
list_entry
(
tmp
,
struct
usb_driver
,
driver_list
);
tmp
=
tmp
->
next
;
intf
=
to_usb_interface
(
dev
);
private
=
usb_bind_driver
(
driver
,
interface
);
usb_drv
=
to_usb_driver
(
drv
);
id
=
usb_drv
->
id_table
;
/* probe() may have changed the config on us */
interface
=
dev
->
actconfig
->
interface
+
ifnum
;
id
=
usb_match_id
(
intf
,
usb_drv
->
id_table
);
if
(
id
)
return
1
;
if
(
private
)
{
usb_driver_claim_interface
(
driver
,
interface
,
private
);
up
(
&
dev
->
serialize
);
unlock_kernel
();
return
0
;
}
}
unlock_kernel
();
out_err:
up
(
&
dev
->
serialize
);
return
-
1
;
}
#ifdef CONFIG_HOTPLUG
/*
...
...
@@ -890,71 +712,6 @@ show_serial (struct device *dev, char *buf, size_t count, loff_t off)
}
static
DEVICE_ATTR
(
serial
,
S_IRUGO
,
show_serial
,
NULL
);
/*
* This entrypoint gets called for each new device.
*
* All interfaces are scanned for matching drivers.
*/
static
void
usb_find_drivers
(
struct
usb_device
*
dev
)
{
unsigned
ifnum
;
unsigned
rejected
=
0
;
unsigned
claimed
=
0
;
/* FIXME should get called for each new configuration not just the
* first one for a device. switching configs (or altsettings) should
* undo driverfs and HCD state for the previous interfaces.
*/
for
(
ifnum
=
0
;
ifnum
<
dev
->
actconfig
->
bNumInterfaces
;
ifnum
++
)
{
struct
usb_interface
*
interface
=
&
dev
->
actconfig
->
interface
[
ifnum
];
struct
usb_interface_descriptor
*
desc
=
interface
->
altsetting
;
/* register this interface with driverfs */
interface
->
dev
.
parent
=
&
dev
->
dev
;
interface
->
dev
.
bus
=
&
usb_bus_type
;
sprintf
(
&
interface
->
dev
.
bus_id
[
0
],
"%s-%s:%d"
,
dev
->
bus
->
bus_name
,
dev
->
devpath
,
interface
->
altsetting
->
bInterfaceNumber
);
if
(
!
desc
->
iInterface
||
usb_string
(
dev
,
desc
->
iInterface
,
interface
->
dev
.
name
,
sizeof
interface
->
dev
.
name
)
<=
0
)
{
/* typically devices won't bother with interface
* descriptions; this is the normal case. an
* interface's driver might describe it better.
* (also: iInterface is per-altsetting ...)
*/
sprintf
(
&
interface
->
dev
.
name
[
0
],
"usb-%s-%s interface %d"
,
dev
->
bus
->
bus_name
,
dev
->
devpath
,
interface
->
altsetting
->
bInterfaceNumber
);
}
device_register
(
&
interface
->
dev
);
device_create_file
(
&
interface
->
dev
,
&
dev_attr_altsetting
);
/* if this interface hasn't already been claimed */
if
(
!
usb_interface_claimed
(
interface
))
{
if
(
usb_find_interface_driver
(
dev
,
interface
))
rejected
++
;
else
claimed
++
;
}
}
if
(
rejected
)
dbg
(
"unhandled interfaces on device"
);
if
(
!
claimed
)
{
warn
(
"USB device %d (vend/prod 0x%x/0x%x) is not claimed by any active driver."
,
dev
->
devnum
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
);
#ifdef DEBUG
usb_show_device
(
dev
);
#endif
}
}
/**
* usb_alloc_dev - allocate a usb device structure (usbcore-internal)
* @parent: hub to which device is connected
...
...
@@ -1109,32 +866,21 @@ void usb_disconnect(struct usb_device **pdev)
info
(
"USB disconnect on device %d"
,
dev
->
devnum
);
lock_kernel
();
if
(
dev
->
actconfig
)
{
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
interface
=
&
dev
->
actconfig
->
interface
[
i
];
struct
usb_driver
*
driver
=
interface
->
driver
;
if
(
driver
)
{
usb_unbind_driver
(
dev
,
interface
);
/* if driver->disconnect didn't release the interface */
if
(
interface
->
driver
)
usb_driver_release_interface
(
driver
,
interface
);
}
/* remove our device node for this interface */
put_device
(
&
interface
->
dev
);
}
}
unlock_kernel
();
/* Free up all the children.. */
/* Free up all the children before we remove this device */
for
(
i
=
0
;
i
<
USB_MAXCHILDREN
;
i
++
)
{
struct
usb_device
**
child
=
dev
->
children
+
i
;
if
(
*
child
)
usb_disconnect
(
child
);
}
/* Let policy agent unload modules etc */
call_policy
(
"remove"
,
dev
);
if
(
dev
->
actconfig
)
{
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
interface
=
&
dev
->
actconfig
->
interface
[
i
];
/* remove this interface */
put_device
(
&
interface
->
dev
);
}
}
/* Free the device number and remove the /proc/bus/usb entry */
if
(
dev
->
devnum
>
0
)
{
...
...
@@ -1143,6 +889,9 @@ void usb_disconnect(struct usb_device **pdev)
put_device
(
&
dev
->
dev
);
}
/* Let policy agent unload modules etc */
call_policy
(
"remove"
,
dev
);
/* Decrement the reference count, it'll auto free everything when */
/* it hits 0 which could very well be now */
usb_put_dev
(
dev
);
...
...
@@ -1271,7 +1020,7 @@ static void set_device_description (struct usb_device *dev)
*/
#define NEW_DEVICE_RETRYS 2
#define SET_ADDRESS_RETRYS 2
int
usb_new_device
(
struct
usb_device
*
dev
)
int
usb_new_device
(
struct
usb_device
*
dev
,
struct
device
*
parent
)
{
int
err
=
0
;
int
i
;
...
...
@@ -1361,10 +1110,23 @@ int usb_new_device(struct usb_device *dev)
usb_show_string
(
dev
,
"SerialNumber"
,
dev
->
descriptor
.
iSerialNumber
);
#endif
/* register this device in the driverfs tree */
/*
* Set the driver for the usb device to point to the "generic" driver.
* This prevents the main usb device from being sent to the usb bus
* probe function. Yes, it's a hack, but a nice one :)
*/
usb_generic_driver
.
bus
=
&
usb_bus_type
;
dev
->
dev
.
parent
=
parent
;
dev
->
dev
.
driver
=
&
usb_generic_driver
;
dev
->
dev
.
bus
=
&
usb_bus_type
;
if
(
dev
->
dev
.
bus_id
[
0
]
==
0
)
sprintf
(
&
dev
->
dev
.
bus_id
[
0
],
"%d-%s"
,
dev
->
bus
->
busnum
,
dev
->
devpath
);
err
=
device_register
(
&
dev
->
dev
);
if
(
err
)
return
err
;
/* add the USB device specific driverfs files */
device_create_file
(
&
dev
->
dev
,
&
dev_attr_configuration
);
if
(
dev
->
descriptor
.
iManufacturer
)
device_create_file
(
&
dev
->
dev
,
&
dev_attr_manufacturer
);
...
...
@@ -1373,11 +1135,38 @@ int usb_new_device(struct usb_device *dev)
if
(
dev
->
descriptor
.
iSerialNumber
)
device_create_file
(
&
dev
->
dev
,
&
dev_attr_serial
);
/* now that the basic setup is over, add a /proc/bus/usb entry */
usbfs_add_device
(
dev
);
/* Register all of the interfaces for this device with the driver core.
* Remember, interfaces get bound to drivers, not devices. */
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
interface
=
&
dev
->
actconfig
->
interface
[
i
];
struct
usb_interface_descriptor
*
desc
=
interface
->
altsetting
;
/* find drivers willing to handle this device */
usb_find_drivers
(
dev
);
interface
->
dev
.
parent
=
&
dev
->
dev
;
interface
->
dev
.
bus
=
&
usb_bus_type
;
sprintf
(
&
interface
->
dev
.
bus_id
[
0
],
"%d-%s:%d"
,
dev
->
bus
->
busnum
,
dev
->
devpath
,
interface
->
altsetting
->
bInterfaceNumber
);
if
(
!
desc
->
iInterface
||
usb_string
(
dev
,
desc
->
iInterface
,
interface
->
dev
.
name
,
sizeof
interface
->
dev
.
name
)
<=
0
)
{
/* typically devices won't bother with interface
* descriptions; this is the normal case. an
* interface's driver might describe it better.
* (also: iInterface is per-altsetting ...)
*/
sprintf
(
&
interface
->
dev
.
name
[
0
],
"usb-%s-%s interface %d"
,
dev
->
bus
->
bus_name
,
dev
->
devpath
,
interface
->
altsetting
->
bInterfaceNumber
);
}
dbg
(
"%s - registering %s"
,
__FUNCTION__
,
interface
->
dev
.
bus_id
);
device_register
(
&
interface
->
dev
);
device_create_file
(
&
interface
->
dev
,
&
dev_attr_altsetting
);
}
/* add a /proc/bus/usb entry */
usbfs_add_device
(
dev
);
/* userspace may load modules and/or configure further */
call_policy
(
"add"
,
dev
);
...
...
@@ -1385,7 +1174,6 @@ int usb_new_device(struct usb_device *dev)
return
0
;
}
/**
* usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_DMA_MAP
* @dev: device the buffer will be used with
...
...
@@ -1531,7 +1319,6 @@ void usb_buffer_unmap (struct urb *urb)
?
USB_DIR_IN
:
USB_DIR_OUT
);
}
/**
* usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
* @dev: device to which the scatterlist will be mapped
...
...
@@ -1642,20 +1429,10 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
:
USB_DIR_OUT
);
}
#ifdef CONFIG_PROC_FS
struct
list_head
*
usb_driver_get_list
(
void
)
{
return
&
usb_driver_list
;
}
struct
list_head
*
usb_bus_get_list
(
void
)
{
return
&
usb_bus_list
;
}
#endif
struct
bus_type
usb_bus_type
=
{
.
name
=
"usb"
,
.
match
=
usb_device_match
,
};
/*
...
...
@@ -1694,7 +1471,9 @@ EXPORT_SYMBOL(usb_epnum_to_ep_desc);
EXPORT_SYMBOL
(
usb_register
);
EXPORT_SYMBOL
(
usb_deregister
);
EXPORT_SYMBOL
(
usb_scan_devices
);
EXPORT_SYMBOL
(
usb_device_probe
);
EXPORT_SYMBOL
(
usb_device_remove
);
EXPORT_SYMBOL
(
usb_alloc_dev
);
EXPORT_SYMBOL
(
usb_free_dev
);
...
...
include/linux/usb.h
View file @
bfa414e2
...
...
@@ -399,9 +399,6 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern
void
usb_free_dev
(
struct
usb_device
*
);
#define usb_put_dev usb_free_dev
/* for when layers above USB add new non-USB drivers */
extern
void
usb_scan_devices
(
void
);
/* mostly for devices emulating SCSI over USB */
extern
int
usb_reset_device
(
struct
usb_device
*
dev
);
...
...
@@ -623,10 +620,10 @@ struct usb_device_id {
* expose information to user space regardless of where they
* do (or don't) show up otherwise in the filesystem.
* @id_table: USB drivers use ID table to support hotplugging.
* Export this with MODULE_DEVICE_TABLE(usb,...)
, or use NULL to
*
say that probe() should be called for any unclaimed interfce.
* Export this with MODULE_DEVICE_TABLE(usb,...)
. This must be set
*
or your driver's probe function will never get called.
*
* USB drivers
should
provide a name, probe() and disconnect() methods,
* USB drivers
must
provide a name, probe() and disconnect() methods,
* and an id_table. Other driver fields are optional.
*
* The id_table is used in hotplugging. It holds a set of descriptors,
...
...
@@ -643,32 +640,23 @@ struct usb_device_id {
*/
struct
usb_driver
{
struct
module
*
owner
;
const
char
*
name
;
void
*
(
*
probe
)(
struct
usb_device
*
dev
,
/* the device */
unsigned
intf
,
/* what interface */
const
struct
usb_device_id
*
id
/* from id_table */
);
void
(
*
disconnect
)(
struct
usb_device
*
dev
,
/* the device */
void
*
handle
/* as returned by probe() */
);
struct
list_head
driver_list
;
struct
semaphore
serialize
;
int
(
*
probe
)
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
/* ioctl -- userspace apps can talk to drivers through usbfs */
int
(
*
ioctl
)(
struct
usb_device
*
dev
,
unsigned
int
code
,
void
*
buf
);
void
(
*
disconnect
)
(
struct
usb_interface
*
intf
);
int
(
*
ioctl
)
(
struct
usb_device
*
dev
,
unsigned
int
code
,
void
*
buf
);
/* support for "new-style" USB hotplugging */
const
struct
usb_device_id
*
id_table
;
/* suspend before the bus suspends;
* disconnect or resume when the bus resumes */
/* void (*suspend)(struct usb_device *dev); */
/* void (*resume)(struct usb_device *dev); */
struct
device_driver
driver
;
struct
semaphore
serialize
;
};
#define to_usb_driver(d) container_of(d, struct usb_driver, driver)
extern
struct
bus_type
usb_bus_type
;
...
...
@@ -682,6 +670,9 @@ extern void usb_deregister(struct usb_driver *);
extern
int
usb_register_dev
(
struct
file_operations
*
fops
,
int
minor
,
int
num_minors
,
int
*
start_minor
);
extern
void
usb_deregister_dev
(
int
num_minors
,
int
start_minor
);
extern
int
usb_device_probe
(
struct
device
*
dev
);
extern
int
usb_device_remove
(
struct
device
*
dev
);
/* -------------------------------------------------------------------------- */
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment