2 * Driver for the Siano SMS10xx USB dongle
4 * author: Anatoly Greenblat
6 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 3 as
10 * published by the Free Software Foundation;
12 * Software distributed under the License is distributed on an "AS IS"
13 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
15 * See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <linux/kernel.h>
23 #include <linux/init.h>
24 #include <linux/usb.h>
25 #include <linux/firmware.h>
27 #include "smscoreapi.h"
29 #define USB1_BUFFER_SIZE 0x1000
30 #define USB2_BUFFER_SIZE 0x4000
32 #define MAX_BUFFERS 50
35 /* TO DO: move these to a header file */
36 #define USB_VID_SIANO 0x187f
38 #define USB_PID_STELLAR 0x0100
39 #define USB_PID_NOVA_A 0x0200
40 #define USB_PID_NOVA_B 0x0201
41 #define USB_PID_VEGA 0x0300
43 struct smsusb_device_t
;
46 struct smscore_buffer_t
*cb
;
47 struct smsusb_device_t
*dev
;
52 struct smsusb_device_t
{
53 struct usb_device
*udev
;
54 struct smscore_device_t
*coredev
;
56 struct smsusb_urb_t surbs
[MAX_URBS
];
58 int response_alignment
;
62 int smsusb_submit_urb(struct smsusb_device_t
*dev
, struct smsusb_urb_t
*surb
);
64 void smsusb_onresponse(struct urb
*urb
)
66 struct smsusb_urb_t
*surb
= (struct smsusb_urb_t
*) urb
->context
;
67 struct smsusb_device_t
*dev
= surb
->dev
;
69 if (urb
->status
< 0) {
70 printk(KERN_INFO
"%s error, urb status %d, %d bytes\n",
71 __func__
, urb
->status
, urb
->actual_length
);
75 if (urb
->actual_length
> 0) {
76 struct SmsMsgHdr_ST
*phdr
= (struct SmsMsgHdr_ST
*) surb
->cb
->p
;
78 if (urb
->actual_length
>= phdr
->msgLength
) {
79 surb
->cb
->size
= phdr
->msgLength
;
81 if (dev
->response_alignment
&&
82 (phdr
->msgFlags
& MSG_HDR_FLAG_SPLIT_MSG
)) {
85 dev
->response_alignment
+
86 ((phdr
->msgFlags
>> 8) & 3);
89 if (((int) phdr
->msgLength
+
90 surb
->cb
->offset
) > urb
->actual_length
) {
91 printk(KERN_INFO
"%s: invalid "
92 "response msglen %d offset %d "
93 "size %d\n", __func__
,
97 goto exit_and_resubmit
;
100 /* move buffer pointer and
101 * copy header to its new location */
102 memcpy((char *) phdr
+ surb
->cb
->offset
,
103 phdr
, sizeof(struct SmsMsgHdr_ST
));
105 surb
->cb
->offset
= 0;
107 smscore_onresponse(dev
->coredev
, surb
->cb
);
110 printk(KERN_INFO
"%s invalid response "
111 "msglen %d actual %d\n", __func__
,
112 phdr
->msgLength
, urb
->actual_length
);
117 smsusb_submit_urb(dev
, surb
);
120 int smsusb_submit_urb(struct smsusb_device_t
*dev
, struct smsusb_urb_t
*surb
)
123 surb
->cb
= smscore_getbuffer(dev
->coredev
);
125 printk(KERN_INFO
"%s smscore_getbuffer(...) "
126 "returned NULL\n", __func__
);
134 usb_rcvbulkpipe(dev
->udev
, 0x81),
140 surb
->urb
.transfer_dma
= surb
->cb
->phys
;
141 surb
->urb
.transfer_flags
|= URB_NO_TRANSFER_DMA_MAP
;
143 return usb_submit_urb(&surb
->urb
, GFP_ATOMIC
);
146 void smsusb_stop_streaming(struct smsusb_device_t
*dev
)
150 for (i
= 0; i
< MAX_URBS
; i
++) {
151 usb_kill_urb(&dev
->surbs
[i
].urb
);
153 if (dev
->surbs
[i
].cb
) {
154 smscore_putbuffer(dev
->coredev
, dev
->surbs
[i
].cb
);
155 dev
->surbs
[i
].cb
= NULL
;
160 int smsusb_start_streaming(struct smsusb_device_t
*dev
)
164 for (i
= 0; i
< MAX_URBS
; i
++) {
165 rc
= smsusb_submit_urb(dev
, &dev
->surbs
[i
]);
167 printk(KERN_INFO
"%s smsusb_submit_urb(...) "
168 "failed\n", __func__
);
169 smsusb_stop_streaming(dev
);
177 int smsusb_sendrequest(void *context
, void *buffer
, size_t size
)
179 struct smsusb_device_t
*dev
= (struct smsusb_device_t
*) context
;
182 return usb_bulk_msg(dev
->udev
, usb_sndbulkpipe(dev
->udev
, 2),
183 buffer
, size
, &dummy
, 1000);
186 char *smsusb1_fw_lkup
[] = {
187 "dvbt_stellar_usb.inp",
188 "dvbh_stellar_usb.inp",
189 "tdmb_stellar_usb.inp",
191 "dvbt_bda_stellar_usb.inp",
194 int smsusb1_load_firmware(struct usb_device
*udev
, int id
)
196 const struct firmware
*fw
;
200 if (id
< DEVICE_MODE_DVBT
|| id
> DEVICE_MODE_DVBT_BDA
) {
201 printk(KERN_INFO
"%s invalid firmware id specified %d\n",
206 rc
= request_firmware(&fw
, smsusb1_fw_lkup
[id
], &udev
->dev
);
208 printk(KERN_INFO
"%s failed to open \"%s\" mode %d\n",
209 __func__
, smsusb1_fw_lkup
[id
], id
);
213 fw_buffer
= kmalloc(fw
->size
, GFP_KERNEL
);
215 memcpy(fw_buffer
, fw
->data
, fw
->size
);
217 rc
= usb_bulk_msg(udev
, usb_sndbulkpipe(udev
, 2),
218 fw_buffer
, fw
->size
, &dummy
, 1000);
220 printk(KERN_INFO
"%s: sent %d(%d) bytes, rc %d\n",
221 __func__
, fw
->size
, dummy
, rc
);
225 printk(KERN_INFO
"failed to allocate firmware buffer\n");
229 release_firmware(fw
);
234 void smsusb1_detectmode(void *context
, int *mode
)
236 char *product_string
=
237 ((struct smsusb_device_t
*) context
)->udev
->product
;
239 *mode
= DEVICE_MODE_NONE
;
241 if (!product_string
) {
242 product_string
= "none";
243 printk(KERN_ERR
"%s product string not found\n", __func__
);
244 } else if (strstr(product_string
, "DVBH"))
246 else if (strstr(product_string
, "BDA"))
248 else if (strstr(product_string
, "DVBT"))
250 else if (strstr(product_string
, "TDMB"))
253 printk(KERN_INFO
"%s: %d \"%s\"\n", __func__
, *mode
, product_string
);
256 int smsusb1_setmode(void *context
, int mode
)
258 struct SmsMsgHdr_ST Msg
= { MSG_SW_RELOAD_REQ
, 0, HIF_TASK
,
259 sizeof(struct SmsMsgHdr_ST
), 0 };
261 if (mode
< DEVICE_MODE_DVBT
|| mode
> DEVICE_MODE_DVBT_BDA
) {
262 printk(KERN_INFO
"%s invalid firmware id specified %d\n",
267 return smsusb_sendrequest(context
, &Msg
, sizeof(Msg
));
270 void smsusb_term_device(struct usb_interface
*intf
)
272 struct smsusb_device_t
*dev
=
273 (struct smsusb_device_t
*) usb_get_intfdata(intf
);
276 smsusb_stop_streaming(dev
);
278 /* unregister from smscore */
280 smscore_unregister_device(dev
->coredev
);
284 printk(KERN_INFO
"%s device %p destroyed\n", __func__
, dev
);
287 usb_set_intfdata(intf
, NULL
);
290 int smsusb_init_device(struct usb_interface
*intf
)
292 struct smsdevice_params_t params
;
293 struct smsusb_device_t
*dev
;
296 /* create device object */
297 dev
= kzalloc(sizeof(struct smsusb_device_t
), GFP_KERNEL
);
299 printk(KERN_INFO
"%s kzalloc(sizeof(struct smsusb_device_t) "
300 "failed\n", __func__
);
304 memset(¶ms
, 0, sizeof(params
));
305 usb_set_intfdata(intf
, dev
);
306 dev
->udev
= interface_to_usbdev(intf
);
308 switch (dev
->udev
->descriptor
.idProduct
) {
310 case USB_PID_STELLAR
:
311 dev
->buffer_size
= USB1_BUFFER_SIZE
;
313 params
.setmode_handler
= smsusb1_setmode
;
314 params
.detectmode_handler
= smsusb1_detectmode
;
315 params
.device_type
= SMS_STELLAR
;
316 printk(KERN_INFO
"%s stellar device found\n", __func__
);
319 switch (dev
->udev
->descriptor
.idProduct
) {
321 params
.device_type
= SMS_NOVA_A0
;
322 printk(KERN_INFO
"%s nova A0 found\n", __func__
);
326 params
.device_type
= SMS_NOVA_B0
;
327 printk(KERN_INFO
"%s nova B0 found\n", __func__
);
330 params
.device_type
= SMS_VEGA
;
331 printk(KERN_INFO
"%s Vega found\n", __func__
);
334 dev
->buffer_size
= USB2_BUFFER_SIZE
;
335 dev
->response_alignment
=
336 dev
->udev
->ep_in
[1]->desc
.wMaxPacketSize
-
337 sizeof(struct SmsMsgHdr_ST
);
339 params
.flags
|= SMS_DEVICE_FAMILY2
;
343 params
.device
= &dev
->udev
->dev
;
344 params
.buffer_size
= dev
->buffer_size
;
345 params
.num_buffers
= MAX_BUFFERS
;
346 params
.sendrequest_handler
= smsusb_sendrequest
;
347 params
.context
= dev
;
348 snprintf(params
.devpath
, sizeof(params
.devpath
),
349 "usb\\%d-%s", dev
->udev
->bus
->busnum
, dev
->udev
->devpath
);
351 /* register in smscore */
352 rc
= smscore_register_device(¶ms
, &dev
->coredev
);
354 printk(KERN_INFO
"%s smscore_register_device(...) failed, "
355 "rc %d\n", __func__
, rc
);
356 smsusb_term_device(intf
);
360 /* initialize urbs */
361 for (i
= 0; i
< MAX_URBS
; i
++) {
362 dev
->surbs
[i
].dev
= dev
;
363 usb_init_urb(&dev
->surbs
[i
].urb
);
366 printk(KERN_INFO
"%s smsusb_start_streaming(...).\n", __func__
);
367 rc
= smsusb_start_streaming(dev
);
369 printk(KERN_INFO
"%s smsusb_start_streaming(...) failed\n",
371 smsusb_term_device(intf
);
375 rc
= smscore_start_device(dev
->coredev
);
377 printk(KERN_INFO
"%s smscore_start_device(...) failed\n",
379 smsusb_term_device(intf
);
383 printk(KERN_INFO
"%s device %p created\n", __func__
, dev
);
388 int smsusb_probe(struct usb_interface
*intf
, const struct usb_device_id
*id
)
390 struct usb_device
*udev
= interface_to_usbdev(intf
);
394 rc
= usb_clear_halt(udev
, usb_rcvbulkpipe(udev
, 0x81));
395 rc
= usb_clear_halt(udev
, usb_rcvbulkpipe(udev
, 0x02));
397 if (intf
->num_altsetting
> 0) {
398 rc
= usb_set_interface(
399 udev
, intf
->cur_altsetting
->desc
.bInterfaceNumber
, 0);
401 printk(KERN_INFO
"%s usb_set_interface failed, "
402 "rc %d\n", __func__
, rc
);
407 printk(KERN_INFO
"smsusb_probe %d\n",
408 intf
->cur_altsetting
->desc
.bInterfaceNumber
);
409 for (i
= 0; i
< intf
->cur_altsetting
->desc
.bNumEndpoints
; i
++)
410 printk(KERN_INFO
"endpoint %d %02x %02x %d\n", i
,
411 intf
->cur_altsetting
->endpoint
[i
].desc
.bEndpointAddress
,
412 intf
->cur_altsetting
->endpoint
[i
].desc
.bmAttributes
,
413 intf
->cur_altsetting
->endpoint
[i
].desc
.wMaxPacketSize
);
415 if ((udev
->actconfig
->desc
.bNumInterfaces
== 2) &&
416 (intf
->cur_altsetting
->desc
.bInterfaceNumber
== 0)) {
417 printk(KERN_INFO
"rom interface 0 is not used\n");
421 if (intf
->cur_altsetting
->desc
.bInterfaceNumber
== 1) {
422 snprintf(devpath
, sizeof(devpath
), "usb\\%d-%s",
423 udev
->bus
->busnum
, udev
->devpath
);
424 printk(KERN_INFO
"stellar device was found.\n");
425 return smsusb1_load_firmware(
426 udev
, smscore_registry_getmode(devpath
));
429 rc
= smsusb_init_device(intf
);
430 printk(KERN_INFO
"%s rc %d\n", __func__
, rc
);
434 void smsusb_disconnect(struct usb_interface
*intf
)
436 smsusb_term_device(intf
);
439 static struct usb_device_id smsusb_id_table
[] = {
440 { USB_DEVICE(USB_VID_SIANO
, 0x0010) },
441 { USB_DEVICE(USB_VID_SIANO
, USB_PID_STELLAR
) },
442 { USB_DEVICE(USB_VID_SIANO
, USB_PID_NOVA_A
) },
443 { } /* Terminating entry */
445 MODULE_DEVICE_TABLE(usb
, smsusb_id_table
);
447 static struct usb_driver smsusb_driver
= {
449 .probe
= smsusb_probe
,
450 .disconnect
= smsusb_disconnect
,
451 .id_table
= smsusb_id_table
,
454 int smsusb_register(void)
456 int rc
= usb_register(&smsusb_driver
);
458 printk(KERN_INFO
"usb_register failed. Error number %d\n", rc
);
460 printk(KERN_INFO
"%s\n", __func__
);
465 void smsusb_unregister(void)
467 /* Regular USB Cleanup */
468 usb_deregister(&smsusb_driver
);
469 printk(KERN_INFO
"%s\n", __func__
);