花生壳盒子做网站服务器,wordpress文章保存图片不显示,做100个网站效果,作风建设年网站目录
1. ftdi_port_probe
1.1 私有数据结构ftdi_private
1.2 特殊probe处理
1.3 确定FTDI设备类型
1.4 确定最大数据包大小
1.5 设置读取延迟时间
1.6 初始化GPIO
1.6.1 使能GPIO
1.6.2 添加到系统
1.6.2.1 设置GPIO控制器的基本信息
1.6.2.2 设置GPIO控制器的元信息…目录
1. ftdi_port_probe
1.1 私有数据结构ftdi_private
1.2 特殊probe处理
1.3 确定FTDI设备类型
1.4 确定最大数据包大小
1.5 设置读取延迟时间
1.6 初始化GPIO
1.6.1 使能GPIO
1.6.2 添加到系统
1.6.2.1 设置GPIO控制器的基本信息
1.6.2.2 设置GPIO控制器的元信息
1.6.3 GPIO实例 2. ftdi_gpio_remove int (*port_probe)(struct usb_serial_port *port): 端口探测函数ftdi_port_probe用于初始化单个端口。
void (*port_remove)(struct usb_serial_port *port): 端口移除函数ftdi_port_remove ftdi_port_remove用于清理单个端口。
1. ftdi_port_probe
1.1 私有数据结构ftdi_private
这个结构是FTDI设备特有的其实就是用来在驱动中传递参数用的。在这个结构体中定义了FTDI设备私有的一些变量。
struct ftdi_private *priv;
priv kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
if (!priv)return -ENOMEM;
这个私有数据是通过usb_set_serial_port_data放到port的私有数据保存。
usb_set_serial_port_data(port, priv);
1.2 特殊probe处理
和上一节一样端口的probe处理也是有特殊的情况。这个结构体是通过port-serial传递的。
const struct ftdi_quirk *quirk usb_get_serial_data(port-serial);
if (quirk quirk-port_probe)quirk-port_probe(priv);
1.3 确定FTDI设备类型
result ftdi_determine_type(port);
if (result)goto err_free; 该类型是通过设备描述符中的bcdDevice来区别的。
version le16_to_cpu(udev-descriptor.bcdDevice);
以FT4232H为例该值可以在设备属性的硬件ID中查看到如下图REV_0800 case 0x800:priv-chip_type FT4232H;break;
通过当前接口初始化通道编号这只对多串口有意义比如FT2232H和FT4232H
#define CHANNEL_A 1
#define CHANNEL_B 2
#define CHANNEL_C 3
#define CHANNEL_D 4ifnum serial-interface-cur_altsetting-desc.bInterfaceNumber;
priv-channel CHANNEL_A ifnum;
而baud_base是指波特率产生器的参考时钟默认设置的是H系列的值120M的二分频。
priv-baud_base 120000000 / 2;
最后是向设备节点发送消息表明检测到了哪种类型的FTDI芯片。
dev_info(udev-dev, Detected %s\n, ftdi_chip_name[priv-chip_type]);
在命令“sudo dmesg”返回结果中可以找到这句信息内容例如
[16005.322690] usb 2-1: Detected FT4232H
1.4 确定最大数据包大小
ftdi_set_max_packet_size(port);
这是从设备的端点描述符中获取设备端点最大数据包大小。这一步更像是检查FT232R的端点数据包最大值被客制为0的情况当被改为0时数据包大小设置为64字节。
1.5 设置读取延迟时间
if (read_latency_timer(port) 0)priv-latency 16;
write_latency_timer(port);
这段代码的作用是确保设备的读取延迟时间被正确设置如果无法获取当前的延迟时间则会使用一个默认值进行设置。
获取这个参数是通过函数usb_control_msg_recv实现的。
int usb_control_msg_recv(struct usb_device *dev, __u8 endpoint, __u8 request,__u8 requesttype, __u16 value, __u16 index,void *driver_data, __u16 size, int timeout,gfp_t memflags)
对应的调用
rv usb_control_msg_recv(udev, 0, FTDI_SIO_GET_LATENCY_TIMER_REQUEST,FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, 0,priv-channel, buf, 1, WDR_TIMEOUT,GFP_KERNEL);
其中参数request和requesttype在ftdi_sio.h中有定义
#define FTDI_SIO_GET_LATENCY_TIMER 0x0a /* Get the latency timer */
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0
这属于FTDI定义的命令。
同样写这个参数的命令是
#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40rv usb_control_msg(udev,usb_sndctrlpipe(udev, 0),FTDI_SIO_SET_LATENCY_TIMER_REQUEST,FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,l, priv-channel,NULL, 0, WDR_TIMEOUT);
1.6 初始化GPIO
这部分是利用了FTDI的CBUS实现USB转GPIO的功能。这一步是受内核配置CONFIG_GPIOLIB控制的如果没有使能GPIOLIB则没有这部分功能。
1.6.1 使能GPIO
由于不是所有的FTDI芯片都支持CBUS功能所以前面有做芯片类型的判断这里会引用这个变量分别处理。
switch (priv-chip_type) {
case FT232H:result ftdi_gpio_init_ft232h(port);break;
case FT232R:result ftdi_gpio_init_ft232r(port);break;
case FTX:result ftdi_gpio_init_ftx(port);break;
default:return 0;
}
只有3类芯片支持CBUS功能这里3个分支都是从芯片或外置EEPROM中读取CBUS配置信息使能CBUS脚。例如FT232H一共有4个CBUS脚分别为AC5AC6AC8和AC9从eeprom的地址0x1a读入4个字节
ret ftdi_read_eeprom(port-serial, buf, 0x1a, 4);
if (ret 0)goto out_free;
每个GPIO由4位表示方向和电平。
/*
* FT232H CBUS Memory Map
*
* 0x1a: X- (upper nibble - AC5)
* 0x1b: -X (lower nibble - AC6)
* 0x1c: XX (upper nibble - AC9 | lower nibble - AC8)
*/
cbus_config buf[2] 8 | (buf[1] 0xf) 4 | (buf[0] 0xf0) 4;
最后更新priv-gc.ngpio和gpio_altfunc对应GPIO使能的话gpio_altfunc对应的位清零
priv-gc.ngpio 4;
priv-gpio_altfunc 0xff;for (i 0; i priv-gc.ngpio; i) {if ((cbus_config 0xf) FTDI_FTX_CBUS_MUX_GPIO)priv-gpio_altfunc ~BIT(i);cbus_config 4;
}
1.6.2 添加到系统
这一步是通过标准的gpiochip的驱动API函数gpiochip_add_data实现。
priv-gc.label ftdi-cbus;
priv-gc.request ftdi_gpio_request;
priv-gc.get_direction ftdi_gpio_direction_get;
priv-gc.direction_input ftdi_gpio_direction_input;
priv-gc.direction_output ftdi_gpio_direction_output;
priv-gc.init_valid_mask ftdi_gpio_init_valid_mask;
priv-gc.get ftdi_gpio_get;
priv-gc.set ftdi_gpio_set;
priv-gc.get_multiple ftdi_gpio_get_multiple;
priv-gc.set_multiple ftdi_gpio_set_multiple;
priv-gc.owner THIS_MODULE;
priv-gc.parent serial-interface-dev;
priv-gc.base -1;
priv-gc.can_sleep true;result gpiochip_add_data(priv-gc, port);
if (!result)priv-gpio_registered true;
第一个参数priv-gc是配置好的gpio_chip结构体第二个参数是该gpio_chip的私有数据即实现接口参数的传递例如
static int ftdi_gpio_request(struct gpio_chip *gc, unsigned int offset)
{struct usb_serial_port *port gpiochip_get_data(gc);
1.6.2.1 设置GPIO控制器的基本信息
priv-gc.label: 设置GPIO控制器的标签为ftdi-cbus。priv-gc.request: 设置请求GPIO引脚的函数为ftdi_gpio_request用于在使用前申请GPIO资源。priv-gc.get_direction: 设置获取GPIO引脚方向输入或输出的函数为ftdi_gpio_direction_get。priv-gc.direction_input: 设置将GPIO引脚配置为输入模式的函数为ftdi_gpio_direction_input。priv-gc.direction_output: 设置将GPIO引脚配置为输出模式的函数为ftdi_gpio_direction_output。priv-gc.init_valid_mask: 设置初始化有效掩码的函数为ftdi_gpio_init_valid_mask用于确定哪些GPIO引脚可以被使用。priv-gc.get: 设置读取GPIO引脚状态的函数为ftdi_gpio_get。priv-gc.set: 设置设置GPIO引脚状态的函数为ftdi_gpio_set。priv-gc.get_multiple: 设置批量读取GPIO引脚状态的函数为ftdi_gpio_get_multiple。priv-gc.set_multiple: 设置批量设置GPIO引脚状态的函数为ftdi_gpio_set_multiple。
1.6.2.2 设置GPIO控制器的元信息
priv-gc.owner: 设置拥有者为当前模块表明这个GPIO控制器是由当前驱动程序管理的。priv-gc.parent: 设置父设备为serial-interface-dev这通常是一个USB设备或串口设备表明GPIO控制器与之关联。priv-gc.base: 设置GPIO引脚的起始编号为-1实际值将在注册时由系统分配。priv-gc.can_sleep: 设置为true表示这个GPIO控制器可以在睡眠状态下工作。
1.6.3 GPIO实例
例如使用FT232H使用FT_PROG设置AC9为I/O Mode 在Linux中可以看到多一个gpiochip512的文件夹
/sys/class/gpio$ ls
export gpiochip512 unexport
/sys/class/gpio/gpiochip512$ ls
base device label ngpio power subsystem uevent
/sys/class/gpio/gpiochip512$ cat label
ftdi-cbus
/sys/class/gpio/gpiochip512$ cat ngpio
4
/sys/class/gpio/gpiochip512$ cat base
512
可以看到一共分配了4个gpio因为AC9是第四个GPIO所以其GPIO编号应该为512 3 515.
/sys/class/gpio# echo 515 /sys/class/gpio/export
/sys/class/gpio# ls
export gpio515 gpiochip512 unexport
注意这里FT_PROG虽然只配置了一个GPIO但是驱动层还是按照4个GPIO分配如果暴露512可以看到返回错误
/sys/class/gpio# echo 512 /sys/class/gpio/export
bash: echo: 写入错误无效的参数 2. ftdi_gpio_remove
这个函数将gpio移除和释放内存。
文章转载自: http://www.morning.gskzy.cn.gov.cn.gskzy.cn http://www.morning.kbynw.cn.gov.cn.kbynw.cn http://www.morning.jtmrx.cn.gov.cn.jtmrx.cn http://www.morning.dwfxl.cn.gov.cn.dwfxl.cn http://www.morning.qnkqk.cn.gov.cn.qnkqk.cn http://www.morning.pwqyd.cn.gov.cn.pwqyd.cn http://www.morning.nkddq.cn.gov.cn.nkddq.cn http://www.morning.yrflh.cn.gov.cn.yrflh.cn http://www.morning.rcqyk.cn.gov.cn.rcqyk.cn http://www.morning.xmbhc.cn.gov.cn.xmbhc.cn http://www.morning.gbgdm.cn.gov.cn.gbgdm.cn http://www.morning.xpqsk.cn.gov.cn.xpqsk.cn http://www.morning.gfjgq.cn.gov.cn.gfjgq.cn http://www.morning.knswz.cn.gov.cn.knswz.cn http://www.morning.dbqcw.com.gov.cn.dbqcw.com http://www.morning.zxhpx.cn.gov.cn.zxhpx.cn http://www.morning.xflzm.cn.gov.cn.xflzm.cn http://www.morning.cryb.cn.gov.cn.cryb.cn http://www.morning.sglcg.cn.gov.cn.sglcg.cn http://www.morning.nfpct.cn.gov.cn.nfpct.cn http://www.morning.wrtw.cn.gov.cn.wrtw.cn http://www.morning.jpnw.cn.gov.cn.jpnw.cn http://www.morning.mqgqf.cn.gov.cn.mqgqf.cn http://www.morning.rwrn.cn.gov.cn.rwrn.cn http://www.morning.hqllx.cn.gov.cn.hqllx.cn http://www.morning.ldzxf.cn.gov.cn.ldzxf.cn http://www.morning.ltpzr.cn.gov.cn.ltpzr.cn http://www.morning.ljzss.cn.gov.cn.ljzss.cn http://www.morning.thwcg.cn.gov.cn.thwcg.cn http://www.morning.cctgww.cn.gov.cn.cctgww.cn http://www.morning.qsdnt.cn.gov.cn.qsdnt.cn http://www.morning.kxypt.cn.gov.cn.kxypt.cn http://www.morning.ltypx.cn.gov.cn.ltypx.cn http://www.morning.mzgq.cn.gov.cn.mzgq.cn http://www.morning.zcwtl.cn.gov.cn.zcwtl.cn http://www.morning.gidmag.com.gov.cn.gidmag.com http://www.morning.jpnw.cn.gov.cn.jpnw.cn http://www.morning.gnkbf.cn.gov.cn.gnkbf.cn http://www.morning.hyhqd.cn.gov.cn.hyhqd.cn http://www.morning.zbgqt.cn.gov.cn.zbgqt.cn http://www.morning.rrcrs.cn.gov.cn.rrcrs.cn http://www.morning.qnhpq.cn.gov.cn.qnhpq.cn http://www.morning.hsklc.cn.gov.cn.hsklc.cn http://www.morning.xbwqg.cn.gov.cn.xbwqg.cn http://www.morning.tfbpz.cn.gov.cn.tfbpz.cn http://www.morning.klyyd.cn.gov.cn.klyyd.cn http://www.morning.wpcfh.cn.gov.cn.wpcfh.cn http://www.morning.xclgf.cn.gov.cn.xclgf.cn http://www.morning.wrtw.cn.gov.cn.wrtw.cn http://www.morning.ngkgy.cn.gov.cn.ngkgy.cn http://www.morning.zgdnd.cn.gov.cn.zgdnd.cn http://www.morning.yhjrc.cn.gov.cn.yhjrc.cn http://www.morning.blfll.cn.gov.cn.blfll.cn http://www.morning.nrzbq.cn.gov.cn.nrzbq.cn http://www.morning.ngzkt.cn.gov.cn.ngzkt.cn http://www.morning.rlxg.cn.gov.cn.rlxg.cn http://www.morning.mrccd.cn.gov.cn.mrccd.cn http://www.morning.yxyyp.cn.gov.cn.yxyyp.cn http://www.morning.qjzgj.cn.gov.cn.qjzgj.cn http://www.morning.rhzzf.cn.gov.cn.rhzzf.cn http://www.morning.mlnby.cn.gov.cn.mlnby.cn http://www.morning.xinxianzhi005.com.gov.cn.xinxianzhi005.com http://www.morning.rbbzn.cn.gov.cn.rbbzn.cn http://www.morning.rcdmp.cn.gov.cn.rcdmp.cn http://www.morning.tgxrm.cn.gov.cn.tgxrm.cn http://www.morning.yqyhr.cn.gov.cn.yqyhr.cn http://www.morning.kntsd.cn.gov.cn.kntsd.cn http://www.morning.huxinzuche.cn.gov.cn.huxinzuche.cn http://www.morning.mpngp.cn.gov.cn.mpngp.cn http://www.morning.tdgwg.cn.gov.cn.tdgwg.cn http://www.morning.kmbgl.cn.gov.cn.kmbgl.cn http://www.morning.gjsjt.cn.gov.cn.gjsjt.cn http://www.morning.btlmb.cn.gov.cn.btlmb.cn http://www.morning.bdwqy.cn.gov.cn.bdwqy.cn http://www.morning.nbgfk.cn.gov.cn.nbgfk.cn http://www.morning.qxnlc.cn.gov.cn.qxnlc.cn http://www.morning.mtsgx.cn.gov.cn.mtsgx.cn http://www.morning.ydflc.cn.gov.cn.ydflc.cn http://www.morning.lyhrg.cn.gov.cn.lyhrg.cn http://www.morning.mmqng.cn.gov.cn.mmqng.cn