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
90a89de4
Commit
90a89de4
authored
Mar 20, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
f289aa67
1966de6f
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
532 additions
and
621 deletions
+532
-621
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+18
-9
drivers/usb/core/message.c
drivers/usb/core/message.c
+2
-2
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-dbg.c
+3
-3
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+8
-7
drivers/usb/image/scanner.c
drivers/usb/image/scanner.c
+3
-2
drivers/usb/image/scanner.h
drivers/usb/image/scanner.h
+13
-0
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+4
-0
drivers/usb/misc/Makefile
drivers/usb/misc/Makefile
+0
-2
drivers/usb/misc/atmsar.c
drivers/usb/misc/atmsar.c
+0
-380
drivers/usb/misc/atmsar.h
drivers/usb/misc/atmsar.h
+0
-87
drivers/usb/misc/speedtch.c
drivers/usb/misc/speedtch.c
+313
-40
drivers/usb/net/cdc-ether.c
drivers/usb/net/cdc-ether.c
+16
-4
drivers/usb/net/pegasus.c
drivers/usb/net/pegasus.c
+3
-3
drivers/usb/serial/whiteheat.c
drivers/usb/serial/whiteheat.c
+1
-1
drivers/usb/usb-skeleton.c
drivers/usb/usb-skeleton.c
+148
-81
No files found.
drivers/usb/core/hub.c
View file @
90a89de4
...
@@ -1175,7 +1175,7 @@ void usb_hub_cleanup(void)
...
@@ -1175,7 +1175,7 @@ void usb_hub_cleanup(void)
int
usb_reset_device
(
struct
usb_device
*
dev
)
int
usb_reset_device
(
struct
usb_device
*
dev
)
{
{
struct
usb_device
*
parent
=
dev
->
parent
;
struct
usb_device
*
parent
=
dev
->
parent
;
struct
usb_device_descriptor
descriptor
;
struct
usb_device_descriptor
*
descriptor
;
int
i
,
ret
,
port
=
-
1
;
int
i
,
ret
,
port
=
-
1
;
if
(
!
parent
)
{
if
(
!
parent
)
{
...
@@ -1224,17 +1224,24 @@ int usb_reset_device(struct usb_device *dev)
...
@@ -1224,17 +1224,24 @@ int usb_reset_device(struct usb_device *dev)
* If nothing changed, we reprogram the configuration and then
* If nothing changed, we reprogram the configuration and then
* the alternate settings.
* the alternate settings.
*/
*/
ret
=
usb_get_descriptor
(
dev
,
USB_DT_DEVICE
,
0
,
&
descriptor
,
descriptor
=
kmalloc
(
sizeof
*
descriptor
,
GFP_NOIO
);
sizeof
(
descriptor
));
if
(
!
descriptor
)
{
if
(
ret
<
0
)
return
-
ENOMEM
;
}
ret
=
usb_get_descriptor
(
dev
,
USB_DT_DEVICE
,
0
,
descriptor
,
sizeof
(
*
descriptor
));
if
(
ret
<
0
)
{
kfree
(
descriptor
);
return
ret
;
return
ret
;
}
le16_to_cpus
(
&
descriptor
.
bcdUSB
);
le16_to_cpus
(
&
descriptor
->
bcdUSB
);
le16_to_cpus
(
&
descriptor
.
idVendor
);
le16_to_cpus
(
&
descriptor
->
idVendor
);
le16_to_cpus
(
&
descriptor
.
idProduct
);
le16_to_cpus
(
&
descriptor
->
idProduct
);
le16_to_cpus
(
&
descriptor
.
bcdDevice
);
le16_to_cpus
(
&
descriptor
->
bcdDevice
);
if
(
memcmp
(
&
dev
->
descriptor
,
&
descriptor
,
sizeof
(
descriptor
)))
{
if
(
memcmp
(
&
dev
->
descriptor
,
descriptor
,
sizeof
(
*
descriptor
)))
{
kfree
(
descriptor
);
usb_destroy_configuration
(
dev
);
usb_destroy_configuration
(
dev
);
ret
=
usb_get_device_descriptor
(
dev
);
ret
=
usb_get_device_descriptor
(
dev
);
...
@@ -1268,6 +1275,8 @@ int usb_reset_device(struct usb_device *dev)
...
@@ -1268,6 +1275,8 @@ int usb_reset_device(struct usb_device *dev)
return
1
;
return
1
;
}
}
kfree
(
descriptor
);
ret
=
usb_set_configuration
(
dev
,
dev
->
actconfig
->
desc
.
bConfigurationValue
);
ret
=
usb_set_configuration
(
dev
,
dev
->
actconfig
->
desc
.
bConfigurationValue
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
err
(
"failed to set dev %s active configuration (error=%d)"
,
err
(
"failed to set dev %s active configuration (error=%d)"
,
...
...
drivers/usb/core/message.c
View file @
90a89de4
...
@@ -88,7 +88,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
...
@@ -88,7 +88,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
int
retv
;
int
retv
;
int
length
;
int
length
;
urb
=
usb_alloc_urb
(
0
,
GFP_
KERNEL
);
urb
=
usb_alloc_urb
(
0
,
GFP_
NOIO
);
if
(
!
urb
)
if
(
!
urb
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -131,7 +131,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
...
@@ -131,7 +131,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
int
usb_control_msg
(
struct
usb_device
*
dev
,
unsigned
int
pipe
,
__u8
request
,
__u8
requesttype
,
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
)
__u16
value
,
__u16
index
,
void
*
data
,
__u16
size
,
int
timeout
)
{
{
struct
usb_ctrlrequest
*
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_
KERNEL
);
struct
usb_ctrlrequest
*
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_
NOIO
);
int
ret
;
int
ret
;
if
(
!
dr
)
if
(
!
dr
)
...
...
drivers/usb/host/ehci-dbg.c
View file @
90a89de4
...
@@ -117,10 +117,10 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {}
...
@@ -117,10 +117,10 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {}
static
void
__attribute__
((
__unused__
))
static
void
__attribute__
((
__unused__
))
dbg_qh
(
char
*
label
,
struct
ehci_hcd
*
ehci
,
struct
ehci_qh
*
qh
)
dbg_qh
(
char
*
label
,
struct
ehci_hcd
*
ehci
,
struct
ehci_qh
*
qh
)
{
{
dbg
(
"%s %p info1 %x info2 %x hw_curr %x qtd_next %x"
,
label
,
dbg
(
"%s %p
n%08x
info1 %x info2 %x hw_curr %x qtd_next %x"
,
label
,
qh
,
qh
->
hw_info1
,
qh
->
hw_info2
,
qh
,
qh
->
hw_
next
,
qh
->
hw_
info1
,
qh
->
hw_info2
,
qh
->
hw_current
,
qh
->
hw_qtd_next
);
qh
->
hw_current
,
qh
->
hw_qtd_next
);
dbg
(
" alt+
errs
= %x, token= %x, page0= %x, page1= %x"
,
dbg
(
" alt+
nak+t
= %x, token= %x, page0= %x, page1= %x"
,
qh
->
hw_alt_next
,
qh
->
hw_token
,
qh
->
hw_alt_next
,
qh
->
hw_token
,
qh
->
hw_buf
[
0
],
qh
->
hw_buf
[
1
]);
qh
->
hw_buf
[
0
],
qh
->
hw_buf
[
1
]);
if
(
qh
->
hw_buf
[
2
])
{
if
(
qh
->
hw_buf
[
2
])
{
...
...
drivers/usb/host/ehci-hcd.c
View file @
90a89de4
...
@@ -576,7 +576,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
...
@@ -576,7 +576,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
int
ports
;
int
ports
;
int
i
;
int
i
;
dbg
(
"%s: suspend to %d"
,
hcd_to_bus
(
hcd
)
->
bus_name
,
state
);
ehci_dbg
(
ehci
,
"suspend to %d
\n
"
,
state
);
ports
=
HCS_N_PORTS
(
ehci
->
hcs_params
);
ports
=
HCS_N_PORTS
(
ehci
->
hcs_params
);
...
@@ -593,7 +593,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
...
@@ -593,7 +593,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
if
((
temp
&
PORT_PE
)
==
0
if
((
temp
&
PORT_PE
)
==
0
||
(
temp
&
PORT_OWNER
)
!=
0
)
||
(
temp
&
PORT_OWNER
)
!=
0
)
continue
;
continue
;
dbg
(
"%s: suspend port %d"
,
hcd_to_bus
(
hcd
)
->
bus_name
,
i
);
ehci_dbg
(
ehci
,
"suspend port %d"
,
i
);
temp
|=
PORT_SUSPEND
;
temp
|=
PORT_SUSPEND
;
writel
(
temp
,
&
ehci
->
regs
->
port_status
[
i
]);
writel
(
temp
,
&
ehci
->
regs
->
port_status
[
i
]);
}
}
...
@@ -615,7 +615,7 @@ static int ehci_resume (struct usb_hcd *hcd)
...
@@ -615,7 +615,7 @@ static int ehci_resume (struct usb_hcd *hcd)
int
ports
;
int
ports
;
int
i
;
int
i
;
dbg
(
"%s: resume"
,
hcd_to_bus
(
hcd
)
->
bus_name
);
ehci_dbg
(
ehci
,
"resume
\n
"
);
ports
=
HCS_N_PORTS
(
ehci
->
hcs_params
);
ports
=
HCS_N_PORTS
(
ehci
->
hcs_params
);
...
@@ -635,7 +635,7 @@ static int ehci_resume (struct usb_hcd *hcd)
...
@@ -635,7 +635,7 @@ static int ehci_resume (struct usb_hcd *hcd)
if
((
temp
&
PORT_PE
)
==
0
if
((
temp
&
PORT_PE
)
==
0
||
(
temp
&
PORT_SUSPEND
)
!=
0
)
||
(
temp
&
PORT_SUSPEND
)
!=
0
)
continue
;
continue
;
dbg
(
"%s: resume port %d"
,
hcd_to_bus
(
hcd
)
->
bus_name
,
i
);
ehci_dbg
(
ehci
,
"resume port %d"
,
i
);
temp
|=
PORT_RESUME
;
temp
|=
PORT_RESUME
;
writel
(
temp
,
&
ehci
->
regs
->
port_status
[
i
]);
writel
(
temp
,
&
ehci
->
regs
->
port_status
[
i
]);
readl
(
&
ehci
->
regs
->
command
);
/* unblock posted writes */
readl
(
&
ehci
->
regs
->
command
);
/* unblock posted writes */
...
@@ -880,8 +880,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
...
@@ -880,8 +880,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
/* ASSERT: no requests/urbs are still linked (so no TDs) */
/* ASSERT: no requests/urbs are still linked (so no TDs) */
/* ASSERT: nobody can be submitting urbs for this any more */
/* ASSERT: nobody can be submitting urbs for this any more */
dbg
(
"%s: free_config devnum %d
"
,
ehci_dbg
(
ehci
,
"free_config %s devnum %d
\n
"
,
hcd_to_bus
(
hcd
)
->
bus_name
,
udev
->
devnum
);
udev
->
devpath
,
udev
->
devnum
);
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
for
(
i
=
0
;
i
<
32
;
i
++
)
{
for
(
i
=
0
;
i
<
32
;
i
++
)
{
...
@@ -912,7 +912,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
...
@@ -912,7 +912,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
dev
->
ep
[
i
]
=
0
;
dev
->
ep
[
i
]
=
0
;
if
(
qh
->
qh_state
==
QH_STATE_IDLE
)
if
(
qh
->
qh_state
==
QH_STATE_IDLE
)
goto
idle
;
goto
idle
;
dbg
(
"free_config, async ep 0x%02x qh %p"
,
i
,
qh
);
ehci_dbg
(
ehci
,
"free_config, async ep 0x%02x qh %p"
,
i
,
qh
);
/* scan_async() empties the ring as it does its work,
/* scan_async() empties the ring as it does its work,
* using IAA, but doesn't (yet?) turn it off. if it
* using IAA, but doesn't (yet?) turn it off. if it
...
...
drivers/usb/image/scanner.c
View file @
90a89de4
...
@@ -347,8 +347,9 @@
...
@@ -347,8 +347,9 @@
* - Don't print errors when the device is busy.
* - Don't print errors when the device is busy.
*
*
* 0.4.11 2003-02-25
* 0.4.11 2003-02-25
* - Added vendor/product ids for Artec, Avision, Brother, Medion, Primax,
* - Added vendor/product ids for Artec, Avision, Brother, Canon, Compaq,
* Prolink, Fujitsu, Plustek, and SYSCAN scanners.
* Fujitsu, Hewlett-Packard, Lexmark, LG Electronics, Medion, Microtek,
* Primax, Prolink, Plustek, SYSCAN, Trust and UMAX scanners.
* - Fixed generation of devfs names if dynamic minors are disabled.
* - Fixed generation of devfs names if dynamic minors are disabled.
* - Used kobject reference counting to free the scn struct when the device
* - Used kobject reference counting to free the scn struct when the device
* is closed and disconnected. Avoids crashes when writing to a
* is closed and disconnected. Avoids crashes when writing to a
...
...
drivers/usb/image/scanner.h
View file @
90a89de4
...
@@ -105,6 +105,7 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -105,6 +105,7 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x0638
,
0x0a10
)
},
/* iVina FB1600 (=Umax Astra 4500) */
{
USB_DEVICE
(
0x0638
,
0x0a10
)
},
/* iVina FB1600 (=Umax Astra 4500) */
/* Benq: see Acer */
/* Benq: see Acer */
/* Brother */
/* Brother */
{
USB_DEVICE
(
0x04f9
,
0x010f
)
},
/* MFC 5100C */
{
USB_DEVICE
(
0x04f9
,
0x0111
)
},
/* MFC 6800 */
{
USB_DEVICE
(
0x04f9
,
0x0111
)
},
/* MFC 6800 */
/* Canon */
/* Canon */
{
USB_DEVICE
(
0x04a9
,
0x2201
)
},
/* CanoScan FB320U */
{
USB_DEVICE
(
0x04a9
,
0x2201
)
},
/* CanoScan FB320U */
...
@@ -118,9 +119,11 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -118,9 +119,11 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x04a9
,
0x220c
)
},
/* CanoScan D1250U2 */
{
USB_DEVICE
(
0x04a9
,
0x220c
)
},
/* CanoScan D1250U2 */
{
USB_DEVICE
(
0x04a9
,
0x220d
)
},
/* CanoScan N670U/N676U/LIDE 20 */
{
USB_DEVICE
(
0x04a9
,
0x220d
)
},
/* CanoScan N670U/N676U/LIDE 20 */
{
USB_DEVICE
(
0x04a9
,
0x220e
)
},
/* CanoScan N1240U/LIDE 30 */
{
USB_DEVICE
(
0x04a9
,
0x220e
)
},
/* CanoScan N1240U/LIDE 30 */
{
USB_DEVICE
(
0x04a9
,
0x2213
)
},
/* LIDE 50 */
{
USB_DEVICE
(
0x04a9
,
0x3042
)
},
/* FS4000US */
{
USB_DEVICE
(
0x04a9
,
0x3042
)
},
/* FS4000US */
/* Colorado -- See Primax/Colorado below */
/* Colorado -- See Primax/Colorado below */
/* Compaq */
/* Compaq */
{
USB_DEVICE
(
0x049f
,
0x001a
)
},
/* S4 100 */
{
USB_DEVICE
(
0x049f
,
0x0021
)
},
/* S200 */
{
USB_DEVICE
(
0x049f
,
0x0021
)
},
/* S200 */
/* Epson -- See Seiko/Epson below */
/* Epson -- See Seiko/Epson below */
/* Fujitsu */
/* Fujitsu */
...
@@ -152,6 +155,8 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -152,6 +155,8 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x03f0
,
0x0705
)
},
/* ScanJet 4400C */
{
USB_DEVICE
(
0x03f0
,
0x0705
)
},
/* ScanJet 4400C */
// { USB_DEVICE(0x03f0, 0x0801) }, /* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */
// { USB_DEVICE(0x03f0, 0x0801) }, /* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */
{
USB_DEVICE
(
0x03f0
,
0x0901
)
},
/* ScanJet 2300C */
{
USB_DEVICE
(
0x03f0
,
0x0901
)
},
/* ScanJet 2300C */
{
USB_DEVICE
(
0x03F0
,
0x1005
)
},
/* ScanJet 5400C */
{
USB_DEVICE
(
0x03F0
,
0x1105
)
},
/* ScanJet 5470C */
{
USB_DEVICE
(
0x03f0
,
0x1305
)
},
/* Scanjet 4570c */
{
USB_DEVICE
(
0x03f0
,
0x1305
)
},
/* Scanjet 4570c */
{
USB_DEVICE
(
0x03f0
,
0x2005
)
},
/* ScanJet 3570c */
{
USB_DEVICE
(
0x03f0
,
0x2005
)
},
/* ScanJet 3570c */
{
USB_DEVICE
(
0x03f0
,
0x2205
)
},
/* ScanJet 3500c */
{
USB_DEVICE
(
0x03f0
,
0x2205
)
},
/* ScanJet 3500c */
...
@@ -159,12 +164,16 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -159,12 +164,16 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x0638
,
0x0268
)
},
/* 1200U */
{
USB_DEVICE
(
0x0638
,
0x0268
)
},
/* 1200U */
/* Lexmark */
/* Lexmark */
{
USB_DEVICE
(
0x043d
,
0x002d
)
},
/* X70/X73 */
{
USB_DEVICE
(
0x043d
,
0x002d
)
},
/* X70/X73 */
{
USB_DEVICE
(
0x043d
,
0x003d
)
},
/* X83 */
/* LG Electronics */
{
USB_DEVICE
(
0x0461
,
0x0364
)
},
/* Scanworks 600U (repackaged Primax?) */
/* Medion */
/* Medion */
{
USB_DEVICE
(
0x0461
,
0x0377
)
},
/* MD 5345 - repackaged Primax? */
{
USB_DEVICE
(
0x0461
,
0x0377
)
},
/* MD 5345 - repackaged Primax? */
/* Memorex */
/* Memorex */
{
USB_DEVICE
(
0x0461
,
0x0346
)
},
/* 6136u - repackaged Primax ? */
{
USB_DEVICE
(
0x0461
,
0x0346
)
},
/* 6136u - repackaged Primax ? */
/* Microtek */
/* Microtek */
{
USB_DEVICE
(
0x05da
,
0x30ce
)
},
/* ScanMaker 3800 */
{
USB_DEVICE
(
0x05da
,
0x30ce
)
},
/* ScanMaker 3800 */
{
USB_DEVICE
(
0x05da
,
0x30cf
)
},
/* ScanMaker 4800 */
/* The following SCSI-over-USB Microtek devices are supported by the
/* The following SCSI-over-USB Microtek devices are supported by the
microtek driver: Enable SCSI and USB Microtek in kernel config */
microtek driver: Enable SCSI and USB Microtek in kernel config */
// { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */
// { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */
...
@@ -259,7 +268,11 @@ static struct usb_device_id scanner_device_ids [] = {
...
@@ -259,7 +268,11 @@ static struct usb_device_id scanner_device_ids [] = {
{
USB_DEVICE
(
0x04b8
,
0x0802
)
},
/* Stylus CX3200 */
{
USB_DEVICE
(
0x04b8
,
0x0802
)
},
/* Stylus CX3200 */
/* SYSCAN */
/* SYSCAN */
{
USB_DEVICE
(
0x0a82
,
0x4600
)
},
/* TravelScan 460/464 */
{
USB_DEVICE
(
0x0a82
,
0x4600
)
},
/* TravelScan 460/464 */
/* Trust */
{
USB_DEVICE
(
0x05cb
,
0x1483
)
},
/* CombiScan 19200 */
{
USB_DEVICE
(
0x05d8
,
0x4006
)
},
/* Easy Webscan 19200 (repackaged Artec?) */
/* Umax */
/* Umax */
{
USB_DEVICE
(
0x05d8
,
0x4009
)
},
/* Astraslim (actually Artec?) */
{
USB_DEVICE
(
0x1606
,
0x0010
)
},
/* Astra 1220U */
{
USB_DEVICE
(
0x1606
,
0x0010
)
},
/* Astra 1220U */
{
USB_DEVICE
(
0x1606
,
0x0030
)
},
/* Astra 2000U */
{
USB_DEVICE
(
0x1606
,
0x0030
)
},
/* Astra 2000U */
{
USB_DEVICE
(
0x1606
,
0x0060
)
},
/* Astra 3400U/3450U */
{
USB_DEVICE
(
0x1606
,
0x0060
)
},
/* Astra 3400U/3450U */
...
...
drivers/usb/input/hid-core.c
View file @
90a89de4
...
@@ -1334,6 +1334,9 @@ void hid_init_reports(struct hid_device *hid)
...
@@ -1334,6 +1334,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_TANGTOP 0x0d3d
#define USB_VENDOR_ID_TANGTOP 0x0d3d
#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001
#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
struct
hid_blacklist
{
struct
hid_blacklist
{
__u16
idVendor
;
__u16
idVendor
;
__u16
idProduct
;
__u16
idProduct
;
...
@@ -1377,6 +1380,7 @@ struct hid_blacklist {
...
@@ -1377,6 +1380,7 @@ struct hid_blacklist {
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
400
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
400
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
500
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
500
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_TANGTOP
,
USB_DEVICE_ID_TANGTOP_USBPS2
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_TANGTOP
,
USB_DEVICE_ID_TANGTOP_USBPS2
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ESSENTIAL_REALITY
,
USB_DEVICE_ID_ESSENTIAL_REALITY_P5
,
HID_QUIRK_IGNORE
},
{
0
,
0
}
{
0
,
0
}
};
};
...
...
drivers/usb/misc/Makefile
View file @
90a89de4
...
@@ -12,5 +12,3 @@ obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o
...
@@ -12,5 +12,3 @@ obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o
obj-$(CONFIG_USB_TEST)
+=
usbtest.o
obj-$(CONFIG_USB_TEST)
+=
usbtest.o
obj-$(CONFIG_USB_TIGL)
+=
tiglusb.o
obj-$(CONFIG_USB_TIGL)
+=
tiglusb.o
obj-$(CONFIG_USB_USS720)
+=
uss720.o
obj-$(CONFIG_USB_USS720)
+=
uss720.o
speedtch-objs
:=
speedtouch.o atmsar.o
drivers/usb/misc/atmsar.c
deleted
100644 → 0
View file @
f289aa67
/******************************************************************************
* atmsar.c -- General SAR library for ATM devices.
*
* Copyright (C) 2000, Johan Verrept
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
******************************************************************************/
/*
* Written by Johan Verrept (Johan.Verrept@advalvas.be)
*
* 0.2.4A: - Version for inclusion in 2.5 series kernel
* - Modifications by Richard Purdie (rpurdie@rpsys.net)
* - replaced "sarlib" with "atmsar"
* - adaptations for inclusion in kernel tree
*
* 0.2.4: - Fixed wrong buffer overrun check in atmsar_decode_rawcell()
* reported by Stephen Robinson <stephen.robinson@zen.co.uk>
* - Fixed bug when input skb did not contain a multple of 52/53
* bytes (would happen when the speedtouch device resynced)
* also reported by Stephen Robinson <stephen.robinson@zen.co.uk>
*
* 0.2.3: - Fixed wrong allocation size. caused memory corruption in some
* cases. Reported by Vladimir Dergachev <volodya@mindspring.com>
* - Added some comments
*
* 0.2.2: - Fixed CRCASM
* patch from Linus Flannagan <linusf@netservices.eng.net>
* - Fixed problem when user did NOT use the
* ATMSAR_USE_53BYTE_CELL flag.
* reported by Piers Scannell <email@lot105.com>
* - No more in-buffer rewriting for cloned buffers.
* - Removed the PII specific CFLAGS in the Makefile.
*
* 0.2.1: - removed dependency on alloc_tx. tis presented problems when
* using this with the br2684 code.
*
* 0.2: - added AAL0 reassembly
* - added alloc_tx support
* - replaced alloc_skb in decode functions to dev_alloc_skb to
* allow calling from interrupt
* - fixed embarassing AAL5 bug. I was setting the pti bit in the
* wrong byte...
* - fixed another emabrassing bug.. picked up the wrong crc type
* and forgot to invert the crc result...
* - fixed AAL5 length calculations.
* - removed automatic skb freeing from encode functions.
* This caused problems because i did kfree_skb it, while it
* needed to be popped. I cannot determine though whether it
* needs to be popped or not. Figu'e it out ye'self ;-)
* - added mru field. This is the buffersize. atmsar_decode_aal0
* will use when it allocates a receive buffer. A stop gap for
* real buffer management.
*
* 0.1: - library created.
* - only contains AAL5, AAL0 can be easily added. (actually, only
* AAL0 reassembly is missing)
*
*/
#include <linux/crc32.h>
#include "atmsar.h"
/***********************
**
** things to remember
**
***********************/
/*
1. the atmsar_vcc_data list pointer MUST be initialized to NULL
2. atmsar_encode_rawcell will drop incomplete cells.
3. ownership of the skb goes to the library !
*/
#define ATM_HDR_VPVC_MASK (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)
/***********************
**
** LOCAL STRUCTURES
**
***********************/
/***********************
**
** LOCAL MACROS
**
***********************/
/*
#define DEBUG 1
*/
#ifdef DEBUG
#define PDEBUG(arg...) printk(KERN_DEBUG "atmsar: " arg)
#else
#define PDEBUG(arg...)
#endif
#define ADD_HEADER(dest, header) \
*dest++ = (unsigned char) (header >> 24); \
*dest++ = (unsigned char) (header >> 16); \
*dest++ = (unsigned char) (header >> 8); \
*dest++ = (unsigned char) (header & 0xff);
struct
atmsar_vcc_data
*
atmsar_open
(
struct
atmsar_vcc_data
**
list
,
struct
atm_vcc
*
vcc
,
uint
type
,
ushort
vpi
,
ushort
vci
,
unchar
pti
,
unchar
gfc
,
uint
flags
)
{
struct
atmsar_vcc_data
*
new
;
if
(
!
vcc
)
return
NULL
;
new
=
kmalloc
(
sizeof
(
struct
atmsar_vcc_data
),
GFP_KERNEL
);
if
(
!
new
)
return
NULL
;
memset
(
new
,
0
,
sizeof
(
struct
atmsar_vcc_data
));
new
->
vcc
=
vcc
;
new
->
stats
=
vcc
->
stats
;
new
->
type
=
type
;
new
->
next
=
NULL
;
new
->
gfc
=
gfc
;
new
->
vp
=
vpi
;
new
->
vc
=
vci
;
new
->
pti
=
pti
;
switch
(
type
)
{
case
ATMSAR_TYPE_AAL0
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL0
;
break
;
case
ATMSAR_TYPE_AAL1
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL1
;
break
;
case
ATMSAR_TYPE_AAL2
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL2
;
break
;
case
ATMSAR_TYPE_AAL34
:
/* not supported */
new
->
mtu
=
ATMSAR_DEF_MTU_AAL34
;
break
;
case
ATMSAR_TYPE_AAL5
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL5
;
break
;
}
new
->
atmHeader
=
((
unsigned
long
)
gfc
<<
ATM_HDR_GFC_SHIFT
)
|
((
unsigned
long
)
vpi
<<
ATM_HDR_VPI_SHIFT
)
|
((
unsigned
long
)
vci
<<
ATM_HDR_VCI_SHIFT
)
|
((
unsigned
long
)
pti
<<
ATM_HDR_PTI_SHIFT
);
new
->
flags
=
flags
;
new
->
next
=
NULL
;
new
->
reasBuffer
=
NULL
;
new
->
next
=
*
list
;
*
list
=
new
;
PDEBUG
(
"Allocated new SARLib vcc 0x%p with vp %d vc %d
\n
"
,
new
,
vpi
,
vci
);
return
new
;
}
void
atmsar_close
(
struct
atmsar_vcc_data
**
list
,
struct
atmsar_vcc_data
*
vcc
)
{
struct
atmsar_vcc_data
*
work
;
if
(
*
list
==
vcc
)
{
*
list
=
(
*
list
)
->
next
;
}
else
{
for
(
work
=
*
list
;
work
&&
work
->
next
&&
(
work
->
next
!=
vcc
);
work
=
work
->
next
);
/* return if not found */
if
(
work
->
next
!=
vcc
)
return
;
work
->
next
=
work
->
next
->
next
;
}
if
(
vcc
->
reasBuffer
)
{
dev_kfree_skb
(
vcc
->
reasBuffer
);
}
PDEBUG
(
"Allocated SARLib vcc 0x%p with vp %d vc %d
\n
"
,
vcc
,
vcc
->
vp
,
vcc
->
vc
);
kfree
(
vcc
);
}
/***********************
**
** DECODE FUNCTIONS
**
***********************/
struct
sk_buff
*
atmsar_decode_rawcell
(
struct
atmsar_vcc_data
*
list
,
struct
sk_buff
*
skb
,
struct
atmsar_vcc_data
**
ctx
)
{
while
(
skb
->
len
)
{
unsigned
char
*
cell
=
skb
->
data
;
unsigned
char
*
cell_payload
;
struct
atmsar_vcc_data
*
vcc
=
list
;
unsigned
long
atmHeader
=
((
unsigned
long
)
(
cell
[
0
])
<<
24
)
|
((
unsigned
long
)
(
cell
[
1
])
<<
16
)
|
((
unsigned
long
)
(
cell
[
2
])
<<
8
)
|
(
cell
[
3
]
&
0xff
);
PDEBUG
(
"atmsar_decode_rawcell (0x%p, 0x%p, 0x%p) called
\n
"
,
list
,
skb
,
ctx
);
PDEBUG
(
"atmsar_decode_rawcell skb->data %p, skb->tail %p
\n
"
,
skb
->
data
,
skb
->
tail
);
if
(
!
list
||
!
skb
||
!
ctx
)
return
NULL
;
if
(
!
skb
->
data
||
!
skb
->
tail
)
return
NULL
;
/* here should the header CRC check be... */
/* look up correct vcc */
for
(;
vcc
&&
((
vcc
->
atmHeader
&
ATM_HDR_VPVC_MASK
)
!=
(
atmHeader
&
ATM_HDR_VPVC_MASK
));
vcc
=
vcc
->
next
);
PDEBUG
(
"atmsar_decode_rawcell found vcc %p for packet on vp %d, vc %d
\n
"
,
vcc
,
(
int
)
((
atmHeader
&
ATM_HDR_VPI_MASK
)
>>
ATM_HDR_VPI_SHIFT
),
(
int
)
((
atmHeader
&
ATM_HDR_VCI_MASK
)
>>
ATM_HDR_VCI_SHIFT
));
if
(
vcc
&&
(
skb
->
len
>=
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
)))
{
cell_payload
=
cell
+
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
5
:
4
);
switch
(
vcc
->
type
)
{
case
ATMSAR_TYPE_AAL0
:
/* case ATMSAR_TYPE_AAL1: when we have a decode AAL1 function... */
{
struct
sk_buff
*
tmp
=
dev_alloc_skb
(
vcc
->
mtu
);
if
(
tmp
)
{
memcpy
(
tmp
->
tail
,
cell_payload
,
48
);
skb_put
(
tmp
,
48
);
if
(
vcc
->
stats
)
atomic_inc
(
&
vcc
->
stats
->
rx
);
skb_pull
(
skb
,
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
));
PDEBUG
(
"atmsar_decode_rawcell returns ATMSAR_TYPE_AAL0 pdu 0x%p with length %d
\n
"
,
tmp
,
tmp
->
len
);
return
tmp
;
};
}
break
;
case
ATMSAR_TYPE_AAL1
:
case
ATMSAR_TYPE_AAL2
:
case
ATMSAR_TYPE_AAL34
:
/* not supported */
break
;
case
ATMSAR_TYPE_AAL5
:
if
(
!
vcc
->
reasBuffer
)
vcc
->
reasBuffer
=
dev_alloc_skb
(
vcc
->
mtu
);
/* if alloc fails, we just drop the cell. it is possible that we can still
* receive cells on other vcc's
*/
if
(
vcc
->
reasBuffer
)
{
/* if (buffer overrun) discard received cells until now */
if
((
vcc
->
reasBuffer
->
len
)
>
(
vcc
->
mtu
-
48
))
skb_trim
(
vcc
->
reasBuffer
,
0
);
/* copy data */
memcpy
(
vcc
->
reasBuffer
->
tail
,
cell_payload
,
48
);
skb_put
(
vcc
->
reasBuffer
,
48
);
/* check for end of buffer */
if
(
cell
[
3
]
&
0x2
)
{
struct
sk_buff
*
tmp
;
/* the aal5 buffer ends here, cut the buffer. */
/* buffer will always have at least one whole cell, so */
/* don't need to check return from skb_pull */
skb_pull
(
skb
,
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
));
*
ctx
=
vcc
;
tmp
=
vcc
->
reasBuffer
;
vcc
->
reasBuffer
=
NULL
;
PDEBUG
(
"atmsar_decode_rawcell returns ATMSAR_TYPE_AAL5 pdu 0x%p with length %d
\n
"
,
tmp
,
tmp
->
len
);
return
tmp
;
}
}
break
;
};
/* flush the cell */
/* buffer will always contain at least one whole cell, so don't */
/* need to check return value from skb_pull */
skb_pull
(
skb
,
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
));
}
else
{
/* If data is corrupt and skb doesn't hold a whole cell, flush the lot */
if
(
skb_pull
(
skb
,
(
list
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
))
==
NULL
)
return
NULL
;
}
}
return
NULL
;
};
struct
sk_buff
*
atmsar_decode_aal5
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
)
{
uint
crc
=
0xffffffff
;
uint
length
,
pdu_crc
,
pdu_length
;
PDEBUG
(
"atmsar_decode_aal5 (0x%p, 0x%p) called
\n
"
,
ctx
,
skb
);
if
(
skb
->
len
&&
(
skb
->
len
%
48
))
return
NULL
;
length
=
(
skb
->
tail
[
-
6
]
<<
8
)
+
skb
->
tail
[
-
5
];
pdu_crc
=
(
skb
->
tail
[
-
4
]
<<
24
)
+
(
skb
->
tail
[
-
3
]
<<
16
)
+
(
skb
->
tail
[
-
2
]
<<
8
)
+
skb
->
tail
[
-
1
];
pdu_length
=
((
length
+
47
+
8
)
/
48
)
*
48
;
PDEBUG
(
"atmsar_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d
\n
"
,
skb
->
len
,
length
,
pdu_crc
,
pdu_length
);
/* is skb long enough ? */
if
(
skb
->
len
<
pdu_length
)
{
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
rx_err
);
return
NULL
;
}
/* is skb too long ? */
if
(
skb
->
len
>
pdu_length
)
{
PDEBUG
(
"atmsar_decode_aal5: Warning: readjusting illeagl size %d -> %d
\n
"
,
skb
->
len
,
pdu_length
);
/* buffer is too long. we can try to recover
* if we discard the first part of the skb.
* the crc will decide whether this was ok
*/
skb_pull
(
skb
,
skb
->
len
-
pdu_length
);
}
crc
=
~
crc32_be
(
crc
,
skb
->
data
,
pdu_length
-
4
);
/* check crc */
if
(
pdu_crc
!=
crc
)
{
PDEBUG
(
"atmsar_decode_aal5: crc check failed!
\n
"
);
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
rx_err
);
return
NULL
;
}
/* pdu is ok */
skb_trim
(
skb
,
length
);
/* update stats */
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
rx
);
PDEBUG
(
"atmsar_decode_aal5 returns pdu 0x%p with length %d
\n
"
,
skb
,
skb
->
len
);
return
skb
;
};
drivers/usb/misc/atmsar.h
deleted
100644 → 0
View file @
f289aa67
#ifndef _ATMSAR_H_
#define _ATMSAR_H_
/******************************************************************************
* atmsar.h -- General SAR library for ATM devices.
*
* Copyright (C) 2000, Johan Verrept
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
******************************************************************************/
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/atmdev.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <linux/atm.h>
#define ATMSAR_USE_53BYTE_CELL 0x1L
#define ATMSAR_SET_PTI 0x2L
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
/* types */
#define ATMSAR_TYPE_AAL0 ATM_AAL0
#define ATMSAR_TYPE_AAL1 ATM_AAL1
#define ATMSAR_TYPE_AAL2 ATM_AAL2
#define ATMSAR_TYPE_AAL34 ATM_AAL34
#define ATMSAR_TYPE_AAL5 ATM_AAL5
/* default MTU's */
#define ATMSAR_DEF_MTU_AAL0 48
#define ATMSAR_DEF_MTU_AAL1 47
#define ATMSAR_DEF_MTU_AAL2 0
/* not supported */
#define ATMSAR_DEF_MTU_AAL34 0
/* not supported */
#define ATMSAR_DEF_MTU_AAL5 65535
/* max mtu .. */
struct
atmsar_vcc_data
{
struct
atmsar_vcc_data
*
next
;
/* general atmsar flags, per connection */
int
flags
;
int
type
;
/* connection specific non-atmsar data */
struct
atm_vcc
*
vcc
;
struct
k_atm_aal_stats
*
stats
;
unsigned
short
mtu
;
/* max is actually 65k for AAL5... */
/* cell data */
unsigned
int
vp
;
unsigned
int
vc
;
unsigned
char
gfc
;
unsigned
char
pti
;
unsigned
int
headerFlags
;
unsigned
long
atmHeader
;
/* raw cell reassembly */
struct
sk_buff
*
reasBuffer
;
};
extern
struct
atmsar_vcc_data
*
atmsar_open
(
struct
atmsar_vcc_data
**
list
,
struct
atm_vcc
*
vcc
,
uint
type
,
ushort
vpi
,
ushort
vci
,
unchar
pti
,
unchar
gfc
,
uint
flags
);
extern
void
atmsar_close
(
struct
atmsar_vcc_data
**
list
,
struct
atmsar_vcc_data
*
vcc
);
struct
sk_buff
*
atmsar_decode_rawcell
(
struct
atmsar_vcc_data
*
list
,
struct
sk_buff
*
skb
,
struct
atmsar_vcc_data
**
ctx
);
struct
sk_buff
*
atmsar_decode_aal5
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
);
#endif
/* _ATMSAR_H_ */
drivers/usb/misc/speedt
ou
ch.c
→
drivers/usb/misc/speedtch.c
View file @
90a89de4
...
@@ -61,7 +61,6 @@
...
@@ -61,7 +61,6 @@
#include <linux/atm.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmdev.h>
#include <linux/crc32.h>
#include <linux/crc32.h>
#include "atmsar.h"
/*
/*
#define DEBUG 1
#define DEBUG 1
...
@@ -102,6 +101,8 @@ static int udsl_print_packet (const unsigned char *data, int len);
...
@@ -102,6 +101,8 @@ static int udsl_print_packet (const unsigned char *data, int len);
#define UDSL_ENDPOINT_DATA_OUT 0x07
#define UDSL_ENDPOINT_DATA_OUT 0x07
#define UDSL_ENDPOINT_DATA_IN 0x87
#define UDSL_ENDPOINT_DATA_IN 0x87
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )
/* usb_device_id struct */
/* usb_device_id struct */
...
@@ -147,6 +148,30 @@ struct udsl_control {
...
@@ -147,6 +148,30 @@ struct udsl_control {
#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb)
#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb)
struct
atmsar_vcc_data
{
struct
atmsar_vcc_data
*
next
;
/* general atmsar flags, per connection */
int
flags
;
int
type
;
/* connection specific non-atmsar data */
struct
atm_vcc
*
vcc
;
struct
k_atm_aal_stats
*
stats
;
unsigned
short
mtu
;
/* max is actually 65k for AAL5... */
/* cell data */
unsigned
int
vp
;
unsigned
int
vc
;
unsigned
char
gfc
;
unsigned
char
pti
;
unsigned
int
headerFlags
;
unsigned
long
atmHeader
;
/* raw cell reassembly */
struct
sk_buff
*
reasBuffer
;
};
/*
/*
* UDSL main driver data
* UDSL main driver data
*/
*/
...
@@ -229,6 +254,188 @@ static struct usb_driver udsl_usb_driver = {
...
@@ -229,6 +254,188 @@ static struct usb_driver udsl_usb_driver = {
};
};
/*************
** decode **
*************/
#define ATM_HDR_VPVC_MASK (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)
#define ATMSAR_USE_53BYTE_CELL 0x1L
struct
sk_buff
*
atmsar_decode_rawcell
(
struct
atmsar_vcc_data
*
list
,
struct
sk_buff
*
skb
,
struct
atmsar_vcc_data
**
ctx
)
{
while
(
skb
->
len
)
{
unsigned
char
*
cell
=
skb
->
data
;
unsigned
char
*
cell_payload
;
struct
atmsar_vcc_data
*
vcc
=
list
;
unsigned
long
atmHeader
=
((
unsigned
long
)
(
cell
[
0
])
<<
24
)
|
((
unsigned
long
)
(
cell
[
1
])
<<
16
)
|
((
unsigned
long
)
(
cell
[
2
])
<<
8
)
|
(
cell
[
3
]
&
0xff
);
dbg
(
"atmsar_decode_rawcell (0x%p, 0x%p, 0x%p) called"
,
list
,
skb
,
ctx
);
dbg
(
"atmsar_decode_rawcell skb->data %p, skb->tail %p"
,
skb
->
data
,
skb
->
tail
);
if
(
!
list
||
!
skb
||
!
ctx
)
return
NULL
;
if
(
!
skb
->
data
||
!
skb
->
tail
)
return
NULL
;
/* here should the header CRC check be... */
/* look up correct vcc */
for
(;
vcc
&&
((
vcc
->
atmHeader
&
ATM_HDR_VPVC_MASK
)
!=
(
atmHeader
&
ATM_HDR_VPVC_MASK
));
vcc
=
vcc
->
next
);
dbg
(
"atmsar_decode_rawcell found vcc %p for packet on vp %d, vc %d"
,
vcc
,
(
int
)
((
atmHeader
&
ATM_HDR_VPI_MASK
)
>>
ATM_HDR_VPI_SHIFT
),
(
int
)
((
atmHeader
&
ATM_HDR_VCI_MASK
)
>>
ATM_HDR_VCI_SHIFT
));
if
(
vcc
&&
(
skb
->
len
>=
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
)))
{
cell_payload
=
cell
+
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
5
:
4
);
switch
(
vcc
->
type
)
{
case
ATM_AAL0
:
/* case ATM_AAL1: when we have a decode AAL1 function... */
{
struct
sk_buff
*
tmp
=
dev_alloc_skb
(
vcc
->
mtu
);
if
(
tmp
)
{
memcpy
(
tmp
->
tail
,
cell_payload
,
48
);
skb_put
(
tmp
,
48
);
if
(
vcc
->
stats
)
atomic_inc
(
&
vcc
->
stats
->
rx
);
skb_pull
(
skb
,
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
));
dbg
(
"atmsar_decode_rawcell returns ATM_AAL0 pdu 0x%p with length %d"
,
tmp
,
tmp
->
len
);
return
tmp
;
};
}
break
;
case
ATM_AAL1
:
case
ATM_AAL2
:
case
ATM_AAL34
:
/* not supported */
break
;
case
ATM_AAL5
:
if
(
!
vcc
->
reasBuffer
)
vcc
->
reasBuffer
=
dev_alloc_skb
(
vcc
->
mtu
);
/* if alloc fails, we just drop the cell. it is possible that we can still
* receive cells on other vcc's
*/
if
(
vcc
->
reasBuffer
)
{
/* if (buffer overrun) discard received cells until now */
if
((
vcc
->
reasBuffer
->
len
)
>
(
vcc
->
mtu
-
48
))
skb_trim
(
vcc
->
reasBuffer
,
0
);
/* copy data */
memcpy
(
vcc
->
reasBuffer
->
tail
,
cell_payload
,
48
);
skb_put
(
vcc
->
reasBuffer
,
48
);
/* check for end of buffer */
if
(
cell
[
3
]
&
0x2
)
{
struct
sk_buff
*
tmp
;
/* the aal5 buffer ends here, cut the buffer. */
/* buffer will always have at least one whole cell, so */
/* don't need to check return from skb_pull */
skb_pull
(
skb
,
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
));
*
ctx
=
vcc
;
tmp
=
vcc
->
reasBuffer
;
vcc
->
reasBuffer
=
NULL
;
dbg
(
"atmsar_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d"
,
tmp
,
tmp
->
len
);
return
tmp
;
}
}
break
;
};
/* flush the cell */
/* buffer will always contain at least one whole cell, so don't */
/* need to check return value from skb_pull */
skb_pull
(
skb
,
(
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
));
}
else
{
/* If data is corrupt and skb doesn't hold a whole cell, flush the lot */
if
(
skb_pull
(
skb
,
(
list
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
))
==
NULL
)
return
NULL
;
}
}
return
NULL
;
};
struct
sk_buff
*
atmsar_decode_aal5
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
)
{
uint
crc
=
0xffffffff
;
uint
length
,
pdu_crc
,
pdu_length
;
dbg
(
"atmsar_decode_aal5 (0x%p, 0x%p) called"
,
ctx
,
skb
);
if
(
skb
->
len
&&
(
skb
->
len
%
48
))
return
NULL
;
length
=
(
skb
->
tail
[
-
6
]
<<
8
)
+
skb
->
tail
[
-
5
];
pdu_crc
=
(
skb
->
tail
[
-
4
]
<<
24
)
+
(
skb
->
tail
[
-
3
]
<<
16
)
+
(
skb
->
tail
[
-
2
]
<<
8
)
+
skb
->
tail
[
-
1
];
pdu_length
=
((
length
+
47
+
8
)
/
48
)
*
48
;
dbg
(
"atmsar_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d"
,
skb
->
len
,
length
,
pdu_crc
,
pdu_length
);
/* is skb long enough ? */
if
(
skb
->
len
<
pdu_length
)
{
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
rx_err
);
return
NULL
;
}
/* is skb too long ? */
if
(
skb
->
len
>
pdu_length
)
{
dbg
(
"atmsar_decode_aal5: Warning: readjusting illeagl size %d -> %d"
,
skb
->
len
,
pdu_length
);
/* buffer is too long. we can try to recover
* if we discard the first part of the skb.
* the crc will decide whether this was ok
*/
skb_pull
(
skb
,
skb
->
len
-
pdu_length
);
}
crc
=
~
crc32_be
(
crc
,
skb
->
data
,
pdu_length
-
4
);
/* check crc */
if
(
pdu_crc
!=
crc
)
{
dbg
(
"atmsar_decode_aal5: crc check failed!"
);
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
rx_err
);
return
NULL
;
}
/* pdu is ok */
skb_trim
(
skb
,
length
);
/* update stats */
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
rx
);
dbg
(
"atmsar_decode_aal5 returns pdu 0x%p with length %d"
,
skb
,
skb
->
len
);
return
skb
;
};
/*************
/*************
** encode **
** encode **
*************/
*************/
...
@@ -396,7 +603,7 @@ static void udsl_process_receive (unsigned long data)
...
@@ -396,7 +603,7 @@ static void udsl_process_receive (unsigned long data)
dbg
(
"(after cell processing)skb->len = %d"
,
new
->
len
);
dbg
(
"(after cell processing)skb->len = %d"
,
new
->
len
);
switch
(
atmsar_vcc
->
type
)
{
switch
(
atmsar_vcc
->
type
)
{
case
ATM
SAR_TYPE
_AAL5
:
case
ATM_AAL5
:
tmp
=
new
;
tmp
=
new
;
new
=
atmsar_decode_aal5
(
atmsar_vcc
,
new
);
new
=
atmsar_decode_aal5
(
atmsar_vcc
,
new
);
...
@@ -690,15 +897,98 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
...
@@ -690,15 +897,98 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
}
}
/************
/**********
** ATM **
** ATM **
************/
**********/
#define ATMSAR_DEF_MTU_AAL0 48
#define ATMSAR_DEF_MTU_AAL1 47
#define ATMSAR_DEF_MTU_AAL2 0
/* not supported */
#define ATMSAR_DEF_MTU_AAL34 0
/* not supported */
#define ATMSAR_DEF_MTU_AAL5 65535
/* max mtu .. */
struct
atmsar_vcc_data
*
atmsar_open
(
struct
atmsar_vcc_data
**
list
,
struct
atm_vcc
*
vcc
,
uint
type
,
ushort
vpi
,
ushort
vci
,
unchar
pti
,
unchar
gfc
,
uint
flags
)
{
struct
atmsar_vcc_data
*
new
;
if
(
!
vcc
)
return
NULL
;
new
=
kmalloc
(
sizeof
(
struct
atmsar_vcc_data
),
GFP_KERNEL
);
if
(
!
new
)
return
NULL
;
memset
(
new
,
0
,
sizeof
(
struct
atmsar_vcc_data
));
new
->
vcc
=
vcc
;
new
->
stats
=
vcc
->
stats
;
new
->
type
=
type
;
new
->
next
=
NULL
;
new
->
gfc
=
gfc
;
new
->
vp
=
vpi
;
new
->
vc
=
vci
;
new
->
pti
=
pti
;
switch
(
type
)
{
case
ATM_AAL0
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL0
;
break
;
case
ATM_AAL1
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL1
;
break
;
case
ATM_AAL2
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL2
;
break
;
case
ATM_AAL34
:
/* not supported */
new
->
mtu
=
ATMSAR_DEF_MTU_AAL34
;
break
;
case
ATM_AAL5
:
new
->
mtu
=
ATMSAR_DEF_MTU_AAL5
;
break
;
}
new
->
atmHeader
=
((
unsigned
long
)
gfc
<<
ATM_HDR_GFC_SHIFT
)
|
((
unsigned
long
)
vpi
<<
ATM_HDR_VPI_SHIFT
)
|
((
unsigned
long
)
vci
<<
ATM_HDR_VCI_SHIFT
)
|
((
unsigned
long
)
pti
<<
ATM_HDR_PTI_SHIFT
);
new
->
flags
=
flags
;
new
->
next
=
NULL
;
new
->
reasBuffer
=
NULL
;
new
->
next
=
*
list
;
*
list
=
new
;
dbg
(
"Allocated new SARLib vcc 0x%p with vp %d vc %d"
,
new
,
vpi
,
vci
);
return
new
;
}
void
atmsar_close
(
struct
atmsar_vcc_data
**
list
,
struct
atmsar_vcc_data
*
vcc
)
{
struct
atmsar_vcc_data
*
work
;
if
(
*
list
==
vcc
)
{
*
list
=
(
*
list
)
->
next
;
}
else
{
for
(
work
=
*
list
;
work
&&
work
->
next
&&
(
work
->
next
!=
vcc
);
work
=
work
->
next
);
/* return if not found */
if
(
work
->
next
!=
vcc
)
return
;
/***************************************************************************
work
->
next
=
work
->
next
->
next
;
*
}
* init functions
*
if
(
vcc
->
reasBuffer
)
{
****************************************************************************/
dev_kfree_skb
(
vcc
->
reasBuffer
);
}
dbg
(
"Allocated SARLib vcc 0x%p with vp %d vc %d"
,
vcc
,
vcc
->
vp
,
vcc
->
vc
);
kfree
(
vcc
);
}
static
void
udsl_atm_dev_close
(
struct
atm_dev
*
dev
)
static
void
udsl_atm_dev_close
(
struct
atm_dev
*
dev
)
{
{
...
@@ -718,13 +1008,6 @@ static void udsl_atm_dev_close (struct atm_dev *dev)
...
@@ -718,13 +1008,6 @@ static void udsl_atm_dev_close (struct atm_dev *dev)
dev
->
dev_data
=
NULL
;
dev
->
dev_data
=
NULL
;
}
}
/***************************************************************************
*
* ATM helper functions
*
****************************************************************************/
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
)
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
)
{
{
struct
udsl_instance_data
*
instance
=
atm_dev
->
dev_data
;
struct
udsl_instance_data
*
instance
=
atm_dev
->
dev_data
;
...
@@ -778,12 +1061,7 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
...
@@ -778,12 +1061,7 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
return
0
;
return
0
;
}
}
#define ATMSAR_SET_PTI 0x2L
/***************************************************************************
*
* SAR driver entries
*
****************************************************************************/
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
)
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
)
{
{
...
@@ -803,7 +1081,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
...
@@ -803,7 +1081,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
MOD_INC_USE_COUNT
;
MOD_INC_USE_COUNT
;
vcc
->
dev_data
=
vcc
->
dev_data
=
atmsar_open
(
&
(
instance
->
atmsar_vcc_list
),
vcc
,
ATM
SAR_TYPE
_AAL5
,
vpi
,
vci
,
0
,
0
,
atmsar_open
(
&
(
instance
->
atmsar_vcc_list
),
vcc
,
ATM_AAL5
,
vpi
,
vci
,
0
,
0
,
ATMSAR_USE_53BYTE_CELL
|
ATMSAR_SET_PTI
);
ATMSAR_USE_53BYTE_CELL
|
ATMSAR_SET_PTI
);
if
(
!
vcc
->
dev_data
)
{
if
(
!
vcc
->
dev_data
)
{
MOD_DEC_USE_COUNT
;
MOD_DEC_USE_COUNT
;
...
@@ -866,9 +1144,9 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg)
...
@@ -866,9 +1144,9 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg)
}
}
/**********
**
/**********
**
USB
**
**
USB
**
**********
**
/
**********/
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
)
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
)
{
{
...
@@ -1180,11 +1458,9 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
...
@@ -1180,11 +1458,9 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
}
}
/***************************************************************************
/***********
*
** init **
* Driver Init
***********/
*
****************************************************************************/
static
int
__init
udsl_usb_init
(
void
)
static
int
__init
udsl_usb_init
(
void
)
{
{
...
@@ -1215,13 +1491,11 @@ MODULE_DESCRIPTION (DRIVER_DESC);
...
@@ -1215,13 +1491,11 @@ MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
#ifdef DEBUG_PACKET
/************
/*******************************************************************************
** debug **
*
************/
* Debug
*
*******************************************************************************/
#ifdef DEBUG_PACKET
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
)
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
)
{
{
unsigned
char
buffer
[
256
];
unsigned
char
buffer
[
256
];
...
@@ -1237,5 +1511,4 @@ static int udsl_print_packet (const unsigned char *data, int len)
...
@@ -1237,5 +1511,4 @@ static int udsl_print_packet (const unsigned char *data, int len)
}
}
return
i
;
return
i
;
}
}
#endif
#endif
/* PACKETDEBUG */
drivers/usb/net/cdc-ether.c
View file @
90a89de4
...
@@ -1064,15 +1064,23 @@ static void set_ethernet_addr( ether_dev_t *ether_dev )
...
@@ -1064,15 +1064,23 @@ static void set_ethernet_addr( ether_dev_t *ether_dev )
// Used by driver's probe routine ////////////////////////////////////////////
// Used by driver's probe routine ////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void
log_device_info
(
ether_dev_t
*
ether_dev
)
static
void
log_device_info
(
ether_dev_t
*
ether_dev
)
{
{
int
len
;
int
len
;
int
string_num
;
int
string_num
;
unsigned
char
manu
[
256
]
;
unsigned
char
*
manu
=
NULL
;
unsigned
char
prod
[
256
]
;
unsigned
char
*
prod
=
NULL
;
unsigned
char
sern
[
256
]
;
unsigned
char
*
sern
=
NULL
;
unsigned
char
*
mac_addr
;
unsigned
char
*
mac_addr
;
manu
=
kmalloc
(
256
,
GFP_KERNEL
);
prod
=
kmalloc
(
256
,
GFP_KERNEL
);
sern
=
kmalloc
(
256
,
GFP_KERNEL
);
if
(
!
manu
||
!
prod
||
!
sern
)
{
dbg
(
"no mem for log_device_info"
);
goto
fini
;
}
// Default empty strings in case we don't find a real one
// Default empty strings in case we don't find a real one
manu
[
0
]
=
0x00
;
manu
[
0
]
=
0x00
;
prod
[
0
]
=
0x00
;
prod
[
0
]
=
0x00
;
...
@@ -1113,6 +1121,10 @@ void log_device_info(ether_dev_t *ether_dev)
...
@@ -1113,6 +1121,10 @@ void log_device_info(ether_dev_t *ether_dev)
ether_dev
->
net
->
name
,
manu
,
prod
,
sern
,
mac_addr
[
0
],
ether_dev
->
net
->
name
,
manu
,
prod
,
sern
,
mac_addr
[
0
],
mac_addr
[
1
],
mac_addr
[
2
],
mac_addr
[
3
],
mac_addr
[
4
],
mac_addr
[
1
],
mac_addr
[
2
],
mac_addr
[
3
],
mac_addr
[
4
],
mac_addr
[
5
]
);
mac_addr
[
5
]
);
fini:
kfree
(
manu
);
kfree
(
prod
);
kfree
(
sern
);
}
}
/* Forward declaration */
/* Forward declaration */
...
...
drivers/usb/net/pegasus.c
View file @
90a89de4
...
@@ -121,7 +121,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
...
@@ -121,7 +121,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
char
*
buffer
;
char
*
buffer
;
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
buffer
=
kmalloc
(
size
,
GFP_
DMA
);
buffer
=
kmalloc
(
size
,
GFP_
KERNEL
);
if
(
!
buffer
)
{
if
(
!
buffer
)
{
warn
(
"%s: looks like we're out of memory"
,
__FUNCTION__
);
warn
(
"%s: looks like we're out of memory"
,
__FUNCTION__
);
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -170,7 +170,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
...
@@ -170,7 +170,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
char
*
buffer
;
char
*
buffer
;
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
buffer
=
kmalloc
(
size
,
GFP_
DMA
);
buffer
=
kmalloc
(
size
,
GFP_
KERNEL
);
if
(
!
buffer
)
{
if
(
!
buffer
)
{
warn
(
"%s: looks like we're out of memory"
,
__FUNCTION__
);
warn
(
"%s: looks like we're out of memory"
,
__FUNCTION__
);
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -218,7 +218,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
...
@@ -218,7 +218,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
char
*
tmp
;
char
*
tmp
;
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
tmp
=
kmalloc
(
1
,
GFP_
DMA
);
tmp
=
kmalloc
(
1
,
GFP_
KERNEL
);
if
(
!
tmp
)
{
if
(
!
tmp
)
{
warn
(
"%s: looks like we're out of memory"
,
__FUNCTION__
);
warn
(
"%s: looks like we're out of memory"
,
__FUNCTION__
);
return
-
ENOMEM
;
return
-
ENOMEM
;
...
...
drivers/usb/serial/whiteheat.c
View file @
90a89de4
...
@@ -783,7 +783,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
...
@@ -783,7 +783,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
if
(
info
->
mcr
&
UART_MCR_RTS
)
if
(
info
->
mcr
&
UART_MCR_RTS
)
modem_signals
|=
TIOCM_RTS
;
modem_signals
|=
TIOCM_RTS
;
if
(
copy_to_user
((
unsigned
int
*
)
arg
,
&
modem_signals
,
sizeof
(
unsigned
int
)))
;
if
(
copy_to_user
((
unsigned
int
*
)
arg
,
&
modem_signals
,
sizeof
(
unsigned
int
)))
return
-
EFAULT
;
return
-
EFAULT
;
break
;
break
;
...
...
drivers/usb/usb-skeleton.c
View file @
90a89de4
/*
/*
* USB Skeleton driver -
0.9
* USB Skeleton driver -
1.0
*
*
* Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
*
*
...
@@ -12,14 +12,17 @@
...
@@ -12,14 +12,17 @@
* USB driver quickly. The design of it is based on the usb-serial and
* USB driver quickly. The design of it is based on the usb-serial and
* dc2xx drivers.
* dc2xx drivers.
*
*
* Thanks to Oliver Neukum
and David Brownell for their help in debugging
* Thanks to Oliver Neukum
, David Brownell, and Alan Stern for their help
* this driver.
*
in debugging
this driver.
*
*
* TODO:
* - fix urb->status race condition in write sequence
*
*
* History:
* History:
*
*
* 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and
* disconnect. Fix transfer amount in read(). Use
* macros instead of magic numbers in probe(). Change
* size variables to size_t. Show how to eliminate
* DMA bounce buffer.
* 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
* 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
* 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
* 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
* driver.
* driver.
...
@@ -33,7 +36,7 @@
...
@@ -33,7 +36,7 @@
* 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel
* 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel
* 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people
* 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people
* 2001_05_01 - 0.1 - first version
* 2001_05_01 - 0.1 - first version
*
*
*/
*/
#include <linux/config.h>
#include <linux/config.h>
...
@@ -42,8 +45,8 @@
...
@@ -42,8 +45,8 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/usb.h>
...
@@ -60,7 +63,7 @@
...
@@ -60,7 +63,7 @@
/* Version Information */
/* Version Information */
#define DRIVER_VERSION "v
0.4
"
#define DRIVER_VERSION "v
1.0
"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
#define DRIVER_DESC "USB Skeleton Driver"
#define DRIVER_DESC "USB Skeleton Driver"
...
@@ -101,15 +104,16 @@ struct usb_skel {
...
@@ -101,15 +104,16 @@ struct usb_skel {
char
num_bulk_out
;
/* number of bulk out endpoints we have */
char
num_bulk_out
;
/* number of bulk out endpoints we have */
unsigned
char
*
bulk_in_buffer
;
/* the buffer to receive data */
unsigned
char
*
bulk_in_buffer
;
/* the buffer to receive data */
in
t
bulk_in_size
;
/* the size of the receive buffer */
size_
t
bulk_in_size
;
/* the size of the receive buffer */
__u8
bulk_in_endpointAddr
;
/* the address of the bulk in endpoint */
__u8
bulk_in_endpointAddr
;
/* the address of the bulk in endpoint */
unsigned
char
*
bulk_out_buffer
;
/* the buffer to send data */
unsigned
char
*
bulk_out_buffer
;
/* the buffer to send data */
in
t
bulk_out_size
;
/* the size of the send buffer */
size_
t
bulk_out_size
;
/* the size of the send buffer */
struct
urb
*
write_urb
;
/* the urb used to send data */
struct
urb
*
write_urb
;
/* the urb used to send data */
__u8
bulk_out_endpointAddr
;
/* the address of the bulk out endpoint */
__u8
bulk_out_endpointAddr
;
/* the address of the bulk out endpoint */
atomic_t
write_busy
;
/* true iff write urb is busy */
struct
completion
write_finished
;
/* wait for the write to finish */
struct
work_struct
work
;
/* work queue entry for line discipline waking up */
int
open
;
/* if the port is open or not */
int
open
;
/* if the port is open or not */
struct
semaphore
sem
;
/* locks this structure */
struct
semaphore
sem
;
/* locks this structure */
};
};
...
@@ -118,6 +122,8 @@ struct usb_skel {
...
@@ -118,6 +122,8 @@ struct usb_skel {
/* the global usb devfs handle */
/* the global usb devfs handle */
extern
devfs_handle_t
usb_devfs_handle
;
extern
devfs_handle_t
usb_devfs_handle
;
/* prevent races between open() and disconnect() */
static
DECLARE_MUTEX
(
disconnect_sem
);
/* local function prototypes */
/* local function prototypes */
static
ssize_t
skel_read
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
);
static
ssize_t
skel_read
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
);
...
@@ -125,7 +131,7 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
...
@@ -125,7 +131,7 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
static
int
skel_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
static
int
skel_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
static
int
skel_open
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
skel_open
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
skel_release
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
skel_release
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
skel_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
static
int
skel_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
static
void
skel_disconnect
(
struct
usb_interface
*
intf
);
static
void
skel_disconnect
(
struct
usb_interface
*
intf
);
...
@@ -138,7 +144,7 @@ static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
...
@@ -138,7 +144,7 @@ static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
* to have a node in the /dev directory. If the USB
* to have a node in the /dev directory. If the USB
* device were for a network interface then the driver
* device were for a network interface then the driver
* would use "struct net_driver" instead, and a serial
* would use "struct net_driver" instead, and a serial
* device would use "struct tty_driver".
* device would use "struct tty_driver".
*/
*/
static
struct
file_operations
skel_fops
=
{
static
struct
file_operations
skel_fops
=
{
/*
/*
...
@@ -167,7 +173,7 @@ static struct file_operations skel_fops = {
...
@@ -167,7 +173,7 @@ static struct file_operations skel_fops = {
.
ioctl
=
skel_ioctl
,
.
ioctl
=
skel_ioctl
,
.
open
=
skel_open
,
.
open
=
skel_open
,
.
release
=
skel_release
,
.
release
=
skel_release
,
};
};
/* usb specific object needed to register this driver with the usb subsystem */
/* usb specific object needed to register this driver with the usb subsystem */
...
@@ -188,8 +194,8 @@ static inline void usb_skel_debug_data (const char *function, int size, const un
...
@@ -188,8 +194,8 @@ static inline void usb_skel_debug_data (const char *function, int size, const un
if
(
!
debug
)
if
(
!
debug
)
return
;
return
;
printk
(
KERN_DEBUG
__FILE__
": %s - length = %d, data = "
,
printk
(
KERN_DEBUG
__FILE__
": %s - length = %d, data = "
,
function
,
size
);
function
,
size
);
for
(
i
=
0
;
i
<
size
;
++
i
)
{
for
(
i
=
0
;
i
<
size
;
++
i
)
{
printk
(
"%.2x "
,
data
[
i
]);
printk
(
"%.2x "
,
data
[
i
]);
...
@@ -206,7 +212,9 @@ static inline void skel_delete (struct usb_skel *dev)
...
@@ -206,7 +212,9 @@ static inline void skel_delete (struct usb_skel *dev)
if
(
dev
->
bulk_in_buffer
!=
NULL
)
if
(
dev
->
bulk_in_buffer
!=
NULL
)
kfree
(
dev
->
bulk_in_buffer
);
kfree
(
dev
->
bulk_in_buffer
);
if
(
dev
->
bulk_out_buffer
!=
NULL
)
if
(
dev
->
bulk_out_buffer
!=
NULL
)
kfree
(
dev
->
bulk_out_buffer
);
usb_buffer_free
(
dev
->
udev
,
dev
->
bulk_out_size
,
dev
->
bulk_out_buffer
,
dev
->
write_urb
->
transfer_dma
);
if
(
dev
->
write_urb
!=
NULL
)
if
(
dev
->
write_urb
!=
NULL
)
usb_free_urb
(
dev
->
write_urb
);
usb_free_urb
(
dev
->
write_urb
);
kfree
(
dev
);
kfree
(
dev
);
...
@@ -222,22 +230,28 @@ static int skel_open (struct inode *inode, struct file *file)
...
@@ -222,22 +230,28 @@ static int skel_open (struct inode *inode, struct file *file)
struct
usb_interface
*
interface
;
struct
usb_interface
*
interface
;
int
subminor
;
int
subminor
;
int
retval
=
0
;
int
retval
=
0
;
dbg
(
"%s"
,
__FUNCTION__
);
dbg
(
"%s"
,
__FUNCTION__
);
subminor
=
minor
(
inode
->
i_rdev
);
subminor
=
minor
(
inode
->
i_rdev
);
/* prevent disconnects */
down
(
&
disconnect_sem
);
interface
=
usb_find_interface
(
&
skel_driver
,
interface
=
usb_find_interface
(
&
skel_driver
,
mk_kdev
(
USB_MAJOR
,
subminor
));
mk_kdev
(
USB_MAJOR
,
subminor
));
if
(
!
interface
)
{
if
(
!
interface
)
{
err
(
"%s - error, can't find device for minor %d"
,
err
(
"%s - error, can't find device for minor %d"
,
__FUNCTION__
,
subminor
);
__FUNCTION__
,
subminor
);
return
-
ENODEV
;
retval
=
-
ENODEV
;
goto
exit_no_device
;
}
}
dev
=
usb_get_intfdata
(
interface
);
dev
=
usb_get_intfdata
(
interface
);
if
(
!
dev
)
if
(
!
dev
)
{
return
-
ENODEV
;
retval
=
-
ENODEV
;
goto
exit_no_device
;
}
/* lock this device */
/* lock this device */
down
(
&
dev
->
sem
);
down
(
&
dev
->
sem
);
...
@@ -251,6 +265,8 @@ static int skel_open (struct inode *inode, struct file *file)
...
@@ -251,6 +265,8 @@ static int skel_open (struct inode *inode, struct file *file)
/* unlock this device */
/* unlock this device */
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
exit_no_device:
up
(
&
disconnect_sem
);
return
retval
;
return
retval
;
}
}
...
@@ -280,6 +296,12 @@ static int skel_release (struct inode *inode, struct file *file)
...
@@ -280,6 +296,12 @@ static int skel_release (struct inode *inode, struct file *file)
goto
exit_not_opened
;
goto
exit_not_opened
;
}
}
/* wait for any bulk writes that might be going on to finish up */
if
(
atomic_read
(
&
dev
->
write_busy
))
wait_for_completion
(
&
dev
->
write_finished
);
dev
->
open
=
0
;
if
(
dev
->
udev
==
NULL
)
{
if
(
dev
->
udev
==
NULL
)
{
/* the device was unplugged before the file was released */
/* the device was unplugged before the file was released */
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
...
@@ -287,11 +309,6 @@ static int skel_release (struct inode *inode, struct file *file)
...
@@ -287,11 +309,6 @@ static int skel_release (struct inode *inode, struct file *file)
return
0
;
return
0
;
}
}
/* shutdown any bulk writes that might be going on */
usb_unlink_urb
(
dev
->
write_urb
);
dev
->
open
=
0
;
exit_not_opened:
exit_not_opened:
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
...
@@ -308,7 +325,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
...
@@ -308,7 +325,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
int
retval
=
0
;
int
retval
=
0
;
dev
=
(
struct
usb_skel
*
)
file
->
private_data
;
dev
=
(
struct
usb_skel
*
)
file
->
private_data
;
dbg
(
"%s - minor %d, count = %d"
,
__FUNCTION__
,
dev
->
minor
,
count
);
dbg
(
"%s - minor %d, count = %d"
,
__FUNCTION__
,
dev
->
minor
,
count
);
/* lock this object */
/* lock this object */
...
@@ -319,12 +336,13 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
...
@@ -319,12 +336,13 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
/* do a
n immediate
bulk read to get data from the device */
/* do a
blocking
bulk read to get data from the device */
retval
=
usb_bulk_msg
(
dev
->
udev
,
retval
=
usb_bulk_msg
(
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
dev
->
bulk_in_endpointAddr
),
dev
->
bulk_in_endpointAddr
),
dev
->
bulk_in_buffer
,
dev
->
bulk_in_size
,
dev
->
bulk_in_buffer
,
min
(
dev
->
bulk_in_size
,
count
),
&
count
,
HZ
*
10
);
&
count
,
HZ
*
10
);
/* if the read was successful, copy the data to userspace */
/* if the read was successful, copy the data to userspace */
...
@@ -334,7 +352,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
...
@@ -334,7 +352,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
else
else
retval
=
count
;
retval
=
count
;
}
}
/* unlock the device */
/* unlock the device */
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
return
retval
;
return
retval
;
...
@@ -343,6 +361,18 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
...
@@ -343,6 +361,18 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t
/**
/**
* skel_write
* skel_write
*
* A device driver has to decide how to report I/O errors back to the
* user. The safest course is to wait for the transfer to finish before
* returning so that any errors will be reported reliably. skel_read()
* works like this. But waiting for I/O is slow, so many drivers only
* check for errors during I/O initiation and do not report problems
* that occur during the actual transfer. That's what we will do here.
*
* A driver concerned with maximum I/O throughput would use double-
* buffering: Two urbs would be devoted to write transfers, so that
* one urb could always be active while the other was waiting for the
* user to send more data.
*/
*/
static
ssize_t
skel_write
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
skel_write
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
{
...
@@ -369,37 +399,38 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
...
@@ -369,37 +399,38 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count,
goto
exit
;
goto
exit
;
}
}
/*
see if we are already in the middle of a write */
/*
wait for a previous write to finish up; we don't use a timeout
if
(
dev
->
write_urb
->
status
==
-
EINPROGRESS
)
{
* and so a nonresponsive device can delay us indefinitely.
dbg
(
"%s - already writing"
,
__FUNCTION__
);
*/
goto
exit
;
if
(
atomic_read
(
&
dev
->
write_busy
))
}
wait_for_completion
(
&
dev
->
write_finished
);
/* we can only write as much as 1 urb will hold */
/* we can only write as much as our buffer will hold */
bytes_written
=
(
count
>
dev
->
bulk_out_size
)
?
bytes_written
=
min
(
dev
->
bulk_out_size
,
count
);
dev
->
bulk_out_size
:
count
;
/* copy the data from userspace into our urb */
/* copy the data from userspace into our transfer buffer;
if
(
copy_from_user
(
dev
->
write_urb
->
transfer_buffer
,
buffer
,
* this is the only copy required.
*/
if
(
copy_from_user
(
dev
->
write_urb
->
transfer_buffer
,
buffer
,
bytes_written
))
{
bytes_written
))
{
retval
=
-
EFAULT
;
retval
=
-
EFAULT
;
goto
exit
;
goto
exit
;
}
}
usb_skel_debug_data
(
__FUNCTION__
,
bytes_written
,
usb_skel_debug_data
(
__FUNCTION__
,
bytes_written
,
dev
->
write_urb
->
transfer_buffer
);
dev
->
write_urb
->
transfer_buffer
);
/* set up our urb */
/* this urb was already set up, except for this write size */
usb_fill_bulk_urb
(
dev
->
write_urb
,
dev
->
udev
,
dev
->
write_urb
->
transfer_buffer_length
=
bytes_written
;
usb_sndbulkpipe
(
dev
->
udev
,
dev
->
bulk_out_endpointAddr
),
dev
->
write_urb
->
transfer_buffer
,
bytes_written
,
skel_write_bulk_callback
,
dev
);
/* send the data out the bulk port */
/* send the data out the bulk port */
/* a character device write uses GFP_KERNEL,
/* a character device write uses GFP_KERNEL,
unless a spinlock is held */
unless a spinlock is held */
init_completion
(
&
dev
->
write_finished
);
atomic_set
(
&
dev
->
write_busy
,
1
);
retval
=
usb_submit_urb
(
dev
->
write_urb
,
GFP_KERNEL
);
retval
=
usb_submit_urb
(
dev
->
write_urb
,
GFP_KERNEL
);
if
(
retval
)
{
if
(
retval
)
{
atomic_set
(
&
dev
->
write_busy
,
0
);
err
(
"%s - failed submitting write urb, error %d"
,
err
(
"%s - failed submitting write urb, error %d"
,
__FUNCTION__
,
retval
);
__FUNCTION__
,
retval
);
}
else
{
}
else
{
...
@@ -435,12 +466,11 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
...
@@ -435,12 +466,11 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
dbg
(
"%s - minor %d, cmd 0x%.4x, arg %ld"
,
__FUNCTION__
,
dbg
(
"%s - minor %d, cmd 0x%.4x, arg %ld"
,
__FUNCTION__
,
dev
->
minor
,
cmd
,
arg
);
dev
->
minor
,
cmd
,
arg
);
/* fill in your device specific stuff here */
/* fill in your device specific stuff here */
/* unlock the device */
/* unlock the device */
up
(
&
dev
->
sem
);
up
(
&
dev
->
sem
);
/* return that we did not understand this ioctl call */
/* return that we did not understand this ioctl call */
return
-
ENOTTY
;
return
-
ENOTTY
;
}
}
...
@@ -455,14 +485,16 @@ static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
...
@@ -455,14 +485,16 @@ static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
dbg
(
"%s - minor %d"
,
__FUNCTION__
,
dev
->
minor
);
dbg
(
"%s - minor %d"
,
__FUNCTION__
,
dev
->
minor
);
if
((
urb
->
status
!=
-
ENOENT
)
&&
/* sync/async unlink faults aren't errors */
(
urb
->
status
!=
-
ECONNRESET
))
{
if
(
urb
->
status
&&
!
(
urb
->
status
==
-
ENOENT
||
urb
->
status
==
-
ECONNRESET
))
{
dbg
(
"%s - nonzero write bulk status received: %d"
,
dbg
(
"%s - nonzero write bulk status received: %d"
,
__FUNCTION__
,
urb
->
status
);
__FUNCTION__
,
urb
->
status
);
return
;
}
}
return
;
/* notify anyone waiting that the write has finished */
atomic_set
(
&
dev
->
write_busy
,
0
);
complete
(
&
dev
->
write_finished
);
}
}
...
@@ -479,12 +511,12 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
...
@@ -479,12 +511,12 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
struct
usb_host_interface
*
iface_desc
;
struct
usb_host_interface
*
iface_desc
;
struct
usb_endpoint_descriptor
*
endpoint
;
struct
usb_endpoint_descriptor
*
endpoint
;
int
minor
;
int
minor
;
in
t
buffer_size
;
size_
t
buffer_size
;
int
i
;
int
i
;
int
retval
;
int
retval
;
char
name
[
10
];
char
name
[
10
];
/* See if the device offered us matches what we can accept */
/* See if the device offered us matches what we can accept */
if
((
udev
->
descriptor
.
idVendor
!=
USB_SKEL_VENDOR_ID
)
||
if
((
udev
->
descriptor
.
idVendor
!=
USB_SKEL_VENDOR_ID
)
||
(
udev
->
descriptor
.
idProduct
!=
USB_SKEL_PRODUCT_ID
))
{
(
udev
->
descriptor
.
idProduct
!=
USB_SKEL_PRODUCT_ID
))
{
...
@@ -513,12 +545,15 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
...
@@ -513,12 +545,15 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
/* set up the endpoint information */
/* set up the endpoint information */
/* check out the endpoints */
/* check out the endpoints */
/* use only the first bulk-in and bulk-out endpoints */
iface_desc
=
&
interface
->
altsetting
[
0
];
iface_desc
=
&
interface
->
altsetting
[
0
];
for
(
i
=
0
;
i
<
iface_desc
->
desc
.
bNumEndpoints
;
++
i
)
{
for
(
i
=
0
;
i
<
iface_desc
->
desc
.
bNumEndpoints
;
++
i
)
{
endpoint
=
&
iface_desc
->
endpoint
[
i
].
desc
;
endpoint
=
&
iface_desc
->
endpoint
[
i
].
desc
;
if
((
endpoint
->
bEndpointAddress
&
0x80
)
&&
if
(
!
dev
->
bulk_in_endpointAddr
&&
((
endpoint
->
bmAttributes
&
3
)
==
0x02
))
{
(
endpoint
->
bEndpointAddress
&
USB_DIR_IN
)
&&
((
endpoint
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_BULK
))
{
/* we found a bulk in endpoint */
/* we found a bulk in endpoint */
buffer_size
=
endpoint
->
wMaxPacketSize
;
buffer_size
=
endpoint
->
wMaxPacketSize
;
dev
->
bulk_in_size
=
buffer_size
;
dev
->
bulk_in_size
=
buffer_size
;
...
@@ -529,9 +564,11 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
...
@@ -529,9 +564,11 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
goto
error
;
goto
error
;
}
}
}
}
if
(((
endpoint
->
bEndpointAddress
&
0x80
)
==
0x00
)
&&
if
(
!
dev
->
bulk_out_endpointAddr
&&
((
endpoint
->
bmAttributes
&
3
)
==
0x02
))
{
!
(
endpoint
->
bEndpointAddress
&
USB_DIR_IN
)
&&
((
endpoint
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_BULK
))
{
/* we found a bulk out endpoint */
/* we found a bulk out endpoint */
/* a probe() may sleep and has no restrictions on memory allocations */
/* a probe() may sleep and has no restrictions on memory allocations */
dev
->
write_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
dev
->
write_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
...
@@ -539,40 +576,56 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
...
@@ -539,40 +576,56 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
err
(
"No free urbs available"
);
err
(
"No free urbs available"
);
goto
error
;
goto
error
;
}
}
dev
->
bulk_out_endpointAddr
=
endpoint
->
bEndpointAddress
;
/* on some platforms using this kind of buffer alloc
* call eliminates a dma "bounce buffer".
*
* NOTE: you'd normally want i/o buffers that hold
* more than one packet, so that i/o delays between
* packets don't hurt throughput.
*/
buffer_size
=
endpoint
->
wMaxPacketSize
;
buffer_size
=
endpoint
->
wMaxPacketSize
;
dev
->
bulk_out_size
=
buffer_size
;
dev
->
bulk_out_size
=
buffer_size
;
dev
->
bulk_out_endpointAddr
=
endpoint
->
bEndpointAddress
;
dev
->
write_urb
->
transfer_flags
=
(
URB_NO_DMA_MAP
|
dev
->
bulk_out_buffer
=
kmalloc
(
buffer_size
,
GFP_KERNEL
);
URB_ASYNC_UNLINK
);
dev
->
bulk_out_buffer
=
usb_buffer_alloc
(
udev
,
buffer_size
,
GFP_KERNEL
,
&
dev
->
write_urb
->
transfer_dma
);
if
(
!
dev
->
bulk_out_buffer
)
{
if
(
!
dev
->
bulk_out_buffer
)
{
err
(
"Couldn't allocate bulk_out_buffer"
);
err
(
"Couldn't allocate bulk_out_buffer"
);
goto
error
;
goto
error
;
}
}
usb_fill_bulk_urb
(
dev
->
write_urb
,
udev
,
usb_fill_bulk_urb
(
dev
->
write_urb
,
udev
,
usb_sndbulkpipe
(
udev
,
usb_sndbulkpipe
(
udev
,
endpoint
->
bEndpointAddress
),
endpoint
->
bEndpointAddress
),
dev
->
bulk_out_buffer
,
buffer_size
,
dev
->
bulk_out_buffer
,
buffer_size
,
skel_write_bulk_callback
,
dev
);
skel_write_bulk_callback
,
dev
);
}
}
}
}
if
(
!
(
dev
->
bulk_in_endpointAddr
&&
dev
->
bulk_out_endpointAddr
))
{
err
(
"Couldn't find both bulk-in and bulk-out endpoints"
);
goto
error
;
}
/* initialize the devfs node for this device and register it */
/* initialize the devfs node for this device and register it */
sprintf
(
name
,
"skel%d"
,
dev
->
minor
);
sprintf
(
name
,
"skel%d"
,
dev
->
minor
);
dev
->
devfs
=
devfs_register
(
usb_devfs_handle
,
name
,
dev
->
devfs
=
devfs_register
(
usb_devfs_handle
,
name
,
DEVFS_FL_DEFAULT
,
USB_MAJOR
,
DEVFS_FL_DEFAULT
,
USB_MAJOR
,
dev
->
minor
,
dev
->
minor
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
|
S_IFCHR
|
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
|
S_IROTH
,
S_IRGRP
|
S_IWGRP
|
S_IROTH
,
&
skel_fops
,
NULL
);
&
skel_fops
,
NULL
);
/* let the user know what node this device is now attached to */
/* let the user know what node this device is now attached to */
info
(
"USB Skeleton device now attached to USBSkel%d"
,
dev
->
minor
);
info
(
"USB Skeleton device now attached to USBSkel
-
%d"
,
dev
->
minor
);
/* add device id so the device works when advertised */
/* add device id so the device works when advertised */
interface
->
kdev
=
mk_kdev
(
USB_MAJOR
,
dev
->
minor
);
interface
->
kdev
=
mk_kdev
(
USB_MAJOR
,
dev
->
minor
);
goto
exit
;
goto
exit
;
error:
error:
skel_delete
(
dev
);
skel_delete
(
dev
);
dev
=
NULL
;
dev
=
NULL
;
...
@@ -593,12 +646,21 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
...
@@ -593,12 +646,21 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
* skel_disconnect
* skel_disconnect
*
*
* Called by the usb core when the device is removed from the system.
* Called by the usb core when the device is removed from the system.
*
* This routine guarantees that the driver will not submit any more urbs
* by clearing dev->udev. It is also supposed to terminate any currently
* active urbs. Unfortunately, usb_bulk_msg(), used in skel_read(), does
* not provide any way to do this. But at least we can cancel an active
* write.
*/
*/
static
void
skel_disconnect
(
struct
usb_interface
*
interface
)
static
void
skel_disconnect
(
struct
usb_interface
*
interface
)
{
{
struct
usb_skel
*
dev
;
struct
usb_skel
*
dev
;
int
minor
;
int
minor
;
/* prevent races with open() */
down
(
&
disconnect_sem
);
dev
=
usb_get_intfdata
(
interface
);
dev
=
usb_get_intfdata
(
interface
);
usb_set_intfdata
(
interface
,
NULL
);
usb_set_intfdata
(
interface
,
NULL
);
...
@@ -606,7 +668,7 @@ static void skel_disconnect(struct usb_interface *interface)
...
@@ -606,7 +668,7 @@ static void skel_disconnect(struct usb_interface *interface)
return
;
return
;
down
(
&
dev
->
sem
);
down
(
&
dev
->
sem
);
/* remove device id to disable open() */
/* remove device id to disable open() */
interface
->
kdev
=
NODEV
;
interface
->
kdev
=
NODEV
;
...
@@ -617,15 +679,21 @@ static void skel_disconnect(struct usb_interface *interface)
...
@@ -617,15 +679,21 @@ static void skel_disconnect(struct usb_interface *interface)
/* give back our dynamic minor */
/* give back our dynamic minor */
usb_deregister_dev
(
1
,
minor
);
usb_deregister_dev
(
1
,
minor
);
/* terminate an ongoing write */
if
(
atomic_read
(
&
dev
->
write_busy
))
{
usb_unlink_urb
(
dev
->
write_urb
);
wait_for_completion
(
&
dev
->
write_finished
);
}
dev
->
udev
=
NULL
;
up
(
&
dev
->
sem
);
/* if the device is not opened, then we clean up right now */
/* if the device is not opened, then we clean up right now */
if
(
!
dev
->
open
)
{
if
(
!
dev
->
open
)
up
(
&
dev
->
sem
);
skel_delete
(
dev
);
skel_delete
(
dev
);
}
else
{
dev
->
udev
=
NULL
;
up
(
&
disconnect_sem
);
up
(
&
dev
->
sem
);
}
info
(
"USB Skeleton #%d now disconnected"
,
minor
);
info
(
"USB Skeleton #%d now disconnected"
,
minor
);
}
}
...
@@ -668,4 +736,3 @@ module_exit (usb_skel_exit);
...
@@ -668,4 +736,3 @@ module_exit (usb_skel_exit);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
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