title: usb输入子系统写程序

tags: linux

date: 2018/12/18/ 18:46:04

toc: true

usb输入子系统写程序

目标:usb鼠标模拟一个键盘,左键L,右键S,中键enter

参考: drivers/hid/usbhid/usbmouse.c这是自带的USB鼠标驱动

入口函数

static int __init usb_mouse_init(void)
{
int retval = usb_register(&usb_mouse_driver);
if (retval == 0)
info(DRIVER_VERSION ":" DRIVER_DESC);
return retval;
} static struct usb_driver usb_mouse_driver = {
.name = "usbmouse",
.probe = usb_mouse_probe,
.disconnect = usb_mouse_disconnect,
.id_table = usb_mouse_id_table,
};

小结

  1. 构造匹配的id_table以供usb总线驱动的match匹配,然后执行驱动的probe

    struct usb_device_id xxx[]={}
  2. 构造probe来达到初始化相关操作

  3. usb传输数据使用urb = usb request block 也就是usb 请求块来传输,数据传输三要素源+长度+目的

    • 源=Usb设备的端点,也就是包含了usb设备地址+端点地址+端点类型

      struct usb_host_interface *interface;
      interface = intf->cur_altsetting;
      //获得端点地址
      endpoint = &interface->endpoint[0].desc;
      //usb_rcvintpipe 构造了设备地址+端点地址
      pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
      //PIPE_INTERRUPT 表示端点的类型
      #define usb_rcvintpipe(dev,endpoint) \
      ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
      //__create_pipe 包含了设备地址和端点的地址
      static inline unsigned int __create_pipe(struct usb_device *dev,
      unsigned int endpoint)
      {
      return (dev->devnum << 8) | (endpoint << 15);
      }
    • 长度从usb的端点描述符中获取

      len = endpoint->wMaxPacketSize;
    • 目的缓存需要是一块连续的物理地址,需要分配

      static char *usb_buf;			//目的buf虚拟地址
      static dma_addr_t usb_buf_phys; //目的buf实际获得的地址
      usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys);
  4. 设置这个URB,首先分配一块空间,然后填充相关数据

    static struct urb *uk_urb;
    uk_urb = usb_alloc_urb(0, GFP_KERNEL);
    // urb 分配得到的urb
    // pipe usb设备端点
    // transfer_buffer 传输的目的地址,虚拟地址
    // buffer_length 传输的长度
    // complete_fn 收到传输数据的回调函数
    // context 可以为null
    // interval 轮询间隔,在端点描述符中查询
    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)
    // 需要设置物理地址和标志
    uk_urb->transfer_dma = usb_buf_phys;
    uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
  5. 启动这个urb,也就是说每次传输前都要先操作一遍,每次数据获取后也需要重新启动

    usb_submit_urb(uk_urb, GFP_KERNEL);
  6. 如何获取数据上报? 在urb的完成回调函数中实现,usb_bufurb中的虚拟地址,获取数据后需要重新启动urb

    static void usbxxx_irq(struct urb *urb)
    {
    for (i = 0; i < len; i++)
    {
    printk("%02x ", usb_buf[i]);
    }
    usb_submit_urb(uk_urb, GFP_KERNEL);
    }
  7. 如何上报到按键?这里用到以前的输入子系统,也就是在probe注册input_dev,然后在urb中的回调函数中获取到函数后上报

    input_dev = input_allocate_device();
    /* b. 设置 */
    /* b.1 能产生哪类事件 */
    input_dev->evbit[0]=0;
    set_bit(EV_KEY, input_dev->evbit);
    set_bit(EV_REP, input_dev->evbit);
    /* b.2 能产生哪些事件 */
    set_bit(KEY_L, input_dev->keybit);
    set_bit(KEY_S, input_dev->keybit);
    set_bit(KEY_ENTER, input_dev->keybit);
    /* c. 注册 */
    input_register_device(input_dev);

内核修改

去除内核原有的模块Device Drivers > HID Devices > USB Human Interface Device (full HID) support

怎么写代码

usb总线设备也是一种总线设备驱动,总体上可以分为两个部分,左边部分是usb总线程序做好了,我们需要编写右边的usb_driver部分,也就是分配设置注册usb_driver

类型匹配

首先是usb子系统会调用match来匹配id_table中的类型后会调用probe。所以先来确定这个类型匹配,也就是设备描述符的匹配。例子如下:

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 */
};

这里的宏展开如下,通过接口类匹配,也就是匹配了类+子类+协议

