Davinci V4L2视频采集框架分析

这里只是记录一些日志,难免有些错误,欢迎批评指正。Davinci V4L2视频采集框架主要是分析davinci_capture.c这个模块。
 
V4L2简介
 
Davinci V4L2视频采集驱动其是根据V4L2采集驱动来编写的,想要熟悉其驱动流程,也就比先要了解V4L2德的一些相关知识。我们这里只了解它的采集部分
 
V4L2(video for linux) 可以支持多种设备,它可以有以下5种接口:
 
1、视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.下面也是着重讲解这种应用;
 
2、视频输出接口(video output interface):可以驱动计算机的外围视频图像设备——像可以输出电视信号格式的设备;
 
3、直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU;
 
4、视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号;
 
5、收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流;
 
V4L2驱动的主要功能是使程序有发现设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频压缩格式和图像像参数等等.
 
关于它的采集流程可以查看http://blog.csdn.net/piaozhiye/article/details/7537419这里我就不罗嗦了。


模块注册与注销
 

3290module_init(vpif_init);
 
3291 module_exit(vpif_cleanup);
 
另外向其他模块提供了两个导出函数,提供给视频设备注册和注销。
 
3286 EXPORT_SYMBOL(vpif_register_decoder);
 
3287 EXPORT_SYMBOL(vpif_unregister_decoder);
 

vpif_initVPIF采集接口的初始化工作
 

主要是分配缓冲,检查设备类型,分配内存给channel objects,建立VBI处理的工作队列,注册vpif_driver,注册_vpif_device,申请request_irq,引脚复用的设置。在注册的时候会使用vpif_driver 的probe来进行注册,注册一些相关的ioctrol等。
 
