ds2490.c 20 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2
 *	dscore.c
Linus Torvalds's avatar
Linus Torvalds committed
3
4
 *
 * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
5
 *
Linus Torvalds's avatar
Linus Torvalds committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 * 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 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/usb.h>

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "../w1_int.h"
#include "../w1.h"

/* COMMAND TYPE CODES */
#define CONTROL_CMD			0x00
#define COMM_CMD			0x01
#define MODE_CMD			0x02

/* CONTROL COMMAND CODES */
#define CTL_RESET_DEVICE		0x0000
#define CTL_START_EXE			0x0001
#define CTL_RESUME_EXE			0x0002
#define CTL_HALT_EXE_IDLE		0x0003
#define CTL_HALT_EXE_DONE		0x0004
#define CTL_FLUSH_COMM_CMDS		0x0007
#define CTL_FLUSH_RCV_BUFFER		0x0008
#define CTL_FLUSH_XMT_BUFFER		0x0009
#define CTL_GET_COMM_CMDS		0x000A

/* MODE COMMAND CODES */
#define MOD_PULSE_EN			0x0000
#define MOD_SPEED_CHANGE_EN		0x0001
#define MOD_1WIRE_SPEED			0x0002
#define MOD_STRONG_PU_DURATION		0x0003
#define MOD_PULLDOWN_SLEWRATE		0x0004
#define MOD_PROG_PULSE_DURATION		0x0005
#define MOD_WRITE1_LOWTIME		0x0006
#define MOD_DSOW0_TREC			0x0007

/* COMMUNICATION COMMAND CODES */
#define COMM_ERROR_ESCAPE		0x0601
#define COMM_SET_DURATION		0x0012
#define COMM_BIT_IO			0x0020
#define COMM_PULSE			0x0030
#define COMM_1_WIRE_RESET		0x0042
#define COMM_BYTE_IO			0x0052
#define COMM_MATCH_ACCESS		0x0064
#define COMM_BLOCK_IO			0x0074
#define COMM_READ_STRAIGHT		0x0080
#define COMM_DO_RELEASE			0x6092
#define COMM_SET_PATH			0x00A2
#define COMM_WRITE_SRAM_PAGE		0x00B2
#define COMM_WRITE_EPROM		0x00C4
#define COMM_READ_CRC_PROT_PAGE		0x00D4
#define COMM_READ_REDIRECT_PAGE_CRC	0x21E4
#define COMM_SEARCH_ACCESS		0x00F4

/* Communication command bits */
#define COMM_TYPE			0x0008
#define COMM_SE				0x0008
#define COMM_D				0x0008
#define COMM_Z				0x0008
#define COMM_CH				0x0008
#define COMM_SM				0x0008
#define COMM_R				0x0008
#define COMM_IM				0x0001

#define COMM_PS				0x4000
#define COMM_PST			0x4000
#define COMM_CIB			0x4000
#define COMM_RTS			0x4000
#define COMM_DT				0x2000
#define COMM_SPU			0x1000
#define COMM_F				0x0800
#define COMM_NTP			0x0400
#define COMM_ICP			0x0200
#define COMM_RST			0x0100

#define PULSE_PROG			0x01
#define PULSE_SPUE			0x02

#define BRANCH_MAIN			0xCC
#define BRANCH_AUX			0x33

/*
 * Duration of the strong pull-up pulse in milliseconds.
 */
#define PULLUP_PULSE_DURATION		750

/* Status flags */
#define ST_SPUA				0x01  /* Strong Pull-up is active */
#define ST_PRGA				0x02  /* 12V programming pulse is being generated */
#define ST_12VP				0x04  /* external 12V programming voltage is present */
#define ST_PMOD				0x08  /* DS2490 powered from USB and external sources */
#define ST_HALT				0x10  /* DS2490 is currently halted */
#define ST_IDLE				0x20  /* DS2490 is currently idle */
#define ST_EPOF				0x80