#define USB_INTERFACE_INFO(cl,sc,pr) \
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr) cl:接口类,我们USB鼠标为HID类,所以填入0X03,也就是USB_INTERFACE_CLASS_HID
sc:接口子类为启动设备,填入USB_INTERFACE_SUBCLASS_BOOT
pr:接口协议为鼠标协议,填入USB_INTERFACE_PROTOCOL_MOUSE //ch9.h
/* USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor {
__u8 bLength;
__u8 bDescriptorType; __u8 bInterfaceNumber;
__u8 bAlternateSetting;
__u8 bNumEndpoints;
__u8 bInterfaceClass; //类
__u8 bInterfaceSubClass; //子类
__u8 bInterfaceProtocol; //协议
__u8 iInterface;
} __attribute__ ((packed));

也可以单独匹配某个厂家ID使用USB_DEVICE

#define USB_DEVICE(vend,prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
.idProduct = (prod)

可以在usb.h查看这个匹配的大类

#define USB_DEVICE_ID_MATCH_DEVICE \
(USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
#define USB_DEVICE_ID_MATCH_DEV_RANGE \
(USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
(USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
#define USB_DEVICE_ID_MATCH_DEV_INFO \
(USB_DEVICE_ID_MATCH_DEV_CLASS | \
USB_DEVICE_ID_MATCH_DEV_SUBCLASS | \
USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
#define USB_DEVICE_ID_MATCH_INT_INFO \
(USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_SUBCLASS | \
USB_DEVICE_ID_MATCH_INT_PROTOCOL) #define USB_DEVICE(vend,prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \
.idProduct = (prod)
#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)
#define USB_DEVICE_INFO(cl,sc,pr) \
.match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), \
.bDeviceSubClass = (sc), .bDeviceProtocol = (pr)
#define USB_INTERFACE_INFO(cl,sc,pr) \
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)

probe

参考usb_mouse_probe可以看到有以下操作

  1. 分配一个 input_dev 结构体
  2. 设置事件
  3. 注册输入子系统
  4. 硬件相关操作

disconnect

拔掉USB会调用该函数,可以加入打印先

程序设计

1th匹配probe

验证id匹配后执行probe函数,这里并没有加入输入子系统

#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> //struct input_dev *input_dev; static struct usb_device_id myusb_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) },
{ } /* Terminating entry */
}; static int myusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
//input_dev = input_allocate_device();
struct usb_device *dev = interface_to_usbdev(intf); printk("found usbmouse!\n");
printk("bcdUSB = %x\n", dev->descriptor.bcdUSB);
printk("VID = 0x%x\n", dev->descriptor.idVendor);
printk("PID = 0x%x\n", dev->descriptor.idProduct); return 0; } static void myusb_disconnect(struct usb_interface *intf)
{
printk("disconnect usbmouse!\n");
}
static struct usb_driver myusb_driver = {
.name = "myusb",
.probe = myusb_probe,
.disconnect = myusb_disconnect,
.id_table = myusb_id_table,
}; static int __init myusb_init(void)
{
int retval = usb_register(&myusb_driver);
return retval;
} static void __exit myusb_exit(void)
{
usb_deregister(&myusb_driver);
} module_init(myusb_init);
module_exit(myusb_exit);
MODULE_LICENSE("GPL");

测试

烧录去除Device Drivers > HID Devices > USB Human Interface Device (full HID) support 的内核,加载模块,显示如下

# insmod myusb_1th.ko
new id 0x6019 !
found usbmouse!
bcdUSB = 110
VID = 0x93a
PID = 0x2510
usbcore: registered new interface driver myusb

2th 获取usb数据

  • 数据鼠标上报的数据,在这里其实并不需要输入子系统的参与,输入子系统是为了上报按键的数据,而不是为了获取鼠标的数据
  • 可以进一步在probe中判断是否为鼠标设备,可以获取接口描述符,获取端点个数(除了端点0)
  • 如何上报数据? usb这里使用urb usb request block也就是usb 请求块来传输数据

测试后可以看到打印的数据,可以根据这个判断转换为按键值左键L,右键S,中键ENTER

data cnt 187: 01 00 00 00
data cnt 188: 00 00 00 00
data cnt 189: 02 00 00 00
data cnt 190: 00 00 00 00
data cnt 191: 04 00 00 00
data cnt 192: 00 00 00 00
上报次数 指示了按键 其他值
data cnt 187: 01 左键 00 00 00
data cnt 188: 00 00 00 00
data cnt 189: 02 右键 00 00 00
data cnt 190: 00 00 00 00
data cnt 191: 04 中键 00 00 00
data cnt 192: 00 00 00 00

