全球热推荐:06_usb_device_id USB驱动简介
一:Linux USB驱动介绍
1:USB驱动简介
(资料图片)
USB采用树形拓扑结构,主机侧和设备侧的USB控制器分别称为主机控制器(Host)和USB设备控制器(UDC),每条总线上只要一个主机控制器,负责协调主机和设备间的通讯,而设备不能主动向主机发送任何信息。
从主机侧观察,在Linux驱动中,处于USB驱动的最底层的时USB主机控制器硬件,在其上运行的时USB主机控制器驱动,在主机控制器上的为USB核心层,再上层为USB设备驱动层(U盘,鼠标,键盘,USB转串口等设备驱动)。因此,在主机侧的层次结构中,要实现的USB驱动包括两类:USB主机控制器驱动和USB设备驱动,前者控制插入其中的USB设备,后者控制USB设备如何与主机通讯。Linux内核中的USB核心负责USB驱动管理和协议处理的主要工作。主机控制器驱动和设备驱动之间的USB核心非常重要,其功能包括:通过定义一些数据结构,宏和功能函数,向上为设备驱动提供编程接口,向下为USB主机控制器驱动提供编程接口;维护整个系统的USB设备信息;完成设备热插拔控制,总线数据传输控制等。
USB设备热插拔的硬件原理:
在USB集线器(hub)的每个下游端口的D+和D-上,分别接了一个15K欧姆的下拉电阻到地。这样,在集线器的端口悬空时,就被这两个下拉电阻拉到了低电平。而在USB设备端,在D+或者D-上接了1.5K欧姆上拉电阻。对于全速和高速设备,上拉电阻是接在D+上;而低速设备则是上拉电阻接在D-上。这样,当设备插入到集线器时,由1.5K的上拉电阻和15K的下拉电阻分压,结果就将差分数据线中的一条拉高了。集线器检测到这个状态后,它就报告给USB主控制器(或者通过它上一层的集线器报告给USB主控制器),这样就检测到设备的插入了。USB高速设备先是被识别为全速设备,然后通过HOST和DEVICE两者之间的确认,再切换到高速模式的。在高速模式下,是电流传输模式,这时将D+上的上拉电阻断开。
USB主机控制器接口:
OHCI(Open Host Controller Interface): 微软主导的低速USB1.0(1.5Mbps)和全速USB1.1(12Mbps),OHCI接口的软件简单,硬件复杂 UHCI(Universal Host Controller Interface): Intel主导的低速USB1.0(1.5Mbps)和全速USB1.1(12Mbps), UHCI接口的软件复杂,硬件简单EHCI(Enhanced Host Controller Interface):高速USB2.0(480Mbps), xHCI(eXtensible Host Controller Interface):USB3.0(5.0Gbps),采用了9针脚设计,同时也支持USB2.0、1.1等
USB的4种传输类型:
(1)控制传输(control):是每一个USB设备必须支持的,通常用来获取设备描述符、设置设备的状态等等。一个USB设备从插入到最后的拔出这个过程一定会产生控制传输(即便这个USB设备不能被这个系统支持)。
(2)中断传输(interrupt):支持中断传输的典型设备有USB鼠标、 USB键盘等等。中断传输不是说我的设备真正发出一个中断,然后主机会来读取数据。它其实是一种轮询的方式来完成数据的通信。USB设备会在设备驱动程序中设置一个参数叫做interval,它是endpoint的一个成员。 interval是间隔时间的意思,表示我这个设备希望主机多长时间来轮询自己,只要这个值确定了之后,我主机就会周期性的来查看有没有数据需要处理
(3)批量传输(bulk):支持批量传输最典型的设备就是U盘,它进行大数量的数据传输,能够保证数据的准确性,但是时间不是固定的。
(4)实时传输(isochronous) :USB摄像头就是实时传输设备的典型代表,它同样进行大数量的数据传输,数据的准确性无法保证,但是对传输延迟非常敏感,也就是说对实时性要求比较高
2:设备、配置、接口、端点
在USB设备的逻辑组织中,包含设备,配置,接口和端点4个层次。每个USB设备都提供不同级别的设备信息,可以包含一个或多个配置,不同的配置使设备表现出不同的功能组合,配置由多个接口组成,在USB协议中,接口由多个端点组成,代表一个基本的功能,是USB设备驱动程序控制的对象,一个功能复杂的USB设备可以具有多个接口。每个配置中可以有多个接口,而设备接口是端点的汇集。
端点是USB通信的最基本形式,每一个USB设备接口在主机看来就是一个端点的集合。主机只能通过端点与设备进行通信,以使用设备的功能。在USB系统中每一个的端点都有唯一的地址,这是由设备地址和端点号给出的。每个端点都有一定的属性,其中包括传输方式,总线访问频率,带宽,端点号和数据包的最大容量等。一个USB端点只能在一个方向上承载数据,从主机到设备(输出端点)或者从设备到主机(输入端点),因此端点可以看作是一个单向的管道。端点0通常为控制端点,用于设备初始化参数能。只要设备连接到USB上并且上电,端点0就可以被访问。端点1,2等一般作用数据端点,存放主机与设备间往来的数据。
设备通常有一个或多个配置;配置通常有一个或多个接口;接口通常有一个或多个设置;接口有零个或多个端点。二:USB设备框架分析
1:usb_hub初始化时创建hub线程并进入等待队列khubd_wait等待唤醒
int usb_hub_init(void){ ... ...khubd_task = kthread_run(hub_thread, NULL, "khubd");if (!IS_ERR(khubd_task))return 0; ... ...}static int hub_thread(void *__unused){ ... ... hub_events();wait_event_interruptible(khubd_wait, //进入等待唤醒队列!list_empty(&hub_event_list) ||kthread_should_stop()); ... ...}
2:插入USB设备后,D+或者D-会被拉高,USB主机控制器会产生一个hub_irq中断并唤醒等待队列khubd_wait
static void hub_irq(struct urb *urb){ ... .../* Something happened, let khubd figure it out */kick_khubd(hub); ... ...}static void kick_khubd(struct usb_hub *hub){ ... ...wake_up(&khubd_wait); ... ...}
3:hub线程中的hub事件分析
static void hub_events(void){ ... ... if (connect_change) hub_port_connect_change(hub, i,portstatus, portchange); ... ...}
4:hub_port_connect_change分析
static void hub_port_connect_change(struct usb_hub *hub, int port1,u16 portstatus, u16 portchange){ ... ... udev = usb_alloc_dev(hdev, hdev->bus, port1); //(1)注册一个usb_device,然后会放在usb总线上 choose_address(udev); //(2)给新的设备分配一个地址编号 status = hub_port_init(hub, udev, port1, i); //(3)初始化端口,与USB设备建立连接 status = usb_new_device(udev); //(4)创建USB设备,与USB设备驱动连接 ... ...}
usb_alloc_dev:分配usb_device并设置
struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1){ struct usb_device *dev; //分配usb_device dev = kzalloc(sizeof(*dev), GFP_KERNEL); ... ... device_initialize(&dev->dev); //初始化 dev->dev.bus = &usb_bus_type; //设置bus成员 dev->dev.type = &usb_device_type; //设置device成员 ... ... return dev; //返回usb_device}struct bus_type usb_bus_type = { // bus总线,跟platform平台总线相似.name ="usb",.match =usb_device_match,.uevent =usb_uevent,.suspend =usb_suspend,.resume =usb_resume,};struct device_type usb_device_type = {.name ="usb_device",.release =usb_release_dev,};
choose_address:选择地址,在devnum_next和128之间寻找一个空设备编号
static void choose_address(struct usb_device *udev){intdevnum;struct usb_bus*bus = udev->bus;/* If khubd ever becomes multithreaded, this will need a lock *//* Try to allocate the next devnum beginning at bus->devnum_next. */devnum = find_next_zero_bit(bus->devmap.devicemap, 128,bus->devnum_next);if (devnum >= 128)devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);if (devnum < 128) {set_bit(devnum, bus->devmap.devicemap);udev->devnum = devnum;}}
hub_port_init:设置地址,获取设备描述符
static inthub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,int retry_counter){ ... ... for (j = 0; j < SET_ADDRESS_TRIES; ++j) { retval = hub_set_address(udev); if (retval >= 0) break; msleep(200); } ... ... retval = usb_get_device_descriptor(udev, 8); ... ... retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);}
usb_new_device:获取usb设备配置,将新创建的设备添加进dev链表中,寻求与之匹配的驱动
int usb_new_device(struct usb_device *udev){ err = usb_get_configuration(udev); ... ... err = device_add(&udev->dev);}
三:USB驱动框架分析
LInux系统实现了几类通用的USB设备驱动,可划分为以下几种:
音频设备类通信设备类HID(人机接口)设备类显示设备类海量存储设备类电源设备类打印设备类集线器设备类usb总线跟platform总线,i2c等总线类似,在Linux内核中,使用usb_driver结构体描述一个usb设备驱动,其结构体定义如下:
struct usb_driver {const char *name;int (*probe) (struct usb_interface *intf, const struct usb_device_id *id);void (*disconnect) (struct usb_interface *intf);int (*ioctl) (struct usb_interface *intf, unsigned int code,void *buf);int (*suspend) (struct usb_interface *intf, pm_message_t message);int (*resume) (struct usb_interface *intf);void (*pre_reset) (struct usb_interface *intf);void (*post_reset) (struct usb_interface *intf);const struct usb_device_id *id_table;struct usb_dynids dynids;struct usbdrv_wrap drvwrap;unsigned int no_dynamic_id:1;unsigned int supports_autosuspend:1;};
在编写新的USB设备驱动时,主要完成的是probe()和disconnect()函数,即探测和断开函数,它们分别在设备被插入和拔出的时候调用,用于初始化和释放软硬件资源。usb_driver的注册和注销函数如下:
int usb_register(struct usb_driver *driver);void usb_deregister(struct usb_driver *driver);
usb_driver结构体中的id_table成员描述了这个USB驱动所支持的USB设备列表,它指向一个usb_device_id数组,usb_device_id结构体包含有USB设备的制造商ID,产品ID,产品版本,设备类,接口类等信息及其要匹配标志成员match_flags。可以借助下面一组宏生成usb_device_id结构体的实例:
(1) 该宏根据制造商ID和产品ID生成一个usb_device_id结构体的实例,在数组中增加该元素将意味着该驱动可支持与制造商ID,产品ID匹配的设备。
#define USB_DEVICE(vend,prod) \.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \.idProduct = (prod)
(2)该宏根据制造商ID,产品ID,产品版本的最小值和最大值生成一个usb_device_id结构体的实例,在数组中增加该元素将意味着该驱动可支持与制造商ID,产品ID匹配和lo~hi范围内版本的设备。
#define USB_DEVICE_VER(vend,prod,lo,hi) \.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, \.idVendor = (vend), .idProduct = (prod), \.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
(3) 该宏用于创建一个匹配设备指定类型的usb_device_id结构体的实例。
#define USB_DEVICE_INFO(cl,sc,pr) \.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \.bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
(4) 该宏用于创建一个匹配接口指定类型的usb_device_id结构体的实例。
#define USB_INTERFACE_INFO(cl,sc,pr) \.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
例如:linux内核自带usb鼠标驱动支持的usb_device_id结构体
static struct usb_device_id usb_mouse_id_table [] = {{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,USB_INTERFACE_PROTOCOL_MOUSE) },{ }/* Terminating entry */};MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
当USB核心检测到某个设备的属性和某个驱动程序的usb_device_id结构体所携带的信息一致时,这个驱动程序的probe()函数就会被执行,拔掉设备或者卸载驱动模块后,USB核心就会执行disconnect()函数来响应这个动作。
上述usb_driver结构体中的函数是USB设备驱动中与USB相关的部分,而USB只是一个总线,USB设备驱动真正的主体工作仍然是USB设备本身所属类型的驱动,如字符设备,tty设备,块设备,输入设备等。因此USB设备驱动包含其作为总线上挂载设备的驱动和本身所属设备类型的驱动两部分。
与platform_driver,i2c_driver类似,usb_driver起到了“牵线”的作用,即在probe()里注册相应的字符,tty等设备,在disconnect()注销相应的设备,而原先对设备的注册和注销一般直接发生在模块加载和卸载函数中。
四:USB请求块介绍
USB请求块(URB)是USB设备驱动中用来描述与USB设备通信所用的基本载体和核心数据结构,USB设备中的每个端点都处理一个URB队列,在队列被清空之前,一个URB的典型生命周期如下:
1:被一个USB设备驱动创建,释放
struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags);void usb_free_urb(struct urb *urb);
iso_packets是这个URB应当包含的等时数据包的数目,若为0表示不创建等时数据包。mem_flags参数是分配内存的标志,和kmalloc()函数的分配标志参数含义相同。如果分配成功,该函数返回一个URB结构体指针,否则返回0.
2:初始化,被安排给一个特定USB设备的特定端点。对于中断URB,使用如下函数来初始化URB
static inline void usb_fill_int_urb (struct urb *urb, struct usb_device *dev, unsigned int pipe, void *transfer_buffer, int buffer_length, usb_complete_t complete_fn, void *context, int interval);
(1)URB参数指向要被初始化的URB指针;
static struct urb *urb;
(2)dev指向这个URB要被发送到的USB设备;
struct usb_device *dev = interface_to_usbdev(intf);
(3)pipe是这个URB要被发送到的USB设备的特定端点;
int pipe;pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
(4)transfer_buffer是指向发送数据或接收数据的缓冲区的指针,和URB一样,它也不能是静态缓冲器,必须使用kmalloc()来分配;
static char *transfer_buffer;transfer_buffer= usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
(5)buffer_length是transfer_buffer指针所指向缓冲区的大小;
static int len;struct usb_host_interface *interface;struct usb_endpoint_descriptor *endpoint;interface = intf->cur_altsetting;endpoint = &interface->endpoint[0].desc;buffer_length = endpoint->wMaxPacketSize;
(6)complete_fn指针指向当这个URB完成时被调用的完成处理函数;
(7)context是完成处理函数的“上下文”;
(8)interval是这个URB应当被调度的间隔。
endpoint->bInterval
3:提交URB给USB核心
int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
提交URB到USB核心后,直到完成函数被调用之前,不要访问URB中的任何成员,usb_submit_urb()在原子上下文和进程上下文中都可以被调用,mem_flags变量需根据调用环境进行相应的设置:
GFP_ATOMIC:在中断处理函数,底半部,tasklet,定时器处理函数以及URB完成函数中,在调用者持有自旋锁或者读写锁时以及当驱动将current->state修改为非TASK_RUNNING时,应使用此标志。GFP_NOIO:在存储设备块I/O和错误处理路径中,应使用此标志。GFP_KERNEL:如果没有任何理由使用GFP_ATOMIC和GFP_NOIO,就使用此标志。如果usb_submit_urb()调用成功,即URB的控制权被移交给USB核心,该函数返回0;否则,返回错误号。
五:示例代码
#include <linux/kernel.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/init.h>#include <linux/usb/input.h>#include <linux/hid.h>static struct input_dev *usb_kbd_dev; //input_devstatic unsigned char *usb_kbd_buf; //虚拟地址缓存区static dma_addr_t usb_kbd_phyc; //DMA缓存区;static int usb_kbd_len; //数据包长度static struct urb *usb_kbd_urb; //urbstatic const unsigned char usb_kbd_keycode[252] = { 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 150,158,159,128,136,177,178,176,142,152,173,140}; //键盘码表共有252个数据 static void myusb_kbd_irq(struct urb *urb) //键盘中断函数{ static unsigned char buf1[8]={0,0,0,0,0,0,0,0}; int i; /*上传左右crtl、shift、atl、windows按键*/ for (i = 0; i < 8; i++) { if(((usb_kbd_buf[0]>>i)&1)!=((buf1[0]>>i)&1)) { input_report_key(usb_kbd_dev, usb_kbd_keycode[i + 224], (usb_kbd_buf[0]>> i) & 1); input_sync(usb_kbd_dev); //上传同步事件 } } /*上传普通按键*/ for(i=2;i<8;i++) { if(usb_kbd_buf[i]!=buf1[i]) { if(usb_kbd_buf[i] ) //按下事件 { input_report_key(usb_kbd_dev,usb_kbd_keycode[usb_kbd_buf[i]], 1); input_sync(usb_kbd_dev); //上传同步事件 } else if(buf1[i]) //松开事件 { input_report_key(usb_kbd_dev,usb_kbd_keycode[buf1[i]], 0); input_sync(usb_kbd_dev); //上传同步事件 } } } memcpy(buf1, usb_kbd_buf, 8); //更新数据 usb_submit_urb(usb_kbd_urb, GFP_KERNEL);}static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id){ volatile unsigned char i; struct usb_device *dev = interface_to_usbdev(intf); struct usb_endpoint_descriptor *endpoint; struct usb_host_interface *interface; int pipe; interface=intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; /* a. 分配一个input_dev */ usb_kbd_dev=input_allocate_device();/* b. 设置 *//* b.1 能产生哪类事件 */set_bit(EV_KEY, usb_kbd_dev->evbit); set_bit(EV_REP, usb_kbd_dev->evbit); /* b.2 能产生哪些事件 */ for (i = 0; i < 252; i++) set_bit(usb_kbd_keycode[i], usb_kbd_dev->keybit); //添加所有键 clear_bit(0, usb_kbd_dev->keybit);/* c. 注册 */ input_register_device(usb_kbd_dev);/* d. 硬件相关操作 *//* 数据传输3要素: 源,目的,长度 *//* 源: USB设备的某个端点 */ pipe=usb_rcvintpipe(dev,endpoint->bEndpointAddress); /* 长度: */ usb_kbd_len=endpoint->wMaxPacketSize; /* 目的: */ usb_kbd_buf=usb_buffer_alloc(dev,usb_kbd_len,GFP_ATOMIC,&usb_kbd_phyc);/* 使用"3要素" *//* 分配usb request block */usb_kbd_urb=usb_alloc_urb(0,GFP_KERNEL);/* 使用"3要素设置urb" */ usb_fill_int_urb (usb_kbd_urb, dev, pipe, usb_kbd_buf, usb_kbd_len, myusb_kbd_irq, 0, endpoint->bInterval); usb_kbd_urb->transfer_dma = usb_kbd_phyc; //设置DMA地址 usb_kbd_urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; //设置使用DMA地址/* 使用URB */ usb_submit_urb(usb_kbd_urb, GFP_KERNEL); return 0;}static void usb_kbd_disconnect(struct usb_interface *intf){ struct usb_device *dev = interface_to_usbdev(intf); usb_kill_urb(usb_kbd_urb); usb_free_urb(usb_kbd_urb); usb_buffer_free(dev, usb_kbd_len, usb_kbd_buf,usb_kbd_phyc); input_unregister_device(usb_kbd_dev); //注销内核中的input_dev input_free_device(usb_kbd_dev); //释放input_dev}static struct usb_device_id usb_kbd_id_table [] = {{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,USB_INTERFACE_PROTOCOL_KEYBOARD) },{ }/* Terminating entry */};static struct usb_driver usb_kbd_drv = { .name = "usbkbd_drv", .probe = usb_kbd_probe, .disconnect = usb_kbd_disconnect, .id_table = usb_kbd_id_table,};/*入口函数*/static int usb_kbd_init(void){ usb_register(&usb_kbd_drv); return 0;} /*出口函数*/static void usb_kbd_exit(void){ usb_deregister(&usb_kbd_drv);}module_init(usb_kbd_init);module_exit(usb_kbd_exit);MODULE_LICENSE("GPL");
测试方法:
(1)配置内核,取消自带的usb键盘驱动,使用新内核启动
-> Device Drivers -> HID Devices
<> USB Human Interface Device (full HID) support
(2)加载新驱动,插入usb键盘
(3)exec 0</dev/tty1 进入测试模式
exec 0<&- 退出测试模式
相关阅读
-
当前热议!怎样更换计算机主板电池,笔记本电脑主板电池怎么更换?教你更换主板电池的方法...
花火网消息,笔记本主板电池是非常重要的笔记本零部件之一,那么,我们在生活中如何更换笔记本主板电池...
2022-09-29 -
今亮点!MonkeyTest——简单无脑的移动端自动化测试(初级篇)_monkeytest
MonkeyTest-操作步骤:1 下载AndroidsdkX64位,必须和你的电脑操作系统一致。2 安装完成后,增加adb的...
2022-09-29 -
环球新资讯:linux封装函数,libc库和封装函数 | 求索阁
Linux系统调用这部分经常出现两个词:libc库和封装函数,不知道你是否清楚它们的含义?libc1)libc概念li...
2022-09-29 -
诺基亚发布2022年Q3财报 第三季度营业利润6.58 亿欧元
DoNews10月20日消息(丁编程凡)今日,诺基亚公布了2022年Q3季度运营利润,低于市场预期。数据显示,该...
2022-10-20 -
电竞党双·11剁手指南:拯救者Y9000P超强配置 3A大作的游戏本标杆-环球微头条
10月20日晚8点,一年一度的双11购物节正式拉开帷幕。伴随着消费升级趋势来临,人们生活水平不断提高,大...
2022-10-20 -
调查:67%的欧洲科技界女性认为与男性相比报酬过低 一半的人遭遇过性别歧视
据TechCrunch报道,上个月,在国际同工同酬日,国际劳工组织(ILO)组织透露,全球女性的平均工资比男性...
2022-10-20 -
iPhone7 Plus多少钱?iPhone7 Plus价格
iPhone7Plus起价6388元。有银色、金色、玫瑰金、黑色和钢琴黑。iPhone7Plus搭载新一代A10Fusion芯片,采...
2022-10-20 -
webcheck.dll是什么
DLL文件:webcheck或者webcheck dll。DLL名称:WebSiteMonitor。webcheck dll是用于对网站进行监视的C...
2022-10-20 -
马斯克发推特宣布BurntHair香水已售罄 二手转售价更加夸张
10 月 12 日马斯克的隧道初创公司 Boring Company 推出新品 Burnt Hair(烧焦的头发)限量版香水...
2022-10-20 -
iTouch5和iTouch4有什么区别 iTouch5和iTouch4区别
iTouch4和iTouch5iTouch4iTouch5 上一次iTouch4更新还是在2010年的时候时隔两年。iTouch系列总算赢来又...
2022-10-20 -
网友猜测自购国行版苹果14ProMax为印度组装 官方技术顾问回应
有网友在网上晒出自己买到的国行 iPhone 14 Pro Max 是在印度组装的。据该网友透露,其上周在苹果...
2022-10-20 -
十铨首创双冷头强效散热新品亮相 设计焕新不惧大功率SSD
十铨宣布推出 T-FORCE SIREN DUO360 ARGB CPU & SSD 一体式水冷散热器,业界首创双冷头强效散热...
2022-10-20 -
USB80Gbps解决方案特点一览:Type-C可非对称配置 速度更快
USB-IF 宣布发布 USB4 版本 2 0 规范,可实现 80Gbps 传输性能,与此相关的 USB Type-C 和 USB Power Delivery (USB PD)
2022-10-20 -
微软悄然公布WSA路线图:即将引入Android 13系统支持
微软近日对Windows11端的WindowsSubsystemforAndroid(WSA)子系统带来了一些更新。根据微软在Github上...
2022-10-20 -
漫威免费卡牌游戏已可在Steam开玩 游戏节奏快且万分精彩
漫威卡牌游戏《MARVEL SNAP》现已上线 Steam,免费开玩。据官方介绍,漫威 SNAP 是一款超快节奏的策...
2022-10-20 -
皓丽2022线上发布会:5大新品亮相,多位行业大咖与合作伙伴助阵!
10月20日,皓丽举行了2022年度新品发布会,30多家平台同步线上直播,超百万人次在线观看。发布会上,皓...
2022-10-20 -
iPhone14系列进行专业跌落测试 结果表明Plus比ProMax更坚固
一家设备保险公司对苹果 iPhone 14 Plus 和 iPhone 14 Pro Max 进行的跌落测试清楚地表明,哪...
2022-10-20 -
KTC公开M27T20S显示器新品 配置较原版减去RGB灯与支架
KTC 今日公布新款 M27T20S 显示器,在原版 2K165Hz MiniLED 规格的 M27T20 的基础上砍掉了 RGB 灯、升降支架,90W USB-C 变为
2022-10-20 -
加量不加价!苹果将未发货iPad Pro免费升级到M2款-天天快讯
在新款发布前购买2021款iPadPro且尚未发货的网友表示,苹果已经提醒用户2021款iPadPro已经自动升级为新款iPadPro。
2022-10-20 -
ROG正式SwiftPG27AQN显示器详细规格 上市计划有望即日实现
在今年 CES 上,ROG 发布了新款 Swift PG27AQN 显示器,达到了 2K 360Hz 的超高规格。现在,这...
2022-10-20 -
《蝙蝠侠》新游被指要求过高:1080p推荐RTX 2070显卡及8核i7
动作游戏《蝙蝠侠》最新作《哥谭骑士》即将在10月21日发售,主机版因为锁30帧的事被玩家吐槽,PC版玩家...
2022-10-20 -
三星G8显示器今晚开售:2K+175Hz高刷 首发9999元-世界滚动
此前在海外发布的三星OdysseyOLEDG8带鱼屏显示器现已上架京东,今晚8点正式开启预售,原价13999元,预售...
2022-10-20 -
macOS13Ventura正式版即将上线 官方宣传称其将更加高效
苹果官网更新信息显示,macOS 13 Ventura 正式版将于 10 月 25 日推出,与 iPadOS 16 正式版...
2022-10-20
精彩推荐
阅读排行
相关词
- yelp
- startup
- bml050
- fleksy
- 福步斯
- msm8974ab
- arj 21
- mwc2014
- modobag
- 周枫
- 布加迪发布Carbone智能手表:限量2500只 售价超1.8万-当前资讯
- 淘宝购物车扩容至300 新增分组、优惠筛选等功能
- 番茄小说免费版真的可以赚钱吗
- 怎么取消XP系统的开机密码 windows无法删除密码
- 王者荣耀升级防沉迷措施:限制未成年游戏时间、氪金上限
- 李国庆成立感觉良好公司 经营范围含互联网直播服务
- 光影魔术手多图边框的快捷键是什么
- vivo X9s什么时候上市_vivo X9s上市时间
- 几款索尼投影仪价格介绍
- 空气开关规格型号大全 方便您的居家选择
- 马斯克卖香水、小鹏卖麻将,大厂“不务正业”有多疯狂-今日要闻
- 美的加湿器怎么用 美的加湿器使用方法
- 如何使用3G无线上网卡来上网 笔记本3G无线上网卡上网指南
- 可视对讲机的工作原理是什么 可视对讲机原理
- oem和odm是什么意思 oem与odm区别是什么
- 索尼vr眼镜怎么样 索尼vr眼镜报价和评测
- 比亚迪新专利曝光 可用方向盘操控车载游戏
- APP是什么意思_APP是什么
- 任务栏输入法图标不见了怎么办
- win7怎么装回xp系统 win7系统改装xp的方法-快播
- 荣耀申请灵动胶囊/精灵商标:领先苹果iPhone 14 Pro四年
- 怎么查宽带上网时间 具体方法如下
- 甲骨文公司官宣:将在OCI中部署上万个英伟达顶级计算GPU
- dnf深渊怎么开 关于dnf深渊怎么开的问题
- 华硕主板前面板耳机没有声音的解决方法-环球今热点
- KOOBEE A106怎么样
- Meta最强交易官离开公司 曾帮助脸书收购Ins
- WindowsTerminal现已成为微软最新系统默认体验终端工具
- win8运行在哪里 如何打开win8系统的运行命令-全球快消息
- 网页视频看不了怎么办_网页视频看不了的解决方法-每日报道
- win7玩cf老是与主机连接不稳定的解决方法-报资讯
- 无线AP是什么 无线AP怎么用
- 康福中国 Camfrog 6.0 中文版安装教程(英文版转中文版设置方法)
- LED背光板原理是什么 LED背光板原理详细介绍
- windows双系统怎么设置启动顺序 win双系统默认开机启动项设置方法-环球即时
- 安装电地暖价格是多少 安装电地暖价格预算
- 广汽透露将在明年投产自主品牌PHEV产品 并分析相关车型布局
- win7系统安装英雄联盟补丁包的两种方法-热消息
- qq腾讯网迷你版怎么设置不弹岀来
- 联想win8重装系统步骤 联想win8系统重装教程-世界速看
- 世纪之星机箱怎么样 世纪之星机箱介绍
- ibackupbot怎么用 ibackupbot使用教程(附ibackupbot中文版下载地址)
- 原版dell oem xp pro sp3光盘镜像下载地址-环球资讯
- win10系统电脑没有手机驱动的解决方法-时快讯
- 163邮箱登录入口 手机端163邮箱登录入口
- 蔚来总裁秦力洪回复网友建议 并称将考虑开卖欧版汽车一事
- QQ空间日志图片如何加水印
- 了解什么是电源控制器 电源控制器功能
- IPhone13pro电池容量多大-IPhone13Pro电池参数续航介绍
- 哪种植物会寄生在梭梭根部?蚂蚁庄园今日答案11.23
- 华为nova5pro和nova5i的区别
- 如何在手机QQ中下载表情包 具体操作方法
- 怎么自动识别查询快递单号查询-自动识别查询快递单号查询方法
- 电脑打电话给手机步骤详解
- win7系统下怎么调cf烟雾头-环球热议
- 电视直播软件哪个好 网络电视直播软件排行2014详情介绍
- MSN帐号格式以及MSN用户名格式的详细介绍
- 电脑进入桌面后黑屏如何修复_电脑经常进入桌面之后黑屏的处理方法-全球新动态
- xbox360手柄模拟器怎么样 xbox360手柄模拟器介绍
- ie浏览器打不开_ie浏览器打不开网页_IE浏览器打不开网页的解决方法
- 把rmvb格式转换成dvd的详细图文教程
- 数码闲聊站曝光OPPO新折叠屏手机:电池容量有望超过ZFlip4
- Win7锁定计算机快捷键是什么 Win7使用锁定计算机快捷键的方法-全球动态
- xr是什么意思-xr改的意思介绍
- 如何让win7自动拨号上网|让win7自动拨号上网的教程-全球速看
- 电脑性能怎么检测 电脑性能检测的方法
- Win7系统打开IE浏览器后页面自动关闭的四种解决方法-重点聚焦
- Win10系统如何打开内涵图种子-世界微速讯
- 鸿海董事长刘扬伟:新款电车零配件将优先采用MIH联盟成员产品
- ie浏览器网页字体怎么变大|如何将网页字体变大-全球速讯
- windows xp3 原版下载_windows xp3 原版下载地址-环球热资讯
- 怎么用硬盘装xp系统 硬盘安装xp系统步骤图解-全球聚焦
- 如何禁用和开启电脑光驱 电脑禁用和开启光驱的方法-世界新要闻
- 分析师称苹果将在后年发布OLED版iPadPro 屏幕亮度获提升
- deepmoss 2022 Autumn Winter 甲板之上
- “抱冷门”赢世界杯定制礼品!容声WILL健康冰箱羊毛“鲜”薅为敬
- “狲思邈”离世,中国“最穷”动物园出圈
- 1.8万就能拥有布加迪!全球第一款全碳纤维智能手表发布-微资讯
- 精悍小巧,功能不少! 华硕电竞路由新品RT-AX57来了
- P站宣布将区分AI画图和真人作品 提供单独的排行榜-环球速读
- 迷宫探险动作游戏《迷宫传说》繁体中文版今天正式上市!-当前快播
- “极境之域”加载中,请准备进入
- 荣耀畅玩40 Plus新机发布:首发1199元 6000mAh大电池
- PS4版《女神异闻录5:皇家版》价格永久下调100元 10月31日生效-世界球精选
- 值得买科技获2022年度第一批“北京市企业技术中心”认定
- 有了这个智能枕头 睡觉再也不打鼾了!-环球精选
- 淘宝购物车扩容至300 新增分组、优惠筛选等功能
- 摸鱼5分钟:去鹤岗全款买房幸福感飙升 90后父母给儿子取名叫“张总”-播报
- 秋冬大衣千万别在款式上作妖了!
- 联想专业电竞鼠标来了:拯救者M7将于10月底发布-环球时讯
- 最酷的姐姐就是穿着球鞋把婚结了
- 腾讯阿里抢在双11前一连三通
- 京东PLUS会员年卡76元-全球滚动
- 今晚八点正式开启预售 京东11·11促销时间表曝光
- 【手慢无】摆着都美 华硕创意游戏电脑主机只需6199元-新视野
- iPhone 14 Plus减产规模在70%-90% 刷新苹果历史
- 《寂静岭2重制版》PS5版无加载画面 支持触觉反馈等-快资讯
- 联想小新Air14 2023公开部分规格:新笔电将搭载下沉式键盘
- 骁龙处理器排名天梯图最新 骁龙处理器排行榜2022-每日聚焦
- 北京冬奥上火爆全球:谷爱凌获最佳女运动员表现奖
- 缺锂怎么办?马斯克式解决方案:特斯拉自己干
- HKC新MiniLED显示器上架:2K 240Hz 首发价2999元-全球报道
- 科乐美推出《寂静岭》周边:护士姐姐依旧吸睛-全球头条
- 超越人类的交互感受,深度体验小鹏G9智能语音-全球播报
- 朗科新推绝影NV5000-t固态硬盘 温控技术更高 售价暂未公布
- 4999元起,机械革命极光Z游戏本发布,最高可选i7-12700H-观察
- 【手慢无】无蓝光液晶屏 小米液晶小黑板仅售89元-当前动态
- Redmi X Pro 正式发布-天天快报
- ios16.1正式版推送时间计划 ios16.1正式版什么时候更新-热头条
- 【手慢无】锐龙R7-5800H处理器+2.8K OLED屏 华硕无畏14电脑入手仅需3999元-天天快播
- 微信朋友圈提到了我是什么意思 提醒谁看别人能看到吗-当前视点
- 【手慢无】小巧精悍的惠普迷你主机秒杀价2997元-世界速看料
- DXO披露Xperia10IV影像测试分数 并称其具备户外拍摄细节
- 【手慢无】联想ThinkPad neo 14英寸高性能标压笔记本,活动直降1000元-每日看点
- 特斯拉真正自动驾驶要来了?马斯克将在2023年申请监管批准
- Nreal携手LGD推出开「大」联名礼盒 LGD夺冠0元到手
- 【手慢无】护眼学习平板联想小新Pad只要899元。-天天新动态
- 联想概念新品亮相LenovoTechWorld 并提出CyberSpaces方案
- 【手慢无】小尺寸游戏平板,联想拯救者y700活动优惠价只要2269元-环球热消息
- 双·11大促即将开启 三款主流价位段3060游戏本闭眼入-天天热资讯
- 双十一前淘宝购物车扩容至300:新增分组、排序等功能
- 开发商343i为肢体残缺儿童提供《光环》主题义肢
- 微软专利揭示能调节表面粗糙度的先进显示屏
- 报道称三星正研发新款智能戒指 相关专利早已在去年提出申请
- 摩托罗拉最新演示卷轴屏概念手机 为纵向扩展还有配套动态壁纸
- 科学家在3D打印食品中直接加入二维码 且完全不影响其口感
- 云南小熊猫翘班跑进学生宿舍 动物园:将会调查其具体溜出途径
- NASA公布天体景象创生之柱新图像 其旧照曾被评为哈勃十佳之一
- 中国天眼发现迄今最大原子气体结构:或将向宇宙演化提出挑战
- 研究发现黑洞饭后会“打嗝”:吞噬小恒星多年后却又将其喷出
- 女生求职碰壁遇HR帮改简历:学会换位思考或许就能锦上添花
- 大妈跳舞过于陶醉把自己转到湖里 掉河后众人合力将大妈拉上岸
- 次世代模拟人生游戏及其开发代号正式公开 新品将可跨平台游玩
- 苹果官网最新上架编织充电线产品 接口未包含Lightning版本
- Solidigm新发布PCIe4.0SSD 最高容量为2TB 为NAND技术制造
- iPad专用妙控键盘双面夹来了 具备全尺寸按键 还有更宽触控板
- 2015款AppleTV HD将被官方停售 其操作系统为iOS完全适配
- 安卓平板所用Chrome正发布一系列更新 标签页变化更加多样
- 贝尔金最新百元iPhone支架开售:专为连续互通相机使用而设计
- 一加AcePro原神限定版发布会确定将在下周一上线 宣传语放出
- 2022款iPadPro将可使用视频编辑软件达芬奇 使用软件更专业
- 模拟人生4正式成为免费游戏 并可在PS4/XboxOne等平台开玩
- 郭明錤预测称:苹果AppleTV下代新品或将进一步下调起售价
- 苹果全新推出AppleTV 4K产品:流式传输可以千兆以太网进行
- 赛博朋克2077衍生动画制片人:现在还未有制作续集的计划
- 三星990PRO PCIe4.0SSD有望即日上市 随机读写已提高五成
- 光电编码器的工作原理介绍 光电编码器的优缺点都有什么?
- 光电编码器测速方法有哪些?光电编码器和磁电编码器的区别都有什么?
- 苹果发布iPad10后再火速上架新配件 可转换至原有Pencil接口
- 光电编码器如何判断方向?光电编码器的工作原理是什么?