#define SPEED_NORMAL			0x00
#define SPEED_FLEXIBLE			0x01
#define SPEED_OVERDRIVE			0x02

#define NUM_EP				4
#define EP_CONTROL			0
#define EP_STATUS			1
#define EP_DATA_OUT			2
#define EP_DATA_IN			3

struct ds_device
{
	struct list_head	ds_entry;

	struct usb_device	*udev;
	struct usb_interface	*intf;

	int			ep[NUM_EP];

	struct w1_bus_master	master;
};

struct ds_status
{
	u8			enable;
	u8			speed;
	u8			pullup_dur;
	u8			ppuls_dur;
	u8			pulldown_slew;
	u8			write1_time;
	u8			write0_time;
	u8			reserved0;
	u8			status;
	u8			command0;
	u8			command1;
	u8			command_buffer_status;
	u8			data_out_buffer_status;
	u8			data_in_buffer_status;
	u8			reserved1;
	u8			reserved2;

};
Linus Torvalds's avatar
Linus Torvalds committed
157
158
159
160
161
162
163

static struct usb_device_id ds_id_table [] = {
	{ USB_DEVICE(0x04fa, 0x2490) },
	{ },
};
MODULE_DEVICE_TABLE(usb, ds_id_table);

164
165
static int ds_probe(struct usb_interface *, const struct usb_device_id *);
static void ds_disconnect(struct usb_interface *);
Linus Torvalds's avatar
Linus Torvalds committed
166
167
168
169
170

static inline void ds_dump_status(unsigned char *, unsigned char *, int);
static int ds_send_control(struct ds_device *, u16, u16);
static int ds_send_control_cmd(struct ds_device *, u16, u16);

171
172
static LIST_HEAD(ds_devices);
static DECLARE_MUTEX(ds_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
173
174
175
176
177
178
179
180
181
182
183

static struct usb_driver ds_driver = {
	.name =		"DS9490R",
	.probe =	ds_probe,
	.disconnect =	ds_disconnect,
	.id_table =	ds_id_table,
};

static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
{
	int err;
184
185

	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
Linus Torvalds's avatar
Linus Torvalds committed
186
187
			CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
	if (err < 0) {
188
		printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
Linus Torvalds's avatar
Linus Torvalds committed
189
190
191
192
193
194
				value, index, err);
		return err;
	}

	return err;
}
195
#if 0
Linus Torvalds's avatar
Linus Torvalds committed
196
197
198
static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
{
	int err;
199
200

	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
Linus Torvalds's avatar
Linus Torvalds committed
201
202
			MODE_CMD, 0x40, value, index, NULL, 0, 1000);
	if (err < 0) {
203
		printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
Linus Torvalds's avatar
Linus Torvalds committed
204
205
206
207
208
209
				value, index, err);
		return err;
	}

	return err;
}
210
#endif
Linus Torvalds's avatar
Linus Torvalds committed
211
212
213
static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
{
	int err;
214
215

	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
Linus Torvalds's avatar
Linus Torvalds committed
216
217
			COMM_CMD, 0x40, value, index, NULL, 0, 1000);
	if (err < 0) {
218
		printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
Linus Torvalds's avatar
Linus Torvalds committed
219
220
221
222
223
224
225
226
227
228
229
230
				value, index, err);
		return err;
	}

	return err;
}

static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
{
	printk("%45s: %8x\n", str, buf[off]);
}

231
232
static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
				 unsigned char *buf, int size)
Linus Torvalds's avatar
Linus Torvalds committed
233
234
{
	int count, err;
235

Linus Torvalds's avatar
Linus Torvalds committed
236
	memset(st, 0, sizeof(st));
237

Linus Torvalds's avatar
Linus Torvalds committed
238
239
240
241
242
243
	count = 0;
	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
	if (err < 0) {
		printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
		return err;
	}
244

Linus Torvalds's avatar
Linus Torvalds committed
245
246
247
248
249
250
251
252
253
254
	if (count >= sizeof(*st))
		memcpy(st, buf, sizeof(*st));

	return count;
}