01.    具体如下: 
02.2979 /* vpif_init : This function registers device and driver to
03.2980  * the kernel, requests irq handler and allocates memory
04.2981  * for channel objects
05.2982  */ 
06.2983 static __init int vpif_init(void) 
07.2984 { 
08.2985         intfree_irq_no_index; 
09.2986         int err = 0, i,j; 
10.2987         intfree_channel_objects_index; 
11.2988         intfree_buffer_channel_index; 
12.2989         intfree_buffer_index; 
13.2990         u8 *addr; 
14.2991         u32 size; 
15.2992  
16.2993         /* Default number ofbuffers should be 3 */ 
17.2994         if((channel0_numbuffers > 0) && 
18.2995            (channel0_numbuffers < config_params.min_numbuffers)) 
19.2996                channel0_numbuffers = config_params.min_numbuffers; 
20.2997         if((channel1_numbuffers > 0) && 
21.2998            (channel1_numbuffers < config_params.min_numbuffers)) 
22.2999                channel1_numbuffers = config_params.min_numbuffers; 
23.3000  
24.3001         /* Set buffer size tomin buffers size if invalid buffer size is
25.3002          * given */ 
26.3003         if (channel0_bufsize< config_params.min_bufsize[VPIF_CHANNEL0_VIDEO]) 
27.3004                channel0_bufsize = 
28.3005                    config_params.min_bufsize[VPIF_CHANNEL0_VIDEO]; 
29.3006         if (channel1_bufsize< config_params.min_bufsize[VPIF_CHANNEL1_VIDEO]) 
30.3007                channel1_bufsize = 
31.3008                    config_params.min_bufsize[VPIF_CHANNEL1_VIDEO]; 
32.3009  
33.3010        config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = channel0_numbuffers; 
34.3011        config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = channel1_numbuffers; 
35.3012         if(channel0_numbuffers) { 
36.3013                config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO] 
37.3014                    = channel0_bufsize; 
38.3015         } 
39.3016         if (channel1_numbuffers){ 
40.3017                config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO] 
41.3018                    = channel1_bufsize; 
42.3019         } 
43.3020  
44.3021         /* Check the correctvalue of device_type */ 
45.3022         if ((device_type >config_params.max_device_type) || (device_type < 0)) { 
46.3023                config_params.device_type = 0; 
47.3024         } else { 
48.3025                config_params.device_type = device_type; 
49.3026         } 
50.3027         /* Allocate memory forsix channel objects */ 
51.3028         for (i = 0; i <VPIF_CAPTURE_MAX_DEVICES; i++) { 
52.3029                vpif_obj.dev[i] = 
53.3030                    kmalloc(sizeof(struct channel_obj), GFP_KERNEL); 
54.3031                /* If memory allocation fails, return error */ 
55.3032                if (!vpif_obj.dev[i]) { 
56.3033                        free_channel_objects_index = i; 
57.3034                        goto vpif_init_free_channel_objects; 
58.3035                        err = -ENOMEM; 
59.3036                } 
60.3037         } 
61.3038        free_channel_objects_index = VPIF_CAPTURE_MAX_DEVICES; 
62.3039  
63.3040         /* Allocate memory forbuffers */ 
64.3041         for (i = 0; i <VPIF_CAPTURE_NUM_CHANNELS; i++) { 
65.3042                size = config_params.channel_bufsize[i]; 
66.3043                for (j = 0; j < config_params.numbuffers[i]; j++) { 
67.3044                        addr = (u8 *) vpif_alloc_buffer(size); 
68.3045                        if (!addr) { 
69.3046                                free_buffer_channel_index = i; 
70.3047                                free_buffer_index = j; 
71.3048                                err = -ENOMEM; 
72.3049                                goto vpif_init_free_buffers; 
73.3050                        } 
74.3051                        vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].fbuffers[j] = 
75.3052                            addr; 
76.3053                } 
77.3054         } 
78.3055        free_buffer_channel_index = VPIF_CAPTURE_NUM_CHANNELS; 
79.3056         free_buffer_index =config_params.numbuffers[i - 1]; 
80.3057  
81.3058         /* Create the workqueue*/ 
82.3059         vbi_workqueue =create_singlethread_workqueue("vbi"); 
83.3060         if (!vbi_workqueue){ 
84.3061                err = -ENOMEM; 
85.3062                goto vpif_init_free_buffers; 
86.3063         } 
87.3064  
88.3065         /* Register driver tothe kernel */ 
89.3066         err =driver_register(&vpif_driver); 
90.3067         if (0 != err) { 
91.3068                goto vpif_init_free_buffers; 
92.3069         } 
93.3070         /* register device as aplatform device to the kernel */ 
94.3071         err = platform_device_register(&_vpif_device); 
95.3072         if (0 != err) { 
96.3073                goto vpif_init_unregister_vpif_driver; 
97.3074         } 
98.3075         for (j = 0; j <VPIF_CAPTURE_NUM_CHANNELS; j++) { 
99.3076                err = 
100.3077                    request_irq(vpif_get_irq_number(j), 
101.3078                                vpif_channel_isr, SA_INTERRUPT, 
102.3079                                "DM646x_Capture", 
103.3080                                (void *)(&(vpif_obj.dev[j]->channel_id))); 
104.3081                if (0 != err) { 
105.3082                        if (j == 0) { 
106.3083                                goto vpif_init_unregister_vpif_device; 
107.3084                        } else { 
108.3085                                free_irq_no_index = j; 
109.3086                                goto vpif_init_free_irq; 
110.3087                        } 
111.3088                } 
112.3089         } 
113.3090         free_irq_no_index =VPIF_CAPTURE_NUM_CHANNELS; 
114.3091  
115.3092         /*err = request_irq(4,vpif_err_isr, SA_INTERRUPT, "DM646x_Capture_err",*/ 
116.3093         /*(void*)NULL);*/ 
117.3094         /*if (0 !=err)*/ 
118.3095         /*{*/ 
119.3096         /*printk("requesterror interrupt is err!\n");*/ 
120.3097         /*return err;*/ 
121.3098         /*}*/ 
122.3099  
123.3100         /*//initialize errorinterrupt register.*/ 
124.3101        /*init_int_err();*/ 
125.3102  
126.3103         /* Set the pinmuxsettings */ 
127.3104        set_vpif_pinmux(); 
128.3105        set_vpif_capture_pinmux(); 
129.3106  
130.3107         return 0; 
131.3108  
132.3109 vpif_init_free_irq: 
133.3110         for (j = 0; j <free_irq_no_index; j++) { 
134.3111                free_irq(vpif_get_irq_number(j), 
135.3112                         (void *)(&(vpif_obj.dev[j]->channel_id))); 
136.3113         } 
137.3114 vpif_init_unregister_vpif_device: 
138.3115        platform_device_unregister(&_vpif_device); 
139.3116  
140.3117 vpif_init_unregister_vpif_driver: 
141.3118        driver_unregister(&vpif_driver); 
142.3119  
143.3120 vpif_init_free_buffers: 
144.3121         for (i = 0; i <free_buffer_channel_index; i++) { 
145.3122                for (j = 0; j < config_params.numbuffers[i]; j++) { 
146.3123                        addr = vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX]. 
147.3124                            fbuffers[j]; 
148.3125                        if (addr) { 
149.3126                                vpif_free_buffer((unsigned long)addr, 
150.3127                                                 config_params. 
151.3128                                                 channel_bufsize[i] 
152.3129                                    ); 
153.3130                                vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX]. 
154.3131                                    fbuffers[j] = NULL; 
155.3132                        } 
156.3133                } 
157.3134         } 
158.3135         for (j = 0; j <free_buffer_index; j++) { 
159.3136                addr = 
160.3137                    vpif_obj.dev[free_buffer_channel_index]-> 
161.3138                    common[VPIF_VIDEO_INDEX].fbuffers[j]; 
162.3139                if (addr) { 
163.3140                        vpif_free_buffer((unsigned long)addr, 
164.3141                                         config_params.channel_bufsize[i]); 
165.3142                        vpif_obj.dev[free_buffer_channel_index]-> 
166.3143                            common[VPIF_VIDEO_INDEX].fbuffers[j] 
167.3144                            = NULL; 
168.3145                } 
169.3146         } 
170.3147  
171.3148 vpif_init_free_channel_objects: 
172.3149         for (j = 0; j <free_channel_objects_index; j++) { 
173.3150                if (vpif_obj.dev[i]) { 
174.3151                        kfree(vpif_obj.dev[j]); 
175.3152                        vpif_obj.dev[i] = NULL; 
176.3153                } 
177.3154         } 
178.3155         return err; 
179.3156 }  

