Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
8949d2aa | 2 | * dscore.c |
1da177e4 LT |
3 | * |
4 | * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> | |
8949d2aa | 5 | * |
1da177e4 LT |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | */ | |
21 | ||
22 | #include <linux/module.h> | |
23 | #include <linux/kernel.h> | |
24 | #include <linux/mod_devicetable.h> | |
25 | #include <linux/usb.h> | |
26 | ||
27 | #include "dscore.h" | |
28 | ||
29 | static struct usb_device_id ds_id_table [] = { | |
30 | { USB_DEVICE(0x04fa, 0x2490) }, | |
31 | { }, | |
32 | }; | |
33 | MODULE_DEVICE_TABLE(usb, ds_id_table); | |
34 | ||
8949d2aa EP |
35 | static int ds_probe(struct usb_interface *, const struct usb_device_id *); |
36 | static void ds_disconnect(struct usb_interface *); | |
1da177e4 LT |
37 | |
38 | int ds_touch_bit(struct ds_device *, u8, u8 *); | |
39 | int ds_read_byte(struct ds_device *, u8 *); | |
40 | int ds_read_bit(struct ds_device *, u8 *); | |
41 | int ds_write_byte(struct ds_device *, u8); | |
42 | int ds_write_bit(struct ds_device *, u8); | |
8949d2aa | 43 | static int ds_start_pulse(struct ds_device *, int); |
1da177e4 | 44 | int ds_reset(struct ds_device *, struct ds_status *); |
1da177e4 LT |
45 | struct ds_device * ds_get_device(void); |
46 | void ds_put_device(struct ds_device *); | |
47 | ||
48 | static inline void ds_dump_status(unsigned char *, unsigned char *, int); | |
49 | static int ds_send_control(struct ds_device *, u16, u16); | |
50 | static int ds_send_control_mode(struct ds_device *, u16, u16); | |
51 | static int ds_send_control_cmd(struct ds_device *, u16, u16); | |
52 | ||
53 | ||
54 | static struct usb_driver ds_driver = { | |
55 | .owner = THIS_MODULE, | |
56 | .name = "DS9490R", | |
57 | .probe = ds_probe, | |
58 | .disconnect = ds_disconnect, | |
59 | .id_table = ds_id_table, | |
60 | }; | |
61 | ||
62 | static struct ds_device *ds_dev; | |
63 | ||
64 | struct ds_device * ds_get_device(void) | |
65 | { | |
66 | if (ds_dev) | |
67 | atomic_inc(&ds_dev->refcnt); | |
68 | return ds_dev; | |
69 | } | |
70 | ||
71 | void ds_put_device(struct ds_device *dev) | |
72 | { | |
73 | atomic_dec(&dev->refcnt); | |
74 | } | |
75 | ||
76 | static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) | |
77 | { | |
78 | int err; | |
8949d2aa EP |
79 | |
80 | err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), | |
1da177e4 LT |
81 | CONTROL_CMD, 0x40, value, index, NULL, 0, 1000); |
82 | if (err < 0) { | |
8949d2aa | 83 | printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", |
1da177e4 LT |
84 | value, index, err); |
85 | return err; | |
86 | } | |
87 | ||
88 | return err; | |
89 | } | |
90 | ||
91 | static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) | |
92 | { | |
93 | int err; | |
8949d2aa EP |
94 | |
95 | err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), | |
1da177e4 LT |
96 | MODE_CMD, 0x40, value, index, NULL, 0, 1000); |
97 | if (err < 0) { | |
8949d2aa | 98 | printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", |
1da177e4 LT |
99 | value, index, err); |
100 | return err; | |
101 | } | |
102 | ||
103 | return err; | |
104 | } | |
105 | ||
106 | static int ds_send_control(struct ds_device *dev, u16 value, u16 index) | |
107 | { | |
108 | int err; | |
8949d2aa EP |
109 | |
110 | err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), | |
1da177e4 LT |
111 | COMM_CMD, 0x40, value, index, NULL, 0, 1000); |
112 | if (err < 0) { | |
8949d2aa | 113 | printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", |
1da177e4 LT |
114 | value, index, err); |
115 | return err; | |
116 | } | |
117 | ||
118 | return err; | |
119 | } | |
120 | ||
121 | static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off) | |
122 | { | |
123 | printk("%45s: %8x\n", str, buf[off]); | |
124 | } | |
125 | ||
8949d2aa EP |
126 | static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, |
127 | unsigned char *buf, int size) | |
1da177e4 LT |
128 | { |
129 | int count, err; | |
8949d2aa | 130 | |
1da177e4 | 131 | memset(st, 0, sizeof(st)); |
8949d2aa | 132 | |
1da177e4 LT |
133 | count = 0; |
134 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); | |
135 | if (err < 0) { | |
136 | printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err); | |
137 | return err; | |
138 | } | |
8949d2aa | 139 | |
1da177e4 LT |
140 | if (count >= sizeof(*st)) |
141 | memcpy(st, buf, sizeof(*st)); | |
142 | ||
143 | return count; | |
144 | } | |
145 | ||
146 | static int ds_recv_status(struct ds_device *dev, struct ds_status *st) | |
147 | { | |
148 | unsigned char buf[64]; | |
149 | int count, err = 0, i; | |
8949d2aa | 150 | |
1da177e4 | 151 | memcpy(st, buf, sizeof(*st)); |
8949d2aa | 152 | |
1da177e4 LT |
153 | count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); |
154 | if (count < 0) | |
155 | return err; | |
8949d2aa | 156 | |
1da177e4 LT |
157 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); |
158 | for (i=0; i<count; ++i) | |
159 | printk("%02x ", buf[i]); | |
160 | printk("\n"); | |
161 | ||
162 | if (count >= 16) { | |
163 | ds_dump_status(buf, "enable flag", 0); | |
164 | ds_dump_status(buf, "1-wire speed", 1); | |
165 | ds_dump_status(buf, "strong pullup duration", 2); | |
166 | ds_dump_status(buf, "programming pulse duration", 3); | |
167 | ds_dump_status(buf, "pulldown slew rate control", 4); | |
168 | ds_dump_status(buf, "write-1 low time", 5); | |
169 | ds_dump_status(buf, "data sample offset/write-0 recovery time", 6); | |
170 | ds_dump_status(buf, "reserved (test register)", 7); | |
171 | ds_dump_status(buf, "device status flags", 8); | |
172 | ds_dump_status(buf, "communication command byte 1", 9); | |
173 | ds_dump_status(buf, "communication command byte 2", 10); | |
174 | ds_dump_status(buf, "communication command buffer status", 11); | |
175 | ds_dump_status(buf, "1-wire data output buffer status", 12); | |
176 | ds_dump_status(buf, "1-wire data input buffer status", 13); | |
177 | ds_dump_status(buf, "reserved", 14); | |
178 | ds_dump_status(buf, "reserved", 15); | |
179 | } | |
180 | ||
181 | memcpy(st, buf, sizeof(*st)); | |
182 | ||
183 | if (st->status & ST_EPOF) { | |
184 | printk(KERN_INFO "Resetting device after ST_EPOF.\n"); | |
185 | err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); | |
186 | if (err) | |
187 | return err; | |
188 | count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | |
189 | if (count < 0) | |
190 | return err; | |
191 | } | |
192 | #if 0 | |
193 | if (st->status & ST_IDLE) { | |
194 | printk(KERN_INFO "Resetting pulse after ST_IDLE.\n"); | |
195 | err = ds_start_pulse(dev, PULLUP_PULSE_DURATION); | |
196 | if (err) | |
197 | return err; | |
198 | } | |
199 | #endif | |
8949d2aa | 200 | |
1da177e4 LT |
201 | return err; |
202 | } | |
203 | ||
204 | static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) | |
205 | { | |
206 | int count, err; | |
207 | struct ds_status st; | |
8949d2aa | 208 | |
1da177e4 | 209 | count = 0; |
8949d2aa | 210 | err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), |
1da177e4 LT |
211 | buf, size, &count, 1000); |
212 | if (err < 0) { | |
213 | printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); | |
214 | usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); | |
215 | ds_recv_status(dev, &st); | |
216 | return err; | |
217 | } | |
218 | ||
219 | #if 0 | |
220 | { | |
221 | int i; | |
222 | ||
223 | printk("%s: count=%d: ", __func__, count); | |
224 | for (i=0; i<count; ++i) | |
225 | printk("%02x ", buf[i]); | |
226 | printk("\n"); | |
227 | } | |
228 | #endif | |
229 | return count; | |
230 | } | |
231 | ||
232 | static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) | |
233 | { | |
234 | int count, err; | |
8949d2aa | 235 | |
1da177e4 LT |
236 | count = 0; |
237 | err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); | |
238 | if (err < 0) { | |
239 | printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err); | |
240 | return err; | |
241 | } | |
242 | ||
243 | return err; | |
244 | } | |
245 | ||
8949d2aa EP |
246 | #if 0 |
247 | ||
1da177e4 LT |
248 | int ds_stop_pulse(struct ds_device *dev, int limit) |
249 | { | |
250 | struct ds_status st; | |
251 | int count = 0, err = 0; | |
252 | u8 buf[0x20]; | |
8949d2aa | 253 | |
1da177e4 LT |
254 | do { |
255 | err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); | |
256 | if (err) | |
257 | break; | |
258 | err = ds_send_control(dev, CTL_RESUME_EXE, 0); | |
259 | if (err) | |
260 | break; | |
261 | err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); | |
262 | if (err) | |
263 | break; | |
264 | ||
265 | if ((st.status & ST_SPUA) == 0) { | |
266 | err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); | |
267 | if (err) | |
268 | break; | |
269 | } | |
270 | } while(++count < limit); | |
271 | ||
272 | return err; | |
273 | } | |
274 | ||
275 | int ds_detect(struct ds_device *dev, struct ds_status *st) | |
276 | { | |
277 | int err; | |
8949d2aa | 278 | |
1da177e4 LT |
279 | err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); |
280 | if (err) | |
281 | return err; | |
282 | ||
283 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); | |
284 | if (err) | |
285 | return err; | |
8949d2aa | 286 | |
1da177e4 LT |
287 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); |
288 | if (err) | |
289 | return err; | |
8949d2aa | 290 | |
1da177e4 LT |
291 | err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); |
292 | if (err) | |
293 | return err; | |
294 | ||
295 | err = ds_recv_status(dev, st); | |
296 | ||
297 | return err; | |
298 | } | |
299 | ||
8949d2aa EP |
300 | #endif /* 0 */ |
301 | ||
302 | static int ds_wait_status(struct ds_device *dev, struct ds_status *st) | |
1da177e4 LT |
303 | { |
304 | u8 buf[0x20]; | |
305 | int err, count = 0; | |
306 | ||
307 | do { | |
308 | err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); | |
309 | #if 0 | |
8949d2aa | 310 | if (err >= 0) { |
1da177e4 LT |
311 | int i; |
312 | printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); | |
313 | for (i=0; i<err; ++i) | |
314 | printk("%02x ", buf[i]); | |
315 | printk("\n"); | |
316 | } | |
317 | #endif | |
318 | } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); | |
319 | ||
320 | ||
321 | if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) { | |
322 | ds_recv_status(dev, st); | |
323 | return -1; | |
8949d2aa | 324 | } else |
1da177e4 | 325 | return 0; |
1da177e4 LT |
326 | } |
327 | ||
328 | int ds_reset(struct ds_device *dev, struct ds_status *st) | |
329 | { | |
330 | int err; | |
331 | ||
332 | //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); | |
333 | err = ds_send_control(dev, 0x43, SPEED_NORMAL); | |
334 | if (err) | |
335 | return err; | |
336 | ||
337 | ds_wait_status(dev, st); | |
338 | #if 0 | |
339 | if (st->command_buffer_status) { | |
340 | printk(KERN_INFO "Short circuit.\n"); | |
341 | return -EIO; | |
342 | } | |
343 | #endif | |
344 | ||
345 | return 0; | |
346 | } | |
347 | ||
8949d2aa | 348 | #if 0 |
1da177e4 LT |
349 | int ds_set_speed(struct ds_device *dev, int speed) |
350 | { | |
351 | int err; | |
352 | ||
353 | if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) | |
354 | return -EINVAL; | |
355 | ||
356 | if (speed != SPEED_OVERDRIVE) | |
357 | speed = SPEED_FLEXIBLE; | |
358 | ||
359 | speed &= 0xff; | |
8949d2aa | 360 | |
1da177e4 LT |
361 | err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); |
362 | if (err) | |
363 | return err; | |
364 | ||
365 | return err; | |
366 | } | |
8949d2aa | 367 | #endif /* 0 */ |
1da177e4 | 368 | |
8949d2aa | 369 | static int ds_start_pulse(struct ds_device *dev, int delay) |
1da177e4 LT |
370 | { |
371 | int err; | |
372 | u8 del = 1 + (u8)(delay >> 4); | |
373 | struct ds_status st; | |
8949d2aa | 374 | |
1da177e4 LT |
375 | #if 0 |
376 | err = ds_stop_pulse(dev, 10); | |
377 | if (err) | |
378 | return err; | |
379 | ||
380 | err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE); | |
381 | if (err) | |
382 | return err; | |
383 | #endif | |
384 | err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); | |
385 | if (err) | |
386 | return err; | |
387 | ||
388 | err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0); | |
389 | if (err) | |
390 | return err; | |
391 | ||
392 | mdelay(delay); | |
393 | ||
394 | ds_wait_status(dev, &st); | |
8949d2aa | 395 | |
1da177e4 LT |
396 | return err; |
397 | } | |
398 | ||
399 | int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) | |
400 | { | |
401 | int err, count; | |
402 | struct ds_status st; | |
403 | u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0); | |
404 | u16 cmd; | |
8949d2aa | 405 | |
1da177e4 LT |
406 | err = ds_send_control(dev, value, 0); |
407 | if (err) | |
408 | return err; | |
409 | ||
410 | count = 0; | |
411 | do { | |
412 | err = ds_wait_status(dev, &st); | |
413 | if (err) | |
414 | return err; | |
415 | ||
416 | cmd = st.command0 | (st.command1 << 8); | |
417 | } while (cmd != value && ++count < 10); | |
418 | ||
419 | if (err < 0 || count >= 10) { | |
420 | printk(KERN_ERR "Failed to obtain status.\n"); | |
421 | return -EINVAL; | |
422 | } | |
423 | ||
424 | err = ds_recv_data(dev, tbit, sizeof(*tbit)); | |
425 | if (err < 0) | |
426 | return err; | |
427 | ||
428 | return 0; | |
429 | } | |
430 | ||
431 | int ds_write_bit(struct ds_device *dev, u8 bit) | |
432 | { | |
433 | int err; | |
434 | struct ds_status st; | |
8949d2aa | 435 | |
1da177e4 LT |
436 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0); |
437 | if (err) | |
438 | return err; | |
439 | ||
440 | ds_wait_status(dev, &st); | |
441 | ||
442 | return 0; | |
443 | } | |
444 | ||
445 | int ds_write_byte(struct ds_device *dev, u8 byte) | |
446 | { | |
447 | int err; | |
448 | struct ds_status st; | |
449 | u8 rbyte; | |
8949d2aa | 450 | |
1da177e4 LT |
451 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); |
452 | if (err) | |
453 | return err; | |
454 | ||
455 | err = ds_wait_status(dev, &st); | |
456 | if (err) | |
457 | return err; | |
8949d2aa | 458 | |
1da177e4 LT |
459 | err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); |
460 | if (err < 0) | |
461 | return err; | |
8949d2aa | 462 | |
1da177e4 LT |
463 | ds_start_pulse(dev, PULLUP_PULSE_DURATION); |
464 | ||
465 | return !(byte == rbyte); | |
466 | } | |
467 | ||
468 | int ds_read_bit(struct ds_device *dev, u8 *bit) | |
469 | { | |
470 | int err; | |
471 | ||
472 | err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE); | |
473 | if (err) | |
474 | return err; | |
8949d2aa | 475 | |
1da177e4 LT |
476 | err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0); |
477 | if (err) | |
478 | return err; | |
8949d2aa | 479 | |
1da177e4 LT |
480 | err = ds_recv_data(dev, bit, sizeof(*bit)); |
481 | if (err < 0) | |
482 | return err; | |
483 | ||
484 | return 0; | |
485 | } | |
486 | ||
487 | int ds_read_byte(struct ds_device *dev, u8 *byte) | |
488 | { | |
489 | int err; | |
490 | struct ds_status st; | |
491 | ||
492 | err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff); | |
493 | if (err) | |
494 | return err; | |
495 | ||
496 | ds_wait_status(dev, &st); | |
8949d2aa | 497 | |
1da177e4 LT |
498 | err = ds_recv_data(dev, byte, sizeof(*byte)); |
499 | if (err < 0) | |
500 | return err; | |
501 | ||
502 | return 0; | |
503 | } | |
504 | ||
505 | int ds_read_block(struct ds_device *dev, u8 *buf, int len) | |
506 | { | |
507 | struct ds_status st; | |
508 | int err; | |
509 | ||
510 | if (len > 64*1024) | |
511 | return -E2BIG; | |
512 | ||
513 | memset(buf, 0xFF, len); | |
8949d2aa | 514 | |
1da177e4 LT |
515 | err = ds_send_data(dev, buf, len); |
516 | if (err < 0) | |
517 | return err; | |
8949d2aa | 518 | |
1da177e4 LT |
519 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); |
520 | if (err) | |
521 | return err; | |
522 | ||
523 | ds_wait_status(dev, &st); | |
8949d2aa | 524 | |
1da177e4 LT |
525 | memset(buf, 0x00, len); |
526 | err = ds_recv_data(dev, buf, len); | |
527 | ||
528 | return err; | |
529 | } | |
530 | ||
531 | int ds_write_block(struct ds_device *dev, u8 *buf, int len) | |
532 | { | |
533 | int err; | |
534 | struct ds_status st; | |
8949d2aa | 535 | |
1da177e4 LT |
536 | err = ds_send_data(dev, buf, len); |
537 | if (err < 0) | |
538 | return err; | |
8949d2aa | 539 | |
1da177e4 LT |
540 | ds_wait_status(dev, &st); |
541 | ||
542 | err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); | |
543 | if (err) | |
544 | return err; | |
545 | ||
546 | ds_wait_status(dev, &st); | |
547 | ||
548 | err = ds_recv_data(dev, buf, len); | |
549 | if (err < 0) | |
550 | return err; | |
551 | ||
552 | ds_start_pulse(dev, PULLUP_PULSE_DURATION); | |
8949d2aa | 553 | |
1da177e4 LT |
554 | return !(err == len); |
555 | } | |
556 | ||
8949d2aa EP |
557 | #if 0 |
558 | ||
1da177e4 LT |
559 | int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) |
560 | { | |
561 | int err; | |
562 | u16 value, index; | |
563 | struct ds_status st; | |
564 | ||
565 | memset(buf, 0, sizeof(buf)); | |
8949d2aa | 566 | |
1da177e4 LT |
567 | err = ds_send_data(ds_dev, (unsigned char *)&init, 8); |
568 | if (err) | |
569 | return err; | |
8949d2aa | 570 | |
1da177e4 LT |
571 | ds_wait_status(ds_dev, &st); |
572 | ||
573 | value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; | |
574 | index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); | |
575 | err = ds_send_control(ds_dev, value, index); | |
576 | if (err) | |
577 | return err; | |
578 | ||
579 | ds_wait_status(ds_dev, &st); | |
580 | ||
581 | err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); | |
582 | if (err < 0) | |
583 | return err; | |
584 | ||
585 | return err/8; | |
586 | } | |
587 | ||
588 | int ds_match_access(struct ds_device *dev, u64 init) | |
589 | { | |
590 | int err; | |
591 | struct ds_status st; | |
592 | ||
593 | err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); | |
594 | if (err) | |
595 | return err; | |
8949d2aa | 596 | |
1da177e4 LT |
597 | ds_wait_status(dev, &st); |
598 | ||
599 | err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); | |
600 | if (err) | |
601 | return err; | |
602 | ||
603 | ds_wait_status(dev, &st); | |
604 | ||
605 | return 0; | |
606 | } | |
607 | ||
608 | int ds_set_path(struct ds_device *dev, u64 init) | |
609 | { | |
610 | int err; | |
611 | struct ds_status st; | |
612 | u8 buf[9]; | |
613 | ||
614 | memcpy(buf, &init, 8); | |
615 | buf[8] = BRANCH_MAIN; | |
8949d2aa | 616 | |
1da177e4 LT |
617 | err = ds_send_data(dev, buf, sizeof(buf)); |
618 | if (err) | |
619 | return err; | |
8949d2aa | 620 | |
1da177e4 LT |
621 | ds_wait_status(dev, &st); |
622 | ||
623 | err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); | |
624 | if (err) | |
625 | return err; | |
626 | ||
627 | ds_wait_status(dev, &st); | |
628 | ||
629 | return 0; | |
630 | } | |
631 | ||
8949d2aa EP |
632 | #endif /* 0 */ |
633 | ||
634 | static int ds_probe(struct usb_interface *intf, | |
635 | const struct usb_device_id *udev_id) | |
1da177e4 LT |
636 | { |
637 | struct usb_device *udev = interface_to_usbdev(intf); | |
638 | struct usb_endpoint_descriptor *endpoint; | |
639 | struct usb_host_interface *iface_desc; | |
640 | int i, err; | |
641 | ||
642 | ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); | |
643 | if (!ds_dev) { | |
644 | printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); | |
645 | return -ENOMEM; | |
646 | } | |
647 | ||
648 | ds_dev->udev = usb_get_dev(udev); | |
649 | usb_set_intfdata(intf, ds_dev); | |
650 | ||
651 | err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); | |
652 | if (err) { | |
653 | printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", | |
654 | intf->altsetting[0].desc.bInterfaceNumber, err); | |
655 | return err; | |
656 | } | |
657 | ||
658 | err = usb_reset_configuration(ds_dev->udev); | |
659 | if (err) { | |
660 | printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); | |
661 | return err; | |
662 | } | |
8949d2aa | 663 | |
1da177e4 LT |
664 | iface_desc = &intf->altsetting[0]; |
665 | if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { | |
666 | printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); | |
667 | return -ENODEV; | |
668 | } | |
669 | ||
670 | atomic_set(&ds_dev->refcnt, 0); | |
671 | memset(ds_dev->ep, 0, sizeof(ds_dev->ep)); | |
8949d2aa | 672 | |
1da177e4 | 673 | /* |
8949d2aa | 674 | * This loop doesn'd show control 0 endpoint, |
1da177e4 LT |
675 | * so we will fill only 1-3 endpoints entry. |
676 | */ | |
677 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { | |
678 | endpoint = &iface_desc->endpoint[i].desc; | |
679 | ||
680 | ds_dev->ep[i+1] = endpoint->bEndpointAddress; | |
8949d2aa | 681 | |
1da177e4 LT |
682 | printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", |
683 | i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), | |
684 | (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", | |
685 | endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); | |
686 | } | |
8949d2aa | 687 | |
1da177e4 LT |
688 | #if 0 |
689 | { | |
690 | int err, i; | |
691 | u64 buf[3]; | |
692 | u64 init=0xb30000002078ee81ull; | |
693 | struct ds_status st; | |
8949d2aa | 694 | |
1da177e4 LT |
695 | ds_reset(ds_dev, &st); |
696 | err = ds_search(ds_dev, init, buf, 3, 0); | |
697 | if (err < 0) | |
698 | return err; | |
699 | for (i=0; i<err; ++i) | |
700 | printk("%d: %llx\n", i, buf[i]); | |
8949d2aa EP |
701 | |
702 | printk("Resetting...\n"); | |
1da177e4 LT |
703 | ds_reset(ds_dev, &st); |
704 | printk("Setting path for %llx.\n", init); | |
705 | err = ds_set_path(ds_dev, init); | |
706 | if (err) | |
707 | return err; | |
708 | printk("Calling MATCH_ACCESS.\n"); | |
709 | err = ds_match_access(ds_dev, init); | |
710 | if (err) | |
711 | return err; | |
712 | ||
713 | printk("Searching the bus...\n"); | |
714 | err = ds_search(ds_dev, init, buf, 3, 0); | |
715 | ||
716 | printk("ds_search() returned %d\n", err); | |
8949d2aa | 717 | |
1da177e4 LT |
718 | if (err < 0) |
719 | return err; | |
720 | for (i=0; i<err; ++i) | |
721 | printk("%d: %llx\n", i, buf[i]); | |
8949d2aa | 722 | |
1da177e4 LT |
723 | return 0; |
724 | } | |
725 | #endif | |
726 | ||
727 | return 0; | |
728 | } | |
729 | ||
8949d2aa | 730 | static void ds_disconnect(struct usb_interface *intf) |
1da177e4 LT |
731 | { |
732 | struct ds_device *dev; | |
8949d2aa | 733 | |
1da177e4 LT |
734 | dev = usb_get_intfdata(intf); |
735 | usb_set_intfdata(intf, NULL); | |
736 | ||
737 | while (atomic_read(&dev->refcnt)) { | |
738 | printk(KERN_INFO "Waiting for DS to become free: refcnt=%d.\n", | |
739 | atomic_read(&dev->refcnt)); | |
740 | ||
741 | if (msleep_interruptible(1000)) | |
742 | flush_signals(current); | |
743 | } | |
744 | ||
745 | usb_put_dev(dev->udev); | |
746 | kfree(dev); | |
747 | ds_dev = NULL; | |
748 | } | |
749 | ||
8949d2aa | 750 | static int ds_init(void) |
1da177e4 LT |
751 | { |
752 | int err; | |
753 | ||
754 | err = usb_register(&ds_driver); | |
755 | if (err) { | |
756 | printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); | |
757 | return err; | |
758 | } | |
759 | ||
760 | return 0; | |
761 | } | |
762 | ||
8949d2aa | 763 | static void ds_fini(void) |
1da177e4 LT |
764 | { |
765 | usb_deregister(&ds_driver); | |
766 | } | |
767 | ||
768 | module_init(ds_init); | |
769 | module_exit(ds_fini); | |
770 | ||
771 | MODULE_LICENSE("GPL"); | |
772 | MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); | |
773 | ||
774 | EXPORT_SYMBOL(ds_touch_bit); | |
775 | EXPORT_SYMBOL(ds_read_byte); | |
776 | EXPORT_SYMBOL(ds_read_bit); | |
777 | EXPORT_SYMBOL(ds_read_block); | |
778 | EXPORT_SYMBOL(ds_write_byte); | |
779 | EXPORT_SYMBOL(ds_write_bit); | |
780 | EXPORT_SYMBOL(ds_write_block); | |
781 | EXPORT_SYMBOL(ds_reset); | |
782 | EXPORT_SYMBOL(ds_get_device); | |
783 | EXPORT_SYMBOL(ds_put_device); | |
784 | ||
785 | /* | |
8949d2aa EP |
786 | * This functions can be used for EEPROM programming, |
787 | * when driver will be included into mainline this will | |
1da177e4 LT |
788 | * require uncommenting. |
789 | */ | |
790 | #if 0 | |
791 | EXPORT_SYMBOL(ds_start_pulse); | |
792 | EXPORT_SYMBOL(ds_set_speed); | |
793 | EXPORT_SYMBOL(ds_detect); | |
794 | EXPORT_SYMBOL(ds_stop_pulse); | |
795 | EXPORT_SYMBOL(ds_search); | |
796 | #endif |