imx6 i2c分析

本文主要分析:
      1. i2c设备注册
      2. i2c驱动注册
      3. 上层调用过程
参考:
  http://www.cnblogs.com/helloworldtoyou/p/5126618.html

1
. i2c设备注册 kernel/arch/arm/mach-mx6/board-mx6q_sabresd.c static void __init mx6_sabresd_board_init(void) { mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_pads, ---------------+ ARRAY_SIZE(mx6q_sabresd_pads)); | ... ... | strcpy(mxc_i2c0_board_info[0].type, "wm8962"); | mxc_i2c0_board_info[0].platform_data = &wm8962_config_data; | | //注册i2c总线 | imx6q_add_imx_i2c(0, &mx6q_sabresd_i2c_data); ------------+ | imx6q_add_imx_i2c(1, &mx6q_sabresd_i2c_data); ----+ | | imx6q_add_imx_i2c(2, &mx6q_sabresd_i2c_data); | | | | | | i2c_register_board_info(0, mxc_i2c0_board_info, ----------------+ | ARRAY_SIZE(mxc_i2c0_board_info)); | | | | i2c_register_board_info(1, mxc_i2c1_board_info, | | | | ARRAY_SIZE(mxc_i2c1_board_info)); | | | | i2c_register_board_info(2, mxc_i2c2_board_info, | | | | ARRAY_SIZE(mxc_i2c2_board_info)); | | | | ... ... | | | | } | | | | | | | | static iomux_v3_cfg_t mx6q_sabresd_pads[] = { <----------|-----|--+ /* I2C1, WM8958 */ | | | MX6Q_PAD_CSI0_DAT8__I2C1_SDA, | | | MX6Q_PAD_CSI0_DAT9__I2C1_SCL, | | | | | | /* I2C2, Camera, MIPI */ | | | MX6Q_PAD_KEY_COL3__I2C2_SCL, | | | MX6Q_PAD_KEY_ROW3__I2C2_SDA, | | | | | | #ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO | | | MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1, | | | #else | | | /* I2C3 */ | | | MX6Q_PAD_GPIO_3__I2C3_SCL, /* GPIO1[3] */ | | | MX6Q_PAD_GPIO_6__I2C3_SDA, | | | #endif | | | }; | | | | | | //总线速率 V | | static struct imxi2c_platform_data mx6q_sabresd_i2c_data = { | | .bitrate = 100000, | | }; | | | | #define imx6q_add_imx_i2c(id, pdata) \ <-----------+ | imx_add_imx_i2c(&imx6q_imx_i2c_data[id], pdata) | | | | struct platform_device *__init imx_add_imx_i2c( <-----------+ | const struct imx_imx_i2c_data *data, | const struct imxi2c_platform_data *pdata) | { | struct resource res[] = { | { | .start = data->iobase, | .end = data->iobase + data->iosize - 1, | .flags = IORESOURCE_MEM, | }, { | .start = data->irq, | .end = data->irq, | .flags = IORESOURCE_IRQ, | }, | }; | | return imx_add_platform_device("imx-i2c", data->id, | res, ARRAY_SIZE(res), | pdata, sizeof(*pdata)); | } | | //指定i2c链接设备的名称,和地址 | static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { <-+ { | I2C_BOARD_INFO("wm89**", 0x1a), | }, | /* | { | I2C_BOARD_INFO("ov564x", 0x3c), | .platform_data = (void *)&camera_data, | }, | { | I2C_BOARD_INFO("mma8451", 0x1d), | .platform_data = (void *)&mma8451_position, | }, | { | I2C_BOARD_INFO("isl1208", 0x6f), | }, | */ | }; | | int __init | i2c_register_board_info(int busnum, <------------------+ struct i2c_board_info const *info, unsigned len) { int status; down_write(&__i2c_board_lock); //动态更新总线个数 /* dynamic bus numbers will be assigned after the last static one */ if (busnum >= __i2c_first_dynamic_bus_num) __i2c_first_dynamic_bus_num = busnum + 1; //将同一个i2c接口的所有设备都添加到一个链表中 for (status = 0; len; len--, info++) { struct i2c_devinfo *devinfo; devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); if (!devinfo) { pr_debug("i2c-core: can't register boardinfo!\n"); status = -ENOMEM; break; } devinfo->busnum = busnum; devinfo->board_info = *info; list_add_tail(&devinfo->list, &__i2c_board_list); } up_write(&__i2c_board_lock); return status; } 2. i2c驱动注册 kernel/drivers/i2c/busses/i2c-imx.c static int __init i2c_adap_imx_init(void) { return platform_driver_probe(&i2c_imx_driver, i2c_imx_probe); ----------+ } | | int __init_or_module platform_driver_probe(struct platform_driver *drv, | int (*probe)(struct platform_device *)) | { | int retval, code; | | drv->driver.suppress_bind_attrs = true; | //指定驱动的probe函数 | drv->probe = probe; | //注册平台驱动 | retval = code = platform_driver_register(drv); | | spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); | drv->probe = NULL; | if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) | retval = -ENODEV; | drv->driver.probe = platform_drv_probe_fail; | spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); | | if (code != retval) | platform_driver_unregister(drv); | return retval; | } | EXPORT_SYMBOL_GPL(platform_driver_probe); | | static struct platform_driver i2c_imx_driver = { <-----------------+ .remove = __exit_p(i2c_imx_remove), | .driver = { | .name = DRIVER_NAME, // "imx-i2c" | .owner = THIS_MODULE, | } | }; | | static int __init i2c_imx_probe(struct platform_device *pdev) <---------+ { struct imx_i2c_struct *i2c_imx; struct resource *res; struct imxi2c_platform_data *pdata; void __iomem *base; resource_size_t res_size; int irq; int ret; dev_dbg(&pdev->dev, "<%s>\n", __func__); //获得i2c寄存器地址的信息 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "can't get device resources\n"); return -ENOENT; } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "can't get irq number\n"); return -ENOENT; } pdata = pdev->dev.platform_data; if (pdata && pdata->init) { ret = pdata->init(&pdev->dev); if (ret) return ret; } res_size = resource_size(res); if (!request_mem_region(res->start, res_size, DRIVER_NAME)) { ret = -EBUSY; goto fail0; } base = ioremap(res->start, res_size); if (!base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -EIO; goto fail1; } i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL); if (!i2c_imx) { dev_err(&pdev->dev, "can't allocate interface\n"); ret = -ENOMEM; goto fail2; } /* Setup i2c_imx driver structure */ strcpy(i2c_imx->adapter.name, pdev->name); i2c_imx->adapter.owner = THIS_MODULE; i2c_imx->adapter.algo = &i2c_imx_algo; // i2c算法 ---------------+i2c_imx->adapter.dev.parent = &pdev->dev; | i2c_imx->adapter.nr = pdev->id; | i2c_imx->irq = irq; | i2c_imx->base = base; | i2c_imx->res = res; | | /* Get I2C clock */ | i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); | if (IS_ERR(i2c_imx->clk)) { | ret = PTR_ERR(i2c_imx->clk); | dev_err(&pdev->dev, "can't get I2C clock\n"); | goto fail3; | } | | /* Request IRQ */ | ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); | if (ret) { | dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq); | goto fail4; | } | | /* Init queue */ | init_waitqueue_head(&i2c_imx->queue); | | /* Set up adapter data */ | i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); | | /* Set up clock divider */ | if (pdata && pdata->bitrate) | i2c_imx_set_clk(i2c_imx, pdata->bitrate); | else | i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE); | | /* Set up chip registers to defaults */ | writeb(0, i2c_imx->base + IMX_I2C_I2CR); | writeb(0, i2c_imx->base + IMX_I2C_I2SR); | //添加adapter,一个i2c对应一个adapter | /* Add I2C adapter */ | ret = i2c_add_numbered_adapter(&i2c_imx->adapter); -----------------+ | if (ret < 0) { | | dev_err(&pdev->dev, "registration failed\n"); | | goto fail5; | | } | | | | /* Set up platform driver data */ | | platform_set_drvdata(pdev, i2c_imx); | | | | dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", i2c_imx->irq); | | dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",| | i2c_imx->res->start, i2c_imx->res->end); | | dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n", | | res_size, i2c_imx->res->start); | | dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", | | i2c_imx->adapter.name); | | dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); | | | | return 0; /* Return OK */ | | | | fail5: | | free_irq(i2c_imx->irq, i2c_imx); | | fail4: | | clk_put(i2c_imx->clk); | | fail3: | | kfree(i2c_imx); | | fail2: | | iounmap(base); | | fail1: | | release_mem_region(res->start, resource_size(res)); | | fail0: | | if (pdata && pdata->exit) | | pdata->exit(&pdev->dev); | | return ret; /* Return error number */ | | } | |
| | kernel/drivers/i2c/i2c-core.c | | int i2c_add_numbered_adapter(struct i2c_adapter *adap) <----------+ | { | int id; | int status; | | if (adap->nr & ~MAX_ID_MASK) | return -EINVAL; | | retry: | if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) | return -ENOMEM; | | mutex_lock(&core_lock); | /* "above" here means "above or equal to", sigh; | * we need the "equal to" result to force the result | */ | status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id); | if (status == 0 && id != adap->nr) { | status = -EBUSY; | idr_remove(&i2c_adapter_idr, id); | } | mutex_unlock(&core_lock); | if (status == -EAGAIN) | goto retry; | | if (status == 0) | status = i2c_register_adapter(adap); ---------------+ | return status; | | } | | EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); | | | | static int i2c_register_adapter(struct i2c_adapter *adap) <--+ | { | int res = 0; | | /* Can't register until after driver model init */ | if (unlikely(WARN_ON(!i2c_bus_type.p))) { | res = -EAGAIN; | goto out_list; | } | | /* Sanity checks */ | if (unlikely(adap->name[0] == '\0')) { | pr_err("i2c-core: Attempt to register an adapter with " | "no name!\n"); | return -EINVAL; | } | if (unlikely(!adap->algo)) { | pr_err("i2c-core: Attempt to register adapter '%s' with " | "no algo!\n", adap->name); | return -EINVAL; | } | | rt_mutex_init(&adap->bus_lock); | mutex_init(&adap->userspace_clients_lock); | INIT_LIST_HEAD(&adap->userspace_clients); | | /* Set default timeout to 1 second if not already set */ | if (adap->timeout == 0) | adap->timeout = HZ; | //设置设备名,这里就是/dev显示的 /dev/i2c-1, /dev/i2c-2... | dev_set_name(&adap->dev, "i2c-%d", adap->nr); | adap->dev.bus = &i2c_bus_type; | adap->dev.type = &i2c_adapter_type; | res = device_register(&adap->dev); | if (res) | goto out_list; | | dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); | | #ifdef CONFIG_I2C_COMPAT | res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev, | adap->dev.parent); | if (res) | dev_warn(&adap->dev, | "Failed to create compatibility class link\n"); | #endif | | /* create pre-declared device nodes */ | if (adap->nr < __i2c_first_dynamic_bus_num) | i2c_scan_static_board_info(adap); | | /* Notify drivers */ | mutex_lock(&core_lock); | bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); | mutex_unlock(&core_lock); | | return 0; | | out_list: | mutex_lock(&core_lock); | idr_remove(&i2c_adapter_idr, adap->nr); | mutex_unlock(&core_lock); | return res; | } | kernel/driver/i2c/busses/i2c-imx.c | static struct i2c_algorithm i2c_imx_algo = { <--------------------+ .master_xfer = i2c_imx_xfer, ----------------------------------+.functionality = i2c_imx_func, | }; | static u32 i2c_imx_func(struct i2c_adapter *adapter) | { |return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | } | //发送接收会调用的函数 | static int i2c_imx_xfer(struct i2c_adapter *adapter, <---------------------+struct i2c_msg *msgs, int num) | { |unsigned int i, temp; |int result; |struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); ||dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); ||/* Start I2C transfer */ |result = i2c_imx_start(i2c_imx); |if (result) |goto fail0; ||/* read/write data */ |for (i = 0; i < num; i++) { |if (i) { |dev_dbg(&i2c_imx->adapter.dev, |"<%s> repeated start\n", __func__); |temp = readb(i2c_imx->base + IMX_I2C_I2CR); |temp |= I2CR_RSTA; |writeb(temp, i2c_imx->base + IMX_I2C_I2CR); |result = i2c_imx_bus_busy(i2c_imx, 1); |if (result) |goto fail0; |} |dev_dbg(&i2c_imx->adapter.dev, |"<%s> transfer message: %d\n", __func__, i); |/* write/read data */ | #ifdef CONFIG_I2C_DEBUG_BUS |temp = readb(i2c_imx->base + IMX_I2C_I2CR); |dev_dbg(&i2c_imx->adapter.dev, "<%s> CONTROL: IEN=%d, IIEN=%d, " |"MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n", __func__, |(temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0), |(temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0), |(temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0)); |temp = readb(i2c_imx->base + IMX_I2C_I2SR); |dev_dbg(&i2c_imx->adapter.dev, |"<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, " |"IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n", __func__, |(temp & I2SR_ICF ? 1 : 0), (temp & I2SR_IAAS ? 1 : 0), |(temp & I2SR_IBB ? 1 : 0), (temp & I2SR_IAL ? 1 : 0), |(temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0), |(temp & I2SR_RXAK ? 1 : 0)); | #endif |if (msgs[i].flags & I2C_M_RD) |result = i2c_imx_read(i2c_imx, &msgs[i]); |else |result = i2c_imx_write(i2c_imx, &msgs[i]); |if (result) |goto fail0; |} || fail0: |/* Stop I2C transfer */ |i2c_imx_stop(i2c_imx); ||dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, |(result < 0) ? "error" : "success msg", |(result < 0) ? result : num); |return (result < 0) ? result : num; | } || // i2c_msg记录了i2c地址 | struct i2c_msg { |__u16 addr; /* slave address */ |__u16 flags; | #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ | #define I2C_M_RD 0x0001 /* read data, from slave to master */ | #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ | #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ | #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ | #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ | #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */|__u16 len; /* msg length */ |__u8 *buf; /* pointer to msg data */ | }; ||| 3. 上层应用调用 | kernel/driver/i2c/busses/i2c-dev.c | static int __init i2c_dev_init(void) | { |int res; ||printk(KERN_INFO "i2c /dev entries driver\n"); ||res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops); ------------+ |if (res) | |goto out; | || |i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); | |if (IS_ERR(i2c_dev_class)) { | |res = PTR_ERR(i2c_dev_class); | |goto out_unreg_chrdev; | |} | || |/* Keep track of adapters which will be added or removed later */ | |res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); | |if (res) | |goto out_unreg_class; | || |/* Bind to already existing adapters right away */ | |i2c_for_each_dev(NULL, i2cdev_attach_adapter); | || |return 0; | || | out_unreg_class: | |class_destroy(i2c_dev_class); | | out_unreg_chrdev: | |unregister_chrdev(I2C_MAJOR, "i2c"); | | out: | |printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); | |return res; | | } | | static const struct file_operations i2cdev_fops = { <-------------+ |.owner = THIS_MODULE, |.llseek = no_llseek, |.read = i2cdev_read, ----------+ |.write = i2cdev_write, | |.unlocked_ioctl = i2cdev_ioctl, | |.open = i2cdev_open, | |.release = i2cdev_release, | | }; | |V | static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count, |loff_t *offset) | { |char *tmp; |int ret; ||struct i2c_client *client = file->private_data; ||if (count > 8192) |count = 8192; ||tmp = kmalloc(count, GFP_KERNEL); |if (tmp == NULL) |return -ENOMEM; ||pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n", |iminor(file->f_path.dentry->d_inode), count); ||ret = i2c_master_recv(client, tmp, count); ---------------+ |if (ret >= 0) | |ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; | |kfree(tmp); | |return ret; | | } | |V | int i2c_master_recv(const struct i2c_client *client, char *buf, int count) | { |struct i2c_adapter *adap = client->adapter; |struct i2c_msg msg; |int ret; ||msg.addr = client->addr; //地址 | msg.flags = client->flags & I2C_M_TEN; //判断是否使用10位地址 | msg.flags |= I2C_M_RD; //读操作 | msg.len = count; //发送个数 | msg.buf = buf; //发送数据 | |ret = i2c_transfer(adap, &msg, 1); ---------------------------+ || |/* If everything went ok (i.e. 1 msg transmitted), return #bytes | |transmitted, else error code. */ | |return (ret == 1) ? count : ret; | | } | || | int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) <--+ | { |unsigned long orig_jiffies; |int ret, try; ||/* REVISIT the fault reporting model here is weak: |* |* - When we get an error after receiving N bytes from a slave, |* there is no way to report "N". |* |* - When we get a NAK after transmitting N bytes to a slave, |* there is no way to report "N" ... or to let the master |* continue executing the rest of this combined message, if |* that's the appropriate response. |* |* - When for example "num" is two and we successfully complete |* the first message but get an error part way through the |* second, it's unclear whether that should be reported as |* one (discarding status on the second message) or errno |* (discarding status on the first one). |*/ |//判断master_xfer函数指针是否存在,存在的话就是指向i2c_imx_xfer |if (adap->algo->master_xfer) { <-----------+ #ifdef DEBUG |for (ret = 0; ret < num; ret++) { |dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " |"len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) |? 'R' : 'W', msgs[ret].addr, msgs[ret].len, |(msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); |} | #endif ||if (in_atomic() || irqs_disabled()) { |ret = i2c_trylock_adapter(adap); |if (!ret) |/* I2C activity is ongoing. */ |return -EAGAIN; |} else { |i2c_lock_adapter(adap); |} ||/* Retry automatically on arbitration loss */ |orig_jiffies = jiffies; |for (ret = 0, try = 0; try <= adap->retries; try++) { |//调用 i2c_imx_xfer函数 | ret = adap->algo->master_xfer(adap, msgs, num); <---------+if (ret != -EAGAIN) break; if (time_after(jiffies, orig_jiffies + adap->timeout)) break; } i2c_unlock_adapter(adap); return ret; } else { dev_dbg(&adap->dev, "I2C level transfers not supported\n"); return -EOPNOTSUPP; } } //同理write函数也是一样 static ssize_t i2cdev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { int ret; char *tmp; struct i2c_client *client = file->private_data; if (count > 8192) count = 8192; tmp = memdup_user(buf, count); if (IS_ERR(tmp)) return PTR_ERR(tmp); pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", iminor(file->f_path.dentry->d_inode), count); ret = i2c_master_send(client, tmp, count); -----------+ kfree(tmp); | return ret; | } | V int i2c_master_send(const struct i2c_client *client, const char *buf, int count) { int ret; struct i2c_adapter *adap = client->adapter; struct i2c_msg msg; msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.len = count; msg.buf = (char *)buf; ret = i2c_transfer(adap, &msg, 1); /* If everything went ok (i.e. 1 msg transmitted), return #bytes transmitted, else error code. */ return (ret == 1) ? count : ret; }

 

kernel/drivers/i2c/busses/i2c-imx.c

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/294597.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java原来如此-随机数

在Java中&#xff0c;生成随机数有两种方法。1是使用Random类。2是使用Math类中的random方法。 我们现在做个例子&#xff0c;比如生成20个0到10之间的随机数。 1.使用Random类的nextInt(n)方法&#xff0c;n代表0到n之间&#xff0c;包括0&#xff0c;不包括n。 Random random…

python列表双中括号_python – Pandas中双括号`[[…]]`和单括号`[....

考虑一下: 来源DF: In [79]: df Out[79]: Brains Bodies 0 42 34 1 32 23 选择一列 – 导致Pandas.Series: In [80]: df[Brains] Out[80]: 0 42 1 32 Name: Brains, dtype: int64 In [81]: type(df[Brains]) Out[81]: pandas.core.series.Series 选择DataFrame的子集 – 导致…

TableView详解

&#xff0d;、建立 UITableView DataTable [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 420)]; [DataTable setDelegate:self]; [DataTable setDataSource:self]; [self.view addSubview:DataTable]; [DataTable release]; 二、UITableView各Method说明 //Sec…

PowerToys插件扩展(类似Alfred)

在mac系统除了自带的Spotlight还有一个很好用的工具叫Alfredimage在windows系统也有一个很好用的工具叫PowerToys&#xff0c;是微软的一个开源项目imagehttps://github.com/microsoft/PowerToys从上面的github地址可以下载安装包。image它有很多快捷功能&#xff0c;请大家自己…

Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4]

http://blog.csdn.net/shimiso/article/details/8156439 前面几篇给大家系统讲解的有关xmpp openfire smack asmack相关的技术和使用&#xff0c;大家如果有所遗忘可以参考 顺便也一起回顾下xmpp的历程 xmpp协议起源于著名的Linux即时通讯服务服务器jabber,有时候我们会把xmp…

12年前的高考到底有多难,只在这一道题上就看出来了...

▲ 点击查看2008年高考江西数学考卷的最后一题&#xff0c;说是高考史上最恐怖的数学题&#xff0c;应该没有异议。这道题到底有多难呢&#xff1f;最后这道压轴题一共是14分。考试结果出来&#xff0c;所有考生的平均分是0.31分。曾有一位同学这样介绍&#xff1a;“在我们学校…

Cypher查询语言--Neo4j-WHERE(三)

目录 WhereBoolean 操作类型节点属性上的过滤正则表达式转义正则表达式不分大小些正则表达式关系类型上的过滤属性存在性如果缺失属性默认为true如果缺失属性默认为false空置null过滤关系过滤Where 如果需要从查找的数据的图中过滤&#xff0c;可以在查询语句中添加where子句。…

12篇学通C#网络编程——第一篇 基础之进程线程

在C#的网络编程中&#xff0c;进程和线程是必备的基础知识&#xff0c;同时也是一个重点&#xff0c;所以我们要好好的掌握一下。 一&#xff1a;概念 首先我们要知道什么是”进程”&#xff0c;什么是“线程”&#xff0c;好&#xff0c;查一下baike。 进程&#xff1a;是一个…

建立学生选课表 mysql 语句_MySQL常用SQL语句(Python实现学生、课程、选课表增删改查)...

以基本的学生选课为例&#xff0c;建立选课数据库&#xff0c;学生、班级、选课信息三张表&#xff0c;并分别对表进行插删改操作&#xff1a;import MySQLdbtry:conn MySQLdb.connect(host localhost, user root, passwd root, db xuanke, port 3306)cur conn.cursor()…

加快网站访问速度--jquery.js

jquery现在是越来越大&#xff0c;网络加载速度上我们应该做到能省就省&#xff0c;毫无疑问google的服务器和cdn以及访问速度是非常快的&#xff0c;而且google敞开怀抱&#xff0c;提供各种代码库给我们下载调用。jquery就是其中一个。 在jquery官网有从google 微软microsoft…

Android之Google推荐的图片加载库Glide介绍

原文链接:Google推荐的图片加载库Glide介绍作者 : nuuneoi译者 : jianghejie校对者 :

也谈程序员的35岁危机

前言本来这期要推一篇观察者模式和发布订阅模式的技术文给各位看官(在写了)&#xff0c;但无奈最近爱奇艺裁员事件引起了轩然大波&#xff0c;互联网上和各种技术群又展开了轰轰烈烈的讨论&#xff0c;每位IT从业者都不能独善其身。那么今天这一期我们就聊聊程序员的35岁危机究…

豆瓣评分9.4!这部大片你不应该错过,每一秒都是不敢看的残忍!

全世界只有3.14 % 的人关注了爆炸吧知识人类占据了地球上绝大多数宜居的地方&#xff0c;我们面对着温柔的地球母亲&#xff0c;但对野生动物们来说&#xff0c;地球却是一个水深火热的星球。你觉得你已经一无所有了&#xff0c;你觉得生活的负荷已经让你难以前进了&#xff1b…

Unity3D4.* NGUI制作动态字库

新建一个工程&#xff0c;这个工程必须没有中文路径&#xff0c;否则会不识别字体&#xff01;&#xff01;&#xff01; 首先导入NGUI插件&#xff0c;这里我用的是NGUI 3.0.2版本的。 在Assets 下创建一个文件夹&#xff0c;用来存放接下来的工作文件 。 这里随便选择一种字体…

【Mongodb】用户和认证 权限总结

开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以对数据库任意操作而且可以远程访问数据库&#xff01; 在刚安装完毕的时候MongoDB都默认有一个admin数据库,此时admin数据库是空的,没有记录权限相关的信息&#xff01;当admin.system.users一个用户…

java解析json_JAVA解析JSON数据

在使用第三方api的使用&#xff0c;有时候会从网络中获得json数据&#xff0c;所以说我们将如何解析json数据&#xff1f;下面小编将通过以下几点来进行json的讲解JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read…

Android之android studio如何解决‘:app:packageDebug‘.(Duplicate files copied in APK META-INF/DEPENDENCIES)

不废话&#xff0c;先爆照 今天在使用glide的时候&#xff0c;我在项目里面添加了httpcore-4.3.2.jar和4.3.5.jar包&#xff0c;但是当我运行的时候就出现了这个错误 然后在build.gradle里面配置下面的信息就好了&#xff0c; android { packagingOptions { exclude META-IN…

Asp.Net MVC4.0 官方教程 入门指南之一-- 入门介绍

本教程将为您讲解使用微软的Visual Studio 2012 来建立一个ASP.NET MVC4 Web应用程序所需要的基础知识。 本示例将构建什么样的应用程序&#xff1f; 您将实现一个简单的电影管理应用程序&#xff0c;此程序将从数据库中选取记录展示列表&#xff0c;支持查询和查看&#xff0…

关注!这所211高校通知不放寒假!校园将实行封闭管理!

全世界只有3.14 % 的人关注了爆炸吧知识本文转自&#xff1a;募格学术新年伊始&#xff0c;北京顺义&#xff0c;辽宁大连、沈阳&#xff0c;黑龙江黑河&#xff0c;河北石家庄、邢台等地相继报告新增本土病例&#xff0c;随着春节的临近&#xff0c;人员流动和聚集增加&#x…

MediatR 在.NET应用中的实践

MediatR 简介MediatR是.NET中的开源简单中介者模式实现.它通过一种进程内消息传递机制&#xff08;无其他外部依赖&#xff09;&#xff0c;进行请求/响应、命令、查询、通知和事件的消息传递&#xff0c;并通过泛型来支持消息的智能调度。开源库地址是https://github.com/jbog…