static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
{
	unsigned char buf[64];
	int count, err = 0, i;
255

Linus Torvalds's avatar
Linus Torvalds committed
256
	memcpy(st, buf, sizeof(*st));
257

Linus Torvalds's avatar
Linus Torvalds committed
258
259
260
	count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
	if (count < 0)
		return err;
261

Linus Torvalds's avatar
Linus Torvalds committed
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
	printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
	for (i=0; i<count; ++i)
		printk("%02x ", buf[i]);
	printk("\n");

	if (count >= 16) {
		ds_dump_status(buf, "enable flag", 0);
		ds_dump_status(buf, "1-wire speed", 1);
		ds_dump_status(buf, "strong pullup duration", 2);
		ds_dump_status(buf, "programming pulse duration", 3);
		ds_dump_status(buf, "pulldown slew rate control", 4);
		ds_dump_status(buf, "write-1 low time", 5);
		ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
		ds_dump_status(buf, "reserved (test register)", 7);
		ds_dump_status(buf, "device status flags", 8);
		ds_dump_status(buf, "communication command byte 1", 9);
		ds_dump_status(buf, "communication command byte 2", 10);
		ds_dump_status(buf, "communication command buffer status", 11);
		ds_dump_status(buf, "1-wire data output buffer status", 12);
		ds_dump_status(buf, "1-wire data input buffer status", 13);
		ds_dump_status(buf, "reserved", 14);
		ds_dump_status(buf, "reserved", 15);
	}

	memcpy(st, buf, sizeof(*st));

	if (st->status & ST_EPOF) {
		printk(KERN_INFO "Resetting device after ST_EPOF.\n");
		err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
		if (err)
			return err;
		count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
		if (count < 0)
			return err;
	}
#if 0
	if (st->status & ST_IDLE) {
		printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
		err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
		if (err)
			return err;
	}
#endif
305

Linus Torvalds's avatar
Linus Torvalds committed
306
307
308
309
310
311
312
	return err;
}

static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
{
	int count, err;
	struct ds_status st;
313

Linus Torvalds's avatar
Linus Torvalds committed
314
	count = 0;
315
	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
Linus Torvalds's avatar
Linus Torvalds committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
				buf, size, &count, 1000);
	if (err < 0) {
		printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
		usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
		ds_recv_status(dev, &st);
		return err;
	}

#if 0
	{
		int i;

		printk("%s: count=%d: ", __func__, count);
		for (i=0; i<count; ++i)
			printk("%02x ", buf[i]);
		printk("\n");
	}
#endif
	return count;
}

static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
{
	int count, err;
340

Linus Torvalds's avatar
Linus Torvalds committed
341
342
343
344
345
346
347
348
349
350
	count = 0;
	err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
	if (err < 0) {
		printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
		return err;
	}

	return err;
}

351
352
#if 0

Linus Torvalds's avatar
Linus Torvalds committed
353
354
355
356
357
int ds_stop_pulse(struct ds_device *dev, int limit)
{
	struct ds_status st;
	int count = 0, err = 0;
	u8 buf[0x20];
358

Linus Torvalds's avatar
Linus Torvalds committed
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
	do {
		err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
		if (err)
			break;
		err = ds_send_control(dev, CTL_RESUME_EXE, 0);
		if (err)
			break;
		err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
		if (err)
			break;

		if ((st.status & ST_SPUA) == 0) {
			err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
			if (err)
				break;
		}
	} while(++count < limit);

	return err;
}

int ds_detect(struct ds_device *dev, struct ds_status *st)
{
	int err;
383

Linus Torvalds's avatar
Linus Torvalds committed
384
385
386
387
388
389
390
	err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
	if (err)
		return err;

	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
	if (err)
		return err;
391

Linus Torvalds's avatar
Linus Torvalds committed
392
393
394
	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
	if (err)
		return err;
395

Linus Torvalds's avatar
Linus Torvalds committed
396
397
398
399
400
401
402
403
404
	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
	if (err)
		return err;

	err = ds_recv_status(dev, st);

	return err;
}

