1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Linux V4L2 radio driver for the Griffin radioSHARK2 USB radio receiver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Note the radioSHARK2 offers the audio through a regular USB audio device,
5*4882a593Smuzhiyun * this driver only handles the tuning.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * The info necessary to drive the shark2 was taken from the small userspace
8*4882a593Smuzhiyun * shark2.c program by Hisaaki Shibata, which he kindly placed in the Public
9*4882a593Smuzhiyun * Domain.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Copyright (c) 2012 Hans de Goede <hdegoede@redhat.com>
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
14*4882a593Smuzhiyun * it under the terms of the GNU General Public License as published by
15*4882a593Smuzhiyun * the Free Software Foundation; either version 2 of the License, or
16*4882a593Smuzhiyun * (at your option) any later version.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful,
19*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
20*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21*4882a593Smuzhiyun * GNU General Public License for more details.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include <linux/init.h>
25*4882a593Smuzhiyun #include <linux/kernel.h>
26*4882a593Smuzhiyun #include <linux/leds.h>
27*4882a593Smuzhiyun #include <linux/module.h>
28*4882a593Smuzhiyun #include <linux/slab.h>
29*4882a593Smuzhiyun #include <linux/usb.h>
30*4882a593Smuzhiyun #include <linux/workqueue.h>
31*4882a593Smuzhiyun #include <media/v4l2-device.h>
32*4882a593Smuzhiyun #include "radio-tea5777.h"
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #if defined(CONFIG_LEDS_CLASS) || \
35*4882a593Smuzhiyun (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK2_MODULE))
36*4882a593Smuzhiyun #define SHARK_USE_LEDS 1
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
40*4882a593Smuzhiyun MODULE_DESCRIPTION("Griffin radioSHARK2, USB radio receiver driver");
41*4882a593Smuzhiyun MODULE_LICENSE("GPL");
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun static int debug;
44*4882a593Smuzhiyun module_param(debug, int, 0);
45*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "Debug level (0-1)");
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #define SHARK_IN_EP 0x83
48*4882a593Smuzhiyun #define SHARK_OUT_EP 0x05
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define TB_LEN 7
51*4882a593Smuzhiyun #define DRV_NAME "radioshark2"
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #define v4l2_dev_to_shark(d) container_of(d, struct shark_device, v4l2_dev)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun enum { BLUE_LED, RED_LED, NO_LEDS };
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun struct shark_device {
58*4882a593Smuzhiyun struct usb_device *usbdev;
59*4882a593Smuzhiyun struct v4l2_device v4l2_dev;
60*4882a593Smuzhiyun struct radio_tea5777 tea;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun #ifdef SHARK_USE_LEDS
63*4882a593Smuzhiyun struct work_struct led_work;
64*4882a593Smuzhiyun struct led_classdev leds[NO_LEDS];
65*4882a593Smuzhiyun char led_names[NO_LEDS][32];
66*4882a593Smuzhiyun atomic_t brightness[NO_LEDS];
67*4882a593Smuzhiyun unsigned long brightness_new;
68*4882a593Smuzhiyun #endif
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun u8 *transfer_buffer;
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static atomic_t shark_instance = ATOMIC_INIT(0);
74*4882a593Smuzhiyun
shark_write_reg(struct radio_tea5777 * tea,u64 reg)75*4882a593Smuzhiyun static int shark_write_reg(struct radio_tea5777 *tea, u64 reg)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun struct shark_device *shark = tea->private_data;
78*4882a593Smuzhiyun int i, res, actual_len;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun memset(shark->transfer_buffer, 0, TB_LEN);
81*4882a593Smuzhiyun shark->transfer_buffer[0] = 0x81; /* Write register command */
82*4882a593Smuzhiyun for (i = 0; i < 6; i++)
83*4882a593Smuzhiyun shark->transfer_buffer[i + 1] = (reg >> (40 - i * 8)) & 0xff;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-write: %*ph\n",
86*4882a593Smuzhiyun 7, shark->transfer_buffer);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun res = usb_interrupt_msg(shark->usbdev,
89*4882a593Smuzhiyun usb_sndintpipe(shark->usbdev, SHARK_OUT_EP),
90*4882a593Smuzhiyun shark->transfer_buffer, TB_LEN,
91*4882a593Smuzhiyun &actual_len, 1000);
92*4882a593Smuzhiyun if (res < 0) {
93*4882a593Smuzhiyun v4l2_err(tea->v4l2_dev, "write error: %d\n", res);
94*4882a593Smuzhiyun return res;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun return 0;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
shark_read_reg(struct radio_tea5777 * tea,u32 * reg_ret)100*4882a593Smuzhiyun static int shark_read_reg(struct radio_tea5777 *tea, u32 *reg_ret)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun struct shark_device *shark = tea->private_data;
103*4882a593Smuzhiyun int i, res, actual_len;
104*4882a593Smuzhiyun u32 reg = 0;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun memset(shark->transfer_buffer, 0, TB_LEN);
107*4882a593Smuzhiyun shark->transfer_buffer[0] = 0x82;
108*4882a593Smuzhiyun res = usb_interrupt_msg(shark->usbdev,
109*4882a593Smuzhiyun usb_sndintpipe(shark->usbdev, SHARK_OUT_EP),
110*4882a593Smuzhiyun shark->transfer_buffer, TB_LEN,
111*4882a593Smuzhiyun &actual_len, 1000);
112*4882a593Smuzhiyun if (res < 0) {
113*4882a593Smuzhiyun v4l2_err(tea->v4l2_dev, "request-read error: %d\n", res);
114*4882a593Smuzhiyun return res;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun res = usb_interrupt_msg(shark->usbdev,
118*4882a593Smuzhiyun usb_rcvintpipe(shark->usbdev, SHARK_IN_EP),
119*4882a593Smuzhiyun shark->transfer_buffer, TB_LEN,
120*4882a593Smuzhiyun &actual_len, 1000);
121*4882a593Smuzhiyun if (res < 0) {
122*4882a593Smuzhiyun v4l2_err(tea->v4l2_dev, "read error: %d\n", res);
123*4882a593Smuzhiyun return res;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun for (i = 0; i < 3; i++)
127*4882a593Smuzhiyun reg |= shark->transfer_buffer[i] << (16 - i * 8);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %*ph\n",
130*4882a593Smuzhiyun 3, shark->transfer_buffer);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun *reg_ret = reg;
133*4882a593Smuzhiyun return 0;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun static const struct radio_tea5777_ops shark_tea_ops = {
137*4882a593Smuzhiyun .write_reg = shark_write_reg,
138*4882a593Smuzhiyun .read_reg = shark_read_reg,
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun #ifdef SHARK_USE_LEDS
shark_led_work(struct work_struct * work)142*4882a593Smuzhiyun static void shark_led_work(struct work_struct *work)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun struct shark_device *shark =
145*4882a593Smuzhiyun container_of(work, struct shark_device, led_work);
146*4882a593Smuzhiyun int i, res, brightness, actual_len;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun for (i = 0; i < 2; i++) {
149*4882a593Smuzhiyun if (!test_and_clear_bit(i, &shark->brightness_new))
150*4882a593Smuzhiyun continue;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun brightness = atomic_read(&shark->brightness[i]);
153*4882a593Smuzhiyun memset(shark->transfer_buffer, 0, TB_LEN);
154*4882a593Smuzhiyun shark->transfer_buffer[0] = 0x83 + i;
155*4882a593Smuzhiyun shark->transfer_buffer[1] = brightness;
156*4882a593Smuzhiyun res = usb_interrupt_msg(shark->usbdev,
157*4882a593Smuzhiyun usb_sndintpipe(shark->usbdev,
158*4882a593Smuzhiyun SHARK_OUT_EP),
159*4882a593Smuzhiyun shark->transfer_buffer, TB_LEN,
160*4882a593Smuzhiyun &actual_len, 1000);
161*4882a593Smuzhiyun if (res < 0)
162*4882a593Smuzhiyun v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n",
163*4882a593Smuzhiyun shark->led_names[i], res);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
shark_led_set_blue(struct led_classdev * led_cdev,enum led_brightness value)167*4882a593Smuzhiyun static void shark_led_set_blue(struct led_classdev *led_cdev,
168*4882a593Smuzhiyun enum led_brightness value)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun struct shark_device *shark =
171*4882a593Smuzhiyun container_of(led_cdev, struct shark_device, leds[BLUE_LED]);
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun atomic_set(&shark->brightness[BLUE_LED], value);
174*4882a593Smuzhiyun set_bit(BLUE_LED, &shark->brightness_new);
175*4882a593Smuzhiyun schedule_work(&shark->led_work);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
shark_led_set_red(struct led_classdev * led_cdev,enum led_brightness value)178*4882a593Smuzhiyun static void shark_led_set_red(struct led_classdev *led_cdev,
179*4882a593Smuzhiyun enum led_brightness value)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun struct shark_device *shark =
182*4882a593Smuzhiyun container_of(led_cdev, struct shark_device, leds[RED_LED]);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun atomic_set(&shark->brightness[RED_LED], value);
185*4882a593Smuzhiyun set_bit(RED_LED, &shark->brightness_new);
186*4882a593Smuzhiyun schedule_work(&shark->led_work);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static const struct led_classdev shark_led_templates[NO_LEDS] = {
190*4882a593Smuzhiyun [BLUE_LED] = {
191*4882a593Smuzhiyun .name = "%s:blue:",
192*4882a593Smuzhiyun .brightness = LED_OFF,
193*4882a593Smuzhiyun .max_brightness = 127,
194*4882a593Smuzhiyun .brightness_set = shark_led_set_blue,
195*4882a593Smuzhiyun },
196*4882a593Smuzhiyun [RED_LED] = {
197*4882a593Smuzhiyun .name = "%s:red:",
198*4882a593Smuzhiyun .brightness = LED_OFF,
199*4882a593Smuzhiyun .max_brightness = 1,
200*4882a593Smuzhiyun .brightness_set = shark_led_set_red,
201*4882a593Smuzhiyun },
202*4882a593Smuzhiyun };
203*4882a593Smuzhiyun
shark_register_leds(struct shark_device * shark,struct device * dev)204*4882a593Smuzhiyun static int shark_register_leds(struct shark_device *shark, struct device *dev)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun int i, retval;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun atomic_set(&shark->brightness[BLUE_LED], 127);
209*4882a593Smuzhiyun INIT_WORK(&shark->led_work, shark_led_work);
210*4882a593Smuzhiyun for (i = 0; i < NO_LEDS; i++) {
211*4882a593Smuzhiyun shark->leds[i] = shark_led_templates[i];
212*4882a593Smuzhiyun snprintf(shark->led_names[i], sizeof(shark->led_names[0]),
213*4882a593Smuzhiyun shark->leds[i].name, shark->v4l2_dev.name);
214*4882a593Smuzhiyun shark->leds[i].name = shark->led_names[i];
215*4882a593Smuzhiyun retval = led_classdev_register(dev, &shark->leds[i]);
216*4882a593Smuzhiyun if (retval) {
217*4882a593Smuzhiyun v4l2_err(&shark->v4l2_dev,
218*4882a593Smuzhiyun "couldn't register led: %s\n",
219*4882a593Smuzhiyun shark->led_names[i]);
220*4882a593Smuzhiyun return retval;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun return 0;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
shark_unregister_leds(struct shark_device * shark)226*4882a593Smuzhiyun static void shark_unregister_leds(struct shark_device *shark)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun int i;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun for (i = 0; i < NO_LEDS; i++)
231*4882a593Smuzhiyun led_classdev_unregister(&shark->leds[i]);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun cancel_work_sync(&shark->led_work);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
shark_resume_leds(struct shark_device * shark)236*4882a593Smuzhiyun static inline void shark_resume_leds(struct shark_device *shark)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun int i;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun for (i = 0; i < NO_LEDS; i++)
241*4882a593Smuzhiyun set_bit(i, &shark->brightness_new);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun schedule_work(&shark->led_work);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun #else
shark_register_leds(struct shark_device * shark,struct device * dev)246*4882a593Smuzhiyun static int shark_register_leds(struct shark_device *shark, struct device *dev)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun v4l2_warn(&shark->v4l2_dev,
249*4882a593Smuzhiyun "CONFIG_LEDS_CLASS not enabled, LED support disabled\n");
250*4882a593Smuzhiyun return 0;
251*4882a593Smuzhiyun }
shark_unregister_leds(struct shark_device * shark)252*4882a593Smuzhiyun static inline void shark_unregister_leds(struct shark_device *shark) { }
shark_resume_leds(struct shark_device * shark)253*4882a593Smuzhiyun static inline void shark_resume_leds(struct shark_device *shark) { }
254*4882a593Smuzhiyun #endif
255*4882a593Smuzhiyun
usb_shark_disconnect(struct usb_interface * intf)256*4882a593Smuzhiyun static void usb_shark_disconnect(struct usb_interface *intf)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
259*4882a593Smuzhiyun struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun mutex_lock(&shark->tea.mutex);
262*4882a593Smuzhiyun v4l2_device_disconnect(&shark->v4l2_dev);
263*4882a593Smuzhiyun radio_tea5777_exit(&shark->tea);
264*4882a593Smuzhiyun mutex_unlock(&shark->tea.mutex);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun shark_unregister_leds(shark);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun v4l2_device_put(&shark->v4l2_dev);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
usb_shark_release(struct v4l2_device * v4l2_dev)271*4882a593Smuzhiyun static void usb_shark_release(struct v4l2_device *v4l2_dev)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun v4l2_device_unregister(&shark->v4l2_dev);
276*4882a593Smuzhiyun kfree(shark->transfer_buffer);
277*4882a593Smuzhiyun kfree(shark);
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
usb_shark_probe(struct usb_interface * intf,const struct usb_device_id * id)280*4882a593Smuzhiyun static int usb_shark_probe(struct usb_interface *intf,
281*4882a593Smuzhiyun const struct usb_device_id *id)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun struct shark_device *shark;
284*4882a593Smuzhiyun int retval = -ENOMEM;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
287*4882a593Smuzhiyun if (!shark)
288*4882a593Smuzhiyun return retval;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun shark->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL);
291*4882a593Smuzhiyun if (!shark->transfer_buffer)
292*4882a593Smuzhiyun goto err_alloc_buffer;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun retval = shark_register_leds(shark, &intf->dev);
297*4882a593Smuzhiyun if (retval)
298*4882a593Smuzhiyun goto err_reg_leds;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun shark->v4l2_dev.release = usb_shark_release;
301*4882a593Smuzhiyun retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev);
302*4882a593Smuzhiyun if (retval) {
303*4882a593Smuzhiyun v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n");
304*4882a593Smuzhiyun goto err_reg_dev;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun shark->usbdev = interface_to_usbdev(intf);
308*4882a593Smuzhiyun shark->tea.v4l2_dev = &shark->v4l2_dev;
309*4882a593Smuzhiyun shark->tea.private_data = shark;
310*4882a593Smuzhiyun shark->tea.ops = &shark_tea_ops;
311*4882a593Smuzhiyun shark->tea.has_am = true;
312*4882a593Smuzhiyun shark->tea.write_before_read = true;
313*4882a593Smuzhiyun strscpy(shark->tea.card, "Griffin radioSHARK2",
314*4882a593Smuzhiyun sizeof(shark->tea.card));
315*4882a593Smuzhiyun usb_make_path(shark->usbdev, shark->tea.bus_info,
316*4882a593Smuzhiyun sizeof(shark->tea.bus_info));
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun retval = radio_tea5777_init(&shark->tea, THIS_MODULE);
319*4882a593Smuzhiyun if (retval) {
320*4882a593Smuzhiyun v4l2_err(&shark->v4l2_dev, "couldn't init tea5777\n");
321*4882a593Smuzhiyun goto err_init_tea;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun return 0;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun err_init_tea:
327*4882a593Smuzhiyun v4l2_device_unregister(&shark->v4l2_dev);
328*4882a593Smuzhiyun err_reg_dev:
329*4882a593Smuzhiyun shark_unregister_leds(shark);
330*4882a593Smuzhiyun err_reg_leds:
331*4882a593Smuzhiyun kfree(shark->transfer_buffer);
332*4882a593Smuzhiyun err_alloc_buffer:
333*4882a593Smuzhiyun kfree(shark);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun return retval;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun #ifdef CONFIG_PM
usb_shark_suspend(struct usb_interface * intf,pm_message_t message)339*4882a593Smuzhiyun static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun return 0;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
usb_shark_resume(struct usb_interface * intf)344*4882a593Smuzhiyun static int usb_shark_resume(struct usb_interface *intf)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
347*4882a593Smuzhiyun struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
348*4882a593Smuzhiyun int ret;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun mutex_lock(&shark->tea.mutex);
351*4882a593Smuzhiyun ret = radio_tea5777_set_freq(&shark->tea);
352*4882a593Smuzhiyun mutex_unlock(&shark->tea.mutex);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun shark_resume_leds(shark);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return ret;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun #endif
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */
361*4882a593Smuzhiyun static const struct usb_device_id usb_shark_device_table[] = {
362*4882a593Smuzhiyun { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
363*4882a593Smuzhiyun USB_DEVICE_ID_MATCH_INT_CLASS,
364*4882a593Smuzhiyun .idVendor = 0x077d,
365*4882a593Smuzhiyun .idProduct = 0x627a,
366*4882a593Smuzhiyun .bcdDevice_lo = 0x0010,
367*4882a593Smuzhiyun .bcdDevice_hi = 0x0010,
368*4882a593Smuzhiyun .bInterfaceClass = 3,
369*4882a593Smuzhiyun },
370*4882a593Smuzhiyun { }
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun MODULE_DEVICE_TABLE(usb, usb_shark_device_table);
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun static struct usb_driver usb_shark_driver = {
375*4882a593Smuzhiyun .name = DRV_NAME,
376*4882a593Smuzhiyun .probe = usb_shark_probe,
377*4882a593Smuzhiyun .disconnect = usb_shark_disconnect,
378*4882a593Smuzhiyun .id_table = usb_shark_device_table,
379*4882a593Smuzhiyun #ifdef CONFIG_PM
380*4882a593Smuzhiyun .suspend = usb_shark_suspend,
381*4882a593Smuzhiyun .resume = usb_shark_resume,
382*4882a593Smuzhiyun .reset_resume = usb_shark_resume,
383*4882a593Smuzhiyun #endif
384*4882a593Smuzhiyun };
385*4882a593Smuzhiyun module_usb_driver(usb_shark_driver);
386