完整的程序

#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 int len;
static char *usb_buf; //目的buf虚拟地址
static dma_addr_t usb_buf_phys; //目的buf实际获得的地址
struct input_dev *input_dev;
static struct urb *uk_urb; static struct usb_device_id myusb_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) }, //{USB_DEVICE(0x17EF,0x6019) } /* right id */
//{USB_DEVICE(0x15EF,0x6055) } /* err */
}; static void usbmouse_as_key_irq(struct urb *urb)
{
int i;
static int cnt = 0;
printk("data cnt %d: ", ++cnt);
for (i = 0; i < len; i++)
{
printk("%02x ", usb_buf[i]);
}
printk("\n");
usb_submit_urb(uk_urb, GFP_KERNEL);
}
static int myusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
int pipe;
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
struct usb_host_interface *interface; printk("new id 2 !\n");
printk("found usbmouse!\n");
printk("bcdUSB = %x\n", dev->descriptor.bcdUSB);
printk("VID = 0x%x\n", dev->descriptor.idVendor);
printk("PID = 0x%x\n", dev->descriptor.idProduct);
interface = intf->cur_altsetting; //data translate for urb //源地址构造
//获得端点地址
endpoint = &interface->endpoint[0].desc;
//usb_rcvintpipe 构造了设备地址+端点地址
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
//长度获取
len = endpoint->wMaxPacketSize;
//目的地址构造,返回虚拟地址和实际地址
usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys); /* 使用"3要素" */
/* 分配usb request block */
uk_urb = usb_alloc_urb(0, GFP_KERNEL);
/* 使用"3要素设置urb" */
usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval);
uk_urb->transfer_dma = usb_buf_phys;
uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* 使用URB */
usb_submit_urb(uk_urb, GFP_KERNEL);
return 0; } static void myusb_disconnect(struct usb_interface *intf)
{ struct usb_device *dev = interface_to_usbdev(intf);
printk("disconnect usbmouse!\n");
usb_kill_urb(uk_urb);
usb_free_urb(uk_urb);
usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
}
static struct usb_driver myusb_driver = {
.name = "myusb",
.probe = myusb_probe,
.disconnect = myusb_disconnect,
.id_table = myusb_id_table,
}; static int __init myusb_init(void)
{
int retval = usb_register(&myusb_driver);
return retval;
} static void __exit myusb_exit(void)
{
usb_deregister(&myusb_driver);
} module_init(myusb_init);
module_exit(myusb_exit);
MODULE_LICENSE("GPL");

3th 输入子系统上报按键

加入输入子系统上报按键事件,测试如下,这里只是输出到显示,并没有执行命令,如果要执行命令需要定位到标准输入

# cat /dev/tty0
ls
llllllllllllllllllll
llllllllllll

或者使用hexdump来显示

# hexdump /dev/event0
【按键值】26 左键 1f右键 1C中键
00001a0 16a7 0000 c426 000b 0001 0026 0001 0000
00001b0 16a7 0000 c430 000b 0000 0000 0000 0000
00001c0 16a7 0000 3b15 000d 0001 0026 0000 0000
00001d0 16a7 0000 3b1d 000d 0000 0000 0000 0000
00001e0 16a8 0000 e834 0005 0001 001f 0001 0000
00001f0 16a8 0000 e83e 0005 0000 0000 0000 0000
0000200 16a8 0000 fb66 0007 0001 001f 0000 0000
0000210 16a8 0000 fb6e 0007 0000 0000 0000 0000
0000220 16a8 0000 f0c1 000e 0001 001c 0001 0000
0000230 16a8 0000 f0cc 000e 0000 0000 0000 0000
0000240 16a9 0000 8319 0001 0001 001c 0000 0000
0000250 16a9 0000 8322 0001 0000 0000 0000 0000 //include/linux
#define KEY_L 38
#define KEY_S 31
#define KEY_ENTER 28

或者使用重定位按键

# exec 0</dev/tty1
# ls
Makefile myusb.ko myusb.o myusb_1th.mod.c
Module.symvers myusb.mod.c myusb_1th.c myusb_1th.mod.o
myusb.c myusb.mod.o myusb_1th.ko myusb_1th.o

完整的程序如下