405
406
407
#endif  /*  0  */

static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
Linus Torvalds's avatar
Linus Torvalds committed
408
409
410
411
412
413
414
{
	u8 buf[0x20];
	int err, count = 0;

	do {
		err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
#if 0
415
		if (err >= 0) {
Linus Torvalds's avatar
Linus Torvalds committed
416
417
418
419
420
421
422
423
424
425
426
427
428
			int i;
			printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
			for (i=0; i<err; ++i)
				printk("%02x ", buf[i]);
			printk("\n");
		}
#endif
	} while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);


	if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
		ds_recv_status(dev, st);
		return -1;
429
	} else
Linus Torvalds's avatar
Linus Torvalds committed
430
431
432
		return 0;
}

433
static int ds_reset(struct ds_device *dev, struct ds_status *st)
Linus Torvalds's avatar
Linus Torvalds committed
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
{
	int err;

	//err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
	err = ds_send_control(dev, 0x43, SPEED_NORMAL);
	if (err)
		return err;

	ds_wait_status(dev, st);
#if 0
	if (st->command_buffer_status) {
		printk(KERN_INFO "Short circuit.\n");
		return -EIO;
	}
#endif
449

Linus Torvalds's avatar
Linus Torvalds committed
450
451
452
	return 0;
}

453
#if 0
454
static int ds_set_speed(struct ds_device *dev, int speed)
Linus Torvalds's avatar
Linus Torvalds committed
455
456
{
	int err;
457

Linus Torvalds's avatar
Linus Torvalds committed
458
459
460
461
462
463
464
	if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
		return -EINVAL;

	if (speed != SPEED_OVERDRIVE)
		speed = SPEED_FLEXIBLE;

	speed &= 0xff;
465

Linus Torvalds's avatar
Linus Torvalds committed
466
467
468
469
470
471
	err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
	if (err)
		return err;

	return err;
}
472
#endif  /*  0  */
Linus Torvalds's avatar
Linus Torvalds committed
473

474
static int ds_start_pulse(struct ds_device *dev, int delay)
Linus Torvalds's avatar
Linus Torvalds committed
475
476
477
478
{
	int err;
	u8 del = 1 + (u8)(delay >> 4);
	struct ds_status st;
479

Linus Torvalds's avatar
Linus Torvalds committed
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
#if 0
	err = ds_stop_pulse(dev, 10);
	if (err)
		return err;

	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
	if (err)
		return err;
#endif
	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
	if (err)
		return err;

	err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
	if (err)
		return err;

	mdelay(delay);

	ds_wait_status(dev, &st);
500

Linus Torvalds's avatar
Linus Torvalds committed
501
502
503
	return err;
}

504
static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
Linus Torvalds's avatar
Linus Torvalds committed
505
506
507
508
509
{
	int err, count;
	struct ds_status st;
	u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
	u16 cmd;
510

Linus Torvalds's avatar
Linus Torvalds committed
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
	err = ds_send_control(dev, value, 0);
	if (err)
		return err;

	count = 0;
	do {
		err = ds_wait_status(dev, &st);
		if (err)
			return err;

		cmd = st.command0 | (st.command1 << 8);
	} while (cmd != value && ++count < 10);

	if (err < 0 || count >= 10) {
		printk(KERN_ERR "Failed to obtain status.\n");
		return -EINVAL;
	}

	err = ds_recv_data(dev, tbit, sizeof(*tbit));
	if (err < 0)
		return err;

	return 0;
}

