root/i2c-tools/trunk/py-smbus/smbusmodule.c

Revision 4451, 16.3 kB (checked in by mmh, 1 year ago)

ported r4446 from trunk

Line 
1 /*
2  * smbusmodule.c - Python bindings for Linux SMBus access through i2c-dev
3  * Copyright (C) 2005-2007 Mark M. Hoffman <mhoffman@lightlink.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; version 2 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #include <Python.h>
20 #include "structmember.h"
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <linux/i2c-dev.h>
25
26 /*
27 ** These are required to build this module against Linux older than 2.6.23.
28 */
29 #ifndef I2C_SMBUS_I2C_BLOCK_BROKEN
30 #undef I2C_SMBUS_I2C_BLOCK_DATA
31 #define I2C_SMBUS_I2C_BLOCK_BROKEN      6
32 #define I2C_SMBUS_I2C_BLOCK_DATA        8
33 #endif
34
35 PyDoc_STRVAR(SMBus_module_doc,
36         "This module defines an object type that allows SMBus transactions\n"
37         "on Linux hosts.  The host kernel must have I2C support, I2C device\n"
38         "interface support, and a bus adapter driver.  All of these can be\n"
39         "either built-in to the kernel, or loaded from modules.\n"
40         "\n"
41         "Because the I2C device interface is opened R/W, users of this\n"
42         "module usually must have root permissions.\n");
43
44 typedef struct {
45         PyObject_HEAD
46
47         int fd;         /* open file descriptor: /dev/i2c-?, or -1 */
48         int addr;       /* current client SMBus address */
49         int pec;        /* !0 => Packet Error Codes enabled */
50 } SMBus;
51
52 static PyObject *
53 SMBus_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
54 {
55         SMBus *self;
56
57         if ((self = (SMBus *)type->tp_alloc(type, 0)) == NULL)
58                 return NULL;
59
60         self->fd = -1;
61         self->addr = -1;
62         self->pec = 0;
63
64         return (PyObject *)self;
65 }
66
67 PyDoc_STRVAR(SMBus_close_doc,
68         "close()\n\n"
69         "Disconnects the object from the bus.\n");
70
71 static PyObject *
72 SMBus_close(SMBus *self)
73 {
74         if ((self->fd != -1) && (close(self->fd) == -1)) {
75                 PyErr_SetFromErrno(PyExc_IOError);
76                 return NULL;
77         }
78
79         self->fd = -1;
80         self->addr = -1;
81         self->pec = 0;
82
83         Py_INCREF(Py_None);
84         return Py_None;
85 }
86
87 static void
88 SMBus_dealloc(SMBus *self)
89 {
90         PyObject *ref = SMBus_close(self);
91         Py_XDECREF(ref);
92
93         self->ob_type->tp_free((PyObject *)self);
94 }
95
96 #define MAXPATH 16
97
98 PyDoc_STRVAR(SMBus_open_doc,
99         "open(bus)\n\n"
100         "Connects the object to the specified SMBus.\n");
101
102 static PyObject *
103 SMBus_open(SMBus *self, PyObject *args, PyObject *kwds)
104 {
105         int bus;
106         char path[MAXPATH];
107
108         static char *kwlist[] = {"bus", NULL};
109
110         if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:open", kwlist, &bus))
111                 return NULL;
112
113         if (snprintf(path, MAXPATH, "/dev/i2c-%d", bus) >= MAXPATH) {
114                 PyErr_SetString(PyExc_OverflowError,
115                         "Bus number is invalid.");
116                 return NULL;
117         }
118
119         if ((self->fd = open(path, O_RDWR, 0)) == -1) {
120                 PyErr_SetFromErrno(PyExc_IOError);
121                 return NULL;
122         }
123
124         Py_INCREF(Py_None);
125         return Py_None;
126 }
127
128 static int
129 SMBus_init(SMBus *self, PyObject *args, PyObject *kwds)
130 {
131         int bus = -1;
132
133         static char *kwlist[] = {"bus", NULL};
134
135         if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:__init__",
136                         kwlist, &bus))
137                 return -1;
138
139         if (bus >= 0) {
140                 SMBus_open(self, args, kwds);
141                 if (PyErr_Occurred())
142                         return -1;
143         }
144
145         return 0;
146 }
147
148 /*
149  * private helper function, 0 => success, !0 => error
150  */
151 static int
152 SMBus_set_addr(SMBus *self, int addr)
153 {
154         int ret = 0;
155
156         if (self->addr != addr) {
157                 ret = ioctl(self->fd, I2C_SLAVE, addr);
158                 self->addr = addr;
159         }
160
161         return ret;
162 }
163
164 #define SMBus_SET_ADDR(self, addr) do { \
165         if (SMBus_set_addr(self, addr)) { \
166                 PyErr_SetFromErrno(PyExc_IOError); \
167                 return NULL; \
168         } \
169 } while(0)
170
171 PyDoc_STRVAR(SMBus_write_quick_doc,
172         "write_quick(addr)\n\n"
173         "Perform SMBus Quick transaction.\n");
174
175 static PyObject *
176 SMBus_write_quick(SMBus *self, PyObject *args)
177 {
178         int addr;
179         __s32 result;
180
181         if (!PyArg_ParseTuple(args, "i:write_quick", &addr))
182                 return NULL;
183
184         SMBus_SET_ADDR(self, addr);
185
186         if ((result = i2c_smbus_write_quick(self->fd, I2C_SMBUS_WRITE))) {
187                 PyErr_SetFromErrno(PyExc_IOError);
188                 return NULL;
189         }
190
191         Py_INCREF(Py_None);
192         return Py_None;
193 }
194
195 PyDoc_STRVAR(SMBus_read_byte_doc,
196         "read_byte(addr) -> result\n\n"
197         "Perform SMBus Read Byte transaction.\n");
198
199 static PyObject *
200 SMBus_read_byte(SMBus *self, PyObject *args)
201 {
202         int addr;
203         __s32 result;
204
205         if (!PyArg_ParseTuple(args, "i:read_byte", &addr))
206                 return NULL;
207
208         SMBus_SET_ADDR(self, addr);
209
210         if ((result = i2c_smbus_read_byte(self->fd)) == -1) {
211                 PyErr_SetFromErrno(PyExc_IOError);
212                 return NULL;
213         }
214
215         return Py_BuildValue("l", (long)result);
216 }
217
218 PyDoc_STRVAR(SMBus_write_byte_doc,
219         "write_byte(addr, val)\n\n"
220         "Perform SMBus Write Byte transaction.\n");
221
222 static PyObject *
223 SMBus_write_byte(SMBus *self, PyObject *args)
224 {
225         int addr, val;
226         __s32 result;
227
228         if (!PyArg_ParseTuple(args, "ii:write_byte", &addr, &val))
229                 return NULL;
230
231         SMBus_SET_ADDR(self, addr);
232
233         if ((result = i2c_smbus_write_byte(self->fd, (__u8)val)) == -1) {
234                 PyErr_SetFromErrno(PyExc_IOError);
235                 return NULL;
236         }
237
238         Py_INCREF(Py_None);
239         return Py_None;
240 }
241
242 PyDoc_STRVAR(SMBus_read_byte_data_doc,
243         "read_byte_data(addr, cmd) -> result\n\n"
244         "Perform SMBus Read Byte Data transaction.\n");
245
246 static PyObject *
247 SMBus_read_byte_data(SMBus *self, PyObject *args)
248 {
249         int addr, cmd;
250         __s32 result;
251
252         if (!PyArg_ParseTuple(args, "ii:read_byte_data", &addr, &cmd))
253                 return NULL;
254
255         SMBus_SET_ADDR(self, addr);
256
257         if ((result = i2c_smbus_read_byte_data(self->fd, (__u8)cmd)) == -1) {
258                 PyErr_SetFromErrno(PyExc_IOError);
259                 return NULL;
260         }
261
262         return Py_BuildValue("l", (long)result);
263 }
264
265 PyDoc_STRVAR(SMBus_write_byte_data_doc,
266         "write_byte_data(addr, cmd, val)\n\n"
267         "Perform SMBus Write Byte Data transaction.\n");
268
269 static PyObject *
270 SMBus_write_byte_data(SMBus *self, PyObject *args)
271 {
272         int addr, cmd, val;
273         __s32 result;
274
275         if (!PyArg_ParseTuple(args, "iii:write_byte_data", &addr, &cmd, &val))
276                 return NULL;
277
278         SMBus_SET_ADDR(self, addr);
279
280         if ((result = i2c_smbus_write_byte_data(self->fd,
281                                 (__u8)cmd, (__u8)val)) == -1) {
282                 PyErr_SetFromErrno(PyExc_IOError);
283                 return NULL;
284         }
285
286         Py_INCREF(Py_None);
287         return Py_None;
288 }
289
290 PyDoc_STRVAR(SMBus_read_word_data_doc,
291         "read_word_data(addr, cmd) -> result\n\n"
292         "Perform SMBus Read Word Data transaction.\n");
293
294 static PyObject *
295 SMBus_read_word_data(SMBus *self, PyObject *args)
296 {
297         int addr, cmd;
298         __s32 result;
299
300         if (!PyArg_ParseTuple(args, "ii:read_word_data", &addr, &cmd))
301                 return NULL;
302
303         SMBus_SET_ADDR(self, addr);
304
305         if ((result = i2c_smbus_read_word_data(self->fd, (__u8)cmd)) == -1) {
306                 PyErr_SetFromErrno(PyExc_IOError);
307                 return NULL;
308         }
309
310         return Py_BuildValue("l", (long)result);
311 }
312
313 PyDoc_STRVAR(SMBus_write_word_data_doc,
314         "write_word_data(addr, cmd, val)\n\n"
315         "Perform SMBus Write Word Data transaction.\n");
316
317 static PyObject *
318 SMBus_write_word_data(SMBus *self, PyObject *args)
319 {
320         int addr, cmd, val;
321         __s32 result;
322
323         if (!PyArg_ParseTuple(args, "iii:write_word_data", &addr, &cmd, &val))
324                 return NULL;
325
326         SMBus_SET_ADDR(self, addr);
327
328         if ((result = i2c_smbus_write_word_data(self->fd,
329                                 (__u8)cmd, (__u16)val)) == -1) {
330                 PyErr_SetFromErrno(PyExc_IOError);
331                 return NULL;
332         }
333
334         Py_INCREF(Py_None);
335         return Py_None;
336 }
337
338 PyDoc_STRVAR(SMBus_process_call_doc,
339         "process_call(addr, cmd, val)\n\n"
340         "Perform SMBus Process Call transaction.\n");
341
342 static PyObject *
343 SMBus_process_call(SMBus *self, PyObject *args)
344 {
345         int addr, cmd, val;
346         __s32 result;
347
348         if (!PyArg_ParseTuple(args, "iii:process_call", &addr, &cmd, &val))
349                 return NULL;
350
351         SMBus_SET_ADDR(self, addr);
352
353         if ((result = i2c_smbus_process_call(self->fd,
354                                 (__u8)cmd, (__u16)val)) == -1) {
355                 PyErr_SetFromErrno(PyExc_IOError);
356                 return NULL;
357         }
358
359         Py_INCREF(Py_None);
360         return Py_None;
361 }
362
363 /*
364  * private helper function; returns a new list of integers
365  */
366 static PyObject *
367 SMBus_buf_to_list(__u8 const *buf, int len)
368 {
369         PyObject *list = PyList_New(len);
370         int ii;
371
372         if (list == NULL)
373                 return NULL;
374
375         for (ii = 0; ii < len; ii++) {
376                 PyObject *val = Py_BuildValue("l", (long)buf[ii]);
377                 PyList_SET_ITEM(list, ii, val);
378         }
379         return list;
380 }
381
382 PyDoc_STRVAR(SMBus_read_block_data_doc,
383         "read_block_data(addr, cmd) -> results\n\n"
384         "Perform SMBus Read Block Data transaction.\n");
385
386 static PyObject *
387 SMBus_read_block_data(SMBus *self, PyObject *args)
388 {
389         int addr, cmd;
390         union i2c_smbus_data data;
391
392         if (!PyArg_ParseTuple(args, "ii:read_block_data", &addr, &cmd))
393                 return NULL;
394
395         SMBus_SET_ADDR(self, addr);
396
397         /* save a bit of code by calling the access function directly */
398         if (i2c_smbus_access(self->fd, I2C_SMBUS_READ, (__u8)cmd,
399                                 I2C_SMBUS_BLOCK_DATA, &data)) {
400                 PyErr_SetFromErrno(PyExc_IOError);
401                 return NULL;
402         }
403
404         /* first byte of the block contains (remaining) data length */
405         return SMBus_buf_to_list(&data.block[1], data.block[0]);
406 }
407
408 /*
409  * private helper function: convert an integer list to union i2c_smbus_data
410  */
411 static int
412 SMBus_list_to_data(PyObject *list, union i2c_smbus_data *data)
413 {
414         static char *msg = "Third argument must be a list of at least one, "
415                                 "but not more than 32 integers";
416         int ii, len;
417
418         if (!PyList_Check(list)) {
419                 PyErr_SetString(PyExc_TypeError, msg);
420                 return 0; /* fail */
421         }
422
423         if ((len = PyList_GET_SIZE(list)) > 32) {
424                 PyErr_SetString(PyExc_OverflowError, msg);
425                 return 0; /* fail */
426         }
427
428         /* first byte is the length */
429         data->block[0] = (__u8)len;
430
431         for (ii = 0; ii < len; ii++) {
432                 PyObject *val = PyList_GET_ITEM(list, ii);
433                 if (!PyInt_Check(val)) {
434                         PyErr_SetString(PyExc_TypeError, msg);
435                         return 0; /* fail */
436                 }
437                 data->block[ii+1] = (__u8)PyInt_AS_LONG(val);
438         }
439
440         return 1; /* success */
441 }
442
443 PyDoc_STRVAR(SMBus_write_block_data_doc,
444         "write_block_data(addr, cmd, [vals])\n\n"
445         "Perform SMBus Write Block Data transaction.\n");
446
447 static PyObject *
448 SMBus_write_block_data(SMBus *self, PyObject *args)
449 {
450         int addr, cmd;
451         union i2c_smbus_data data;
452
453         if (!PyArg_ParseTuple(args, "iiO&:write_block_data", &addr, &cmd,
454                                 SMBus_list_to_data, &data))
455                 return NULL;
456
457         SMBus_SET_ADDR(self, addr);
458
459         /* save a bit of code by calling the access function directly */
460         if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
461                                 I2C_SMBUS_BLOCK_DATA, &data)) {
462                 PyErr_SetFromErrno(PyExc_IOError);
463                 return NULL;
464         }
465
466         Py_INCREF(Py_None);
467         return Py_None;
468 }
469
470 PyDoc_STRVAR(SMBus_block_process_call_doc,
471         "block_process_call(addr, cmd, [vals]) -> results\n\n"
472         "Perform SMBus Block Process Call transaction.\n");
473
474 static PyObject *
475 SMBus_block_process_call(SMBus *self, PyObject *args)
476 {
477         int addr, cmd;
478         union i2c_smbus_data data;
479
480         if (!PyArg_ParseTuple(args, "iiO&:block_process_call", &addr, &cmd,
481                         SMBus_list_to_data, &data))
482                 return NULL;
483
484         SMBus_SET_ADDR(self, addr);
485
486         /* save a bit of code by calling the access function directly */
487         if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
488                                 I2C_SMBUS_BLOCK_PROC_CALL, &data)) {
489                 PyErr_SetFromErrno(PyExc_IOError);
490                 return NULL;
491         }
492
493         /* first byte of the block contains (remaining) data length */
494         return SMBus_buf_to_list(&data.block[1], data.block[0]);
495 }
496
497 PyDoc_STRVAR(SMBus_read_i2c_block_data_doc,
498         "read_i2c_block_data(addr, cmd, len=32) -> results\n\n"
499         "Perform I2C Block Read transaction.\n");
500
501 static PyObject *
502 SMBus_read_i2c_block_data(SMBus *self, PyObject *args)
503 {
504         int addr, cmd, len=32;
505         union i2c_smbus_data data;
506
507         if (!PyArg_ParseTuple(args, "ii|i:read_i2c_block_data", &addr, &cmd,
508                         &len))
509                 return NULL;
510
511         SMBus_SET_ADDR(self, addr);
512
513         data.block[0] = len;
514         /* save a bit of code by calling the access function directly */
515         if (i2c_smbus_access(self->fd, I2C_SMBUS_READ, (__u8)cmd,
516                                 len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN:
517                                 I2C_SMBUS_I2C_BLOCK_DATA, &data)) {
518                 PyErr_SetFromErrno(PyExc_IOError);
519                 return NULL;
520         }
521
522         /* first byte of the block contains (remaining) data length */
523         return SMBus_buf_to_list(&data.block[1], data.block[0]);
524 }
525
526 PyDoc_STRVAR(SMBus_write_i2c_block_data_doc,
527         "write_i2c_block_data(addr, cmd, [vals])\n\n"
528         "Perform I2C Block Write transaction.\n");
529
530 static PyObject *
531 SMBus_write_i2c_block_data(SMBus *self, PyObject *args)
532 {
533         int addr, cmd;
534         union i2c_smbus_data data;
535
536         if (!PyArg_ParseTuple(args, "iiO&:write_i2c_block_data", &addr, &cmd,
537                         SMBus_list_to_data, &data))
538                 return NULL;
539
540         SMBus_SET_ADDR(self, addr);
541
542         /* save a bit of code by calling the access function directly */
543         if (i2c_smbus_access(self->fd, I2C_SMBUS_WRITE, (__u8)cmd,
544                                 I2C_SMBUS_I2C_BLOCK_BROKEN, &data)) {
545                 PyErr_SetFromErrno(PyExc_IOError);
546                 return NULL;
547         }
548
549         Py_INCREF(Py_None);
550         return Py_None;
551 }
552
553 PyDoc_STRVAR(SMBus_type_doc,
554         "SMBus([bus]) -> SMBus\n\n"
555         "Return a new SMBus object that is (optionally) connected to the\n"
556         "specified I2C device interface.\n");
557
558 static PyMethodDef SMBus_methods[] = {
559         {"open", (PyCFunction)SMBus_open, METH_VARARGS | METH_KEYWORDS,
560                 SMBus_open_doc},
561         {"close", (PyCFunction)SMBus_close, METH_NOARGS,
562                 SMBus_close_doc},
563         {"write_quick", (PyCFunction)SMBus_write_quick, METH_VARARGS,
564                 SMBus_write_quick_doc},
565         {"read_byte", (PyCFunction)SMBus_read_byte, METH_VARARGS,
566                 SMBus_read_byte_doc},
567         {"write_byte", (PyCFunction)SMBus_write_byte, METH_VARARGS,
568                 SMBus_write_byte_doc},
569         {"read_byte_data", (PyCFunction)SMBus_read_byte_data, METH_VARARGS,
570                 SMBus_read_byte_data_doc},
571         {"write_byte_data", (PyCFunction)SMBus_write_byte_data, METH_VARARGS,
572                 SMBus_write_byte_data_doc},
573         {"read_word_data", (PyCFunction)SMBus_read_word_data, METH_VARARGS,
574                 SMBus_read_word_data_doc},
575         {"write_word_data", (PyCFunction)SMBus_write_word_data, METH_VARARGS,
576                 SMBus_write_word_data_doc},
577         {"process_call", (PyCFunction)SMBus_process_call, METH_VARARGS,
578                 SMBus_process_call_doc},
579         {"read_block_data", (PyCFunction)SMBus_read_block_data, METH_VARARGS,
580                 SMBus_read_block_data_doc},
581         {"write_block_data", (PyCFunction)SMBus_write_block_data, METH_VARARGS,
582                 SMBus_write_block_data_doc},
583         {"block_process_call", (PyCFunction)SMBus_block_process_call,
584                 METH_VARARGS, SMBus_block_process_call_doc},
585         {"read_i2c_block_data", (PyCFunction)SMBus_read_i2c_block_data,
586                 METH_VARARGS, SMBus_read_i2c_block_data_doc},
587         {"write_i2c_block_data", (PyCFunction)SMBus_write_i2c_block_data,
588                 METH_VARARGS, SMBus_write_i2c_block_data_doc},
589         {NULL},
590 };
591
592 static PyObject *
593 SMBus_get_pec(SMBus *self, void *closure)
594 {
595         PyObject *result = self->pec ? Py_True : Py_False;
596         Py_INCREF(result);
597         return result;
598 }
599
600 static int
601 SMBus_set_pec(SMBus *self, PyObject *val, void *closure)
602 {
603         int pec;
604
605         pec = PyObject_IsTrue(val);
606
607         if (val == NULL) {
608                 PyErr_SetString(PyExc_TypeError,
609                         "Cannot delete attribute");
610                 return -1;
611         }
612         else if (pec == -1) {
613                 PyErr_SetString(PyExc_TypeError,
614                         "The pec attribute must be a boolean.");
615                 return -1;
616         }
617
618         if (self->pec != pec) {
619                 if (ioctl(self->fd, I2C_PEC, pec)) {
620                         PyErr_SetFromErrno(PyExc_IOError);
621                         return -1;
622                 }
623                 self->pec = pec;
624         }
625
626         return 0;
627 }
628
629 static PyGetSetDef SMBus_getset[] = {
630         {"pec", (getter)SMBus_get_pec, (setter)SMBus_set_pec,
631                         "True if Packet Error Codes (PEC) are enabled"},
632         {NULL},
633 };
634
635 static PyTypeObject SMBus_type = {
636         PyObject_HEAD_INIT(NULL)
637         0,                              /* ob_size */
638         "SMBus",                        /* tp_name */
639         sizeof(SMBus),                  /* tp_basicsize */
640         0,                              /* tp_itemsize */
641         (destructor)SMBus_dealloc,      /* tp_dealloc */
642         0,                              /* tp_print */
643         0,                              /* tp_getattr */
644         0,                              /* tp_setattr */
645         0,                              /* tp_compare */
646         0,                              /* tp_repr */
647         0,                              /* tp_as_number */
648         0,                              /* tp_as_sequence */
649         0,                              /* tp_as_mapping */
650         0,                              /* tp_hash */
651         0,                              /* tp_call */
652         0,                              /* tp_str */
653         0,                              /* tp_getattro */
654         0,                              /* tp_setattro */
655         0,                              /* tp_as_buffer */
656         Py_TPFLAGS_DEFAULT,             /* tp_flags */
657         SMBus_type_doc,                 /* tp_doc */
658         0,                              /* tp_traverse */
659         0,                              /* tp_clear */
660         0,                              /* tp_richcompare */
661         0,                              /* tp_weaklistoffset */
662         0,                              /* tp_iter */
663         0,                              /* tp_iternext */
664         SMBus_methods,                  /* tp_methods */
665         0,                              /* tp_members */
666         SMBus_getset,                   /* tp_getset */
667         0,                              /* tp_base */
668         0,                              /* tp_dict */
669         0,                              /* tp_descr_get */
670         0,                              /* tp_descr_set */
671         0,                              /* tp_dictoffset */
672         (initproc)SMBus_init,           /* tp_init */
673         0,                              /* tp_alloc */
674         SMBus_new,                      /* tp_new */
675 };
676
677 static PyMethodDef SMBus_module_methods[] = {
678         {NULL}
679 };
680
681 #ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
682 #define PyMODINIT_FUNC void
683 #endif
684 PyMODINIT_FUNC
685 initsmbus(void)
686 {
687         PyObject* m;
688
689         if (PyType_Ready(&SMBus_type) < 0)
690                 return;
691
692         m = Py_InitModule3("smbus", SMBus_module_methods, SMBus_module_doc);
693
694         Py_INCREF(&SMBus_type);
695         PyModule_AddObject(m, "SMBus", (PyObject *)&SMBus_type);
696 }
697
Note: See TracBrowser for help on using the browser.