#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 int len;
static char *usb_buf; //目的buf虚拟地址
static dma_addr_t usb_buf_phys; //目的buf实际获得的地址
struct input_dev *input_dev;
static struct urb *uk_urb; static struct usb_device_id myusb_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) }, //{USB_DEVICE(0x17EF,0x6019) } /* right id */
//{USB_DEVICE(0x15EF,0x6055) } /* err */
}; static void usbmouse_as_key_irq(struct urb *urb)
{ #if(0)
int i;
static int cnt = 0;
printk("data cnt %d: ", ++cnt);
for (i = 0; i < len; i++)
{
printk("%02x ", usb_buf[i]);
}
printk("\n");
#else
static unsigned char pre_val;
// bit0 left_button bit1=right_button bit2=mid_button
if ((pre_val & (1<<0)) != (usb_buf[0] & (1<<0)))
{
/* 左键发生了变化 */
input_event(input_dev, EV_KEY, KEY_L, (usb_buf[0] & (1<<0)) ? 1 : 0);
input_sync(input_dev);
} if ((pre_val & (1<<1)) != (usb_buf[0] & (1<<1)))
{
/* 右键发生了变化 */
input_event(input_dev, EV_KEY, KEY_S, (usb_buf[0] & (1<<1)) ? 1 : 0);
input_sync(input_dev);
} if ((pre_val & (1<<2)) != (usb_buf[0] & (1<<2)))
{
/* 中键发生了变化 */
input_event(input_dev, EV_KEY, KEY_ENTER, (usb_buf[0] & (1<<2)) ? 1 : 0);
input_sync(input_dev);
} pre_val = usb_buf[0]; #endif usb_submit_urb(uk_urb, GFP_KERNEL);
}
static int myusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
int pipe;
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
struct usb_host_interface *interface; printk("new id 2 !\n");
printk("found usbmouse!\n");
printk("bcdUSB = %x\n", dev->descriptor.bcdUSB);
printk("VID = 0x%x\n", dev->descriptor.idVendor);
printk("PID = 0x%x\n", dev->descriptor.idProduct);
interface = intf->cur_altsetting; input_dev = input_allocate_device();
/* b. 设置 */
/* b.1 能产生哪类事件 */
input_dev->evbit[0]=0;
set_bit(EV_KEY, input_dev->evbit);
set_bit(EV_REP, input_dev->evbit);
/* b.2 能产生哪些事件 */
set_bit(KEY_L, input_dev->keybit);
set_bit(KEY_S, input_dev->keybit);
set_bit(KEY_ENTER, input_dev->keybit);
/* c. 注册 */
input_register_device(input_dev); //data translate for urb //源地址构造
//获得端点地址
endpoint = &interface->endpoint[0].desc;
//usb_rcvintpipe 构造了设备地址+端点地址
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
//长度获取
len = endpoint->wMaxPacketSize;
//目的地址构造,返回虚拟地址和实际地址
usb_buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &usb_buf_phys); /* 使用"3要素" */
/* 分配usb request block */
uk_urb = usb_alloc_urb(0, GFP_KERNEL);
/* 使用"3要素设置urb" */
usb_fill_int_urb(uk_urb, dev, pipe, usb_buf, len, usbmouse_as_key_irq, NULL, endpoint->bInterval);
uk_urb->transfer_dma = usb_buf_phys;
uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* 使用URB */
usb_submit_urb(uk_urb, GFP_KERNEL);
return 0; } static void myusb_disconnect(struct usb_interface *intf)
{ struct usb_device *dev = interface_to_usbdev(intf);
printk("disconnect usbmouse!\n");
usb_kill_urb(uk_urb);
usb_free_urb(uk_urb);
usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
input_unregister_device(input_dev);
input_free_device(input_dev);
}
static struct usb_driver myusb_driver = {
.name = "myusb",
.probe = myusb_probe,
.disconnect = myusb_disconnect,
.id_table = myusb_id_table,
}; static int __init myusb_init(void)
{
int retval = usb_register(&myusb_driver);
return retval;
} static void __exit myusb_exit(void)
{
usb_deregister(&myusb_driver);
} module_init(myusb_init);
module_exit(myusb_exit);
MODULE_LICENSE("GPL");

