b/,!J]W
return; a-A+.7
} K:
o|kd
#X@<U <R
switch (data->state) { a^\- }4yR
case BCM203X_LOAD_MINIDRV: *_/eAi/WG
memcpy(data->buffer, "#", 1);
_Kl{50}]
O<Sc.@~
usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), CDwIq>0j
data->buffer, 1, bcm203x_complete, data); (zJ$oRq
ok%a|Zz+]
data->state = BCM203X_SELECT_MEMORY; #D LT-G0
v8[ek@
/* use workqueue to have a small delay */ D0y,TF
schedule_work(&data->work); TQ\wHJ
break; :KV,:13`D
F `pyhc>1;
case BCM203X_SELECT_MEMORY: 6 ,pZRc
usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), YNgR1:l
data->buffer, 32, bcm203x_complete, data, 1); l`FR.)2h
9Ajgfy>
data->state = BCM203X_CHECK_MEMORY; v>y8s&/
v`+n`DT
if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) o eJC
BT_ERR("Can't submit URB"); z^!A/a[[!
break; +ersP@G
"l[V%f E
case BCM203X_CHECK_MEMORY: Pvg
if (data->buffer[0] != '#') { *4hOCQ[
BT_ERR("Memory select failed"); "Yfr"1RmO
data->state = BCM203X_ERROR; ;sck+FP7w
break; 0(U3~k6
} x U13fl
~Miin
data->state = BCM203X_LOAD_FIRMWARE; fJn3"D'
$E`iqRB
case BCM203X_LOAD_FIRMWARE: 01-\:[{
if (data->fw_sent == data->fw_size) { 76IALJ00V
usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, BCM203X_IN_EP), *`g-gk
data->buffer, 32, bcm203x_complete, data, 1); @u"kX2>Eq
)kL`&+#>
data->state = BCM203X_CHECK_FIRMWARE; Mdlt zy=)L
} else { =Y]'5cn{
len = min_t(uint, data->fw_size - data->fw_sent, 4096); gB{]yA"('
~E3SC@KL
usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), EN-8uY.
data->fw_data + data->fw_sent, len, bcm203x_complete, data); Wp7@
>G4HZE
data->fw_sent += len; 4iYKW2a
} e"o6C\c
7>t$<J
if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) J:~[j
BT_ERR("Can't submit URB"); a_ 9 |xI
break; ^T}}4I_Y
O{")i;v@
case BCM203X_CHECK_FIRMWARE: G%j/eTTf
if (data->buffer[0] != '.') { EvSnZB1 y
BT_ERR("Firmware loading failed"); BYr_Lz|T
data->state = BCM203X_ERROR; *@ <8&M9x
break; V`R)#G>IH%
} z,}c?BP
x ^M5D+o
data->state = BCM203X_RESET; MAwC\7n+X
break; cwM#X;FGq
} xJ=ZQ)&]
} Z0()pT
aeuf, #
static void bcm203x_work(struct work_struct *work) XQ0#0<
{ [Hv*\rb
struct bcm203x_data *data = I8<Il^
container_of(work, struct bcm203x_data, work); KlVi4.]
a%MzNH
if (atomic_read(&data->shutdown)) uKR\Xo}
return; G!!-+n<
;Ch+X$m9
if (usb_submit_urb(data->urb, GFP_KERNEL) < 0) XI@6a9Uk
BT_ERR("Can't submit URB"); e'k;A{Oh
} {(m+M
Qm35{^p+
static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id *id) _S9rF-9G]
{ 5';/@M
const struct firmware *firmware; 1AV1d%F
struct usb_device *udev = interface_to_usbdev(intf); jy\W_CT
struct bcm203x_data *data; y+
6`|
h_
int size; !q~X*ZKse
cS"f
BT_DBG("intf %p id %p", intf, id); 45Nv_4s
K;<NBnH
if (intf->cur_altsetting->desc.bInterfaceNumber != 0) pY{; Yn&t
return -ENODEV; PtVo7zOye
^ [X|As2
data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); ~
V@xu{
if (!data) { ysSjc
BT_ERR("Can't allocate memory for data structure"); ULp)T`P
return -ENOMEM; d'N(w7-Y
} XPHQAo[(s
%+AS0 JhB
data->udev = udev; 8BYIxHHz
data->state = BCM203X_LOAD_MINIDRV; egZyng
pB
Nk lz_]
data->urb = usb_alloc_urb(0, GFP_KERNEL); wFK:Dp_^
if (!data->urb) { 4o1Q7
BT_ERR("Can't allocate URB"); Ez06:]Jd
return -ENOMEM; @wd!&%yzO
} `FZ(#GDF
i&A{L}eCr:
if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) { 2x-'>i_|g
BT_ERR("Mini driver request failed"); 6V'wQqJ
usb_free_urb(data->urb); /[\6oa
return -EIO; 33=Mm/<m$P
} RpHpMtvNo/
?60>'Xjj
BT_DBG("minidrv data %p size %zu", firmware->data, firmware->size); aqcFY8b
'
j4E H2v
size = max_t(uint, firmware->size, 4096); %iK%$
d4jVdOq2
data->buffer = kmalloc(size, GFP_KERNEL); ]*bAF^8i
if (!data->buffer) { mDb-=[W5
BT_ERR("Can't allocate memory for mini driver"); E)KB@f<g*
release_firmware(firmware); R'S c
usb_free_urb(data->urb); e(?:g@]-r
return -ENOMEM; [NQmL=l
} +:Lk^Ny
sFbfFUd
memcpy(data->buffer, firmware->data, firmware->size); 8B}'\e4i
PYdIP\<V
usb_fill_bulk_urb(data->urb, udev, usb_sndbulkpipe(udev, BCM203X_OUT_EP), J)-T:.i|0
data->buffer, firmware->size, bcm203x_complete, data); pG)9=X!9
]WTf< W<
release_firmware(firmware); E"Zb};}
Vh 2Bz
if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) { /yLzDCKn
BT_ERR("Firmware request failed"); uQeqnGp
usb_free_urb(data->urb); }BA9Ka#%
kfree(data->buffer); *
eA{[
return -EIO; W\HLal
} A{4Dzm !
~RcNZ\2y
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); MB1sQReOO
C>AcK#-x,{
data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL); A|2 <A
!
if (!data->fw_data) { 4BHtR017r
BT_ERR("Can't allocate memory for firmware image"); j%#?m2J}
release_firmware(firmware); +#0~:&!9
usb_free_urb(data->urb); 0LS-i% 0
kfree(data->buffer); q_-ma_F#s
return -ENOMEM; Xwn3+tSIa
} YKc>6)j
@/9>=#4c
data->fw_size = firmware->size; U$A/bEhw
data->fw_sent = 0; |a%B|CX
I!61 K
release_firmware(firmware); DNmb[
OWqrD@
INIT_WORK(&data->work, bcm203x_work); B,4q>KQA
5(423"(y
usb_set_intfdata(intf, data); z9^c]U U)E
$+7 ci~gs
/* use workqueue to have a small delay */ D`en%Lf!m
schedule_work(&data->work); f(!E!\&n^
FX7M4t#<
return 0; xtOx|FkYcl
} BlL|s=dlQV
:=y0'f
V(@
static void bcm203x_disconnect(struct usb_interface *intf) :MK=h;5Z
{ yDzdE;
struct bcm203x_data *data = usb_get_intfdata(intf); %Nl`~Kz9U
RV}GK
L>gn
BT_DBG("intf %p", intf); r)Or\HL
aQga3;S!
atomic_inc(&data->shutdown); 4ffU;6~l'
cancel_work_sync(&data->work); "t=UX
-3
n|6?J_{<b>
usb_kill_urb(data->urb); Yhe+u\vGs\
L1rwIOgq^
usb_set_intfdata(intf, NULL); Tj&'KF8?L
p<q].^M
usb_free_urb(data->urb); =9^Q"t4
kfree(data->fw_data); &2Q*1YXj
kfree(data->buffer); QGXQ {
} 8qN"3 Et
B=r0?%DX"1
static struct usb_driver bcm203x_driver = { cI3 y
.name = "bcm203x", i =-8@
.probe = bcm203x_probe, +GYS26
.disconnect = bcm203x_disconnect, A])OPqP{
.id_table = bcm203x_table, @^'$r&M