536
static int ds_write_bit(struct ds_device *dev, u8 bit)
Linus Torvalds's avatar
Linus Torvalds committed
537
538
539
{
	int err;
	struct ds_status st;
540

Linus Torvalds's avatar
Linus Torvalds committed
541
542
543
544
545
546
547
548
549
	err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
	if (err)
		return err;

	ds_wait_status(dev, &st);

	return 0;
}

550
static int ds_write_byte(struct ds_device *dev, u8 byte)
Linus Torvalds's avatar
Linus Torvalds committed
551
552
553
554
{
	int err;
	struct ds_status st;
	u8 rbyte;
555

Linus Torvalds's avatar
Linus Torvalds committed
556
557
558
559
560
561
562
	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
	if (err)
		return err;

	err = ds_wait_status(dev, &st);
	if (err)
		return err;
563

Linus Torvalds's avatar
Linus Torvalds committed
564
565
566
	err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
	if (err < 0)
		return err;
567

Linus Torvalds's avatar
Linus Torvalds committed
568
569
570
571
572
	ds_start_pulse(dev, PULLUP_PULSE_DURATION);

	return !(byte == rbyte);
}

573
static int ds_read_byte(struct ds_device *dev, u8 *byte)
Linus Torvalds's avatar
Linus Torvalds committed
574
575
576
577
578
579
580
581
582
{
	int err;
	struct ds_status st;

	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
	if (err)
		return err;

	ds_wait_status(dev, &st);
583

Linus Torvalds's avatar
Linus Torvalds committed
584
585
586
587
588
589
590
	err = ds_recv_data(dev, byte, sizeof(*byte));
	if (err < 0)
		return err;

	return 0;
}

591
static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
Linus Torvalds's avatar
Linus Torvalds committed
592
593
594
595
596
597
598
599
{
	struct ds_status st;
	int err;

	if (len > 64*1024)
		return -E2BIG;

	memset(buf, 0xFF, len);
600

Linus Torvalds's avatar
Linus Torvalds committed
601
602
603
	err = ds_send_data(dev, buf, len);
	if (err < 0)
		return err;
604

Linus Torvalds's avatar
Linus Torvalds committed
605
606
607
608
609
	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
	if (err)
		return err;

	ds_wait_status(dev, &st);
610

Linus Torvalds's avatar
Linus Torvalds committed
611
612
613
614
615
616
	memset(buf, 0x00, len);
	err = ds_recv_data(dev, buf, len);

	return err;
}

617
static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
Linus Torvalds's avatar
Linus Torvalds committed
618
619
620
{
	int err;
	struct ds_status st;
621

Linus Torvalds's avatar
Linus Torvalds committed
622
623
624
	err = ds_send_data(dev, buf, len);
	if (err < 0)
		return err;
625

Linus Torvalds's avatar
Linus Torvalds committed
626
627
628
629
630
631
632
633
634
635
636
637
638
	ds_wait_status(dev, &st);

	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
	if (err)
		return err;

	ds_wait_status(dev, &st);

	err = ds_recv_data(dev, buf, len);
	if (err < 0)
		return err;

	ds_start_pulse(dev, PULLUP_PULSE_DURATION);
639

Linus Torvalds's avatar
Linus Torvalds committed
640
641
642
	return !(err == len);
}

643
644
#if 0

645
static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
Linus Torvalds's avatar
Linus Torvalds committed
646
647
648
649
650
651
{
	int err;
	u16 value, index;
	struct ds_status st;

	memset(buf, 0, sizeof(buf));
652

Linus Torvalds's avatar
Linus Torvalds committed
653
654
655
	err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
	if (err)
		return err;
656

Linus Torvalds's avatar
Linus Torvalds committed
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
	ds_wait_status(ds_dev, &st);

	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
	index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
	err = ds_send_control(ds_dev, value, index);
	if (err)
		return err;

	ds_wait_status(ds_dev, &st);

	err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
	if (err < 0)
		return err;

	return err/8;
}