usb输入子系统写程序(三)的更多相关文章

  1. usb输入子系统键盘(四)

    目录 usb输入子系统键盘 设计思路 内核的上报代码 完整代码 title: usb输入子系统键盘 tags: linux date: 2018/12/20/ 17:05:08 toc: true - ...

  2. Linux驱动之一个简单的输入子系统程序编写

    的在Linux驱动之输入子系统简析已经分析过了输入子系统的构成,它是由设备层.核心层.事件层共同组成的.其中核心层提供一些设备层与事件层公用的函数,比如说注册函数.反注册函数.事件到来的处理函数等等: ...

  3. 最新用WPF为触摸屏写了一个手写程序,双格输入的

    原文:最新用WPF为触摸屏写了一个手写程序,双格输入的 双格输入可以提高手写速度,当前字写完以后可以自动识别提交,写下一个字.这样比单格手写速度提高一倍.特别适合触摸屏程序使用 界面如下: 程序如下: ...

  4. Linux输入子系统 转载

    NQian 记录成长~ 首页 新随笔 联系 订阅 管理 随笔 - 305  文章 - 0  评论 - 254 12.Linux之输入子系统分析(详解)   在此节之前,我们学的都是简单的字符驱动,涉及 ...

  5. linux内核输入子系统分析

    1.为何引入input system? 以前我们写一些输入设备(键盘.鼠标等)的驱动都是采用字符设备.混杂设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可 ...

  6. 嵌入式Linux驱动学习之路(十六)输入子系统

    以前写的一些输入设备的驱动都是采用字符设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可以实现一种机制,可以对分散的.不同类别的输入设备进行统一的驱动,所以 ...

  7. linux input输入子系统应用分析

    输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理是底层在按键.触摸等动作发送时产生一个中断(或驱动通过timer定时查询),然后CPU通过SPI.I2 C或外部存储器总线读取 ...

  8. Linux输入子系统(一) _驱动编码

    输入设备都有共性:中断驱动+字符IO,基于分层的思想,Linux内核将这些设备的公有的部分提取出来,基于cdev提供接口,设计了输入子系统,所有使用输入子系统构建的设备都使用主设备号13,同时输入子系 ...

  9. 12.Linux之输入子系统分析(详解)

    版权声明:本文为博主原创文章,转载请标注出处:   在此节之前,我们学的都是简单的字符驱动,涉及的内容有字符驱动的框架.自动创建设备节点.linux中断.poll机制.异步通知.同步互斥/非阻塞.定时 ...

随机推荐

  1. Django 数据流程图

    根据学习Django并且通过几个作业,发现Django制作网站的数据流程有些比较难懂,所以制作一个数据流程图,帮助自己理解,也希望对正学习的人有所帮助! 别的不多说,上美图:

  2. Unity ECS 视频笔记

    视频摘要 本文视频资料:使用Entity Component System开发<快乐的Minecraft>游戏 使用Unity2018及以上版本才有ECS功能. 本文是看视频的一些摘要. ...

  3. Python基础——0前言

    python虽然这几年才兴起,但是已经是一门“老”语言了. python的诞生历史也很有趣.Python的创始人为Guido van Rossum(龟叔).1989年圣诞节期间,在阿姆斯特丹,Guid ...

  4. nysql报错1136

    报错信息:> 1136 - Column count doesn't match value count at row 1 代码:insert into class(caption) value ...

  5. 【Python 12】汇率兑换5.0(Lambda函数)

     1.案例描述 设计一个汇率换算程序,其功能是将美元换算成人民币,或者相反. 2.0增加功能:根据输入判断是人民币还是美元,进行相应的转换计算 3.0增加功能:程序可以一直运行,知道用户选择退出 4. ...

  6. ideal中项目resources下txt文件读取不到的问题。

    这次做项目,原来用到了一个txt文件,在ideal中项目启动后报读取不到txt文件.项目原来是在eclipse中的. 在网上找了些文章,发现ideal中要读取到resources下的文件需要加上下面红 ...

  7. 百度杯”CTF比赛 九月场 123

    进去后让登录,先看源码有提示 进到user.php 后发现是空的,看了wp才知道,有bak 下载下来直接爆破 但是那个1990是蛮骚的 直接进去登录 登录成功后是空的,走fd看看是怎么过 的 改包然后 ...

  8. SQL 增删改语句

    阅读目录 一:插入数据 二:更新数据 三:删除数据 回到顶部 一:插入数据 把数据插入表中的最简单方法是使用基本的 INSERT 语法.它的要求是需要我们指定表名和插入到新行中的值. 1.1 插入完整 ...

  9. DeeplabV3+ 训练自己的遥感数据

    一.预处理数据部分 1.创建 tfrecord(修改 deeplab\ dateasets\ build_data.py) 模型本身是把一张张 jpg 和 png 格式图片读到一个 Example 里 ...

  10. C# 使用微软自带的Speech进行语音输出

    1.在VS中使用微软自带的Speech进行语音播报,首先需要添加引用: 2.具体实现逻辑代码如下: