<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      嵌入式Linux中的LED驅動控制(設備樹方式)

      Linux3.1之后的內核版本,引入了設備樹的概念。同時,設備樹還需要Bootloader的支持,如果使用Uboot,在1.1.3版本之后就可以支持設備樹了。

      設備樹概念的提出其實有兩方面的原因。其一當然是代碼冗余,導致Linux內核臃腫不堪。在Linux內核源碼中,只要是通過了基金會的認可,就可以把某個廠商的板級支持代碼納入到Linux內核源碼當中。比如國內曾經風靡一時的友善之臂Mini2440開發板,從Linux-2.6.31版本開始就被Linux官方內核所支持了,至今還可以在Linux內核源碼中看到它的相關文件(如:arch/arm/mach-s3c24xx/mach-mini2440.c以及arch/arm/configs/mini2440_defconfig等)。然而在Linux內核源碼中,同樣還包含有很多其他廠商的板級支持文件。其實這些開發板只要所選用的芯片相同,則很大一部分代碼是相同的。這就造成了內核的冗余和臃腫,并有愈演愈烈的趨勢(難怪Linus要發火了)。第二個原因,其實也是順理成章的。從Linux2.6版本之后內核就引入了platform總線平臺的概念,把驅動分成了設備(platform_device)和驅動(platform_driver)兩個單獨的文件,現在只要把設備文件從內核中提出來,單獨形成一個第三方文件,不就不影響內核了嗎。這樣做還有一個好處,即這個提出來的設備文件,只要在驅動中統一相關接口和命名規則,該文件的大部分工作還可以由廠商來完成(或由廠商提供的工具來完成),大大提高了開發的效率和可靠性。這個被單獨提出來的第三方文件,后來就演化成了現在的設備樹配置文件。

      下面就通過設備樹方式來實現對LED的驅動。先給出設備樹的配置內容,在內核源碼(本例在/opt/ebf_linux_kernel_mp157_depth1/目錄下)的arch/arm/boot/dts目錄下找到一個名為“stm32mp157a-basic.dts”的文件,該文件就是開發板配套提供的設備樹源文件。打開它,并在根節點的最后加入本例LED設備的配置內容,如下。

      / {
          model = "Embedfire STM32MP157 Star LubanCat Robot S1 Board";
          compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
      
          aliases {
              ethernet0 = &ethernet0;
              serial0 = &uart4;
              serial1 = &usart1;
              serial2 = &usart2;
              serial3 = &usart3;        
          };
      
          chosen {
              stdout-path = "serial0:115200n8";
          };
      
          memory@c0000000 {
              reg = <0xc0000000 0x40000000>;
          };
      
          reserved-memory {
              #address-cells = <1>;
              #size-cells = <1>;
              ranges;
      
              retram: retram@0x38000000 {
                  compatible = "shared-dma-pool";
                  reg = <0x38000000 0x10000>;
                  no-map;
              };
      
              mcuram: mcuram@0x30000000 {
                  compatible = "shared-dma-pool";
                  reg = <0x30000000 0x40000>;
                  no-map;
              };
      
              mcuram2: mcuram2@0x10000000 {
                  compatible = "shared-dma-pool";
                  reg = <0x10000000 0x40000>;
                  no-map;
              };
      
              vdev0vring0: vdev0vring0@10040000 {
                  compatible = "shared-dma-pool";
                  reg = <0x10040000 0x2000>;
                  no-map;
              };
      
              vdev0vring1: vdev0vring1@10042000 {
                  compatible = "shared-dma-pool";
                  reg = <0x10042000 0x2000>;
                  no-map;
              };
      
              vdev0buffer: vdev0buffer@10044000 {
                  compatible = "shared-dma-pool";
                  reg = <0x10044000 0x4000>;
                  no-map;
              };
      
              gpu_reserved: gpu@d4000000 {
                  reg = <0xd4000000 0x4000000>;
                  no-map;
              };
          };
      
          sram: sram@10050000 {
              compatible = "mmio-sram";
              reg = <0x10050000 0x10000>;
              #address-cells = <1>;
              #size-cells = <1>;
              ranges = <0 0x10050000 0x10000>;
      
              dma_pool: dma_pool@0 {
                  reg = <0x0 0x10000>;
                  pool;
              };
          };
      
          leds {
              compatible = "gpio-leds";
              status = "okay";
              heartbeat {
                  label = "heartbeat";
                  gpios = <&gpioa 14 GPIO_ACTIVE_HIGH>;
                  linux,default-trigger = "heartbeat";
                  default-state = "off";
              };
          };
          v3v3: regulator-3p3v {
              compatible = "regulator-fixed";
              regulator-name = "v3v3";
              regulator-min-microvolt = <3300000>;
              regulator-max-microvolt = <3300000>;
              regulator-always-on;
              regulator-boot-on;
          };
      
          vdd: regulator-vdd {
              compatible = "regulator-fixed";
              regulator-name = "vdd";
              regulator-min-microvolt = <3300000>;
              regulator-max-microvolt = <3300000>;
              regulator-always-on;
              regulator-boot-on;
          };
      
          vdd_usb: regulator-vdd-usb {
              compatible = "regulator-fixed";
              regulator-name = "vdd_usb";
              regulator-min-microvolt = <3300000>;
              regulator-max-microvolt = <3300000>;
              regulator-always-on;
              regulator-boot-on;
          };
      
          v2v8: v2v8 {
              compatible = "regulator-fixed";
              regulator-name = "v2v8";
              regulator-min-microvolt = <2800000>;
              regulator-max-microvolt = <2800000>;
              regulator-always-on;
              regulator-boot-on;
          };
      
          vbus_otg: regulator-vbus-otg {
              compatible = "regulator-fixed";
              regulator-name = "vbus_otg";
              regulator-min-microvolt = <5000000>;
              regulator-max-microvolt = <5000000>;
              regulator-always-on;
              regulator-boot-on;
          };
      
          usb_phy_tuning: usb-phy-tuning {
              st,hs-dc-level = <2>;
              st,fs-rftime-tuning;
              st,hs-rftime-reduction;
              st,hs-current-trim = <15>;
              st,hs-impedance-trim = <1>;
              st,squelch-level = <3>;
              st,hs-rx-offset = <2>;
              st,no-lsfs-sc;
          };
          
          //以下為本次LED的追加內容
          rgb_led{
              #address-cells = <1>;
              #size-cells = <1>;
              compatible = "fire,rgb_led";
              ranges;
              //紅色LED節點
              led_red@0x50002000{
                  compatible = "fire,led_red";
                  reg = < 0x50002000 0x00000004
                          0x50002004 0x00000004
                          0x50002008 0x00000004
                          0x5000200C 0x00000004
                          0x50002018 0x00000004
                          0x50000A28 0x00000004 >;
                  status = "okay";
              };
              //綠色LED節點
              led_green@0x50008000{
                  compatible = "fire,led_green";
                  reg = < 0x50008000 0x00000004
                          0x50008004 0x00000004
                          0x50008008 0x00000004
                          0x5000800C 0x00000004
                          0x50008018 0x00000004 >;
                  status = "okay";
              };
              //藍色LED節點
              led_blue@0x50003000{
                  compatible = "fire,led_blue";
                  reg = < 0x50003000 0x00000004
                          0x50003004 0x00000004
                          0x50003008 0x00000004
                          0x5000300C 0x00000004
                          0x50003018 0x00000004 >;
                  status = "okay";
              };
          };
      };

      注意,以上內容只是設備樹文件stm32mp157a-basic.dts中的一部分內容,并未全部給出。上面內容中最末尾的部分才是本次追加的內容,其他部分內容是原設備樹就有的,不要改動(包括未給出的部分),完成后保存并編譯它。編譯要在源碼根目錄下進行(即/opt/ebf_linux_kernel_mp157_depth1/目錄下),先執行make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- stm32mp157_ebf_defconfig進行配置,然后執行make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs進行編譯。編譯完成后,會在設備樹所在目錄下(arch/arm/boot/dts)生成名為stm32mp157a-basic.dtb的設備樹文件,把該文件通過NFS拷貝到開發板的/boot/dts/目錄下并替換原有設備樹文件,然后執行reboot重啟開發板(不能按reset鍵重啟)。

      以下是平臺驅動部分的代碼,文件名為led.c。

      #include <linux/init.h>
      #include <linux/module.h>
      #include <linux/fs.h>
      #include <linux/cdev.h>
      #include <linux/uaccess.h>
      #include <linux/types.h>
      #include <linux/kernel.h>
      #include <linux/delay.h>
      #include <linux/ide.h>
      #include <linux/errno.h>
      #include <linux/gpio.h>
      #include <asm/mach/map.h>
      #include <linux/of.h>
      #include <linux/of_address.h>
      #include <linux/of_gpio.h>
      #include <asm/io.h>
      #include <linux/device.h>
      #include <linux/platform_device.h>
      static dev_t devid;                     //設備號
      static struct cdev led_cdev;             //定義字符型結構體
      struct class *led_class;                //類結構體
      struct device_node *rgb_led_device_node; //rgb_led的設備樹節點結構體
      //以下定義led資源結構體,保存獲取得到的節點信息以及轉換后的虛擬寄存器地址
      struct led_resource
      {
          struct device_node *device_node; 
          void __iomem *MODER;
          void __iomem *OTYPER;
          void __iomem *OSPEEDR;
          void __iomem *PUPDR;
          void __iomem *BSRR;
      };
      static void __iomem *clkaddr;    //端口時鐘變量
      //以下定義RGB三個燈的led_resource結構體,保存獲取得到的節點信息
      struct led_resource led_red;
      struct led_resource led_green;
      struct led_resource led_blue;
      //實現open函數,為file_oprations結構體成員函數
      static int led_open(struct inode *inode, struct file *filp)
      {
          unsigned int tmp;
          //以下使能GPIOA、GPIOB、GPIOG端口時鐘
          tmp = ioread32(clkaddr);
          tmp |=  0x43;
          iowrite32(tmp, clkaddr);
          return 0;
      }
      //實現write函數,為file_oprations結構體成員函數
      static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
      {
          unsigned char value;
          unsigned long n;
          n = copy_from_user(&value, buf, cnt);    //從應用空間獲取值
          switch(value)            //根據應用空間的值判斷具體操作
        {
              case 0:                        //全部點亮三個LED
                  iowrite32(0x20000000, led_red.BSRR);
                  iowrite32(0x200000, led_blue.BSRR);
                  iowrite32(0x40000, led_green.BSRR);
                  break;
              case 1:                        //點亮紅色LED
                  iowrite32(0x20000000, led_red.BSRR);
                  break;
              case 2:                        //點亮綠色LED
                  iowrite32(0x40000, led_green.BSRR);
                  break;
              case 3:                        //點亮藍色LED
                  iowrite32(0x200000, led_blue.BSRR);
                  break;
              case 4:                        //熄滅紅色LED
                  iowrite32(0x2000, led_red.BSRR);
                  break;
              case 5:                        //熄滅綠色LED
                  iowrite32(0x04, led_green.BSRR);
                  break;
              case 6:                        //熄滅藍色LED
                  iowrite32(0x20, led_blue.BSRR);
                  break;
              case 7:                        //全部熄滅三個LED
                  iowrite32(0x2000, led_red.BSRR);
                  iowrite32(0x20, led_blue.BSRR);
                  iowrite32(0x04, led_green.BSRR);
                  break;
              default:                        //全部熄滅
                  iowrite32(0x2000, led_red.BSRR);
                  iowrite32(0x20, led_blue.BSRR);
                  iowrite32(0x04, led_green.BSRR);
                  break;
          }
             return cnt;
      }
      //實現release函數,為file_oprations結構體函數
      static int led_release(struct inode *inode, struct file *filp)
      {
          unsigned int tmp;
          //以下禁能GPIOA、GPIOB、GPIOG端口時鐘
          tmp = ioread32(clkaddr);
          tmp &= ~0x43;
          iowrite32(tmp, clkaddr);
          return 0;
      }
      //填充一個file_oprations類型的結構體,名為led_dev_fops,包含上述聲明的成員函數
      static struct file_operations led_dev_fops =
          {
              .owner = THIS_MODULE,
              .open = led_open,            //指定open函數成員
              .write = led_write,            //指定write函數成員
              .release = led_release,    //指定release函數成員
      };
      //probe函數中,驅動提取設備樹中的資源,并完成字符設備的注冊
      static int led_pdrv_probe(struct platform_device *pdv)
      {
          unsigned int tmp;
          //獲取rgb_led的設備樹節點
          rgb_led_device_node = of_find_node_by_path("/rgb_led");
          if (rgb_led_device_node == NULL)
          {
              printk(KERN_ERR "\t  get rgb_led failed!  \n");
              return -1;
          }
          //獲取rgb_led節點的紅燈子節點
          led_red.device_node = of_find_node_by_name(rgb_led_device_node,"led_red");
          if (led_red.device_node == NULL)
          {
              printk(KERN_ERR "\n get rgb_led_red_device_node failed ! \n");
              return -1;
          }
          //以下獲取設備節點中紅燈子節點的reg屬性并轉化為虛擬地址
          led_red.MODER = of_iomap(led_red.device_node, 0);
          led_red.OTYPER = of_iomap(led_red.device_node, 1);
          led_red.OSPEEDR = of_iomap(led_red.device_node, 2);
          led_red.PUPDR = of_iomap(led_red.device_node, 3);
          led_red.BSRR = of_iomap(led_red.device_node, 4);
          clkaddr = of_iomap(led_red.device_node, 5);
          //以下使能GPIOA、GPIOB、GPIOG端口時鐘
          tmp = ioread32(clkaddr);
          tmp |=  0x43;
          iowrite32(tmp, clkaddr);
          //以下設置模式寄存器:輸出模式
          tmp = ioread32(led_red.MODER);
          tmp &= ~(0x3 << (13 * 2));
          tmp |= (0x1 << (13 * 2));
          iowrite32(tmp, led_red.MODER);
          //以下設置輸出類型寄存器:推挽模式
          tmp = ioread32(led_red.OTYPER);
          tmp &= ~(0x1 << 13);
          iowrite32(tmp, led_red.OTYPER);
          //以下設置輸出速度寄存器:高速
          tmp = ioread32(led_red.OSPEEDR);
          tmp &= ~(0x3 << (13 * 2));
          tmp |= (0x2 << (13 * 2));
          iowrite32(tmp, led_red.OSPEEDR);
          //以下設置上下拉寄存器:上拉
          tmp = ioread32(led_red.PUPDR);
          tmp &= ~(0x3 << (13 * 2));
          tmp |= (0x1 << (13 * 2));
          iowrite32(tmp,led_red.PUPDR);
          //以下設置置位寄存器:默認輸出高電平
          tmp = ioread32(led_red.BSRR);
          tmp |= (0x1 << 13);
          iowrite32(tmp, led_red.BSRR);
          //獲取rgb_led節點的綠燈子節點
          led_green.device_node = of_find_node_by_name(rgb_led_device_node,"led_green");
          if (led_green.device_node == NULL)
          {
              printk(KERN_ERR "\n get rgb_led_green_device_node failed ! \n");
              return -1;
          }
          //以下獲取設備節點中綠燈子節點的reg屬性并轉化為虛擬地址
          led_green.MODER = of_iomap(led_green.device_node, 0);
          led_green.OTYPER = of_iomap(led_green.device_node, 1);
          led_green.OSPEEDR = of_iomap(led_green.device_node, 2);
          led_green.PUPDR = of_iomap(led_green.device_node, 3);
          led_green.BSRR = of_iomap(led_green.device_node, 4);
          //以下設置模式寄存器:輸出模式
          tmp = ioread32(led_green.MODER);
          tmp &= ~(0x3 << (2 * 2));
          tmp |= (0x1 << (2 * 2));
          iowrite32(tmp,led_green.MODER);
          //以下設置輸出類型寄存器:推挽模式
          tmp = ioread32(led_green.OTYPER);
          tmp &= ~(0x1 << 2);
          iowrite32(tmp, led_green.OTYPER);
          //以下設置輸出速度寄存器:高速
          tmp = ioread32(led_green.OSPEEDR);
          tmp &= ~(0x3 << (2 * 2));
          tmp |= (0x2 << (2 * 2));
          iowrite32(tmp, led_green.OSPEEDR);
          //以下設置上下拉寄存器:上拉
          tmp = ioread32(led_green.PUPDR);
          tmp &= ~(0x3 << (2 * 2));
          tmp |= (0x1 << (2 * 2));
          iowrite32(tmp,led_green.PUPDR);
          //以下設置置位寄存器:默認輸出高電平
          tmp = ioread32(led_green.BSRR);
          tmp |= (0x1 << 2);
          iowrite32(tmp, led_green.BSRR);
          //獲取rgb_led節點的藍燈子節點
          led_blue.device_node = of_find_node_by_name(rgb_led_device_node,"led_blue");
          if (led_blue.device_node == NULL)
          {
              printk(KERN_ERR "\n get rgb_led_blue_device_node failed ! \n");
              return -1;
          }
          //以下獲取設備節點中藍燈子節點的reg屬性并轉化為虛擬地址
          led_blue.MODER = of_iomap(led_blue.device_node, 0);
          led_blue.OTYPER = of_iomap(led_blue.device_node, 1);
          led_blue.OSPEEDR = of_iomap(led_blue.device_node, 2);
          led_blue.PUPDR = of_iomap(led_blue.device_node, 3);
          led_blue.BSRR = of_iomap(led_blue.device_node, 4);
          //以下設置模式寄存器:輸出模式
          tmp = ioread32(led_blue.MODER);
          tmp &= ~(0x3 << (5 * 2));
          tmp |= (0x1 << (5 * 2));
          iowrite32(tmp,led_blue.MODER);
          //以下設置輸出類型寄存器:推挽模式
          tmp = ioread32(led_blue.OTYPER);
          tmp &= ~(0x1 << 5);
          iowrite32(tmp, led_blue.OTYPER);
          //以下設置輸出速度寄存器:高速
          tmp = ioread32(led_blue.OSPEEDR);
          tmp &= ~(0x3 << (5 * 2));
          tmp |= (0x2 << (5 * 2));
          iowrite32(tmp, led_blue.OSPEEDR);
          //以下設置上下拉寄存器:上拉
          tmp = ioread32(led_blue.PUPDR);
          tmp &= ~(0x3 << (5 * 2));
          tmp |= (0x1 << (5 * 2));
          iowrite32(tmp,led_blue.PUPDR);
          //以下設置置位寄存器:默認輸出高電平
          tmp = ioread32(led_blue.BSRR);
          tmp |= (0x1 << 5);
          iowrite32(tmp, led_blue.BSRR);
          //申請主設備號
          if (alloc_chrdev_region(&devid, 0, 1, "led") < 0)
          {
              printk("fail to alloc devid\n");
              return -EFAULT;
          }
          led_cdev.owner = THIS_MODULE;
          //綁定前面聲明的file_oprations類型的結構體到字符設備
          cdev_init(&led_cdev, &led_dev_fops);
          //填充上面申請到的主設備號到字符設備
          if ( cdev_add(&led_cdev, devid, 1) < 0)
          {
              printk("fail to add cdev\n");
              return -EFAULT;
          }
          //創建一個類
          led_class = class_create(THIS_MODULE, "my_leds");
          //創建一個設備節點
          device_create(led_class, NULL, devid, NULL, "led");
          printk("platform driver probed!\n");
          return 0;
      }
      //remove函數中,刪除設備并釋放設備號
      static int led_pdrv_remove(struct platform_device *pdev)
      {
          //以下實現各個寄存器的解除映射
          iounmap(clkaddr);
          iounmap(led_green.MODER);
          iounmap(led_green.OTYPER);
          iounmap(led_green.OSPEEDR);
          iounmap(led_green.PUPDR);
          iounmap(led_green.BSRR);
          iounmap(led_red.MODER);
          iounmap(led_red.OTYPER);
          iounmap(led_red.OSPEEDR);
          iounmap(led_red.PUPDR);
          iounmap(led_red.BSRR);
          iounmap(led_blue.MODER);
          iounmap(led_blue.OTYPER);
          iounmap(led_blue.OSPEEDR);
          iounmap(led_blue.PUPDR);
          iounmap(led_blue.BSRR);
          unregister_chrdev_region(devid, 1); //釋放主設備號
          cdev_del(&led_cdev);                          //刪除字符設備
          device_destroy(led_class, devid);          //銷毀設備節點
          class_destroy(led_class);                     //銷毀類
          printk("platform driver removed!\n");
          return 0;
      }
      //填充of_device_id結構體,名為rgb_led,用于指明匹配表
      static const struct of_device_id rgb_led[] = {
          {.compatible = "fire,rgb_led"},        //匹配內容
          {/* sentinel */}
      };
      //以下填充一個platform_driver結構體
      struct platform_driver led_platform_driver = {
          .probe = led_pdrv_probe,        //指定probe函數成員
          .remove = led_pdrv_remove,    //指定remove函數成員
          .driver = {
              .name = "rgb-leds-platform",    //指定設備名稱
              .owner = THIS_MODULE,
              .of_match_table = rgb_led,        //指定匹配表名稱
          }
      };
      //以下定義模塊的入口函數
      static int __init led_pdrv_init(void)
      {
          platform_driver_register(&led_platform_driver);//注冊一個platform驅動
          printk("led platform driver initted!\n");
          return 0;
      }
      //以下定義模塊的出口函數
      static void __exit led_pdrv_exit(void)
      {
          platform_driver_unregister(&led_platform_driver); //釋放一個platform驅動
          printk("led platform driver exited!\n");
      }
      module_init(led_pdrv_init);
      module_exit(led_pdrv_exit);
      MODULE_LICENSE("GPL");

      配套的Makefile文件內容如下。

      KERNEL_DIR=/opt/ebf_linux_kernel_mp157_depth1/build_image/build
      ARCH=arm
      CROSS_COMPILE=arm-linux-gnueabihf-
      export ARCH CROSS_COMPILE
      obj-m := led.o
      all:
          $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
      clean:
          $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean

      以下是測試用的應用程序代碼,文件名為app.c。

      #include <stdio.h>
      #include <fcntl.h>
      #include <string.h>
      #include <unistd.h>
      int main(int argc, char *argv[])
      {
         int fd;
         unsigned char val = 0;
         fd = open("/dev/led", O_RDWR);        //打開設備節點
         if( fd < 0 )
            printf("can`t open\n");
         if( argc != 3 )                        //命令參數不對時提示
          {
             printf("Usage :\n");
             printf("%s <all|red|green|blue> <on|off>\n", argv[0]);
             return 0;
          }
         if(strcmp(argv[1], "all") == 0)
          {
            if(strcmp(argv[2], "on") == 0)
               val = 0;                        //值為0時全部點亮
            else
               val = 7;                        //值為7時全部熄滅
          }
         else if(strcmp(argv[1], "red") == 0)
          {
            if(strcmp(argv[2], "on") == 0)
              val = 1;                        //值為1時紅色點亮
            else
              val = 4;                        //值為4時紅色熄滅
          }
         else if(strcmp(argv[1], "green") == 0)
          {
            if(strcmp(argv[2], "on") == 0)
              val = 2;                        //值為2時綠色點亮
            else
              val = 5;                        //值為5時綠色熄滅
          }
         else if(strcmp(argv[1], "blue") == 0)
          {
            if(strcmp(argv[2], "on") == 0)
              val = 3;                        //值為3時藍色點亮
            else
              val = 6;                        //值為6時藍色熄滅
          }
         write(fd, &val, 1);            //把值寫入設備節點
         close(fd);                     //關閉設備節點
         return 0;
      }

      完成后,先執行make命令編譯驅動程序,若成功會生成名為led.ko的驅動模塊文件。然后對應用程序進行交叉編譯,執行“arm-linux-gnueabihf-gcc app.c -o app”即可。實驗結果與“嵌入式Linux中的LED驅動控制”一文中的完全一樣,這里就不給出了。

      --待續--

      posted @ 2024-07-02 23:35  fxzq  閱讀(321)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲理论在线A中文字幕| 久久久午夜精品福利内容| 亚洲国产日韩一区三区| 精品无码成人片一区二区| 一边捏奶头一边高潮视频| 亚洲国产精品一区二区第一页| 亚洲五月天一区二区三区| 四虎成人精品无码| 亚洲ΑV久久久噜噜噜噜噜| 亚洲欧美中文字幕5发布| 日本亚洲欧洲免费无线码| 国产在线乱子伦一区二区| 国产亚洲欧美精品久久久| 国产成人无码午夜视频在线播放| 在线人成免费视频69国产| 国产免费无遮挡吸奶头视频| 亚洲精品中文字幕二区| 中文字幕99国产精品| 777米奇色狠狠888俺也去乱| 男女真人国产牲交a做片野外| 色九月亚洲综合网| 国产精品区一二三四久久| 最新国产精品好看的精品| 肇州县| 国产精品视频中文字幕| 久久无码高潮喷水| 99视频在线精品国自产拍| 美女人妻激情乱人伦| 国产精品福利自产拍在线观看 | 99riav国产精品视频| 国产不卡一区二区精品| 国产亚洲AV电影院之毛片| 日韩在线视频线观看一区| 久久天天躁夜夜躁狠狠85| 热久久美女精品天天吊色| 国产亚洲精品AA片在线播放天| 亚洲av成人无码精品电影在线| 国产午夜一区二区在线观看| 韩国一级毛片中文字幕| 人妻在线无码一区二区三区| 惠来县|