1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/types.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/kmod.h>
29#include <linux/mutex.h>
30#include <linux/pci.h>
31#include <linux/interrupt.h>
32#include <linux/videodev2.h>
33#include <linux/v4l2-dv-timings.h>
34#include <media/v4l2-device.h>
35#include <media/v4l2-dev.h>
36#include <media/v4l2-ioctl.h>
37#include <media/v4l2-dv-timings.h>
38#include <media/v4l2-ctrls.h>
39#include <media/v4l2-event.h>
40#include <media/videobuf2-dma-contig.h>
41
42MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver");
43MODULE_AUTHOR("Hans Verkuil");
44MODULE_LICENSE("GPL v2");
45MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl);
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64struct skeleton {
65 struct pci_dev *pdev;
66 struct v4l2_device v4l2_dev;
67 struct video_device vdev;
68 struct v4l2_ctrl_handler ctrl_handler;
69 struct mutex lock;
70 v4l2_std_id std;
71 struct v4l2_dv_timings timings;
72 struct v4l2_pix_format format;
73 unsigned input;
74
75 struct vb2_queue queue;
76 struct vb2_alloc_ctx *alloc_ctx;
77
78 spinlock_t qlock;
79 struct list_head buf_list;
80 unsigned field;
81 unsigned sequence;
82};
83
84struct skel_buffer {
85 struct vb2_buffer vb;
86 struct list_head list;
87};
88
89static inline struct skel_buffer *to_skel_buffer(struct vb2_buffer *vb2)
90{
91 return container_of(vb2, struct skel_buffer, vb);
92}
93
94static const struct pci_device_id skeleton_pci_tbl[] = {
95
96 { 0, }
97};
98
99
100
101
102
103
104static const struct v4l2_dv_timings_cap skel_timings_cap = {
105 .type = V4L2_DV_BT_656_1120,
106
107 .reserved = { 0 },
108 V4L2_INIT_BT_TIMINGS(
109 720, 1920,
110 480, 1080,
111 27000000, 74250000,
112 V4L2_DV_BT_STD_CEA861,
113
114 V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE
115 )
116};
117
118
119
120
121
122#define SKEL_TVNORMS V4L2_STD_ALL
123
124
125
126
127
128
129
130static irqreturn_t skeleton_irq(int irq, void *dev_id)
131{
132#ifdef TODO
133 struct skeleton *skel = dev_id;
134
135
136
137
138 if (captured_new_frame) {
139 ...
140 spin_lock(&skel->qlock);
141 list_del(&new_buf->list);
142 spin_unlock(&skel->qlock);
143 v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
144 new_buf->vb.v4l2_buf.sequence = skel->sequence++;
145 new_buf->vb.v4l2_buf.field = skel->field;
146 if (skel->format.field == V4L2_FIELD_ALTERNATE) {
147 if (skel->field == V4L2_FIELD_BOTTOM)
148 skel->field = V4L2_FIELD_TOP;
149 else if (skel->field == V4L2_FIELD_TOP)
150 skel->field = V4L2_FIELD_BOTTOM;
151 }
152 vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
153 }
154#endif
155 return IRQ_HANDLED;
156}
157
158
159
160
161
162
163
164
165static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
166 unsigned int *nbuffers, unsigned int *nplanes,
167 unsigned int sizes[], void *alloc_ctxs[])
168{
169 struct skeleton *skel = vb2_get_drv_priv(vq);
170
171 skel->field = skel->format.field;
172 if (skel->field == V4L2_FIELD_ALTERNATE) {
173
174
175
176
177 if (vb2_fileio_is_active(vq))
178 return -EINVAL;
179 skel->field = V4L2_FIELD_TOP;
180 }
181
182 if (vq->num_buffers + *nbuffers < 3)
183 *nbuffers = 3 - vq->num_buffers;
184
185 if (fmt && fmt->fmt.pix.sizeimage < skel->format.sizeimage)
186 return -EINVAL;
187 *nplanes = 1;
188 sizes[0] = fmt ? fmt->fmt.pix.sizeimage : skel->format.sizeimage;
189 alloc_ctxs[0] = skel->alloc_ctx;
190 return 0;
191}
192
193
194
195
196
197static int buffer_prepare(struct vb2_buffer *vb)
198{
199 struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue);
200 unsigned long size = skel->format.sizeimage;
201
202 if (vb2_plane_size(vb, 0) < size) {
203 dev_err(&skel->pdev->dev, "buffer too small (%lu < %lu)\n",
204 vb2_plane_size(vb, 0), size);
205 return -EINVAL;
206 }
207
208 vb2_set_plane_payload(vb, 0, size);
209 return 0;
210}
211
212
213
214
215static void buffer_queue(struct vb2_buffer *vb)
216{
217 struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue);
218 struct skel_buffer *buf = to_skel_buffer(vb);
219 unsigned long flags;
220
221 spin_lock_irqsave(&skel->qlock, flags);
222 list_add_tail(&buf->list, &skel->buf_list);
223
224
225
226 spin_unlock_irqrestore(&skel->qlock, flags);
227}
228
229static void return_all_buffers(struct skeleton *skel,
230 enum vb2_buffer_state state)
231{
232 struct skel_buffer *buf, *node;
233 unsigned long flags;
234
235 spin_lock_irqsave(&skel->qlock, flags);
236 list_for_each_entry_safe(buf, node, &skel->buf_list, list) {
237 vb2_buffer_done(&buf->vb, state);
238 list_del(&buf->list);
239 }
240 spin_unlock_irqrestore(&skel->qlock, flags);
241}
242
243
244
245
246
247
248
249static int start_streaming(struct vb2_queue *vq, unsigned int count)
250{
251 struct skeleton *skel = vb2_get_drv_priv(vq);
252 int ret = 0;
253
254 skel->sequence = 0;
255
256
257
258 if (ret) {
259
260
261
262
263 return_all_buffers(skel, VB2_BUF_STATE_QUEUED);
264 }
265 return ret;
266}
267
268
269
270
271
272static void stop_streaming(struct vb2_queue *vq)
273{
274 struct skeleton *skel = vb2_get_drv_priv(vq);
275
276
277
278
279 return_all_buffers(skel, VB2_BUF_STATE_ERROR);
280}
281
282
283
284
285
286
287static struct vb2_ops skel_qops = {
288 .queue_setup = queue_setup,
289 .buf_prepare = buffer_prepare,
290 .buf_queue = buffer_queue,
291 .start_streaming = start_streaming,
292 .stop_streaming = stop_streaming,
293 .wait_prepare = vb2_ops_wait_prepare,
294 .wait_finish = vb2_ops_wait_finish,
295};
296
297
298
299
300
301static int skeleton_querycap(struct file *file, void *priv,
302 struct v4l2_capability *cap)
303{
304 struct skeleton *skel = video_drvdata(file);
305
306 strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
307 strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card));
308 snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
309 pci_name(skel->pdev));
310 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
311 V4L2_CAP_STREAMING;
312 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
313 return 0;
314}
315
316
317
318
319
320
321
322static void skeleton_fill_pix_format(struct skeleton *skel,
323 struct v4l2_pix_format *pix)
324{
325 pix->pixelformat = V4L2_PIX_FMT_YUYV;
326 if (skel->input == 0) {
327
328 pix->width = 720;
329 pix->height = (skel->std & V4L2_STD_525_60) ? 480 : 576;
330 pix->field = V4L2_FIELD_INTERLACED;
331 pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
332 } else {
333
334 pix->width = skel->timings.bt.width;
335 pix->height = skel->timings.bt.height;
336 if (skel->timings.bt.interlaced) {
337 pix->field = V4L2_FIELD_ALTERNATE;
338 pix->height /= 2;
339 } else {
340 pix->field = V4L2_FIELD_NONE;
341 }
342 pix->colorspace = V4L2_COLORSPACE_REC709;
343 }
344
345
346
347
348
349 pix->bytesperline = pix->width * 2;
350 pix->sizeimage = pix->bytesperline * pix->height;
351 pix->priv = 0;
352}
353
354static int skeleton_try_fmt_vid_cap(struct file *file, void *priv,
355 struct v4l2_format *f)
356{
357 struct skeleton *skel = video_drvdata(file);
358 struct v4l2_pix_format *pix = &f->fmt.pix;
359
360
361
362
363
364
365
366 if (pix->pixelformat != V4L2_PIX_FMT_YUYV)
367 return -EINVAL;
368 skeleton_fill_pix_format(skel, pix);
369 return 0;
370}
371
372static int skeleton_s_fmt_vid_cap(struct file *file, void *priv,
373 struct v4l2_format *f)
374{
375 struct skeleton *skel = video_drvdata(file);
376 int ret;
377
378 ret = skeleton_try_fmt_vid_cap(file, priv, f);
379 if (ret)
380 return ret;
381
382
383
384
385
386 if (vb2_is_busy(&skel->queue))
387 return -EBUSY;
388
389
390 skel->format = f->fmt.pix;
391 return 0;
392}
393
394static int skeleton_g_fmt_vid_cap(struct file *file, void *priv,
395 struct v4l2_format *f)
396{
397 struct skeleton *skel = video_drvdata(file);
398
399 f->fmt.pix = skel->format;
400 return 0;
401}
402
403static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv,
404 struct v4l2_fmtdesc *f)
405{
406 if (f->index != 0)
407 return -EINVAL;
408
409 strlcpy(f->description, "4:2:2, packed, YUYV", sizeof(f->description));
410 f->pixelformat = V4L2_PIX_FMT_YUYV;
411 f->flags = 0;
412 return 0;
413}
414
415static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std)
416{
417 struct skeleton *skel = video_drvdata(file);
418
419
420 if (skel->input)
421 return -ENODATA;
422
423
424
425
426
427
428 if (std == skel->std)
429 return 0;
430
431
432
433
434
435 if (vb2_is_busy(&skel->queue))
436 return -EBUSY;
437
438
439
440 skel->std = std;
441
442
443 skeleton_fill_pix_format(skel, &skel->format);
444 return 0;
445}
446
447static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std)
448{
449 struct skeleton *skel = video_drvdata(file);
450
451
452 if (skel->input)
453 return -ENODATA;
454
455 *std = skel->std;
456 return 0;
457}
458
459
460
461
462
463
464
465
466static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std)
467{
468 struct skeleton *skel = video_drvdata(file);
469
470
471 if (skel->input)
472 return -ENODATA;
473
474#ifdef TODO
475
476
477
478
479 get_signal_info();
480 if (no_signal) {
481 *std = 0;
482 return 0;
483 }
484
485 if (signal_has_525_lines)
486 *std &= V4L2_STD_525_60;
487 else
488 *std &= V4L2_STD_625_50;
489#endif
490 return 0;
491}
492
493static int skeleton_s_dv_timings(struct file *file, void *_fh,
494 struct v4l2_dv_timings *timings)
495{
496 struct skeleton *skel = video_drvdata(file);
497
498
499 if (skel->input == 0)
500 return -ENODATA;
501
502
503 if (!v4l2_valid_dv_timings(timings, &skel_timings_cap, NULL, NULL))
504 return -EINVAL;
505
506
507 if (!v4l2_find_dv_timings_cap(timings, &skel_timings_cap,
508 0, NULL, NULL))
509 return -EINVAL;
510
511
512 if (v4l2_match_dv_timings(timings, &skel->timings, 0))
513 return 0;
514
515
516
517
518
519 if (vb2_is_busy(&skel->queue))
520 return -EBUSY;
521
522
523
524
525 skel->timings = *timings;
526
527
528 skeleton_fill_pix_format(skel, &skel->format);
529 return 0;
530}
531
532static int skeleton_g_dv_timings(struct file *file, void *_fh,
533 struct v4l2_dv_timings *timings)
534{
535 struct skeleton *skel = video_drvdata(file);
536
537
538 if (skel->input == 0)
539 return -ENODATA;
540
541 *timings = skel->timings;
542 return 0;
543}
544
545static int skeleton_enum_dv_timings(struct file *file, void *_fh,
546 struct v4l2_enum_dv_timings *timings)
547{
548 struct skeleton *skel = video_drvdata(file);
549
550
551 if (skel->input == 0)
552 return -ENODATA;
553
554 return v4l2_enum_dv_timings_cap(timings, &skel_timings_cap,
555 NULL, NULL);
556}
557
558
559
560
561
562
563
564
565
566
567static int skeleton_query_dv_timings(struct file *file, void *_fh,
568 struct v4l2_dv_timings *timings)
569{
570 struct skeleton *skel = video_drvdata(file);
571
572
573 if (skel->input == 0)
574 return -ENODATA;
575
576#ifdef TODO
577
578
579
580
581 detect_timings();
582 if (no_signal)
583 return -ENOLINK;
584 if (cannot_lock_to_signal)
585 return -ENOLCK;
586 if (signal_out_of_range_of_capabilities)
587 return -ERANGE;
588
589
590 v4l2_print_dv_timings(skel->v4l2_dev.name, "query_dv_timings:",
591 timings, true);
592#endif
593 return 0;
594}
595
596static int skeleton_dv_timings_cap(struct file *file, void *fh,
597 struct v4l2_dv_timings_cap *cap)
598{
599 struct skeleton *skel = video_drvdata(file);
600
601
602 if (skel->input == 0)
603 return -ENODATA;
604 *cap = skel_timings_cap;
605 return 0;
606}
607
608static int skeleton_enum_input(struct file *file, void *priv,
609 struct v4l2_input *i)
610{
611 if (i->index > 1)
612 return -EINVAL;
613
614 i->type = V4L2_INPUT_TYPE_CAMERA;
615 if (i->index == 0) {
616 i->std = SKEL_TVNORMS;
617 strlcpy(i->name, "S-Video", sizeof(i->name));
618 i->capabilities = V4L2_IN_CAP_STD;
619 } else {
620 i->std = 0;
621 strlcpy(i->name, "HDMI", sizeof(i->name));
622 i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
623 }
624 return 0;
625}
626
627static int skeleton_s_input(struct file *file, void *priv, unsigned int i)
628{
629 struct skeleton *skel = video_drvdata(file);
630
631 if (i > 1)
632 return -EINVAL;
633
634
635
636
637
638 if (vb2_is_busy(&skel->queue))
639 return -EBUSY;
640
641 skel->input = i;
642
643
644
645
646
647 skel->vdev.tvnorms = i ? 0 : SKEL_TVNORMS;
648
649
650 skeleton_fill_pix_format(skel, &skel->format);
651 return 0;
652}
653
654static int skeleton_g_input(struct file *file, void *priv, unsigned int *i)
655{
656 struct skeleton *skel = video_drvdata(file);
657
658 *i = skel->input;
659 return 0;
660}
661
662
663static int skeleton_s_ctrl(struct v4l2_ctrl *ctrl)
664{
665
666
667
668 switch (ctrl->id) {
669 case V4L2_CID_BRIGHTNESS:
670
671 break;
672 case V4L2_CID_CONTRAST:
673
674 break;
675 case V4L2_CID_SATURATION:
676
677 break;
678 case V4L2_CID_HUE:
679
680 break;
681 default:
682 return -EINVAL;
683 }
684 return 0;
685}
686
687
688
689
690
691static const struct v4l2_ctrl_ops skel_ctrl_ops = {
692 .s_ctrl = skeleton_s_ctrl,
693};
694
695
696
697
698
699
700
701
702
703
704
705static const struct v4l2_ioctl_ops skel_ioctl_ops = {
706 .vidioc_querycap = skeleton_querycap,
707 .vidioc_try_fmt_vid_cap = skeleton_try_fmt_vid_cap,
708 .vidioc_s_fmt_vid_cap = skeleton_s_fmt_vid_cap,
709 .vidioc_g_fmt_vid_cap = skeleton_g_fmt_vid_cap,
710 .vidioc_enum_fmt_vid_cap = skeleton_enum_fmt_vid_cap,
711
712 .vidioc_g_std = skeleton_g_std,
713 .vidioc_s_std = skeleton_s_std,
714 .vidioc_querystd = skeleton_querystd,
715
716 .vidioc_s_dv_timings = skeleton_s_dv_timings,
717 .vidioc_g_dv_timings = skeleton_g_dv_timings,
718 .vidioc_enum_dv_timings = skeleton_enum_dv_timings,
719 .vidioc_query_dv_timings = skeleton_query_dv_timings,
720 .vidioc_dv_timings_cap = skeleton_dv_timings_cap,
721
722 .vidioc_enum_input = skeleton_enum_input,
723 .vidioc_g_input = skeleton_g_input,
724 .vidioc_s_input = skeleton_s_input,
725
726 .vidioc_reqbufs = vb2_ioctl_reqbufs,
727 .vidioc_create_bufs = vb2_ioctl_create_bufs,
728 .vidioc_querybuf = vb2_ioctl_querybuf,
729 .vidioc_qbuf = vb2_ioctl_qbuf,
730 .vidioc_dqbuf = vb2_ioctl_dqbuf,
731 .vidioc_expbuf = vb2_ioctl_expbuf,
732 .vidioc_streamon = vb2_ioctl_streamon,
733 .vidioc_streamoff = vb2_ioctl_streamoff,
734
735 .vidioc_log_status = v4l2_ctrl_log_status,
736 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
737 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
738};
739
740
741
742
743
744static const struct v4l2_file_operations skel_fops = {
745 .owner = THIS_MODULE,
746 .open = v4l2_fh_open,
747 .release = vb2_fop_release,
748 .unlocked_ioctl = video_ioctl2,
749 .read = vb2_fop_read,
750 .mmap = vb2_fop_mmap,
751 .poll = vb2_fop_poll,
752};
753
754
755
756
757
758
759static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
760{
761
762 static const struct v4l2_dv_timings timings_def =
763 V4L2_DV_BT_CEA_1280X720P60;
764 struct skeleton *skel;
765 struct video_device *vdev;
766 struct v4l2_ctrl_handler *hdl;
767 struct vb2_queue *q;
768 int ret;
769
770
771 ret = pci_enable_device(pdev);
772 if (ret)
773 return ret;
774 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
775 if (ret) {
776 dev_err(&pdev->dev, "no suitable DMA available.\n");
777 goto disable_pci;
778 }
779
780
781 skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL);
782 if (!skel)
783 return -ENOMEM;
784
785
786 ret = devm_request_irq(&pdev->dev, pdev->irq,
787 skeleton_irq, 0, KBUILD_MODNAME, skel);
788 if (ret) {
789 dev_err(&pdev->dev, "request_irq failed\n");
790 goto disable_pci;
791 }
792 skel->pdev = pdev;
793
794
795 skel->timings = timings_def;
796 skel->std = V4L2_STD_625_50;
797 skeleton_fill_pix_format(skel, &skel->format);
798
799
800 ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev);
801 if (ret)
802 goto disable_pci;
803
804 mutex_init(&skel->lock);
805
806
807 hdl = &skel->ctrl_handler;
808 v4l2_ctrl_handler_init(hdl, 4);
809 v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
810 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
811 v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
812 V4L2_CID_CONTRAST, 0, 255, 1, 16);
813 v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
814 V4L2_CID_SATURATION, 0, 255, 1, 127);
815 v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
816 V4L2_CID_HUE, -128, 127, 1, 0);
817 if (hdl->error) {
818 ret = hdl->error;
819 goto free_hdl;
820 }
821 skel->v4l2_dev.ctrl_handler = hdl;
822
823
824 q = &skel->queue;
825 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
826 q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
827 q->drv_priv = skel;
828 q->buf_struct_size = sizeof(struct skel_buffer);
829 q->ops = &skel_qops;
830 q->mem_ops = &vb2_dma_contig_memops;
831 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
832
833
834
835
836
837 q->min_buffers_needed = 2;
838
839
840
841
842
843
844
845
846
847 q->lock = &skel->lock;
848
849
850
851
852 q->gfp_flags = GFP_DMA32;
853 ret = vb2_queue_init(q);
854 if (ret)
855 goto free_hdl;
856
857 skel->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
858 if (IS_ERR(skel->alloc_ctx)) {
859 dev_err(&pdev->dev, "Can't allocate buffer context");
860 ret = PTR_ERR(skel->alloc_ctx);
861 goto free_hdl;
862 }
863 INIT_LIST_HEAD(&skel->buf_list);
864 spin_lock_init(&skel->qlock);
865
866
867 vdev = &skel->vdev;
868 strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
869
870
871
872
873 vdev->release = video_device_release_empty;
874 vdev->fops = &skel_fops,
875 vdev->ioctl_ops = &skel_ioctl_ops,
876
877
878
879
880
881 vdev->lock = &skel->lock;
882 vdev->queue = q;
883 vdev->v4l2_dev = &skel->v4l2_dev;
884
885 vdev->tvnorms = SKEL_TVNORMS;
886 video_set_drvdata(vdev, skel);
887
888 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
889 if (ret)
890 goto free_ctx;
891
892 dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n");
893 return 0;
894
895free_ctx:
896 vb2_dma_contig_cleanup_ctx(skel->alloc_ctx);
897free_hdl:
898 v4l2_ctrl_handler_free(&skel->ctrl_handler);
899 v4l2_device_unregister(&skel->v4l2_dev);
900disable_pci:
901 pci_disable_device(pdev);
902 return ret;
903}
904
905static void skeleton_remove(struct pci_dev *pdev)
906{
907 struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
908 struct skeleton *skel = container_of(v4l2_dev, struct skeleton, v4l2_dev);
909
910 video_unregister_device(&skel->vdev);
911 v4l2_ctrl_handler_free(&skel->ctrl_handler);
912 vb2_dma_contig_cleanup_ctx(skel->alloc_ctx);
913 v4l2_device_unregister(&skel->v4l2_dev);
914 pci_disable_device(skel->pdev);
915}
916
917static struct pci_driver skeleton_driver = {
918 .name = KBUILD_MODNAME,
919 .probe = skeleton_probe,
920 .remove = skeleton_remove,
921 .id_table = skeleton_pci_tbl,
922};
923
924module_pci_driver(skeleton_driver);
925