libi2c_usb.c 4.14 KB
Newer Older
1
/* Copyright(C) 2006,2007,2008 Jochen Roessner <jochen@lugrot.de>
jochen's avatar
jochen committed
2

3 4 5 6
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
jochen's avatar
jochen committed
7

8 9 10 11
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
jochen's avatar
jochen committed
12

13 14 15 16
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software Foundation,
 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/
jochen's avatar
jochen committed
17
 
jochen's avatar
jochen committed
18 19
#include <sys/stat.h>
#include <fcntl.h>
jochen's avatar
jochen committed
20 21 22 23
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
jochen's avatar
jochen committed
24
#include <time.h>
jochen's avatar
jochen committed
25
#include <usb.h>
jochen's avatar
jochen committed
26
#define LCKFILE "/dev/shm/usb2i2c.lck"
jochen's avatar
jochen committed
27

jochen's avatar
jochen committed
28 29 30 31 32 33 34 35 36
enum
{
	// Generic requests
	USBI2C_READ = 20,
	USBI2C_WRITE,
	USBI2C_STOP,
	USBI2C_STAT,
};

37 38 39 40
struct i2cdev { 
	usb_dev_handle *usbdev;
	int addr;
};
jochen's avatar
jochen committed
41

jochen's avatar
jochen committed
42 43 44
/* open usb2i2c adapter device and set things up to be ready for i2c bus
 * communication.
 */
45 46
struct i2cdev*
i2c_open(const char *device, int addr)
jochen's avatar
jochen committed
47
{
48 49 50 51 52
	struct i2cdev *handle;
	if((handle = malloc(sizeof(*handle))) == NULL){
		perror("malloc");
		return 0;
	}
jochen's avatar
jochen committed
53
	struct usb_bus *bus;
54 55
	unsigned int idVendor;
	unsigned int idProduct;
56 57
	if (sscanf(device, "%04x%04x", &idVendor, &idProduct) == 2)
	{
58 59 60
		usb_init();
		usb_find_busses();
		usb_find_devices();
61 62
		for (bus = usb_busses; bus; bus = bus->next)
		{
jochen's avatar
jochen committed
63
			struct usb_device *dev;
64 65
			for (dev = bus->devices; dev; dev = dev->next)
			{
jochen's avatar
jochen committed
66 67
				usb_dev_handle *usb_bus_dev;
				usb_bus_dev = usb_open(dev);
68 69 70 71 72
				if (usb_bus_dev)
				{
					if (dev->descriptor.idVendor == idVendor &&
									 dev->descriptor.idProduct == idProduct)
					{
jochen's avatar
jochen committed
73
						/* usb i2c adapter gefunden */
74 75
						//printf ("gefunden! devnr: %i %04X - %04X\n",1,
						//				dev->descriptor.idVendor, dev->descriptor.idProduct);
76 77
						handle->usbdev = usb_bus_dev;
						handle->addr = addr;
jochen's avatar
jochen committed
78 79 80 81 82 83
						/* wenn ein altes lock file vorhanden ist, dann loeschen */
						struct stat lckstat;
						if(stat(LCKFILE, &lckstat) == 0){
							if(lckstat.st_mtime < time(NULL)-10)
								unlink(LCKFILE);
						}
84
						return handle;
jochen's avatar
jochen committed
85
					}
jochen's avatar
jochen committed
86 87 88
				}
				if (usb_bus_dev)
					usb_close(usb_bus_dev);
jochen's avatar
jochen committed
89 90 91
			}
		}
	}
92
	fprintf(stderr,"keinen Adapter am usb gefunden\n");
93
	return 0;
jochen's avatar
jochen committed
94 95 96
}


97 98
/* detach the i2c bus and close usb device */
int
99 100 101 102 103 104
i2c_close(struct i2cdev *handle)
{
	if(handle != NULL)
	{
		usb_control_msg(handle->usbdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_ENDPOINT_IN, USBI2C_STOP, 0, 0, 0, 0, 500);
		usb_close(handle->usbdev);
jochen's avatar
jochen committed
105
		unlink(LCKFILE);	
106
		return 1;
107 108 109
	}
	return -1;
}
jochen's avatar
jochen committed
110 111 112

/* send data to i2c device
 */
113 114
int
i2c_send(struct i2cdev *handle, const unsigned char *data, int len)
jochen's avatar
jochen committed
115
{
jochen's avatar
jochen committed
116
	int ret = -1;
jochen's avatar
jochen committed
117 118
	int lckfd;
	int maxtry = 0;
119 120 121
	do
	{
		lckfd = open(LCKFILE, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
jochen's avatar
jochen committed
122
		usleep(10000);
123 124 125
	}
	while( lckfd < 0 && maxtry++ < 200);
	if(handle != NULL && maxtry < 200)
jochen's avatar
jochen committed
126
	{
127 128 129 130
		ret = usb_control_msg(handle->usbdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | 
				USB_ENDPOINT_OUT, USBI2C_WRITE, 0, handle->addr, (char*) data, len, 500);
		if ( ret == len )
		{
131
			char buf[16];
132
			ret = usb_control_msg(handle->usbdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | 
133
					USB_ENDPOINT_IN, USBI2C_STAT, 0, 0, (char*)&buf[0], 1, 500);
134 135
			if (ret == 1)
			{
136 137 138 139 140 141
				if(buf[0] != 0)
					ret = (int)buf[0]*-1;
				else
					ret = len;
			}
		}
jochen's avatar
jochen committed
142 143
		close(lckfd);
		unlink(LCKFILE);	
jochen's avatar
jochen committed
144 145
	}
	return ret; /* > 0 = ok */
jochen's avatar
jochen committed
146 147 148 149 150 151 152
}



/* read data from i2c device
 */
int
153
i2c_recv(struct i2cdev *handle, unsigned char *buf, int len)
jochen's avatar
jochen committed
154
{
jochen's avatar
jochen committed
155
	int ret = -1;
156
	int aktlen = len;
jochen's avatar
jochen committed
157 158
	int lckfd;
	int maxtry = 0;
159 160 161
	do
	{
		lckfd = open(LCKFILE, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
jochen's avatar
jochen committed
162
		usleep(10000);
163 164 165
	}
	while( lckfd < 0 && maxtry++ < 200);
	if(handle != NULL && maxtry < 200)
jochen's avatar
jochen committed
166
	{
jochen's avatar
jochen committed
167
		ret = 0;
168 169 170
		do
		{
			ret += usb_control_msg(handle->usbdev, USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_ENDPOINT_IN, USBI2C_READ, 0, handle->addr, (char*)buf+len-aktlen, aktlen, 500);
171
			aktlen -= 255;
172 173
		}
		while(aktlen > 0);
jochen's avatar
jochen committed
174 175
		close(lckfd);
		unlink(LCKFILE);
jochen's avatar
jochen committed
176 177
	}
	return ret; /* > 0 = ok */
jochen's avatar
jochen committed
178
}