674
static int ds_match_access(struct ds_device *dev, u64 init)
Linus Torvalds's avatar
Linus Torvalds committed
675
676
677
678
679
680
681
{
	int err;
	struct ds_status st;

	err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
	if (err)
		return err;
682

Linus Torvalds's avatar
Linus Torvalds committed
683
684
685
686
687
688
689
690
691
692
693
	ds_wait_status(dev, &st);

	err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
	if (err)
		return err;

	ds_wait_status(dev, &st);

	return 0;
}

694
static int ds_set_path(struct ds_device *dev, u64 init)
Linus Torvalds's avatar
Linus Torvalds committed
695
696
697
698
699
700
701
{
	int err;
	struct ds_status st;
	u8 buf[9];

	memcpy(buf, &init, 8);
	buf[8] = BRANCH_MAIN;
702

Linus Torvalds's avatar
Linus Torvalds committed
703
704
705
	err = ds_send_data(dev, buf, sizeof(buf));
	if (err)
		return err;
706

Linus Torvalds's avatar
Linus Torvalds committed
707
708
709
710
711
712
713
714
715
716
717
	ds_wait_status(dev, &st);

	err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
	if (err)
		return err;

	ds_wait_status(dev, &st);

	return 0;
}

718
719
#endif  /*  0  */

720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
static u8 ds9490r_touch_bit(void *data, u8 bit)
{
	u8 ret;
	struct ds_device *dev = data;

	if (ds_touch_bit(dev, bit, &ret))
		return 0;

	return ret;
}

static void ds9490r_write_bit(void *data, u8 bit)
{
	struct ds_device *dev = data;

	ds_write_bit(dev, bit);
}

static void ds9490r_write_byte(void *data, u8 byte)
{
	struct ds_device *dev = data;

	ds_write_byte(dev, byte);
}

static u8 ds9490r_read_bit(void *data)
{
	struct ds_device *dev = data;
	int err;
	u8 bit = 0;

	err = ds_touch_bit(dev, 1, &bit);
	if (err)
		return 0;

	return bit & 1;
}

static u8 ds9490r_read_byte(void *data)
{
	struct ds_device *dev = data;
	int err;
	u8 byte = 0;

	err = ds_read_byte(dev, &byte);
	if (err)
		return 0;

	return byte;
}

static void ds9490r_write_block(void *data, const u8 *buf, int len)
{
	struct ds_device *dev = data;

	ds_write_block(dev, (u8 *)buf, len);
}

static u8 ds9490r_read_block(void *data, u8 *buf, int len)
{
	struct ds_device *dev = data;
	int err;

	err = ds_read_block(dev, buf, len);
	if (err < 0)
		return 0;

	return len;
}

static u8 ds9490r_reset(void *data)
{
	struct ds_device *dev = data;
	struct ds_status st;
	int err;

	memset(&st, 0, sizeof(st));

	err = ds_reset(dev, &st);
	if (err)
		return 1;

	return 0;
}

static int ds_w1_init(struct ds_device *dev)
{
	memset(&dev->master, 0, sizeof(struct w1_bus_master));

	dev->master.data	= dev;
	dev->master.touch_bit	= &ds9490r_touch_bit;
	dev->master.read_bit	= &ds9490r_read_bit;
	dev->master.write_bit	= &ds9490r_write_bit;
	dev->master.read_byte	= &ds9490r_read_byte;
	dev->master.write_byte	= &ds9490r_write_byte;
	dev->master.read_block	= &ds9490r_read_block;
	dev->master.write_block	= &ds9490r_write_block;
	dev->master.reset_bus	= &ds9490r_reset;

	return w1_add_master_device(&dev->master);
}

static void ds_w1_fini(struct ds_device *dev)
{
	w1_remove_master_device(&dev->master);
}

827
828
static int ds_probe(struct usb_interface *intf,
		    const struct usb_device_id *udev_id)
