]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/media/dvb/siano/smsusb.c
V4L/DVB (8290): sms1xxx: small cleanup
[mv-sheeva.git] / drivers / media / dvb / siano / smsusb.c
1 /*
2  *  Driver for the Siano SMS10xx USB dongle
3  *
4  *  author: Anatoly Greenblat
5  *
6  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
7  *
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;
11  *
12  *  Software distributed under the License is distributed on an "AS IS"
13  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
14  *
15  *  See the GNU General Public License for more details.
16  *
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.
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/init.h>
24 #include <linux/usb.h>
25 #include <linux/firmware.h>
26
27 #include "smscoreapi.h"
28
29 #define USB1_BUFFER_SIZE                0x1000
30 #define USB2_BUFFER_SIZE                0x4000
31
32 #define MAX_BUFFERS             50
33 #define MAX_URBS                10
34
35 /* TO DO: move these to a header file */
36 #define USB_VID_SIANO 0x187f
37
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
42
43 struct smsusb_device_t;
44
45 struct smsusb_urb_t {
46         struct smscore_buffer_t *cb;
47         struct smsusb_device_t  *dev;
48
49         struct urb urb;
50 };
51
52 struct smsusb_device_t {
53         struct usb_device *udev;
54         struct smscore_device_t *coredev;
55
56         struct smsusb_urb_t     surbs[MAX_URBS];
57
58         int             response_alignment;
59         int             buffer_size;
60 };
61
62 int smsusb_submit_urb(struct smsusb_device_t *dev, struct smsusb_urb_t *surb);
63
64 void smsusb_onresponse(struct urb *urb)
65 {
66         struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
67         struct smsusb_device_t *dev = surb->dev;
68
69         if (urb->status < 0) {
70                 printk(KERN_INFO "%s error, urb status %d, %d bytes\n",
71                        __func__, urb->status, urb->actual_length);
72                 return;
73         }
74
75         if (urb->actual_length > 0) {
76                 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p;
77
78                 if (urb->actual_length >= phdr->msgLength) {
79                         surb->cb->size = phdr->msgLength;
80
81                         if (dev->response_alignment &&
82                             (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) {
83
84                                 surb->cb->offset =
85                                         dev->response_alignment +
86                                         ((phdr->msgFlags >> 8) & 3);
87
88                                 /* sanity check */
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__,
94                                                phdr->msgLength,
95                                                surb->cb->offset,
96                                                urb->actual_length);
97                                         goto exit_and_resubmit;
98                                 }
99
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));
104                         } else
105                                 surb->cb->offset = 0;
106
107                         smscore_onresponse(dev->coredev, surb->cb);
108                         surb->cb = NULL;
109                 } else {
110                         printk(KERN_INFO "%s invalid response "
111                                "msglen %d actual %d\n", __func__,
112                                phdr->msgLength, urb->actual_length);
113                 }
114         }
115
116 exit_and_resubmit:
117         smsusb_submit_urb(dev, surb);
118 }
119
120 int smsusb_submit_urb(struct smsusb_device_t *dev, struct smsusb_urb_t *surb)
121 {
122         if (!surb->cb) {
123                 surb->cb = smscore_getbuffer(dev->coredev);
124                 if (!surb->cb) {
125                         printk(KERN_INFO "%s smscore_getbuffer(...) "
126                                "returned NULL\n", __func__);
127                         return -ENOMEM;
128                 }
129         }
130
131         usb_fill_bulk_urb(
132                 &surb->urb,
133                 dev->udev,
134                 usb_rcvbulkpipe(dev->udev, 0x81),
135                 surb->cb->p,
136                 dev->buffer_size,
137                 smsusb_onresponse,
138                 surb
139         );
140         surb->urb.transfer_dma = surb->cb->phys;
141         surb->urb.transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
142
143         return usb_submit_urb(&surb->urb, GFP_ATOMIC);
144 }
145
146 void smsusb_stop_streaming(struct smsusb_device_t *dev)
147 {
148         int i;
149
150         for (i = 0; i < MAX_URBS; i++) {
151                 usb_kill_urb(&dev->surbs[i].urb);
152
153                 if (dev->surbs[i].cb) {
154                         smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
155                         dev->surbs[i].cb = NULL;
156                 }
157         }
158 }
159
160 int smsusb_start_streaming(struct smsusb_device_t *dev)
161 {
162         int i, rc;
163
164         for (i = 0; i < MAX_URBS; i++) {
165                 rc = smsusb_submit_urb(dev, &dev->surbs[i]);
166                 if (rc < 0) {
167                         printk(KERN_INFO "%s smsusb_submit_urb(...) "
168                                "failed\n", __func__);
169                         smsusb_stop_streaming(dev);
170                         break;
171                 }
172         }
173
174         return rc;
175 }
176
177 int smsusb_sendrequest(void *context, void *buffer, size_t size)
178 {
179         struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
180         int dummy;
181
182         return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
183                             buffer, size, &dummy, 1000);
184 }
185
186 char *smsusb1_fw_lkup[] = {
187         "dvbt_stellar_usb.inp",
188         "dvbh_stellar_usb.inp",
189         "tdmb_stellar_usb.inp",
190         "none",
191         "dvbt_bda_stellar_usb.inp",
192 };
193
194 int smsusb1_load_firmware(struct usb_device *udev, int id)
195 {
196         const struct firmware *fw;
197         u8 *fw_buffer;
198         int rc, dummy;
199
200         if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) {
201                 printk(KERN_INFO "%s invalid firmware id specified %d\n",
202                        __func__, id);
203                 return -EINVAL;
204         }
205
206         rc = request_firmware(&fw, smsusb1_fw_lkup[id], &udev->dev);
207         if (rc < 0) {
208                 printk(KERN_INFO "%s failed to open \"%s\" mode %d\n",
209                        __func__, smsusb1_fw_lkup[id], id);
210                 return rc;
211         }
212
213         fw_buffer = kmalloc(fw->size, GFP_KERNEL);
214         if (fw_buffer) {
215                 memcpy(fw_buffer, fw->data, fw->size);
216
217                 rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2),
218                                   fw_buffer, fw->size, &dummy, 1000);
219
220                 printk(KERN_INFO "%s: sent %d(%d) bytes, rc %d\n",
221                        __func__, fw->size, dummy, rc);
222
223                 kfree(fw_buffer);
224         } else {
225                 printk(KERN_INFO "failed to allocate firmware buffer\n");
226                 rc = -ENOMEM;
227         }
228
229         release_firmware(fw);
230
231         return rc;
232 }
233
234 void smsusb1_detectmode(void *context, int *mode)
235 {
236         char *product_string =
237                 ((struct smsusb_device_t *) context)->udev->product;
238
239         *mode = DEVICE_MODE_NONE;
240
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"))
245                 *mode = 1;
246         else if (strstr(product_string, "BDA"))
247                 *mode = 4;
248         else if (strstr(product_string, "DVBT"))
249                 *mode = 0;
250         else if (strstr(product_string, "TDMB"))
251                 *mode = 2;
252
253         printk(KERN_INFO "%s: %d \"%s\"\n", __func__, *mode, product_string);
254 }
255
256 int smsusb1_setmode(void *context, int mode)
257 {
258         struct SmsMsgHdr_ST Msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
259                              sizeof(struct SmsMsgHdr_ST), 0 };
260
261         if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
262                 printk(KERN_INFO "%s invalid firmware id specified %d\n",
263                        __func__, mode);
264                 return -EINVAL;
265         }
266
267         return smsusb_sendrequest(context, &Msg, sizeof(Msg));
268 }
269
270 void smsusb_term_device(struct usb_interface *intf)
271 {
272         struct smsusb_device_t *dev =
273                 (struct smsusb_device_t *) usb_get_intfdata(intf);
274
275         if (dev) {
276                 smsusb_stop_streaming(dev);
277
278                 /* unregister from smscore */
279                 if (dev->coredev)
280                         smscore_unregister_device(dev->coredev);
281
282                 kfree(dev);
283
284                 printk(KERN_INFO "%s device %p destroyed\n", __func__, dev);
285         }
286
287         usb_set_intfdata(intf, NULL);
288 }
289
290 int smsusb_init_device(struct usb_interface *intf)
291 {
292         struct smsdevice_params_t params;
293         struct smsusb_device_t *dev;
294         int i, rc;
295
296         /* create device object */
297         dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
298         if (!dev) {
299                 printk(KERN_INFO "%s kzalloc(sizeof(struct smsusb_device_t) "
300                        "failed\n", __func__);
301                 return -ENOMEM;
302         }
303
304         memset(&params, 0, sizeof(params));
305         usb_set_intfdata(intf, dev);
306         dev->udev = interface_to_usbdev(intf);
307
308         switch (dev->udev->descriptor.idProduct) {
309
310         case USB_PID_STELLAR:
311                 dev->buffer_size = USB1_BUFFER_SIZE;
312
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__);
317                 break;
318         default:
319                 switch (dev->udev->descriptor.idProduct) {
320                 case USB_PID_NOVA_A:
321                         params.device_type = SMS_NOVA_A0;
322                         printk(KERN_INFO "%s nova A0 found\n", __func__);
323                         break;
324                 default:
325                 case USB_PID_NOVA_B:
326                         params.device_type = SMS_NOVA_B0;
327                         printk(KERN_INFO "%s nova B0 found\n", __func__);
328                         break;
329                 case USB_PID_VEGA:
330                         params.device_type = SMS_VEGA;
331                         printk(KERN_INFO "%s Vega found\n", __func__);
332                 }
333
334                 dev->buffer_size = USB2_BUFFER_SIZE;
335                 dev->response_alignment =
336                         dev->udev->ep_in[1]->desc.wMaxPacketSize -
337                         sizeof(struct SmsMsgHdr_ST);
338
339                 params.flags |= SMS_DEVICE_FAMILY2;
340                 break;
341         }
342
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);
350
351         /* register in smscore */
352         rc = smscore_register_device(&params, &dev->coredev);
353         if (rc < 0) {
354                 printk(KERN_INFO "%s smscore_register_device(...) failed, "
355                        "rc %d\n", __func__, rc);
356                 smsusb_term_device(intf);
357                 return rc;
358         }
359
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);
364         }
365
366         printk(KERN_INFO "%s smsusb_start_streaming(...).\n", __func__);
367         rc = smsusb_start_streaming(dev);
368         if (rc < 0) {
369                 printk(KERN_INFO "%s smsusb_start_streaming(...) failed\n",
370                        __func__);
371                 smsusb_term_device(intf);
372                 return rc;
373         }
374
375         rc = smscore_start_device(dev->coredev);
376         if (rc < 0) {
377                 printk(KERN_INFO "%s smscore_start_device(...) failed\n",
378                        __func__);
379                 smsusb_term_device(intf);
380                 return rc;
381         }
382
383         printk(KERN_INFO "%s device %p created\n", __func__, dev);
384
385         return rc;
386 }
387
388 int smsusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
389 {
390         struct usb_device *udev = interface_to_usbdev(intf);
391         char devpath[32];
392         int i, rc;
393
394         rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
395         rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
396
397         if (intf->num_altsetting > 0) {
398                 rc = usb_set_interface(
399                         udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
400                 if (rc < 0) {
401                         printk(KERN_INFO "%s usb_set_interface failed, "
402                                "rc %d\n", __func__, rc);
403                         return rc;
404                 }
405         }
406
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);
414
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");
418                 return -ENODEV;
419         }
420
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));
427         }
428
429         rc = smsusb_init_device(intf);
430         printk(KERN_INFO "%s rc %d\n", __func__, rc);
431         return rc;
432 }
433
434 void smsusb_disconnect(struct usb_interface *intf)
435 {
436         smsusb_term_device(intf);
437 }
438
439 static struct usb_device_id smsusb_id_table [] = {
440         { USB_DEVICE(USB_VID_SIANO, USB_PID_STELLAR) },
441         { USB_DEVICE(USB_VID_SIANO, USB_PID_NOVA_A) },
442         { USB_DEVICE(USB_VID_SIANO, USB_PID_NOVA_B) },
443         { USB_DEVICE(USB_VID_SIANO, USB_PID_VEGA) },
444         { }             /* Terminating entry */
445 };
446 MODULE_DEVICE_TABLE(usb, smsusb_id_table);
447
448 static struct usb_driver smsusb_driver = {
449         .name                   = "smsusb",
450         .probe                  = smsusb_probe,
451         .disconnect             = smsusb_disconnect,
452         .id_table               = smsusb_id_table,
453 };
454
455 int smsusb_register(void)
456 {
457         int rc = usb_register(&smsusb_driver);
458         if (rc)
459                 printk(KERN_INFO "usb_register failed. Error number %d\n", rc);
460
461         printk(KERN_INFO "%s\n", __func__);
462
463         return rc;
464 }
465
466 void smsusb_unregister(void)
467 {
468         printk(KERN_DEBUG "%s\n", __func__);
469         /* Regular USB Cleanup */
470         usb_deregister(&smsusb_driver);
471 }
472