Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
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