Linus Torvalds's avatar
Linus Torvalds committed
829
830
831
832
{
	struct usb_device *udev = interface_to_usbdev(intf);
	struct usb_endpoint_descriptor *endpoint;
	struct usb_host_interface *iface_desc;
833
	struct ds_device *dev;
Linus Torvalds's avatar
Linus Torvalds committed
834
835
	int i, err;

836
837
	dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
	if (!dev) {
Linus Torvalds's avatar
Linus Torvalds committed
838
839
840
		printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
		return -ENOMEM;
	}
841
842
843
844
845
846
	dev->udev = usb_get_dev(udev);
	if (!dev->udev) {
		err = -ENOMEM;
		goto err_out_free;
	}
	memset(dev->ep, 0, sizeof(dev->ep));
Linus Torvalds's avatar
Linus Torvalds committed
847

848
	usb_set_intfdata(intf, dev);
Linus Torvalds's avatar
Linus Torvalds committed
849

850
	err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
Linus Torvalds's avatar
Linus Torvalds committed
851
852
853
	if (err) {
		printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
				intf->altsetting[0].desc.bInterfaceNumber, err);
854
		goto err_out_clear;
Linus Torvalds's avatar
Linus Torvalds committed
855
856
	}

857
	err = usb_reset_configuration(dev->udev);
Linus Torvalds's avatar
Linus Torvalds committed
858
859
	if (err) {
		printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
860
		goto err_out_clear;
Linus Torvalds's avatar
Linus Torvalds committed
861
	}
862

Linus Torvalds's avatar
Linus Torvalds committed
863
864
865
	iface_desc = &intf->altsetting[0];
	if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
		printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
866
867
		err = -EINVAL;
		goto err_out_clear;
Linus Torvalds's avatar
Linus Torvalds committed
868
869
870
	}

	/*
871
	 * This loop doesn'd show control 0 endpoint,
Linus Torvalds's avatar
Linus Torvalds committed
872
873
874
875
876
	 * so we will fill only 1-3 endpoints entry.
	 */
	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
		endpoint = &iface_desc->endpoint[i].desc;

877
878
		dev->ep[i+1] = endpoint->bEndpointAddress;
#if 0
Linus Torvalds's avatar
Linus Torvalds committed
879
880
881
882
		printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
			i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
			(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
			endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
883
#endif
Linus Torvalds's avatar
Linus Torvalds committed
884
	}
885

886
887
888
	err = ds_w1_init(dev);
	if (err)
		goto err_out_clear;
889

890
891
892
	down(&ds_mutex);
	list_add_tail(&dev->ds_entry, &ds_devices);
	up(&ds_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
893
894

	return 0;
895
896
897
898
899
900
901

err_out_clear:
	usb_set_intfdata(intf, NULL);
	usb_put_dev(dev->udev);
err_out_free:
	kfree(dev);
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
902
903
}

904
static void ds_disconnect(struct usb_interface *intf)
Linus Torvalds's avatar
Linus Torvalds committed
905
906
{
	struct ds_device *dev;
907

Linus Torvalds's avatar
Linus Torvalds committed
908
	dev = usb_get_intfdata(intf);
909
910
	if (!dev)
		return;
Linus Torvalds's avatar
Linus Torvalds committed
911

912
913
914
	down(&ds_mutex);
	list_del(&dev->ds_entry);
	up(&ds_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
915

916
917
918
	ds_w1_fini(dev);

	usb_set_intfdata(intf, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
919
920
921
922
923

	usb_put_dev(dev->udev);
	kfree(dev);
}

924
static int ds_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
925
926
927
928
929
930
931
932
933
934
935
936
{
	int err;

	err = usb_register(&ds_driver);
	if (err) {
		printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
		return err;
	}

	return 0;
}

937
static void ds_fini(void)
Linus Torvalds's avatar
Linus Torvalds committed
938
939
940
941
942
943
944
945
946
{
	usb_deregister(&ds_driver);
}

module_init(ds_init);
module_exit(ds_fini);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
947
MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)");