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
Kirill Smelkov
linux
Commits
1a2f7297
Commit
1a2f7297
authored
May 29, 2002
by
Patrick Mochel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
USB: Move synchronous message passing code from usb.c to message.c
parent
76c05fd6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
663 additions
and
655 deletions
+663
-655
drivers/usb/core/Makefile
drivers/usb/core/Makefile
+2
-2
drivers/usb/core/message.c
drivers/usb/core/message.c
+661
-0
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+0
-653
No files found.
drivers/usb/core/Makefile
View file @
1a2f7297
...
...
@@ -2,9 +2,9 @@
# Makefile for USB Core files and filesystem
#
export-objs
:=
usb.o hcd.o urb.o
export-objs
:=
usb.o hcd.o urb.o
message.o
usbcore-objs
:=
usb.o usb-debug.o hub.o hcd.o urb.o
usbcore-objs
:=
usb.o usb-debug.o hub.o hcd.o urb.o
message.o
ifeq
($(CONFIG_USB_DEVICEFS),y)
usbcore-objs
+=
devio.o inode.o drivers.o devices.o
...
...
drivers/usb/core/message.c
0 → 100644
View file @
1a2f7297
/*
* message.c - synchronous message handling
*/
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/byteorder.h>
struct
usb_api_data
{
wait_queue_head_t
wqh
;
int
done
;
};
static
void
usb_api_blocking_completion
(
struct
urb
*
urb
)
{
struct
usb_api_data
*
awd
=
(
struct
usb_api_data
*
)
urb
->
context
;
awd
->
done
=
1
;
wmb
();
wake_up
(
&
awd
->
wqh
);
}
// Starts urb and waits for completion or timeout
static
int
usb_start_wait_urb
(
struct
urb
*
urb
,
int
timeout
,
int
*
actual_length
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
usb_api_data
awd
;
int
status
;
init_waitqueue_head
(
&
awd
.
wqh
);
awd
.
done
=
0
;
set_current_state
(
TASK_UNINTERRUPTIBLE
);
add_wait_queue
(
&
awd
.
wqh
,
&
wait
);
urb
->
context
=
&
awd
;
status
=
usb_submit_urb
(
urb
,
GFP_KERNEL
);
if
(
status
)
{
// something went wrong
usb_free_urb
(
urb
);
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
awd
.
wqh
,
&
wait
);
return
status
;
}
while
(
timeout
&&
!
awd
.
done
)
{
timeout
=
schedule_timeout
(
timeout
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
rmb
();
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
awd
.
wqh
,
&
wait
);
if
(
!
timeout
&&
!
awd
.
done
)
{
if
(
urb
->
status
!=
-
EINPROGRESS
)
{
/* No callback?!! */
printk
(
KERN_ERR
"usb: raced timeout, "
"pipe 0x%x status %d time left %d
\n
"
,
urb
->
pipe
,
urb
->
status
,
timeout
);
status
=
urb
->
status
;
}
else
{
printk
(
"usb_control/bulk_msg: timeout
\n
"
);
usb_unlink_urb
(
urb
);
// remove urb safely
status
=
-
ETIMEDOUT
;
}
}
else
status
=
urb
->
status
;
if
(
actual_length
)
*
actual_length
=
urb
->
actual_length
;
usb_free_urb
(
urb
);
return
status
;
}
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
int
usb_internal_control_msg
(
struct
usb_device
*
usb_dev
,
unsigned
int
pipe
,
struct
usb_ctrlrequest
*
cmd
,
void
*
data
,
int
len
,
int
timeout
)
{
struct
urb
*
urb
;
int
retv
;
int
length
;
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
urb
)
return
-
ENOMEM
;
FILL_CONTROL_URB
(
urb
,
usb_dev
,
pipe
,
(
unsigned
char
*
)
cmd
,
data
,
len
,
usb_api_blocking_completion
,
0
);
retv
=
usb_start_wait_urb
(
urb
,
timeout
,
&
length
);
if
(
retv
<
0
)
return
retv
;
else
return
length
;
}
/**
* usb_control_msg - Builds a control urb, sends it off and waits for completion
* @dev: pointer to the usb device to send the message to
* @pipe: endpoint "pipe" to send the message to
* @request: USB message request value
* @requesttype: USB message request type value
* @value: USB message value
* @index: USB message index value
* @data: pointer to the data to send
* @size: length in bytes of the data to send
* @timeout: time in jiffies to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
* This function sends a simple control message to a specified endpoint
* and waits for the message to complete, or timeout.
*
* If successful, it returns the number of bytes transferred, otherwise a negative error number.
*
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need an asynchronous message, or need to send
* a message from within interrupt context, use usb_submit_urb()
*/
int
usb_control_msg
(
struct
usb_device
*
dev
,
unsigned
int
pipe
,
__u8
request
,
__u8
requesttype
,
__u16
value
,
__u16
index
,
void
*
data
,
__u16
size
,
int
timeout
)
{
struct
usb_ctrlrequest
*
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_KERNEL
);
int
ret
;
if
(
!
dr
)
return
-
ENOMEM
;
dr
->
bRequestType
=
requesttype
;
dr
->
bRequest
=
request
;
dr
->
wValue
=
cpu_to_le16p
(
&
value
);
dr
->
wIndex
=
cpu_to_le16p
(
&
index
);
dr
->
wLength
=
cpu_to_le16p
(
&
size
);
//dbg("usb_control_msg");
ret
=
usb_internal_control_msg
(
dev
,
pipe
,
dr
,
data
,
size
,
timeout
);
kfree
(
dr
);
return
ret
;
}
/**
* usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
* @usb_dev: pointer to the usb device to send the message to
* @pipe: endpoint "pipe" to send the message to
* @data: pointer to the data to send
* @len: length in bytes of the data to send
* @actual_length: pointer to a location to put the actual length transferred in bytes
* @timeout: time in jiffies to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
* This function sends a simple bulk message to a specified endpoint
* and waits for the message to complete, or timeout.
*
* If successful, it returns 0, otherwise a negative error number.
* The number of actual bytes transferred will be stored in the
* actual_length paramater.
*
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need an asynchronous message, or need to
* send a message from within interrupt context, use usb_submit_urb()
*/
int
usb_bulk_msg
(
struct
usb_device
*
usb_dev
,
unsigned
int
pipe
,
void
*
data
,
int
len
,
int
*
actual_length
,
int
timeout
)
{
struct
urb
*
urb
;
if
(
len
<
0
)
return
-
EINVAL
;
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
urb
)
return
-
ENOMEM
;
FILL_BULK_URB
(
urb
,
usb_dev
,
pipe
,
data
,
len
,
usb_api_blocking_completion
,
0
);
return
usb_start_wait_urb
(
urb
,
timeout
,
actual_length
);
}
/**
* usb_get_descriptor - issues a generic GET_DESCRIPTOR request
* @dev: the device whose descriptor is being retrieved
* @type: the descriptor type (USB_DT_*)
* @index: the number of the descriptor
* @buf: where to put the descriptor
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Gets a USB descriptor. Convenience functions exist to simplify
* getting some types of descriptors. Use
* usb_get_device_descriptor() for USB_DT_DEVICE,
* and usb_get_string() or usb_string() for USB_DT_STRING.
* Configuration descriptors (USB_DT_CONFIG) are part of the device
* structure, at least for the current configuration.
* In addition to a number of USB-standard descriptors, some
* devices also use class-specific or vendor-specific descriptors.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_descriptor
(
struct
usb_device
*
dev
,
unsigned
char
type
,
unsigned
char
index
,
void
*
buf
,
int
size
)
{
int
i
=
5
;
int
result
;
memset
(
buf
,
0
,
size
);
// Make sure we parse really received data
while
(
i
--
)
{
/* retries if the returned length was 0; flakey device */
if
((
result
=
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_DESCRIPTOR
,
USB_DIR_IN
,
(
type
<<
8
)
+
index
,
0
,
buf
,
size
,
HZ
*
USB_CTRL_GET_TIMEOUT
))
>
0
||
result
==
-
EPIPE
)
break
;
}
return
result
;
}
/**
* usb_get_string - gets a string descriptor
* @dev: the device whose string descriptor is being retrieved
* @langid: code for language chosen (from string descriptor zero)
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
* in little-endian byte order).
* The usb_string() function will often be a convenient way to turn
* these strings into kernel-printable form.
*
* Strings may be referenced in device, configuration, interface, or other
* descriptors, and could also be used in vendor-specific ways.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_string
(
struct
usb_device
*
dev
,
unsigned
short
langid
,
unsigned
char
index
,
void
*
buf
,
int
size
)
{
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_DESCRIPTOR
,
USB_DIR_IN
,
(
USB_DT_STRING
<<
8
)
+
index
,
langid
,
buf
,
size
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
/**
* usb_get_device_descriptor - (re)reads the device descriptor
* @dev: the device whose device descriptor is being updated
* Context: !in_interrupt ()
*
* Updates the copy of the device descriptor stored in the device structure,
* which dedicates space for this purpose. Note that several fields are
* converted to the host CPU's byte order: the USB version (bcdUSB), and
* vendors product and version fields (idVendor, idProduct, and bcdDevice).
* That lets device drivers compare against non-byteswapped constants.
*
* There's normally no need to use this call, although some devices
* will change their descriptors after events like updating firmware.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_device_descriptor
(
struct
usb_device
*
dev
)
{
int
ret
=
usb_get_descriptor
(
dev
,
USB_DT_DEVICE
,
0
,
&
dev
->
descriptor
,
sizeof
(
dev
->
descriptor
));
if
(
ret
>=
0
)
{
le16_to_cpus
(
&
dev
->
descriptor
.
bcdUSB
);
le16_to_cpus
(
&
dev
->
descriptor
.
idVendor
);
le16_to_cpus
(
&
dev
->
descriptor
.
idProduct
);
le16_to_cpus
(
&
dev
->
descriptor
.
bcdDevice
);
}
return
ret
;
}
/**
* usb_get_status - issues a GET_STATUS call
* @dev: the device whose status is being checked
* @type: USB_RECIP_*; for device, interface, or endpoint
* @target: zero (for device), else interface or endpoint number
* @data: pointer to two bytes of bitmap data
* Context: !in_interrupt ()
*
* Returns device, interface, or endpoint status. Normally only of
* interest to see if the device is self powered, or has enabled the
* remote wakeup facility; or whether a bulk or interrupt endpoint
* is halted ("stalled").
*
* Bits in these status bitmaps are set using the SET_FEATURE request,
* and cleared using the CLEAR_FEATURE request. The usb_clear_halt()
* function should be used to clear halt ("stall") status.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_status
(
struct
usb_device
*
dev
,
int
type
,
int
target
,
void
*
data
)
{
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
type
,
0
,
target
,
data
,
2
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
// hub-only!! ... and only exported for reset/reinit path.
// otherwise used internally, for config/altsetting reconfig.
void
usb_set_maxpacket
(
struct
usb_device
*
dev
)
{
int
i
,
b
;
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
ifp
=
dev
->
actconfig
->
interface
+
i
;
struct
usb_interface_descriptor
*
as
=
ifp
->
altsetting
+
ifp
->
act_altsetting
;
struct
usb_endpoint_descriptor
*
ep
=
as
->
endpoint
;
int
e
;
for
(
e
=
0
;
e
<
as
->
bNumEndpoints
;
e
++
)
{
b
=
ep
[
e
].
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
if
((
ep
[
e
].
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_CONTROL
)
{
/* Control => bidirectional */
dev
->
epmaxpacketout
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
dev
->
epmaxpacketin
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
}
else
if
(
usb_endpoint_out
(
ep
[
e
].
bEndpointAddress
))
{
if
(
ep
[
e
].
wMaxPacketSize
>
dev
->
epmaxpacketout
[
b
])
dev
->
epmaxpacketout
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
}
else
{
if
(
ep
[
e
].
wMaxPacketSize
>
dev
->
epmaxpacketin
[
b
])
dev
->
epmaxpacketin
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
}
}
}
}
/**
* usb_clear_halt - tells device to clear endpoint halt/stall condition
* @dev: device whose endpoint is halted
* @pipe: endpoint "pipe" being cleared
* Context: !in_interrupt ()
*
* This is used to clear halt conditions for bulk and interrupt endpoints,
* as reported by URB completion status. Endpoints that are halted are
* sometimes referred to as being "stalled". Such endpoints are unable
* to transmit or receive data until the halt status is cleared. Any URBs
* queued queued for such an endpoint should normally be unlinked before
* clearing the halt condition.
*
* Note that control and isochronous endpoints don't halt, although control
* endpoints report "protocol stall" (for unsupported requests) using the
* same status code used to report a true stall.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns zero on success, or else the status code returned by the
* underlying usb_control_msg() call.
*/
int
usb_clear_halt
(
struct
usb_device
*
dev
,
int
pipe
)
{
int
result
;
__u16
status
;
unsigned
char
*
buffer
;
int
endp
=
usb_pipeendpoint
(
pipe
)
|
(
usb_pipein
(
pipe
)
<<
7
);
/*
if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
return 0;
*/
result
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_CLEAR_FEATURE
,
USB_RECIP_ENDPOINT
,
0
,
endp
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
/* don't clear if failed */
if
(
result
<
0
)
return
result
;
buffer
=
kmalloc
(
sizeof
(
status
),
GFP_KERNEL
);
if
(
!
buffer
)
{
err
(
"unable to allocate memory for configuration descriptors"
);
return
-
ENOMEM
;
}
result
=
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
USB_RECIP_ENDPOINT
,
0
,
endp
,
// FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ?
buffer
,
sizeof
(
status
),
HZ
*
USB_CTRL_SET_TIMEOUT
);
memcpy
(
&
status
,
buffer
,
sizeof
(
status
));
kfree
(
buffer
);
if
(
result
<
0
)
return
result
;
if
(
le16_to_cpu
(
status
)
&
1
)
return
-
EPIPE
;
/* still halted */
usb_endpoint_running
(
dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
));
/* toggle is reset on clear */
usb_settoggle
(
dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
),
0
);
return
0
;
}
/**
* usb_set_interface - Makes a particular alternate setting be current
* @dev: the device whose interface is being updated
* @interface: the interface being updated
* @alternate: the setting being chosen.
* Context: !in_interrupt ()
*
* This is used to enable data transfers on interfaces that may not
* be enabled by default. Not all devices support such configurability.
*
* Within any given configuration, each interface may have several
* alternative settings. These are often used to control levels of
* bandwidth consumption. For example, the default setting for a high
* speed interrupt endpoint may not send more than about 4KBytes per
* microframe, and isochronous endpoints may never be part of a an
* interface's default setting. To access such bandwidth, alternate
* interface setting must be made current.
*
* Note that in the Linux USB subsystem, bandwidth associated with
* an endpoint in a given alternate setting is not reserved until an
* is submitted that needs that bandwidth. Some other operating systems
* allocate bandwidth early, when a configuration is chosen.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns zero on success, or else the status code returned by the
* underlying usb_control_msg() call.
*/
int
usb_set_interface
(
struct
usb_device
*
dev
,
int
interface
,
int
alternate
)
{
struct
usb_interface
*
iface
;
struct
usb_interface_descriptor
*
iface_as
;
int
i
,
ret
;
iface
=
usb_ifnum_to_if
(
dev
,
interface
);
if
(
!
iface
)
{
warn
(
"selecting invalid interface %d"
,
interface
);
return
-
EINVAL
;
}
/* 9.4.10 says devices don't need this, if the interface
only has one alternate setting */
if
(
iface
->
num_altsetting
==
1
)
{
dbg
(
"ignoring set_interface for dev %d, iface %d, alt %d"
,
dev
->
devnum
,
interface
,
alternate
);
return
0
;
}
if
((
ret
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_SET_INTERFACE
,
USB_RECIP_INTERFACE
,
alternate
,
interface
,
NULL
,
0
,
HZ
*
5
))
<
0
)
return
ret
;
iface
->
act_altsetting
=
alternate
;
/* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
*
* Note:
* Despite EP0 is always present in all interfaces/AS, the list of
* endpoints from the descriptor does not contain EP0. Due to its
* omnipresence one might expect EP0 being considered "affected" by
* any SetInterface request and hence assume toggles need to be reset.
* However, EP0 toggles are re-synced for every individual transfer
* during the SETUP stage - hence EP0 toggles are "don't care" here.
*/
iface_as
=
&
iface
->
altsetting
[
alternate
];
for
(
i
=
0
;
i
<
iface_as
->
bNumEndpoints
;
i
++
)
{
u8
ep
=
iface_as
->
endpoint
[
i
].
bEndpointAddress
;
usb_settoggle
(
dev
,
ep
&
USB_ENDPOINT_NUMBER_MASK
,
usb_endpoint_out
(
ep
),
0
);
}
/* usb_set_maxpacket() sets the maxpacket size for all EP in all
* interfaces but it shouldn't do any harm here: we have changed
* the AS for the requested interface only, hence for unaffected
* interfaces it's just re-application of still-valid values.
*/
usb_set_maxpacket
(
dev
);
return
0
;
}
/**
* usb_set_configuration - Makes a particular device setting be current
* @dev: the device whose configuration is being updated
* @configuration: the configuration being chosen.
* Context: !in_interrupt ()
*
* This is used to enable non-default device modes. Not all devices
* support this kind of configurability. By default, configuration
* zero is selected after enumeration; many devices only have a single
* configuration.
*
* USB devices may support one or more configurations, which affect
* power consumption and the functionality available. For example,
* the default configuration is limited to using 100mA of bus power,
* so that when certain device functionality requires more power,
* and the device is bus powered, that functionality will be in some
* non-default device configuration. Other device modes may also be
* reflected as configuration options, such as whether two ISDN
* channels are presented as independent 64Kb/s interfaces or as one
* bonded 128Kb/s interface.
*
* Note that USB has an additional level of device configurability,
* associated with interfaces. That configurability is accessed using
* usb_set_interface().
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns zero on success, or else the status code returned by the
* underlying usb_control_msg() call.
*/
int
usb_set_configuration
(
struct
usb_device
*
dev
,
int
configuration
)
{
int
i
,
ret
;
struct
usb_config_descriptor
*
cp
=
NULL
;
for
(
i
=
0
;
i
<
dev
->
descriptor
.
bNumConfigurations
;
i
++
)
{
if
(
dev
->
config
[
i
].
bConfigurationValue
==
configuration
)
{
cp
=
&
dev
->
config
[
i
];
break
;
}
}
if
(
!
cp
)
{
warn
(
"selecting invalid configuration %d"
,
configuration
);
return
-
EINVAL
;
}
if
((
ret
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_SET_CONFIGURATION
,
0
,
configuration
,
0
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
))
<
0
)
return
ret
;
dev
->
actconfig
=
cp
;
dev
->
toggle
[
0
]
=
0
;
dev
->
toggle
[
1
]
=
0
;
usb_set_maxpacket
(
dev
);
return
0
;
}
/**
* usb_string - returns ISO 8859-1 version of a string descriptor
* @dev: the device whose string descriptor is being retrieved
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* This converts the UTF-16LE encoded strings returned by devices, from
* usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
* that are more usable in most kernel contexts. Note that all characters
* in the chosen descriptor that can't be encoded using ISO-8859-1
* are converted to the question mark ("?") character, and this function
* chooses strings in the first language supported by the device.
*
* The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
* subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
* and is appropriate for use many uses of English and several other
* Western European languages. (But it doesn't include the "Euro" symbol.)
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns length of the string (>= 0) or usb_control_msg status (< 0).
*/
int
usb_string
(
struct
usb_device
*
dev
,
int
index
,
char
*
buf
,
size_t
size
)
{
unsigned
char
*
tbuf
;
int
err
;
unsigned
int
u
,
idx
;
if
(
size
<=
0
||
!
buf
||
!
index
)
return
-
EINVAL
;
buf
[
0
]
=
0
;
tbuf
=
kmalloc
(
256
,
GFP_KERNEL
);
if
(
!
tbuf
)
return
-
ENOMEM
;
/* get langid for strings if it's not yet known */
if
(
!
dev
->
have_langid
)
{
err
=
usb_get_string
(
dev
,
0
,
0
,
tbuf
,
4
);
if
(
err
<
0
)
{
err
(
"error getting string descriptor 0 (error=%d)"
,
err
);
goto
errout
;
}
else
if
(
tbuf
[
0
]
<
4
)
{
err
(
"string descriptor 0 too short"
);
err
=
-
EINVAL
;
goto
errout
;
}
else
{
dev
->
have_langid
=
-
1
;
dev
->
string_langid
=
tbuf
[
2
]
|
(
tbuf
[
3
]
<<
8
);
/* always use the first langid listed */
dbg
(
"USB device number %d default language ID 0x%x"
,
dev
->
devnum
,
dev
->
string_langid
);
}
}
/*
* Just ask for a maximum length string and then take the length
* that was returned.
*/
err
=
usb_get_string
(
dev
,
dev
->
string_langid
,
index
,
tbuf
,
255
);
if
(
err
<
0
)
goto
errout
;
size
--
;
/* leave room for trailing NULL char in output buffer */
for
(
idx
=
0
,
u
=
2
;
u
<
err
;
u
+=
2
)
{
if
(
idx
>=
size
)
break
;
if
(
tbuf
[
u
+
1
])
/* high byte */
buf
[
idx
++
]
=
'?'
;
/* non ISO-8859-1 character */
else
buf
[
idx
++
]
=
tbuf
[
u
];
}
buf
[
idx
]
=
0
;
err
=
idx
;
errout:
kfree
(
tbuf
);
return
err
;
}
// synchronous request completion model
EXPORT_SYMBOL
(
usb_control_msg
);
EXPORT_SYMBOL
(
usb_bulk_msg
);
// synchronous control message convenience routines
EXPORT_SYMBOL
(
usb_get_descriptor
);
EXPORT_SYMBOL
(
usb_get_device_descriptor
);
EXPORT_SYMBOL
(
usb_get_status
);
EXPORT_SYMBOL
(
usb_get_string
);
EXPORT_SYMBOL
(
usb_string
);
EXPORT_SYMBOL
(
usb_clear_halt
);
EXPORT_SYMBOL
(
usb_set_configuration
);
EXPORT_SYMBOL
(
usb_set_interface
);
drivers/usb/core/usb.c
View file @
1a2f7297
...
...
@@ -1015,189 +1015,6 @@ void usb_free_dev(struct usb_device *dev)
}
/*-------------------------------------------------------------------*
* SYNCHRONOUS CALLS *
*-------------------------------------------------------------------*/
struct
usb_api_data
{
wait_queue_head_t
wqh
;
int
done
;
};
static
void
usb_api_blocking_completion
(
struct
urb
*
urb
)
{
struct
usb_api_data
*
awd
=
(
struct
usb_api_data
*
)
urb
->
context
;
awd
->
done
=
1
;
wmb
();
wake_up
(
&
awd
->
wqh
);
}
// Starts urb and waits for completion or timeout
static
int
usb_start_wait_urb
(
struct
urb
*
urb
,
int
timeout
,
int
*
actual_length
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
usb_api_data
awd
;
int
status
;
init_waitqueue_head
(
&
awd
.
wqh
);
awd
.
done
=
0
;
set_current_state
(
TASK_UNINTERRUPTIBLE
);
add_wait_queue
(
&
awd
.
wqh
,
&
wait
);
urb
->
context
=
&
awd
;
status
=
usb_submit_urb
(
urb
,
GFP_KERNEL
);
if
(
status
)
{
// something went wrong
usb_free_urb
(
urb
);
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
awd
.
wqh
,
&
wait
);
return
status
;
}
while
(
timeout
&&
!
awd
.
done
)
{
timeout
=
schedule_timeout
(
timeout
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
rmb
();
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
awd
.
wqh
,
&
wait
);
if
(
!
timeout
&&
!
awd
.
done
)
{
if
(
urb
->
status
!=
-
EINPROGRESS
)
{
/* No callback?!! */
printk
(
KERN_ERR
"usb: raced timeout, "
"pipe 0x%x status %d time left %d
\n
"
,
urb
->
pipe
,
urb
->
status
,
timeout
);
status
=
urb
->
status
;
}
else
{
printk
(
"usb_control/bulk_msg: timeout
\n
"
);
usb_unlink_urb
(
urb
);
// remove urb safely
status
=
-
ETIMEDOUT
;
}
}
else
status
=
urb
->
status
;
if
(
actual_length
)
*
actual_length
=
urb
->
actual_length
;
usb_free_urb
(
urb
);
return
status
;
}
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
int
usb_internal_control_msg
(
struct
usb_device
*
usb_dev
,
unsigned
int
pipe
,
struct
usb_ctrlrequest
*
cmd
,
void
*
data
,
int
len
,
int
timeout
)
{
struct
urb
*
urb
;
int
retv
;
int
length
;
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
urb
)
return
-
ENOMEM
;
FILL_CONTROL_URB
(
urb
,
usb_dev
,
pipe
,
(
unsigned
char
*
)
cmd
,
data
,
len
,
usb_api_blocking_completion
,
0
);
retv
=
usb_start_wait_urb
(
urb
,
timeout
,
&
length
);
if
(
retv
<
0
)
return
retv
;
else
return
length
;
}
/**
* usb_control_msg - Builds a control urb, sends it off and waits for completion
* @dev: pointer to the usb device to send the message to
* @pipe: endpoint "pipe" to send the message to
* @request: USB message request value
* @requesttype: USB message request type value
* @value: USB message value
* @index: USB message index value
* @data: pointer to the data to send
* @size: length in bytes of the data to send
* @timeout: time in jiffies to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
* This function sends a simple control message to a specified endpoint
* and waits for the message to complete, or timeout.
*
* If successful, it returns the number of bytes transferred, otherwise a negative error number.
*
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need an asynchronous message, or need to send
* a message from within interrupt context, use usb_submit_urb()
*/
int
usb_control_msg
(
struct
usb_device
*
dev
,
unsigned
int
pipe
,
__u8
request
,
__u8
requesttype
,
__u16
value
,
__u16
index
,
void
*
data
,
__u16
size
,
int
timeout
)
{
struct
usb_ctrlrequest
*
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_KERNEL
);
int
ret
;
if
(
!
dr
)
return
-
ENOMEM
;
dr
->
bRequestType
=
requesttype
;
dr
->
bRequest
=
request
;
dr
->
wValue
=
cpu_to_le16p
(
&
value
);
dr
->
wIndex
=
cpu_to_le16p
(
&
index
);
dr
->
wLength
=
cpu_to_le16p
(
&
size
);
//dbg("usb_control_msg");
ret
=
usb_internal_control_msg
(
dev
,
pipe
,
dr
,
data
,
size
,
timeout
);
kfree
(
dr
);
return
ret
;
}
/**
* usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
* @usb_dev: pointer to the usb device to send the message to
* @pipe: endpoint "pipe" to send the message to
* @data: pointer to the data to send
* @len: length in bytes of the data to send
* @actual_length: pointer to a location to put the actual length transferred in bytes
* @timeout: time in jiffies to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
* This function sends a simple bulk message to a specified endpoint
* and waits for the message to complete, or timeout.
*
* If successful, it returns 0, otherwise a negative error number.
* The number of actual bytes transferred will be stored in the
* actual_length paramater.
*
* Don't use this function from within an interrupt context, like a
* bottom half handler. If you need an asynchronous message, or need to
* send a message from within interrupt context, use usb_submit_urb()
*/
int
usb_bulk_msg
(
struct
usb_device
*
usb_dev
,
unsigned
int
pipe
,
void
*
data
,
int
len
,
int
*
actual_length
,
int
timeout
)
{
struct
urb
*
urb
;
if
(
len
<
0
)
return
-
EINVAL
;
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
urb
)
return
-
ENOMEM
;
FILL_BULK_URB
(
urb
,
usb_dev
,
pipe
,
data
,
len
,
usb_api_blocking_completion
,
0
);
return
usb_start_wait_urb
(
urb
,
timeout
,
actual_length
);
}
/**
* usb_get_current_frame_number - return current bus frame number
* @dev: the device whose bus is being queried
...
...
@@ -1801,382 +1618,6 @@ int usb_set_address(struct usb_device *dev)
0
,
dev
->
devnum
,
0
,
NULL
,
0
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
/**
* usb_get_descriptor - issues a generic GET_DESCRIPTOR request
* @dev: the device whose descriptor is being retrieved
* @type: the descriptor type (USB_DT_*)
* @index: the number of the descriptor
* @buf: where to put the descriptor
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Gets a USB descriptor. Convenience functions exist to simplify
* getting some types of descriptors. Use
* usb_get_device_descriptor() for USB_DT_DEVICE,
* and usb_get_string() or usb_string() for USB_DT_STRING.
* Configuration descriptors (USB_DT_CONFIG) are part of the device
* structure, at least for the current configuration.
* In addition to a number of USB-standard descriptors, some
* devices also use class-specific or vendor-specific descriptors.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_descriptor
(
struct
usb_device
*
dev
,
unsigned
char
type
,
unsigned
char
index
,
void
*
buf
,
int
size
)
{
int
i
=
5
;
int
result
;
memset
(
buf
,
0
,
size
);
// Make sure we parse really received data
while
(
i
--
)
{
/* retries if the returned length was 0; flakey device */
if
((
result
=
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_DESCRIPTOR
,
USB_DIR_IN
,
(
type
<<
8
)
+
index
,
0
,
buf
,
size
,
HZ
*
USB_CTRL_GET_TIMEOUT
))
>
0
||
result
==
-
EPIPE
)
break
;
}
return
result
;
}
/**
* usb_get_string - gets a string descriptor
* @dev: the device whose string descriptor is being retrieved
* @langid: code for language chosen (from string descriptor zero)
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
* in little-endian byte order).
* The usb_string() function will often be a convenient way to turn
* these strings into kernel-printable form.
*
* Strings may be referenced in device, configuration, interface, or other
* descriptors, and could also be used in vendor-specific ways.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_string
(
struct
usb_device
*
dev
,
unsigned
short
langid
,
unsigned
char
index
,
void
*
buf
,
int
size
)
{
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_DESCRIPTOR
,
USB_DIR_IN
,
(
USB_DT_STRING
<<
8
)
+
index
,
langid
,
buf
,
size
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
/**
* usb_get_device_descriptor - (re)reads the device descriptor
* @dev: the device whose device descriptor is being updated
* Context: !in_interrupt ()
*
* Updates the copy of the device descriptor stored in the device structure,
* which dedicates space for this purpose. Note that several fields are
* converted to the host CPU's byte order: the USB version (bcdUSB), and
* vendors product and version fields (idVendor, idProduct, and bcdDevice).
* That lets device drivers compare against non-byteswapped constants.
*
* There's normally no need to use this call, although some devices
* will change their descriptors after events like updating firmware.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_device_descriptor
(
struct
usb_device
*
dev
)
{
int
ret
=
usb_get_descriptor
(
dev
,
USB_DT_DEVICE
,
0
,
&
dev
->
descriptor
,
sizeof
(
dev
->
descriptor
));
if
(
ret
>=
0
)
{
le16_to_cpus
(
&
dev
->
descriptor
.
bcdUSB
);
le16_to_cpus
(
&
dev
->
descriptor
.
idVendor
);
le16_to_cpus
(
&
dev
->
descriptor
.
idProduct
);
le16_to_cpus
(
&
dev
->
descriptor
.
bcdDevice
);
}
return
ret
;
}
/**
* usb_get_status - issues a GET_STATUS call
* @dev: the device whose status is being checked
* @type: USB_RECIP_*; for device, interface, or endpoint
* @target: zero (for device), else interface or endpoint number
* @data: pointer to two bytes of bitmap data
* Context: !in_interrupt ()
*
* Returns device, interface, or endpoint status. Normally only of
* interest to see if the device is self powered, or has enabled the
* remote wakeup facility; or whether a bulk or interrupt endpoint
* is halted ("stalled").
*
* Bits in these status bitmaps are set using the SET_FEATURE request,
* and cleared using the CLEAR_FEATURE request. The usb_clear_halt()
* function should be used to clear halt ("stall") status.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns the number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
int
usb_get_status
(
struct
usb_device
*
dev
,
int
type
,
int
target
,
void
*
data
)
{
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
type
,
0
,
target
,
data
,
2
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
// hub-only!! ... and only exported for reset/reinit path.
// otherwise used internally, for config/altsetting reconfig.
void
usb_set_maxpacket
(
struct
usb_device
*
dev
)
{
int
i
,
b
;
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
ifp
=
dev
->
actconfig
->
interface
+
i
;
struct
usb_interface_descriptor
*
as
=
ifp
->
altsetting
+
ifp
->
act_altsetting
;
struct
usb_endpoint_descriptor
*
ep
=
as
->
endpoint
;
int
e
;
for
(
e
=
0
;
e
<
as
->
bNumEndpoints
;
e
++
)
{
b
=
ep
[
e
].
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
if
((
ep
[
e
].
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_CONTROL
)
{
/* Control => bidirectional */
dev
->
epmaxpacketout
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
dev
->
epmaxpacketin
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
}
else
if
(
usb_endpoint_out
(
ep
[
e
].
bEndpointAddress
))
{
if
(
ep
[
e
].
wMaxPacketSize
>
dev
->
epmaxpacketout
[
b
])
dev
->
epmaxpacketout
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
}
else
{
if
(
ep
[
e
].
wMaxPacketSize
>
dev
->
epmaxpacketin
[
b
])
dev
->
epmaxpacketin
[
b
]
=
ep
[
e
].
wMaxPacketSize
;
}
}
}
}
/**
* usb_clear_halt - tells device to clear endpoint halt/stall condition
* @dev: device whose endpoint is halted
* @pipe: endpoint "pipe" being cleared
* Context: !in_interrupt ()
*
* This is used to clear halt conditions for bulk and interrupt endpoints,
* as reported by URB completion status. Endpoints that are halted are
* sometimes referred to as being "stalled". Such endpoints are unable
* to transmit or receive data until the halt status is cleared. Any URBs
* queued queued for such an endpoint should normally be unlinked before
* clearing the halt condition.
*
* Note that control and isochronous endpoints don't halt, although control
* endpoints report "protocol stall" (for unsupported requests) using the
* same status code used to report a true stall.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns zero on success, or else the status code returned by the
* underlying usb_control_msg() call.
*/
int
usb_clear_halt
(
struct
usb_device
*
dev
,
int
pipe
)
{
int
result
;
__u16
status
;
unsigned
char
*
buffer
;
int
endp
=
usb_pipeendpoint
(
pipe
)
|
(
usb_pipein
(
pipe
)
<<
7
);
/*
if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
return 0;
*/
result
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_CLEAR_FEATURE
,
USB_RECIP_ENDPOINT
,
0
,
endp
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
/* don't clear if failed */
if
(
result
<
0
)
return
result
;
buffer
=
kmalloc
(
sizeof
(
status
),
GFP_KERNEL
);
if
(
!
buffer
)
{
err
(
"unable to allocate memory for configuration descriptors"
);
return
-
ENOMEM
;
}
result
=
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
USB_RECIP_ENDPOINT
,
0
,
endp
,
// FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ?
buffer
,
sizeof
(
status
),
HZ
*
USB_CTRL_SET_TIMEOUT
);
memcpy
(
&
status
,
buffer
,
sizeof
(
status
));
kfree
(
buffer
);
if
(
result
<
0
)
return
result
;
if
(
le16_to_cpu
(
status
)
&
1
)
return
-
EPIPE
;
/* still halted */
usb_endpoint_running
(
dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
));
/* toggle is reset on clear */
usb_settoggle
(
dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
),
0
);
return
0
;
}
/**
* usb_set_interface - Makes a particular alternate setting be current
* @dev: the device whose interface is being updated
* @interface: the interface being updated
* @alternate: the setting being chosen.
* Context: !in_interrupt ()
*
* This is used to enable data transfers on interfaces that may not
* be enabled by default. Not all devices support such configurability.
*
* Within any given configuration, each interface may have several
* alternative settings. These are often used to control levels of
* bandwidth consumption. For example, the default setting for a high
* speed interrupt endpoint may not send more than about 4KBytes per
* microframe, and isochronous endpoints may never be part of a an
* interface's default setting. To access such bandwidth, alternate
* interface setting must be made current.
*
* Note that in the Linux USB subsystem, bandwidth associated with
* an endpoint in a given alternate setting is not reserved until an
* is submitted that needs that bandwidth. Some other operating systems
* allocate bandwidth early, when a configuration is chosen.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns zero on success, or else the status code returned by the
* underlying usb_control_msg() call.
*/
int
usb_set_interface
(
struct
usb_device
*
dev
,
int
interface
,
int
alternate
)
{
struct
usb_interface
*
iface
;
struct
usb_interface_descriptor
*
iface_as
;
int
i
,
ret
;
iface
=
usb_ifnum_to_if
(
dev
,
interface
);
if
(
!
iface
)
{
warn
(
"selecting invalid interface %d"
,
interface
);
return
-
EINVAL
;
}
/* 9.4.10 says devices don't need this, if the interface
only has one alternate setting */
if
(
iface
->
num_altsetting
==
1
)
{
dbg
(
"ignoring set_interface for dev %d, iface %d, alt %d"
,
dev
->
devnum
,
interface
,
alternate
);
return
0
;
}
if
((
ret
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_SET_INTERFACE
,
USB_RECIP_INTERFACE
,
alternate
,
interface
,
NULL
,
0
,
HZ
*
5
))
<
0
)
return
ret
;
iface
->
act_altsetting
=
alternate
;
/* 9.1.1.5: reset toggles for all endpoints affected by this iface-as
*
* Note:
* Despite EP0 is always present in all interfaces/AS, the list of
* endpoints from the descriptor does not contain EP0. Due to its
* omnipresence one might expect EP0 being considered "affected" by
* any SetInterface request and hence assume toggles need to be reset.
* However, EP0 toggles are re-synced for every individual transfer
* during the SETUP stage - hence EP0 toggles are "don't care" here.
*/
iface_as
=
&
iface
->
altsetting
[
alternate
];
for
(
i
=
0
;
i
<
iface_as
->
bNumEndpoints
;
i
++
)
{
u8
ep
=
iface_as
->
endpoint
[
i
].
bEndpointAddress
;
usb_settoggle
(
dev
,
ep
&
USB_ENDPOINT_NUMBER_MASK
,
usb_endpoint_out
(
ep
),
0
);
}
/* usb_set_maxpacket() sets the maxpacket size for all EP in all
* interfaces but it shouldn't do any harm here: we have changed
* the AS for the requested interface only, hence for unaffected
* interfaces it's just re-application of still-valid values.
*/
usb_set_maxpacket
(
dev
);
return
0
;
}
/**
* usb_set_configuration - Makes a particular device setting be current
* @dev: the device whose configuration is being updated
* @configuration: the configuration being chosen.
* Context: !in_interrupt ()
*
* This is used to enable non-default device modes. Not all devices
* support this kind of configurability. By default, configuration
* zero is selected after enumeration; many devices only have a single
* configuration.
*
* USB devices may support one or more configurations, which affect
* power consumption and the functionality available. For example,
* the default configuration is limited to using 100mA of bus power,
* so that when certain device functionality requires more power,
* and the device is bus powered, that functionality will be in some
* non-default device configuration. Other device modes may also be
* reflected as configuration options, such as whether two ISDN
* channels are presented as independent 64Kb/s interfaces or as one
* bonded 128Kb/s interface.
*
* Note that USB has an additional level of device configurability,
* associated with interfaces. That configurability is accessed using
* usb_set_interface().
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns zero on success, or else the status code returned by the
* underlying usb_control_msg() call.
*/
int
usb_set_configuration
(
struct
usb_device
*
dev
,
int
configuration
)
{
int
i
,
ret
;
struct
usb_config_descriptor
*
cp
=
NULL
;
for
(
i
=
0
;
i
<
dev
->
descriptor
.
bNumConfigurations
;
i
++
)
{
if
(
dev
->
config
[
i
].
bConfigurationValue
==
configuration
)
{
cp
=
&
dev
->
config
[
i
];
break
;
}
}
if
(
!
cp
)
{
warn
(
"selecting invalid configuration %d"
,
configuration
);
return
-
EINVAL
;
}
if
((
ret
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_SET_CONFIGURATION
,
0
,
configuration
,
0
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
))
<
0
)
return
ret
;
dev
->
actconfig
=
cp
;
dev
->
toggle
[
0
]
=
0
;
dev
->
toggle
[
1
]
=
0
;
usb_set_maxpacket
(
dev
);
return
0
;
}
// hub-only!! ... and only in reset path, or usb_new_device()
// (used by real hubs and virtual root hubs)
...
...
@@ -2280,87 +1721,6 @@ int usb_get_configuration(struct usb_device *dev)
return
result
;
}
/**
* usb_string - returns ISO 8859-1 version of a string descriptor
* @dev: the device whose string descriptor is being retrieved
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* This converts the UTF-16LE encoded strings returned by devices, from
* usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
* that are more usable in most kernel contexts. Note that all characters
* in the chosen descriptor that can't be encoded using ISO-8859-1
* are converted to the question mark ("?") character, and this function
* chooses strings in the first language supported by the device.
*
* The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
* subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
* and is appropriate for use many uses of English and several other
* Western European languages. (But it doesn't include the "Euro" symbol.)
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Returns length of the string (>= 0) or usb_control_msg status (< 0).
*/
int
usb_string
(
struct
usb_device
*
dev
,
int
index
,
char
*
buf
,
size_t
size
)
{
unsigned
char
*
tbuf
;
int
err
;
unsigned
int
u
,
idx
;
if
(
size
<=
0
||
!
buf
||
!
index
)
return
-
EINVAL
;
buf
[
0
]
=
0
;
tbuf
=
kmalloc
(
256
,
GFP_KERNEL
);
if
(
!
tbuf
)
return
-
ENOMEM
;
/* get langid for strings if it's not yet known */
if
(
!
dev
->
have_langid
)
{
err
=
usb_get_string
(
dev
,
0
,
0
,
tbuf
,
4
);
if
(
err
<
0
)
{
err
(
"error getting string descriptor 0 (error=%d)"
,
err
);
goto
errout
;
}
else
if
(
tbuf
[
0
]
<
4
)
{
err
(
"string descriptor 0 too short"
);
err
=
-
EINVAL
;
goto
errout
;
}
else
{
dev
->
have_langid
=
-
1
;
dev
->
string_langid
=
tbuf
[
2
]
|
(
tbuf
[
3
]
<<
8
);
/* always use the first langid listed */
dbg
(
"USB device number %d default language ID 0x%x"
,
dev
->
devnum
,
dev
->
string_langid
);
}
}
/*
* Just ask for a maximum length string and then take the length
* that was returned.
*/
err
=
usb_get_string
(
dev
,
dev
->
string_langid
,
index
,
tbuf
,
255
);
if
(
err
<
0
)
goto
errout
;
size
--
;
/* leave room for trailing NULL char in output buffer */
for
(
idx
=
0
,
u
=
2
;
u
<
err
;
u
+=
2
)
{
if
(
idx
>=
size
)
break
;
if
(
tbuf
[
u
+
1
])
/* high byte */
buf
[
idx
++
]
=
'?'
;
/* non ISO-8859-1 character */
else
buf
[
idx
++
]
=
tbuf
[
u
];
}
buf
[
idx
]
=
0
;
err
=
idx
;
errout:
kfree
(
tbuf
);
return
err
;
}
/*
* By the time we get here, the device has gotten a new device ID
* and is in the default state. We need to identify the thing and
...
...
@@ -2616,18 +1976,5 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL
(
usb_get_current_frame_number
);
// synchronous request completion model
EXPORT_SYMBOL
(
usb_control_msg
);
EXPORT_SYMBOL
(
usb_bulk_msg
);
// synchronous control message convenience routines
EXPORT_SYMBOL
(
usb_get_descriptor
);
EXPORT_SYMBOL
(
usb_get_device_descriptor
);
EXPORT_SYMBOL
(
usb_get_status
);
EXPORT_SYMBOL
(
usb_get_string
);
EXPORT_SYMBOL
(
usb_string
);
EXPORT_SYMBOL
(
usb_clear_halt
);
EXPORT_SYMBOL
(
usb_set_configuration
);
EXPORT_SYMBOL
(
usb_set_interface
);
EXPORT_SYMBOL
(
usb_devfs_handle
);
MODULE_LICENSE
(
"GPL"
);
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