其中的一些关键结构:
 
01.vpif_driver 
02.2950 static struct device_driver vpif_driver = { 
03.2951         .name = "vpifcapture", 
04.2952         .bus =&platform_bus_type, 
05.2953         .probe =vpif_probe, 
06.2954         .remove =vpif_remove, 
07.2955 };       
08.2956 static struct platform_device _vpif_device = { 
09.2957         .name = "vpifcapture", 
10.2958         .id = 1, 
11.2959         .dev = { 
12.2960                .release = vpif_platform_release, 
13.2961                } 
14.2962};               

 

vpif_probe
 
用video_device_alloc(); 给video_device *vfd 分配内存,并初始化,然后channel->video_dev指向vfd,初始化channel objects,最后使用video_register_device注册video_dev。
 
具体如下:
 
01.2816 /* vpif_probe : This function creates device entries by register
02.2817  * itself to the V4L2 driver and initializes fields of each
03.2818  * channel objects */ 
04.2819 static __init int vpif_probe(struct device *device) 
05.2820 { 
06.2821         struct common_obj*common = NULL; 
07.2822         int i, j = 0, k, err =0, index = 0; 
08.2823         struct video_device*vfd = NULL; 
09.2824         struct channel_obj*channel = NULL; 
10.2825         struct video_obj*vid_ch = NULL; 
11.2826         vpif_dev =device; 
12.2827  
13.2828         for (i = 0; i <VPIF_CAPTURE_MAX_DEVICES; i++) { 
14.2829                /* Get the pointer to the channel object */ 
15.2830                channel = vpif_obj.dev[i]; 
16.2831                /* Allocate memory for video device */ 
17.2832                vfd = video_device_alloc(); 
18.2833                if (ISNULL(vfd)) { 
19.2834                        for (j = 0; j < i; j++) { 
20.2835                                video_device_release(vpif_obj.dev[j]-> 
21.2836                                                     video_dev); 
22.2837                        } 
23.2838                        return -ENOMEM; 
24.2839                } 
25.2840  
26.2841                /* Initialize field of video device */ 
27.2842                *vfd = vpif_video_template; 
28.2843                vfd->dev = device; 
29.2844                vfd->release = video_device_release; 
30.2845                snprintf(vfd->name, sizeof(vfd->name), 
31.2846                         "DM646x_VPIFCapture_DRIVER_V%d.%d.%d", 
32.2847                         (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff, 
33.2848                         (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff, 
34.2849                         (VPIF_CAPTURE_VERSION_CODE) & 0xff); 
35.2850                /* Set video_dev to the video device */ 
36.2851                channel->video_dev = vfd; 
37.2852         } 
38.2853  
39.2854         for (j = 0; j <VPIF_CAPTURE_MAX_DEVICES; j++) { 
40.2855                channel = vpif_obj.dev[j]; 
41.2856                channel->usrs = 0; 
42.2857                for (k = VPIF_VIDEO_INDEX; k <= VPIF_HBI_INDEX; k++) { 
43.2858                        common = &(channel->common[k]); 
44.2859                        common->io_usrs = 0; 
45.2860                        common->started = 0; 
46.2861                        spin_lock_init(&common->irqlock); 
47.2862                        init_MUTEX(&common->lock); 
48.2863                        common->numbuffers = 0; 
49.2864                        common->set_addr = NULL; 
50.2865                        common->ytop_off = common->ybtm_off = 0; 
51.2866                        common->ctop_off = common->cbtm_off = 0; 
52.2867                        common->curFrm = common->nextFrm = NULL; 
53.2868                        memset(&common->fmt, 0, sizeof(struct v4l2_format)); 
54.2869                } 
55.2870                channel->video.std = 0; 
56.2871                channel->initialized = 0; 
57.2872                channel->channel_id = j; 
58.2873  
59.2874                common = &(channel->common[VPIF_VIDEO_INDEX]); 
60.2875                vid_ch = &(channel->video); 
61.2876                /* Initialize field of the channel objects */ 
62.2877                channel->usrs = common->io_usrs = vid_ch->std = 0; 
63.2878                common->started = channel->initialized = 0; 
64.2879                channel->channel_id = j; 
65.2880                common->numbuffers = 
66.2881                    config_params.numbuffers[channel->channel_id]; 
67.2882  
68.2883                channel->numdecoders = 0; 
69.2884                channel->current_decoder = 0; 
70.2885                for (index = 0; index < VPIF_CAPTURE_NUM_DECODERS; index++) { 
71.2886                        channel->decoder[index] = NULL; 
72.2887                } 
73.2888  
74.2889                memset(&(channel->vpifparams), 0, sizeof(struct vpif_params)); 
75.2890                /* Initialize prio member of channel object */ 
76.2891                v4l2_prio_init(&channel->prio); 
77.2892  
78.2893                /* Set the tasklet handler in the tasklet struct */ 
79.2894                channel->vbi.vbi_tasklet.func = vbi_work_handler; 
80.2895                /* Set Timer counter */ 
81.2896                channel->vbi.timer_counter = VPIF_TIMER_COUNT; 
82.2897                /* Initialize the work structure */ 
83.2898                INIT_WORK(&vbi_work[channel->channel_id], 
84.2899                          (void (*)(void *))vbi_work_handler, (void *)channel); 
85.2900                /* register video device */ 
86.2901                dev_dbg(vpif_dev, "trying to register vpif device.\n"); 
87.2902                dev_dbg(vpif_dev, "channel=%x,channel->video_dev=%x\n", 
88.2903                        (int)channel, (int)&channel->video_dev); 
89.2904                channel->common[VPIF_VIDEO_INDEX].fmt.type = 
90.2905                    V4L2_BUF_TYPE_VIDEO_OUTPUT; 
91.2906                channel->common[VPIF_VBI_INDEX].fmt.type = 
92.2907                    V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; 
93.2908                channel->common[VPIF_HBI_INDEX].fmt.type = 
94.2909                    V4L2_BUF_TYPE_HBI_CAPTURE; 
95.2910                err = video_register_device(channel->video_dev, 
96.2911                                            VFL_TYPE_GRABBER, vpif_nr[j]); 
97.2912                if (err) 
98.2913                        goto probe_out; 
99.2914         } 
100.2915         return 0; 
101.2916  
102.2917 probe_out: 
103.2918         for (k = 0; k < j;k++) { 
104.2919                /* Get the pointer to the channel object */ 
105.2920                channel = vpif_obj.dev[k]; 
106.2921                /* Unregister video device */ 
107.2922                video_unregister_device(channel->video_dev); 
108.2923                /* Release video device */ 
109.2924                video_device_release(channel->video_dev); 
110.2925                channel->video_dev = NULL; 
111.2926         } 
112.2927         dev_dbg(vpif_dev,"</vpif_probe>\n"); 
113.2928         return err; 
114.2929 } 

structvideo_device  *vfd = vpif_video_template;
 
01.    vfd = vpif_video_template;是V4L2里面的video_device结构, 
02.    在drivers/media/video/davinci/davinci_capture.c中 
03.2809 static struct video_device vpif_video_template = { 
04.2810         .name ="vpif",  
05.2811         .type =VID_TYPE_CAPTURE, 
06.2812         .hardware = 0, 
07.2813         .fops =&vpif_fops,.minor = -1, 
08.2814 };  
09. 
10.2801 static struct file_operations vpif_fops = { 
11.2802         .owner =THIS_MODULE, 
12.2803         .open = vpif_open,//打开设备做一些初始化工作 
13.2804         .release =vpif_release, //释放资源 
14.2805         .ioctl = vpif_ioctl,//控制命令包括V4L2的命令和自定义的命令 
15.2806         .mmap = vpif_mmap,//映射内核空间内存到用户空间 
16.2807         .poll =vpif_poll        
17.2808};                        

 


vpif_ioctl的一些控制命令
 
vpif_ioctl封装了一些自定义的命了和V4L2的命令,其中V4L2的命令主要在vpif_doioctl实现。
 
01./* If the case is for querying capabilities */ 
02.           caseVIDIOC_QUERYCAP: 
03.              /* If the case is for enumerating inputs */ 
04.           caseVIDIOC_ENUMINPUT: 
05.              /* If the case is for getting input */ 
06.           caseVIDIOC_G_INPUT: 
07.              /* If the case is for setting input */ 
08.           caseVIDIOC_S_INPUT: 
09.              /* If the case is for enumerating standards */ 
10.           caseVIDIOC_ENUMSTD: 
11.              /* If the case is for querying standards */ 
12.           caseVIDIOC_QUERYSTD: 
13.              /* If the case is for getting standard */ 
14.           caseVIDIOC_G_STD: 
15.              /* If the case is for setting standard */ 
16.           caseVIDIOC_S_STD: 
17.              /* If the case is for enumerating formats */ 
18.           caseVIDIOC_ENUM_FMT: 
19.              /* If the case is for getting formats */ 
20.           caseVIDIOC_G_FMT: 
21.              /* If the case is for setting formats */ 
22.           caseVIDIOC_S_FMT: 
23.              /* If the case is for trying formats */ 
24.           caseVIDIOC_TRY_FMT: 
25.              /* If the case is for querying controls */ 
26.           caseVIDIOC_QUERYCTRL: 
27.              /* If the case is for getting controls value */ 
28.           caseVIDIOC_G_CTRL: 
29.              /* If the case is for getting controls value */ 
30.           caseVIDIOC_S_CTRL: 
31.              /* If the case is for getting decoder parameters */ 
32.           caseVPIF_CMD_G_DECODER_PARAMS: 
33.              /* If the case is for setting decoder parameters */ 
34.           caseVPIF_CMD_S_DECODER_PARAMS: 
35.              /* If the case is for requesting buffer allocation */ 
36.           caseVIDIOC_REQBUFS: 
37.              /* If the case is for en-queing buffer in the buffer
38.               * queue */ 
39.           caseVIDIOC_QBUF: 
40.              /* If the case is for de-queing buffer from the buffer queue */ 
41.           caseVIDIOC_DQBUF: 
42.             /*If the case is for querying information about
43.               *  buffer for memory mapping io */ 
44.           caseVIDIOC_QUERYBUF: 
45.              /* If the case is starting streaming */ 
46.           caseVIDIOC_STREAMON: 
47.              /* If the case is for stopping streaming */ 
48.           caseVIDIOC_STREAMOFF: 
49.              /* If the case is for setting VPIF parameters */ 
50.           caseVPIF_S_VPIF_PARAMS: 
51.              /* If the case is for getting VPIF Parameters */ 
52.           caseVPIF_G_VPIF_PARAMS: 
53.              /* If the case is for getting TVP5146 parameters */ 
54.           caseVPFE_CMD_CONFIG_TVP5146: 
55.              /* If the case is for setting mt9t001 parameters */ 
56.           caseVPFE_S_MT9T001_PARAMS: 
57.              /* If the case is for setting mt9t001 parameters */ 
58.           caseVPFE_G_MT9T001_PARAMS: 
59.           case VIDIOC_S_PRIORITY: 
60.           caseVIDIOC_G_PRIORITY: 
61.              /* If the case is for getting sliced vbi capabilites */ 
62.           caseVIDIOC_G_SLICED_VBI_CAP: 
63.              /* If the case if for getting cropping parameters */ 
64.           caseVIDIOC_CROPCAP: 
65.           caseVPIF_RESYNC: 
66.           caseVPIF_RESET: 

 
例如使用VIDIOC_ENUMSTD查询标准的时候,大概流程是这样的
 
1、首先判断是芯片驱动std_ops和dec->std_ops->enumstd是否有完成,如果没有完成则返回失败。
 
2、判断index是否是合法的
 
3、最后使用dec->std_ops->enumstd(std, dec),这个会函数直接调用芯片驱动的的xxx_enumstd函数(如sii9013_enumstd)。
 
具体代码如下:
 
01.1377                /* If the case is for enumerating standards */ 
02.1378            case VIDIOC_ENUMSTD: 
03.1379                { 
04.1380                    struct v4l2_standard *std = (struct v4l2_standard *)arg; 
05.1381                    struct video_obj *vid_ch = &(channel->video); 
06.1382                    int index = std->index, dec_idx; 
07.1383                    dev_dbg(vpif_dev, "VIDIOC_ENUMSTD\n"); 
08.1384  
09.1385  
10.1386                    /* Call enumstd function of decoder device */ 
11.1387                    if (ISNULL(dec->std_ops) 
12.1388                            || ISNULL(dec->std_ops->enumstd)) { 
13.1389                        dev_err(vpif_dev, "vpif_doioctl:No enumstd\n"); 
14.1390                        return -EINVAL; 
15.1391                    } 
16.1392                    if (index >= vid_ch->count_std) { 
17.1393                        dev_err(vpif_dev, "Invalid index\n"); 
18.1394                        return -EINVAL; 
19.1395                    } 
20.1396                    dec_idx = vid_ch->std_tbl[index].dec_idx; 
21.1397                    dec = channel->decoder[dec_idx]; 
22.1398                    std->index = vid_ch->std_tbl[index].std_idx; 
23.1399                    ret = dec->std_ops->enumstd(std, dec); 
24.1400                    std->index = index; 
25.1401                    break; 
26.1402                } 

 主要是记录了一些流程,具体的问题没有进行分析,相关芯片的驱动分析可以查阅前面的分析记录。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值